Allow importing assoicated methods

Is there a reason not to allow importing associated methods from types and traits? Enums support importing constructors, which is similar. It would be nice to be able to do stuff like:

use Default::default; 
use std::MaybeUninit::uninit;
1 Like

For enums, the constructor gives an alternative place to put generic arguments. E. g. you can write None::<T> or Option::None::<T> instead of Option::<T>::None. I suppose for a full “importing trait/type methods” feature, one might need a way to still be able to specify the generic arguments of the type, or the generic arguments and/or Self type of the trait, I suppose? Or maybe not...? If yes, it's less straightforward than with enum constructors, because methods can also already have some generic arguments for themselves. If I can import String::new, can I also import String::default, too, or only the more generic Default::default? Maybe I can even import Foo::<Bar>::baz for a specific instantiation (with Bar) of the generic argument(s)? All of this opens a lot of design space that someone would have to address, discuss, and propose best solutions for, before such a feature could be introduced and stabilized.

1 Like

Being conservative, I'd say you cannot import trait methods from structs, since they don't live in that namespace, only associated methods. Maybe that could be supported in the future, but I don't consider it very important as long as traits are supported. And I'd let Self be inferred, if it cannot be inferred, then it just cannot be used (like we do with impl Trait) and universal function call syntax is required, like in other places in the language.

1 Like

FWIW, use Default::default is something that's been discussed a lot as something we'd like to support. See various discussion in #73001 (impl) and #73041 (tracking issue) for fn std::default::default. @petrochenkov says it should be a fairly minor compiler change.

Probably part of the reason progress has been sparse is that for the specific motivating case of ..default() in FRU, the most invested have been exploring/pursuing more first-class field defaults as an alternative.

3 Likes

No reason whatsoever, except that it touches name resolution and hasn't been done yet, and there are relatively few people capable of doing it. (@petrochenkov being one of them, and thanks @CAD97 for the link.)

We should absolutely support this.

7 Likes

I think, for a simple first pass, we could just not support disambiguating this with turbofish or similar. (For a constructor, you'll still often be able to disambiguate on the let or similar.)

3 Likes

At the very least, thankfully we do have

error[E0428]: the name `Name` is defined multiple times
 --> src/lib.rs:2:1
  |
1 | trait Name {}
  | ---------- previous definition of the trait `Name` here
2 | mod Name {}
  | ^^^^^^^^ `Name` redefined here
  |
  = note: `Name` must be defined only once in the type namespace of this module

so there's no namespace ambiguity shenanigans that need to be delt with; we're still only dealing with the single type/mod namespace for nonterminal names in the use tree.

1 Like

Another thing that came to mind, though more of a fact than a hard problem to solve: Since enums already allow use TypeName::* to mean “import all variants of TypeName”, and changing this behavior to “import all variants and associated items” would be too much of a breaking change, a feature for importing associated items should disallow *, except for enums, where the existing behavior is preserved that * refers to enum variants only. Diagnostics can educate/help users when they try to use * on an enum and then expect to be able to call associated functions.

5 Likes

It is worth noting that if there is a way to declare the generics, it could be applied to x.into::<T>() as well. That exact syntax can't work, but something surely can.

1 Like

You can create a static (without generics, unfortunately. I wanted to suggest function-aliases, but nobody gave a damn((( )

For some reference there is a proposal of this on RFC repo: Support use Trait::method and/or Type::method? · Issue #1995 · rust-lang/rfcs · GitHub which I was planning to implement soon :tm:.

1 Like