Skip to content

Commit f55ac69

Browse files
authored
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

File tree

99 files changed

+2788
-532
lines changed

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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 3 additions & 0 deletions
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
}

src/librustc/hir/lowering.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,10 @@ impl<'a> LoweringContext<'a> {
293293
hir::TyTypeof(self.lower_expr(expr))
294294
}
295295
PolyTraitRef(ref bounds) => {
296-
let bounds = bounds.iter().map(|b| self.lower_ty_param_bound(b)).collect();
297-
hir::TyPolyTraitRef(bounds)
296+
hir::TyPolyTraitRef(self.lower_bounds(bounds))
297+
}
298+
ImplTrait(ref bounds) => {
299+
hir::TyImplTrait(self.lower_bounds(bounds))
298300
}
299301
Mac(_) => panic!("TyMac should have been expanded by now."),
300302
},

src/librustc/hir/map/collector.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,14 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
194194
});
195195
}
196196

197+
fn visit_ty(&mut self, ty: &'ast Ty) {
198+
self.insert(ty.id, NodeTy(ty));
199+
200+
self.with_parent(ty.id, |this| {
201+
intravisit::walk_ty(this, ty);
202+
});
203+
}
204+
197205
fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
198206
b: &'ast Block, s: Span, id: NodeId) {
199207
assert_eq!(self.parent_node, id);

src/librustc/hir/map/def_collector.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ impl<'ast> visit::Visitor for DefCollector<'ast> {
268268
if let TyKind::FixedLengthVec(_, ref length) = ty.node {
269269
self.visit_ast_const_integer(length);
270270
}
271+
if let TyKind::ImplTrait(..) = ty.node {
272+
self.create_def(ty.id, DefPathData::ImplTrait);
273+
}
271274
visit::walk_ty(self, ty);
272275
}
273276

@@ -428,6 +431,9 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
428431
if let hir::TyFixedLengthVec(_, ref length) = ty.node {
429432
self.visit_hir_const_integer(length);
430433
}
434+
if let hir::TyImplTrait(..) = ty.node {
435+
self.create_def(ty.id, DefPathData::ImplTrait);
436+
}
431437
intravisit::walk_ty(self, ty);
432438
}
433439

src/librustc/hir/map/definitions.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ pub enum DefPathData {
215215
Initializer,
216216
/// Pattern binding
217217
Binding(InternedString),
218+
/// An `impl Trait` type node.
219+
ImplTrait
218220
}
219221

220222
impl Definitions {
@@ -369,6 +371,10 @@ impl DefPathData {
369371
Initializer => {
370372
InternedString::new("{{initializer}}")
371373
}
374+
375+
ImplTrait => {
376+
InternedString::new("{{impl-Trait}}")
377+
}
372378
}
373379
}
374380

src/librustc/hir/map/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub enum Node<'ast> {
5050
NodeVariant(&'ast Variant),
5151
NodeExpr(&'ast Expr),
5252
NodeStmt(&'ast Stmt),
53+
NodeTy(&'ast Ty),
5354
NodeLocal(&'ast Pat),
5455
NodePat(&'ast Pat),
5556
NodeBlock(&'ast Block),
@@ -76,6 +77,7 @@ pub enum MapEntry<'ast> {
7677
EntryVariant(NodeId, &'ast Variant),
7778
EntryExpr(NodeId, &'ast Expr),
7879
EntryStmt(NodeId, &'ast Stmt),
80+
EntryTy(NodeId, &'ast Ty),
7981
EntryLocal(NodeId, &'ast Pat),
8082
EntryPat(NodeId, &'ast Pat),
8183
EntryBlock(NodeId, &'ast Block),
@@ -104,6 +106,7 @@ impl<'ast> MapEntry<'ast> {
104106
NodeVariant(n) => EntryVariant(p, n),
105107
NodeExpr(n) => EntryExpr(p, n),
106108
NodeStmt(n) => EntryStmt(p, n),
109+
NodeTy(n) => EntryTy(p, n),
107110
NodeLocal(n) => EntryLocal(p, n),
108111
NodePat(n) => EntryPat(p, n),
109112
NodeBlock(n) => EntryBlock(p, n),
@@ -122,6 +125,7 @@ impl<'ast> MapEntry<'ast> {
122125
EntryVariant(id, _) => id,
123126
EntryExpr(id, _) => id,
124127
EntryStmt(id, _) => id,
128+
EntryTy(id, _) => id,
125129
EntryLocal(id, _) => id,
126130
EntryPat(id, _) => id,
127131
EntryBlock(id, _) => id,
@@ -144,6 +148,7 @@ impl<'ast> MapEntry<'ast> {
144148
EntryVariant(_, n) => NodeVariant(n),
145149
EntryExpr(_, n) => NodeExpr(n),
146150
EntryStmt(_, n) => NodeStmt(n),
151+
EntryTy(_, n) => NodeTy(n),
147152
EntryLocal(_, n) => NodeLocal(n),
148153
EntryPat(_, n) => NodePat(n),
149154
EntryBlock(_, n) => NodeBlock(n),
@@ -257,6 +262,7 @@ impl<'ast> Map<'ast> {
257262
EntryVariant(p, _) |
258263
EntryExpr(p, _) |
259264
EntryStmt(p, _) |
265+
EntryTy(p, _) |
260266
EntryLocal(p, _) |
261267
EntryPat(p, _) |
262268
EntryBlock(p, _) |
@@ -297,6 +303,7 @@ impl<'ast> Map<'ast> {
297303
EntryVariant(p, _) |
298304
EntryExpr(p, _) |
299305
EntryStmt(p, _) |
306+
EntryTy(p, _) |
300307
EntryLocal(p, _) |
301308
EntryPat(p, _) |
302309
EntryBlock(p, _) |
@@ -680,6 +687,7 @@ impl<'ast> Map<'ast> {
680687
Some(NodeVariant(variant)) => variant.span,
681688
Some(NodeExpr(expr)) => expr.span,
682689
Some(NodeStmt(stmt)) => stmt.span,
690+
Some(NodeTy(ty)) => ty.span,
683691
Some(NodeLocal(pat)) => pat.span,
684692
Some(NodePat(pat)) => pat.span,
685693
Some(NodeBlock(block)) => block.span,
@@ -971,6 +979,7 @@ impl<'a> NodePrinter for pprust::State<'a> {
971979
NodeVariant(a) => self.print_variant(&a),
972980
NodeExpr(a) => self.print_expr(&a),
973981
NodeStmt(a) => self.print_stmt(&a),
982+
NodeTy(a) => self.print_type(&a),
974983
NodePat(a) => self.print_pat(&a),
975984
NodeBlock(a) => self.print_block(&a),
976985
NodeLifetime(a) => self.print_lifetime(&a),
@@ -1059,6 +1068,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
10591068
Some(NodeStmt(ref stmt)) => {
10601069
format!("stmt {}{}", pprust::stmt_to_string(&stmt), id_str)
10611070
}
1071+
Some(NodeTy(ref ty)) => {
1072+
format!("type {}{}", pprust::ty_to_string(&ty), id_str)
1073+
}
10621074
Some(NodeLocal(ref pat)) => {
10631075
format!("local {}{}", pprust::pat_to_string(&pat), id_str)
10641076
}

src/librustc/hir/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,8 @@ pub enum Ty_ {
11321132
TyObjectSum(P<Ty>, TyParamBounds),
11331133
/// A type like `for<'a> Foo<&'a Bar>`
11341134
TyPolyTraitRef(TyParamBounds),
1135+
/// An `impl TraitA+TraitB` type.
1136+
TyImplTrait(TyParamBounds),
11351137
/// Unused for now
11361138
TyTypeof(P<Expr>),
11371139
/// TyInfer means the type should be inferred instead of it having been

src/librustc/hir/print.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,9 @@ impl<'a> State<'a> {
536536
hir::TyPolyTraitRef(ref bounds) => {
537537
self.print_bounds("", &bounds[..])?;
538538
}
539+
hir::TyImplTrait(ref bounds) => {
540+
self.print_bounds("impl ", &bounds[..])?;
541+
}
539542
hir::TyFixedLengthVec(ref ty, ref v) => {
540543
word(&mut self.s, "[")?;
541544
self.print_type(&ty)?;

src/librustc/infer/freshen.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
170170
ty::TyClosure(..) |
171171
ty::TyTuple(..) |
172172
ty::TyProjection(..) |
173-
ty::TyParam(..) => {
173+
ty::TyParam(..) |
174+
ty::TyAnon(..) => {
174175
t.super_fold_with(self)
175176
}
176177
}

0 commit comments

Comments
 (0)