Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discuss unambiguous function call syntax #45

Merged
merged 3 commits into from
May 26, 2017
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions src/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ exact `self`-type of the left-hand-side is known, or dynamically dispatching if
the left-hand-side expression is an indirect [trait
object](types.html#trait-objects).

[UFCS](#unambiguous-function-call-syntax) allows method invocation using
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this link is still wrong, no?

function-like syntax.

## Field expressions

A _field expression_ consists of an expression followed by a single dot and an
Expand Down Expand Up @@ -544,6 +547,63 @@ let x: i32 = add(1i32, 2i32);
let pi: Result<f32, _> = "3.14".parse();
```

Function calls may sometimes result in ambiguities about receiver or referent.
See [UFCS](#unambiguous-function-call-syntax) for how to resolve this.

### Unambiguous Function Call Syntax (UFCS)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, it's been the opinion of the language team for a long time that "UFCS" is a terrible name and shouldn't be used. It's also not exactly a separate feature, it's that the usual way of calling trait methods is sugar for this syntax. As such, I'm not sure the framing of this PR is right, though there is no way for you to have known that, of course. ☹️

I am tempted to merge it as such, and then, we'll end up doing another pass later that cleans this up. This is okay with me, but I don't know how you feel about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh that's helpful. with that in mind, maybe I can have a sub-section here instead of the new section I created? I can describe roughly what you said: "UFCS" confuses the issue, and the RFC didn't add a separate feature. It merely generalized some syntax and turned the then-current syntax into sugar for the fully-qualified function-call syntax. FQFC.

iono @steveklabnik, I'll push some updates, and you can tell me what you think.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that sounds good to me


Several situations often occur which result in ambiguities about the receiver or
referent of method or associated function calls. These situations may include:

* Multiple in-scope traits define the same method for the same types
* Auto-`deref` is undesirable; for example, distinguishing between methods on a
smart pointer itself and the pointer's referent
* Methods which take no arguments, like `default()`, and return properties of a
type, like `size_of()`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How could default() result in an ambiguity?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fn main() {
    let a = Default::default();
    println!("{:?}", a);
}

You can (must) use a type annotation or UFCS, right?


The programmer may unambiguously refer to their desired method or function using
Unambiguous Function Call Syntax (UFCS), specifying only as much type and path
information as necessary.

For example,

```rust
trait Foo {
fn quux();
}

trait Bar {
fn quux();
}

struct Faz;
impl Foo for Faz {
fn quux() {}
}

struct Baz;
impl Foo for Baz {
fn quux() {}
}
impl Bar for Baz {
fn quux() {}
}

fn main() {
// shorthand, only if unambiguous
Faz::quux();

// Baz::quux(); // Error: multiple `quux` found

// completely unambiguous; works if multiple in-scope traits define `quux`
<Baz as Foo>::quux();
}
```

Refer to [RFC 132] for further details, motivations, and subtleties of syntax.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this temporary? RFC 1636 seems to say that RFCs aren't supposed to be stable documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I want to keep the link to the RFC. I need more explanation before the link, though. As that RFC says, the reference should be good enough for normal users to learn how to use a feature without referring to the RFC. Thanks for pointing that RFC out; I'd forgotten about it!


[RFC 132]: https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md

## Lambda expressions

A _lambda expression_ (sometimes called an "anonymous function expression")
Expand Down
1 change: 0 additions & 1 deletion src/undocumented.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ to shrink!
specified.
- [Flexible target specification] - Some---but not all---flags are documented
in [Conditional compilation]
- [Unambiguous function call syntax]
- [Require parentheses for chained comparisons]
- [Integer overflow not `unsafe`] - documented with a reference to the RFC, but
requires further details
Expand Down