You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: text/0000-return-position-impl-trait-in-traits.md
+27-4Lines changed: 27 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -412,15 +412,34 @@ Yes, so long as the compiler has enough type information to figure out which imp
412
412
413
413
### Can traits migrate from a named associated type to `impl Trait`?
414
414
415
-
Not compatibly, no, because they would no longer have a named associated type.
415
+
Not compatibly, no, because they would no longer have a named associated type. The "future directions" section discusses the possibility of allowing users to explicitly give a name for the associated type created, which would enable this use case.
416
416
417
417
### Can traits migrate from `impl Trait` to a named associated type?
418
418
419
-
Generally yes, but all impls would have to be rewritten.
419
+
Generally yes, but all impls would have to be rewritten to include the definition of the associated type. In many cases, some form of type-alias impl trait (or impl trait in associated type values) would also be required. For example, if we changed the `IntoIntIterator` trait from the motivation to use an explicit associated type..
420
+
421
+
```rust
422
+
traitIntoIntIterator {
423
+
typeIntIter:Iterator<Item=u32>;
424
+
fninto_iter(self) ->Self::IntIter;
425
+
}
426
+
```
427
+
428
+
...then impls like...
429
+
430
+
```rust
431
+
implIntoIntIteratorforMyType {
432
+
fninto_int_iter(self) ->implIterator<Item=u32> {
433
+
(0..self.len()).map(|x|x*2)
434
+
}
435
+
}
436
+
```
437
+
438
+
...would no longer compile, because they are not specifying the value of the `IntIter` associated type. Moreover, the value for this type would be impossible to express without `impl Trait` notation, as it embeds a closure type.
420
439
421
440
### Would there be any way to make it possible to migrate from `impl Trait` to a named associated type compatibly?
422
441
423
-
Potentially! There have been proposals to allow the values of associated types that appear in function return types to be inferred from the function declaration. Sothe trait has `fn method(&self) -> Self::Iter` and the impl has `fn method(&self) -> impl Iterator`, then the impl would also be inferred to have `type Iter = impl Iterator` (and the return type rewritten to reference it). This may be a good idea, but it is not proposed as part of this RFC.
442
+
Potentially! There have been proposals to allow the values of associated types that appear in function return types to be inferred from the function declaration. So, using the example from the previous question, the impl for `IntoIntIterator` could infer the value of `IntIter` based on the return type of `into_int_iter`. This may be a good idea, but it is not proposed as part of this RFC.
424
443
425
444
### What about using a named associated type?
426
445
@@ -468,6 +487,10 @@ Therefore, if we were writing `IntoIterator` today, it would probably use `-> im
468
487
The same is not true for `Iterator::Item`: because `Item` is so central to what an `Iterator` is, and because it rarely makes sense to use an opaque typefor the item, it would remain an explicit associated type.
469
488
470
489
# Prior art
490
+
491
+
## Should library traits migrate to use `implTrait`?
492
+
493
+
Potentially, but not necessarily. Using `impl Trait` in traits imposes some limitations on generic code referencing those traits. While `impl Trait `desugars internally to an associated type, that associated type is anonymous and cannot be directly referenced by users, which prevents them from putting bounds on it or naming it for use in struct declarations. This is similar to `-> impl Trait` in free and inherent functions, which also returns an anonymous type that cannot be directly named. Just as in those cases, this likely means that widely used libraries should avoid the use of `-> impl Trait` and prefer to use an explicit named associated type, at least until some of the "future possibilities" are completed. However, this decision is best reached on a case-by-case basis: the real question is whether the bounds named in the trait will be sufficient, or whether users will wish to put additional bounds. In a trait like `IntoIterator`, for example, it is common to wish to bound the resulting iterator with additional traits, like `ExactLenIterator`. But given a trait that returns `-> impl Debug`, this concern may not apply.
471
494
[prior-art]: #prior-art
472
495
473
496
There are a number of crates that do desugaring like this manually or with procedural macros.One notable example is [real-async-trait](https://crates.io/crates/real-async-trait).
@@ -482,7 +505,7 @@ There are a number of crates that do desugaring like this manually or with proce
482
505
483
506
### Namingreturn types
484
507
485
-
We expect to introduce a mechanismfornaming the result of `->implTrait` return typesina follow-up RFC.
508
+
ThisRFC does not include a wayforgeneric code to name or bound the result of `->implTrait` return types.This means, for example, that for the `IntoIntIterator` trait introduced inthe motivation, it is not possible to write a function that takes a `T:IntoIntIterator` which returns an `ExactLenIterator`; forasyncfunctions, themostcommontimethiscomesupiscodethatwishestotakeanasyncfunctionthatreturnsa `Send` future.WeexpectfutureRFCswilladdresstheseuse cases.
0 commit comments