Skip to content

Commit 3368414

Browse files
committed
More precisely distinguish methods from functions and associated functions.
1 parent e125c71 commit 3368414

File tree

1 file changed

+25
-25
lines changed

1 file changed

+25
-25
lines changed

text/0000-import-trait-methods.md

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
1-
- Feature Name: `import-trait-methods`
1+
- Feature Name: `import-trait-associated-functions`
22
- Start Date: 2024-03-19
33
- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)
44
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)
55

66
# Summary
77
[summary]: #summary
88

9-
Allow importing methods from traits and then using them like regular functions.
9+
Allow importing associated functions from traits and then using them like regular functions.
1010

1111
# Motivation
1212
[motivation]: #motivation
1313

14-
There has for a long time been a desire to shorten the duplication needed to access certain methods, such as `Default::default`. Codebases like [Bevy](https://github.com/bevyengine/bevy/blob/7c7d1e8a6442a4258896b6c605beb1bf50399396/crates/bevy_utils/src/default.rs#L27) provide wrapper methods to shorten this call, and a previous, now-rejected, [RFC](https://github.com/rust-lang/rust/pull/73001) aimed to provide this method as part of the standard library. This RFC was rejected with a note that there is a desire for a more general capability to import any trait method.
14+
There has for a long time been a desire to shorten the duplication needed to access certain associated functions, such as `Default::default`. Codebases like [Bevy](https://github.com/bevyengine/bevy/blob/7c7d1e8a6442a4258896b6c605beb1bf50399396/crates/bevy_utils/src/default.rs#L27) provide wrapper functions to shorten this call, and a previous, now-rejected, [RFC](https://github.com/rust-lang/rust/pull/73001) aimed to provide this function as part of the standard library. This RFC was rejected with a note that there is a desire for a more general capability to import any trait associated functions.
1515

16-
Additionally, if you pull in a crate like [num_traits](https://docs.rs/num-traits/latest/num_traits/), then this feature will allow access to numeric methods such as `sin` using the `sin(x)` syntax that is more common in mathematics. More generally, it will make calls to trait methods shorter without having to write a wrapper function.
16+
Additionally, if you pull in a crate like [num_traits](https://docs.rs/num-traits/latest/num_traits/), then this feature will allow access to numeric functions such as `sin` using the `sin(x)` syntax that is more common in mathematics. More generally, it will make calls to trait associated functions shorter without having to write a wrapper function.
1717

1818
# Guide-level explanation
1919
[guide-level-explanation]: #guide-level-explanation
2020

21-
Importing a method from a trait is the same as importing a method from any module:
21+
Importing an associated functions from a trait is the same as importing a function from any module:
2222
```rust
2323
use Default::default;
2424
```
2525

26-
Once you have done this, the method is made available in your current scope just like any other regular function.
26+
Once you have done this, the function is made available in your current scope just like any other regular function.
2727

2828
```rust
2929
struct S {
@@ -39,7 +39,7 @@ impl S {
3939
}
4040
```
4141

42-
You can also use this with trait methods that take a `self` argument:
42+
You can also use this with trait methods (i.e. associated functions that take a `self` argument):
4343

4444
```rust
4545
use num_traits::float::Float::{sin, cos}
@@ -49,7 +49,7 @@ fn eulers_formula(theta: f64) -> (f64, f64) {
4949
}
5050
```
5151

52-
Importing a method from a trait does not import the trait. If you want to call `self` methods on a trait or `impl` it, then you can import the trait as well as methods in the trait:
52+
Importing an associated function from a trait does not import the trait. If you want to call `self` methods on a trait or `impl` it, then you can import the trait and its associated functions in a single import statement:
5353

5454
```rust
5555
mod a {
@@ -80,7 +80,7 @@ mod b {
8080
}
8181
```
8282

83-
Trait methods can also be renamed when they are imported using the usual `as` syntax:
83+
Associated functions can also be renamed when they are imported using the usual `as` syntax:
8484
```rust
8585
use Default::default as gimme
8686

@@ -97,7 +97,7 @@ impl S {
9797
}
9898
```
9999

100-
You cannot import a parent trait method from a sub-trait:
100+
You cannot import a parent trait associated function from a sub-trait:
101101

102102
```rust
103103
use num_traits::float::Float::zero; // Error: try `use num_traits::identities::Zero::zero` instead.
@@ -114,9 +114,9 @@ fn main() {
114114
When
115115

116116
```rust
117-
use Trait::method as m;
117+
use Trait::func as m;
118118
```
119-
occurs, a new item `m` is made available in the function namespace of the current module. Any attempts to call this item are treated calling the trait method explicitly qualified. As always, the `as` qualifier is optional, in which case the name of the new item is identical with the name of the method in the trait. In other words, the example:
119+
occurs, a new item `m` is made available in the function namespace of the current module. Any attempts to call this item are treated calling the associated function explicitly qualified. As always, the `as` qualifier is optional, in which case the name of the new item is identical with the name of the associated function in the trait. In other words, the example:
120120

121121
```rust
122122
use Default::default;
@@ -149,12 +149,12 @@ impl S {
149149
```
150150
And a call
151151
```rust
152-
use Trait::method as m;
152+
use Trait::func as m;
153153
m(x, y, z);
154154
```
155155
desugars to
156156
```rust
157-
Trait::method(x, y, z);
157+
Trait::func(x, y, z);
158158
```
159159

160160
Additionally, the syntax
@@ -166,14 +166,14 @@ is sugar for
166166
use some_module::Trait;
167167
```
168168

169-
The restriction on importing parent trait methods is a consequence of this desugaring, see https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=51bef9ba69ce1fc20248e987bf106bd4 for examples of the errors you get when you try to call parent trait methods through a child trait. We will likely want better error messages than this if a user tries to import a parent method.
169+
The restriction on importing parent trait associated functions is a consequence of this desugaring, see https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=51bef9ba69ce1fc20248e987bf106bd4 for examples of the errors you get when you try to call parent trait associated functions through a child trait. We will likely want better error messages than this if a user tries to import a parent function.
170170

171171
# Drawbacks
172172
[drawbacks]: #drawbacks
173173

174174
Calls to `default` are less explicit than calls to `Default::default` or to `T::default`, likewise for any other trait. Some users may see this lack of explicitness as bad style.
175175

176-
To expand on this, [the book](https://doc.rust-lang.org/book/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#creating-idiomatic-use-paths) currently recommends that methods should be called using their parent module's name:
176+
To expand on this, [the book](https://doc.rust-lang.org/book/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#creating-idiomatic-use-paths) currently recommends that functions should be called using their parent module's name:
177177
> Although both Listing 7-11 and 7-13 accomplish the same task, Listing 7-11 is the idiomatic way to bring a function into scope with use. Bringing the function’s parent module into scope with use means we have to specify the parent module when calling the function. Specifying the parent module when calling the function makes it clear that the function isn’t locally defined while still minimizing repetition of the full path.
178178
179179
This recommendation makes the most sense when there is a possibility of ambiguity in the mind of the reader. For example, a function like `sin` is unlikely to be ambiguous, because there is only one mathematical function of that name. If a codebase is likely to be making use of multiple different implementations of `sin`, then it makes more sense to require specifically naming the one you are going to use. Similar considerations apply to traits like `Default::default`, or more generally in cases like `Frobnicator::frobnicate`.
@@ -189,32 +189,32 @@ This design is minimalist, it adds no extra syntax, instead providing a natural
189189

190190
## What other designs have been considered and what is the rationale for not choosing them?
191191

192-
In [Zulip](https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Writing.20an.20RFC.20for.20.60use.20Default.3A.3Adefault.60/near/427795694), there was some discussion of whether `use Trait::method` should bring `Trait` into scope. There are three possibilities:
192+
In [Zulip](https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Writing.20an.20RFC.20for.20.60use.20Default.3A.3Adefault.60/near/427795694), there was some discussion of whether `use Trait::func` should bring `Trait` into scope. There are three possibilities:
193193

194194
1. It does not - this may be unexpected, but maybe not
195-
2. It does - then `value.other_method_from_the_same_trait()` will work as well, this may be unexpected too
196-
3. It does, but only for method, that's something new for the language (need new more fine-grained tracking of traits in scope)
195+
2. It does - then `value.other_func_from_the_same_trait()` will work as well, this may be unexpected too
196+
3. It does, but only for `func`, that's something new for the language (need new more fine-grained tracking of traits in scope)
197197

198-
Option 1 is what is proposed here. It has the simplest semantics, and I believe it best matches the user intent when they import a trait method; the desire is to make that method available as-if it were a regular function. Furthermore, it is more minimalist than the other two options in the sense that you can get to option 2 simply by importing the trait also. Option 3 seems like extra complexity for almost no added value.
198+
Option 1 is what is proposed here. It has the simplest semantics, and I believe it best matches the user intent when they import an associated function; the desire is to make that function available as-if it were a regular function. Furthermore, it is more minimalist than the other two options in the sense that you can get to option 2 simply by importing the trait also. Option 3 seems like extra complexity for almost no added value.
199199

200200
## What is the impact of not doing this?
201201

202-
Users of the language continue to create helper methods to access trait methods with regular function syntax. More specifically, each such instance requires a minimum of three lines when using normal rust formatting, corresponding to the following example:
202+
Users of the language continue to create helper functions to access associated with regular function syntax. More specifically, each such instance requires a minimum of three lines when using normal rust formatting, corresponding to the following example:
203203
```rust
204-
fn my_trait_method<T: MyTrait>(args) -> ret {
205-
MyTrait::my_trait_method(args)
204+
fn my_trait_func<T: MyTrait>(args) -> ret {
205+
MyTrait::my_trait_func(args)
206206
}
207207
```
208208
Such code is boilerplate that serves nobody's time to have to write repeatedly.
209209

210210
## If this is a language proposal, could this be done in a library or macro instead? Does the proposed change make Rust code easier or harder to read, understand, and maintain?
211211

212-
A library solution has already been rejected for this. This solves the same problem as a library solution in a much more general way, that doesn't require adding new library methods every time we want shorthand access to trait method names.
212+
A library solution has already been rejected for this. This solves the same problem as a library solution in a much more general way, that doesn't require adding new library functions every time we want shorthand access to trait function names.
213213

214214
# Prior art
215215
[prior-art]: #prior-art
216216

217-
As mentioned in [motivation], there was a rejected [RFC](https://github.com/rust-lang/rust/pull/73001) for adding a method `std::default::default` to make calling `Default::default` less repetitive. This RFC was rejected, with a desire to see something like what this RFC proposes replace it.
217+
As mentioned in [motivation], there was a rejected [RFC](https://github.com/rust-lang/rust/pull/73001) for adding a function `std::default::default` to make calling `Default::default` less repetitive. This RFC was rejected, with a desire to see something like what this RFC proposes replace it.
218218

219219
[This issue](https://github.com/rust-lang/rfcs/issues/1995) also lists some further motivation for this feature.
220220

0 commit comments

Comments
 (0)