Add support for use Trait::func
by obsgolem · Pull Request #3591 · rust-lang/rfcs (original) (raw)
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
[ Show hidden characters]({{ revealButtonHref }})
This feature fully supplants rust-lang/rust#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.
Dirbaio, oriongonza, casey, Jules-Bertholet, GrayJack, svix-jplatte, crumblingstatue, HadrienG2, alex13sh, aznhe21, and 28 more reacted with thumbs up emoji
Relevant to the language team, which will review and decide on the RFC.
label
From The Rust Programming Language section 7.4:
Creating Idiomatic
use
PathsAlthough 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. :)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The RFC text uses the term “method” where it should be using the term “associated function”.
- An associated function is a function defined in an
impl
or declared in atrait
. (reference) - A method is an associated function that has a
self
parameter (and therefore may be used in.func_name()
method-call syntax). (reference)
I recommend that this be corrected to avoid creating confusion. In particular, the central use case of this feature is importing associated functions that are less concise to call because they are not methods, such as Default::default
.
obsgolem changed the title
Add support for Add support for use Trait::method
use Trait::func
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
Just wanted to ping this, is there anything I can do to keep this moving?
Nominated for lang discussion.
@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.)
@rfcbot resolved associated-constants
@obsgolem Would you add some text elaborating on how trait generics work, so we can get the last concern resolved?
The reference seems to still only talk about using inference for the generics on such an imported thing, like
Note that trait generics are handled by this desugaring using type inference.
and
which compiles if and only if T and Self can be inferred from the function call
Is the idea here that something imported like this can only be used inferred, and we block turbofishing it for now?
For use Default::default;
, is no turbofishing allowed because there are no generic parameters on either Default
nor default
? Or is there something that adds a turbofishable generic parameter for the Self
type so I can default::<X>()
?
For use FromIterator::from_iter;
, if I do from_iter::<X>(it)
, is that turbofishing the generic from FromIterator
, the generic from from_iter
, or is it an error?
Ok, with the update to say
Generics on
Trait
are not directly specifiable when a function is called in this way. To call a function with explicit types specified you must use the usual fully qualified syntax.
@rfcbot resolve what-about-turbofish
I do think that people will want to turbofish this in the future, but I'm happy to say that for now they just can't, like we did with APIT, and we can reconsider things later as needed.
rfcbot added the final-comment-period
Will be merged/postponed/closed in ~10 calendar days unless new substational objections are raised.
label
🔔 This is now entering its final comment period, as per the review above. 🔔
The final comment period, with a disposition to merge, as per the review above, is now complete.
As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.
This will be merged soon.
I've updated the links in the RFC and created a tracking issue, so I'm going to merge this. Thank you @obsgolem!