rfcs
rfcs copied to clipboard
Add support for `use Trait::func`
This feature fully supplants https://github.com/rust-lang/rust/pull/73001, allowing you to do things like:
use Default::default;
struct S {
a: HashMap<i32, i32>,
}
impl S {
fn new() -> S {
S {
a: default()
}
}
}
and more.
This is my first RFC, please forgive any missteps I make in the process.
Partially completes #1995.
From The Rust Programming Language section 7.4:
Creating Idiomatic
usePathsAlthough 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.
We have been encouraged for a long time to always import the parent module when calling the function to distinguish locally defined functions and imported functions. However, the syntax sugar suggested in this RFC contradicts to this convention.
I think it is more appropriate to discuss this convention in the RFC to make it more clear how we should use this feature. :)
I'd like to reiterate here what I said on #1995
Many libraries define free functions for constructors to mathy types, like vectors.
Some examples: https://docs.rs/glam/0.24.2/src/glam/f32/vec2.rs.html#12 https://docs.rs/egui/latest/egui/fn.pos2.html
It would be nice if instead of having to create wrapper functions, the user (or the lib author with pub use) could just do use Vec2::new as vec2;
This is some additional motivation that could go into the motivation section. Default::default is hardly the only use case for this.
That being said, I noticed that this RFC doesn't talk about importing inherent methods, which I think should be addressed. If this RFC only proposes importing trait methods, but not inherent methods, then the use cases I mentioned above are nullified. Why should we only support importing trait methods, but not inherent methods?
I discussed that in the future work section. use Type::method is out of scope for this RFC. The difficulty is impl blocks with arbitrary where clauses.
I'm going to go ahead and start the process of seeing if we have consensus on this:
@rfcbot merge
Please do either add support for associated constants inline in the RFC (if it's straightforward to do so) or mention them in future work (if not):
@rfcbot concern associated-constants
Team member @joshtriplett has proposed to merge this. The next step is review by the rest of the tagged team members:
- [x] @joshtriplett
- [ ] @nikomatsakis
- [ ] @pnkfelix
- [x] @scottmcm
- [x] @tmandry
Concerns:
- associated-constants (https://github.com/rust-lang/rfcs/pull/3591#issuecomment-2107067854)
- what-about-turbofish (https://github.com/rust-lang/rfcs/pull/3591#issuecomment-2134070093)
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns. See this document for info about what commands tagged team members can give me.
Apologies for the delay, wasn't able to work up motivation to work on this again until today. Thanks for the review!
👍 to the motivation here.
@rfcbot concern what-about-turbofish
One thing I think needs to be addressed in the reference section is what's supposed to happen with generic parameters.
If one has
trait Trait<A> {
fn method<B>(…);
}
and does a
use othermod::Trait::method;
What happens? Can you turbofish it? Which generics are there there?
The precedent from enum variants doesn't cover generics on the associated items, so something needs to specified for it.
This can be inferred directly from the desugaring described in the RFC. If the trait has generics, they must be inferrable in order for Trait::method() to work, hence the same is true for the imported version. I can spell that out explicitly if you want.
Just wanted to ping this, is there anything I can do to keep this moving?
Nominated for lang discussion.
This is currently implemented on nightly as part of fn_delegation (https://github.com/rust-lang/rust/issues/118212): https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=fe2a0b28cf36b474400ae3faa10c5408
#![expect(incomplete_features)]
#![feature(fn_delegation)]
reuse Default::default;
fn type_name_of_val<T>(_: &T) -> &'static str {
std::any::type_name::<T>()
}
fn main() {
let x: u32 = default();
let y = default::<u64>();
let name = type_name_of_val(&default::<()>);
dbg!(x, y, name);
}
@rfcbot reviewed
This RFC does not propose the ability to import Type::method where method is contained in an impl block. Such a feature would be a natural extension of this work, and would enable numeric features like that discussed in motivation without the need for the num_traits crate. This feature is not proposed in this RFC since initial investigations revealed that it would be difficult to implement in today's rustc.
I would very much like to see this, though I am okay waiting for a future RFC once the implementation challenges are worked out.
If we add a compatibility mechanism to implement a supertrait method when implementing its subtrait, without having to separately implement the supertrait (such that a new supertrait can be extracted from a trait without breaking compatibility), we would also need to lift the limitation on using a supertrait method via a subtrait.
I would also very much like to see this, but yes it belongs in another RFC. While I would prefer to lift the subtrait/supertrait restriction part of this RFC, it sounds annoying to do so it can wait for the next RFC.
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.
Those errors are bizarre and I agree we should make them better (and as I said, eventually remove them altogether).
This can be inferred directly from the desugaring described in the RFC. If the trait has generics, they must be inferrable in order for
Trait::method()to work, hence the same is true for the imported version. I can spell that out explicitly if you want.
Trying to get outstanding concerns resolved: I think the request by @scottmcm was that it be spelled out in the reference section. I don't see a drawback to including implications like this as subsections, even if they are implied by the earlier text. (The paragraph you have on the restriction on important parent trait functions is an example of this.)