From 3053f4990e8a2d2f1a69bc06ecae9d46c9be0575 Mon Sep 17 00:00:00 2001 From: "A.J. Gardner" Date: Tue, 18 Apr 2017 00:33:39 -0500 Subject: [PATCH 1/3] Discuss unambiguous function call syntax And shrink the undocumented list --- src/expressions.md | 38 ++++++++++++++++++++++++++++++++++++++ src/undocumented.md | 1 - 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/expressions.md b/src/expressions.md index df79faba7..0b49339a0 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -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 +function-like syntax. + ## Field expressions A _field expression_ consists of an expression followed by a single dot and an @@ -544,6 +547,41 @@ let x: i32 = add(1i32, 2i32); let pi: Result = "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 + +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 and return properties of a type, like + `SizeOf::size_of()` + +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,ignore +// shorthand, only if `T` is a path +T::size_of() + +// infer trait `SizeOf` based on traits in scope. +::size_of() + +// completely unambiguous; works if multiple in-scope traits define `size_of()` +::size_of() +``` + +Refer to [RFC 132] for further details, motivations, and subtleties of syntax. + +[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") diff --git a/src/undocumented.md b/src/undocumented.md index c3ae24788..72a546127 100644 --- a/src/undocumented.md +++ b/src/undocumented.md @@ -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 From ada9843c296268cdedd313922495e043ff473010 Mon Sep 17 00:00:00 2001 From: "A.J. Gardner" Date: Wed, 26 Apr 2017 09:49:16 -0500 Subject: [PATCH 2/3] Correct UFCS example using Foos and Bars --- src/expressions.md | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index 0b49339a0..497d7afa2 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -550,16 +550,16 @@ let pi: Result = "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 +### Unambiguous Function Call Syntax (UFCS) 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 and return properties of a type, like - `SizeOf::size_of()` + smart pointer itself and the pointer's referent +* Methods which take no arguments, like `default()`, and return properties of a + type, like `size_of()` The programmer may unambiguously refer to their desired method or function using Unambiguous Function Call Syntax (UFCS), specifying only as much type and path @@ -567,15 +567,37 @@ information as necessary. For example, -```rust,ignore -// shorthand, only if `T` is a path -T::size_of() +```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(); -// infer trait `SizeOf` based on traits in scope. -::size_of() + // Baz::quux(); // Error: multiple `quux` found -// completely unambiguous; works if multiple in-scope traits define `size_of()` -::size_of() + // completely unambiguous; works if multiple in-scope traits define `quux` + ::quux(); +} ``` Refer to [RFC 132] for further details, motivations, and subtleties of syntax. From 52b2635b93f10ba165ae3e53be3fdd1fff6cd860 Mon Sep 17 00:00:00 2001 From: "A.J. Gardner" Date: Sun, 21 May 2017 23:46:43 -0500 Subject: [PATCH 3/3] Expand function call discussion a bit --- src/expressions.md | 70 ++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index 497d7afa2..d89d29cb8 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -220,8 +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 -function-like syntax. +The compiler sometimes cannot infer to which function or method a given call +refers. These cases require a [more specific syntax.](#disambiguating-function-calls) +for method and function invocation. ## Field expressions @@ -547,60 +548,75 @@ let x: i32 = add(1i32, 2i32); let pi: Result = "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. +### Disambiguating Function Calls -### Unambiguous Function Call Syntax (UFCS) +Rust treats all function calls as sugar for a more explicit, fully-qualified +syntax. Upon compilation, Rust will desugar all function calls into the explicit +form. Rust may sometimes require you to qualify function calls with trait, +depending on the ambiguity of a call in light of in-scope items. + +> **Note**: In the past, the Rust community used the terms "Unambiguous +> Function Call Syntax", "Universal Function Call Syntax", or "UFCS", in +> documentation, issues, RFCs, and other community writings. However, the term +> lacks descriptive power and potentially confuses the issue at hand. We mention +> it here for searchability's sake. 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 +* Multiple in-scope traits define methods with the same name 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()` -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. +To resolve the ambiguity, the programmer may refer to their desired method or +function using more specific paths, types, or traits. For example, ```rust -trait Foo { - fn quux(); +trait Pretty { + fn print(&self); } -trait Bar { - fn quux(); +trait Ugly { + fn print(&self); } -struct Faz; -impl Foo for Faz { - fn quux() {} +struct Foo; +impl Pretty for Foo { + fn print(&self) {} } -struct Baz; -impl Foo for Baz { - fn quux() {} +struct Bar; +impl Pretty for Bar { + fn print(&self) {} } -impl Bar for Baz { - fn quux() {} +impl Ugly for Bar{ + fn print(&self) {} } fn main() { - // shorthand, only if unambiguous - Faz::quux(); + let f = Foo; + let b = Bar; + + // we can do this because we only have one item called `print` for `Foo`s + f.print(); + // more explicit, and, in the case of `Foo`, not necessary + Foo::print(&f); + // if you're not into the whole brevity thing + ::print(&f); - // Baz::quux(); // Error: multiple `quux` found + // b.print(); // Error: multiple 'print' found + // Bar::print(&b); // Still an error: multiple `print` found - // completely unambiguous; works if multiple in-scope traits define `quux` - ::quux(); + // necessary because of in-scope items defining `print` + ::print(&b); } ``` -Refer to [RFC 132] for further details, motivations, and subtleties of syntax. +Refer to [RFC 132] for further details and motivations. [RFC 132]: https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md