-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow explicitly expressing the type of a -> impl Trait #1738
Comments
cc @eddyb |
My prototype from last year supported impl Iterator for Foo {
type Item = impl Iterator<Item=String>;
fn next(&mut self) -> Option<Self::Item> {...}
} This feature is the minimal extension of #1522 to allow naming IMO it's a better first step because it's smaller in scope: I side-stepped the problem of choosing which functions to give the ability to determine the cc @rust-lang/lang |
I still would like to name the type in the function signature, so it'd be |
I think this would be better served by |
@durka We already have syntax for it: |
@Ericson2314 I don't see how the proposal goes against my model, the difference with |
@eddyb going back to #105 (comment) I've wanted to separate the inference and abstraction aspects of Because impls are similar to (parametertized) modules, it makes sense to put |
What are gotchas around Seems like a more general solution (since you can express original using it) and it applies to more cases eg. where a 3rd party library didn't think it was worth exposing the return type as a type alias. I find it very appealing. |
@cristicbz It's not a silver bullet because it gives you the whole type, being able to name an EDIT: As for gotchas, The only new thing as far as the implementation is concerned is being able to type-check and infer that expression passed to |
There are two possibilities for |
@tomaka Well, it'd have to be a path not an identifier. But yeah, and it could've been implemented in 1.0. |
More generally, you would probably write |
@eddyb I was thinking of |
@tomaka So you'd want arguments of the function to be in scope for |
I like I've almost written :
It'd be far cleaner to write simply Worse, I've needed to write
And similar situations can arise around any method like It'd be much cleaner to write |
Just another idea : I wonder if it's worth adding a name or macro for the current I've previously wanted a version of
I could situations where you wanted to write |
A tricky problem is this: pub struct Foo {
data: ???
}
impl Foo {
pub fn new() -> Foo {
Foo {
data: (0 .. 3).map(|n| n * 2),
}
}
} In this example you can't easily use |
Yes, it'd be nice if |
@burdges but that would collide with method names, right? struct Foo {
data: u32,
}
impl Foo {
fn data() { ... }
}
|
@burdges TBH I wouldn't even expect outer declarations to be accessible, at least not in all cases. There is indeed a problem with accessing derived types that don't depend on inputs, and However, @tomaka's example wouldn't be fixable like that because you'd end up with the field type being equal to... itself. Which is a cyclic type dependency error. In the complementary |
My intuition is that a type alias for For example, I might want to shorten However, this behavior might also be better handled by allowing users to abstract over for example the return type of some function |
-> #2071 |
Seems like the "get the return type of an https://users.rust-lang.org/t/how-do-you-store-the-result-of-an-impl-trait-return-type/14808/8 |
This would be a killer feature. I have a project where i generate an AST via the builder pattern on the type level. Obviously, the type of an AST shouldn't be named by the user; this would be madness for everything more elaborate than a FooBar example ( Yet it is desirable to know the type of (and store) an AST. With When being able to access the return type of the function, we could actually name and store the AST and derivatives without having to write it out! |
Did you mean? |
Closing in favor of #2515. |
Right now, you can do this:
In this issue I suggest that we add this syntax as well:
This means that later we can use
FooRet
to designate the type thatfoo()
returns.This makes it possible to put it in a struct for example:
Unresolved questions
type Foo<R> = impl Trait; fn foo<R>() -> Foo<R>
), but I'm not totally sure that there's a not problem with that.Alternatives
decltype
.Motivation
While the feature itself is -I think- mostly straight-forward, the biggest debate is probably the motivation.
Let's take this code:
Right now you can wrap around it, if you want:
This is a zero-cost abstraction and a good usage of composition.
The problem begins when you want to use
-> impl Trait
:Suddenly, wrapping around it becomes hacky. The primary way to do so is this:
(The alternative way is to create a new trait named
TraitForWrapper
which contains the API ofWrapper
, and makeget_wrapper()
return-> impl TraitForWrapper
)This not only complicates the documentation and makes the usage of
get_wrapper()
more confusing for beginners, but it is also leaky, as it makes wrapping aroundWrapper
more complicated:(using the
TraitForWrapper
method is not better)This looks like an hypothetical example, but for example if I were to use
-> impl Trait
in my project, some equivalents toWrapperWrapper
would look nightmarish:Basically, the problem of the
-> impl Trait
syntax is that it's poisonous. Once you use it in an API, all the codes that use this API will have to use-> impl Trait
as well.This proposition would fix this problem:
The text was updated successfully, but these errors were encountered: