Skip to content

Commit f55ac69

Browse files
authoredAug 12, 2016
Auto merge of #35091 - eddyb:impl-trait, r=nikomatsakis
Implement `impl Trait` in return type position by anonymization. This is the first step towards implementing `impl Trait` (cc #34511). `impl Trait` types are only allowed in function and inherent method return types, and capture all named lifetime and type parameters, being invariant over them. No lifetimes that are not explicitly named lifetime parameters are allowed to escape from the function body. The exposed traits are only those listed explicitly, i.e. `Foo` and `Clone` in `impl Foo + Clone`, with the exception of "auto traits" (like `Send` or `Sync`) which "leak" the actual contents. The implementation strategy is anonymization, i.e.: ```rust fn foo<T>(xs: Vec<T>) -> impl Iterator<Item=impl FnOnce() -> T> { xs.into_iter().map(|x| || x) } // is represented as: type A</*invariant over*/ T> where A<T>: Iterator<Item=B<T>>; type B</*invariant over*/ T> where B<T>: FnOnce() -> T; fn foo<T>(xs: Vec<T>) -> A<T> { xs.into_iter().map(|x| || x): $0 where $0: Iterator<Item=$1>, $1: FnOnce() -> T } ``` `$0` and `$1` are resolved (to `iter::Map<vec::Iter<T>, closure>` and the closure, respectively) and assigned to `A` and `B`, after checking the body of `foo`. `A` and `B` are *never* resolved for user-facing type equality (typeck), but always for the low-level representation and specialization (trans). The "auto traits" exception is implemented by collecting bounds like `impl Trait: Send` that have failed for the obscure `impl Trait` type (i.e. `A` or `B` above), pretending they succeeded within the function and trying them again after type-checking the whole crate, by replacing `impl Trait` with the real type. While passing around values which have explicit lifetime parameters (of the function with `-> impl Trait`) in their type *should* work, regionck appears to assign inference variables in *way* too many cases, and never properly resolving them to either explicit lifetime parameters, or `'static`. We might not be able to handle lifetime parameters in `impl Trait` without changes to lifetime inference, but type parameters can have arbitrary lifetimes in them from the caller, so most type-generic usecases (or not generic at all) should not run into this problem. cc @rust-lang/lang
2 parents 68d9284 + 23f0494 commit f55ac69

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+2788
-532
lines changed
 

‎src/librustc/hir/fold.rs

+3
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,9 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
375375
TyPolyTraitRef(bounds) => {
376376
TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
377377
}
378+
TyImplTrait(bounds) => {
379+
TyImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
380+
}
378381
},
379382
span: fld.new_span(span),
380383
}

‎src/librustc/hir/intravisit.rs

+3
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
427427
TyPolyTraitRef(ref bounds) => {
428428
walk_list!(visitor, visit_ty_param_bound, bounds);
429429
}
430+
TyImplTrait(ref bounds) => {
431+
walk_list!(visitor, visit_ty_param_bound, bounds);
432+
}
430433
TyTypeof(ref expression) => {
431434
visitor.visit_expr(expression)
432435
}

0 commit comments

Comments
 (0)
Please sign in to comment.