From 5c23a2e5a6054b1ec14cd8294e7a12749338d4d9 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 15 Jul 2022 12:58:22 -0300 Subject: [PATCH 01/56] Remove old docs on lower_async_fn_ret_ty --- compiler/rustc_ast_lowering/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a1bf0f94964bb..ff479fa213975 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1582,11 +1582,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // type OpaqueTy = impl Future; // - // `inputs`: lowered types of parameters to the function (used to collect lifetimes) // `output`: unlowered output type (`T` in `-> T`) // `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition) // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created - // `elided_lt_replacement`: replacement for elided lifetimes in the return type #[tracing::instrument(level = "debug", skip(self))] fn lower_async_fn_ret_ty( &mut self, From b14c9571fa93c863f822a37942cdcd339f46d108 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 19 Jul 2022 18:10:27 -0300 Subject: [PATCH 02/56] Make lower_generic_bound_predicate receive AST bounds instead of HIR bounds --- compiler/rustc_ast_lowering/src/item.rs | 10 +++++++--- compiler/rustc_ast_lowering/src/lib.rs | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 99f81afc1e25d..4cf0a8e0d2ed1 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1350,12 +1350,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new(); predicates.extend(generics.params.iter().filter_map(|param| { - let bounds = self.lower_param_bounds(¶m.bounds, itctx); self.lower_generic_bound_predicate( param.ident, param.id, ¶m.kind, - bounds, + ¶m.bounds, + itctx, PredicateOrigin::GenericParam, ) })); @@ -1403,13 +1403,17 @@ impl<'hir> LoweringContext<'_, 'hir> { ident: Ident, id: NodeId, kind: &GenericParamKind, - bounds: &'hir [hir::GenericBound<'hir>], + bounds: &[GenericBound], + itctx: ImplTraitContext, origin: PredicateOrigin, ) -> Option> { // Do not create a clause if we do not have anything inside it. if bounds.is_empty() { return None; } + + let bounds = self.lower_param_bounds(bounds, itctx); + let ident = self.lower_ident(ident); let param_span = ident.span; let span = bounds diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ff479fa213975..8fb29dcb67569 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2013,7 +2013,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Add a definition for the in-band `Param`. let def_id = self.local_def_id(node_id); - let hir_bounds = self.lower_param_bounds(bounds, ImplTraitContext::Universal); // Set the name to `impl Bound1 + Bound2`. let param = hir::GenericParam { hir_id: self.lower_node_id(node_id), @@ -2028,7 +2027,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ident, node_id, &GenericParamKind::Type { default: None }, - hir_bounds, + bounds, + ImplTraitContext::Universal, hir::PredicateOrigin::ImplTrait, ); From 0f11a0cd2482f6c8cf2e4eb00242214172835c36 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 20 Jul 2022 12:58:48 -0300 Subject: [PATCH 03/56] Add captures flag to capture or not while lowering --- compiler/rustc_ast_lowering/src/asm.rs | 1 + compiler/rustc_ast_lowering/src/block.rs | 7 +- compiler/rustc_ast_lowering/src/expr.rs | 28 +++- compiler/rustc_ast_lowering/src/item.rs | 69 ++++++--- compiler/rustc_ast_lowering/src/lib.rs | 180 ++++++++++++++--------- compiler/rustc_ast_lowering/src/pat.rs | 3 + compiler/rustc_ast_lowering/src/path.rs | 34 +++-- 7 files changed, 211 insertions(+), 111 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 4166b4fc2e5bc..7d74007d1cb26 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -234,6 +234,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &sym.path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), + true, ); hir::InlineAsmOperand::SymStatic { path, def_id } } else { diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 7cbfe143b4d83..d51393d88c032 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -84,10 +84,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_local(&mut self, l: &Local) -> &'hir hir::Local<'hir> { - let ty = l - .ty - .as_ref() - .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); + let ty = l.ty.as_ref().map(|t| { + self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable), true) + }); let init = l.kind.init().map(|init| self.lower_expr(init)); let hir_id = self.lower_node_id(l.id); let pat = self.lower_pat(&l.pat); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 983efa48a4579..b41140072418d 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -69,6 +69,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ParamMode::Optional, ParenthesizedGenericArgs::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), + true, )); let args = self.lower_exprs(args); hir::ExprKind::MethodCall(hir_seg, args, self.lower_span(span)) @@ -89,14 +90,20 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Cast(ref expr, ref ty) => { let expr = self.lower_expr(expr); - let ty = - self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty( + ty, + ImplTraitContext::Disallowed(ImplTraitPosition::Type), + true, + ); hir::ExprKind::Cast(expr, ty) } ExprKind::Type(ref expr, ref ty) => { let expr = self.lower_expr(expr); - let ty = - self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty( + ty, + ImplTraitContext::Disallowed(ImplTraitPosition::Type), + true, + ); hir::ExprKind::Type(expr, ty) } ExprKind::AddrOf(k, m, ref ohs) => { @@ -226,6 +233,7 @@ impl<'hir> LoweringContext<'_, 'hir> { path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), + true, ); hir::ExprKind::Path(qpath) } @@ -264,6 +272,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), + true, )), self.arena .alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))), @@ -561,9 +570,11 @@ impl<'hir> LoweringContext<'_, 'hir> { body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> hir::ExprKind<'hir> { let output = match ret_ty { - Some(ty) => hir::FnRetTy::Return( - self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)), - ), + Some(ty) => hir::FnRetTy::Return(self.lower_ty( + &ty, + ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock), + true, + )), None => hir::FnRetTy::DefaultReturn(self.lower_span(span)), }; @@ -1167,6 +1178,7 @@ impl<'hir> LoweringContext<'_, 'hir> { path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), + true, ); // Destructure like a tuple struct. let tuple_struct_pat = @@ -1183,6 +1195,7 @@ impl<'hir> LoweringContext<'_, 'hir> { path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), + true, ); // Destructure like a unit struct. let unit_struct_pat = hir::PatKind::Path(qpath); @@ -1207,6 +1220,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), + true, ); let fields_omitted = match &se.rest { StructRest::Base(e) => { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 4cf0a8e0d2ed1..134876c2086f7 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -308,7 +308,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - |this| this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy), + |this| this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy, true), ); hir::ItemKind::TyAlias(ty, generics) } @@ -386,11 +386,15 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_trait_ref( trait_ref, ImplTraitContext::Disallowed(ImplTraitPosition::Trait), + true, ) }); - let lowered_ty = this - .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let lowered_ty = this.lower_ty( + ty, + ImplTraitContext::Disallowed(ImplTraitPosition::Type), + true, + ); (trait_ref, lowered_ty) }); @@ -434,6 +438,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let bounds = this.lower_param_bounds( bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + true, ); let items = this.arena.alloc_from_iter( items.iter().map(|item| this.lower_trait_item_ref(item)), @@ -453,6 +458,7 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_param_bounds( bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + true, ) }, ); @@ -475,7 +481,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, body: Option<&Expr>, ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type), true); (ty, self.lower_const_body(span, body)) } @@ -661,8 +667,11 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) } ForeignItemKind::Static(ref t, m, _) => { - let ty = - self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty( + t, + ImplTraitContext::Disallowed(ImplTraitPosition::Type), + true, + ); hir::ForeignItemKind::Static(ty, m) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, @@ -731,10 +740,11 @@ impl<'hir> LoweringContext<'_, 'hir> { path, ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124) ImplTraitContext::Disallowed(ImplTraitPosition::Path), + true, ); self.arena.alloc(t) } else { - self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type), true) }; let hir_id = self.lower_node_id(f.id); self.lower_attrs(hir_id, &f.attrs); @@ -757,7 +767,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind, has_default) = match i.kind { AssocItemKind::Const(_, ref ty, ref default) => { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type), true); let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) } @@ -795,12 +806,17 @@ impl<'hir> LoweringContext<'_, 'hir> { ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let ty = ty.as_ref().map(|x| { - this.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + this.lower_ty( + x, + ImplTraitContext::Disallowed(ImplTraitPosition::Type), + true, + ) }); hir::TraitItemKind::Type( this.lower_param_bounds( bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + true, ), ty, ) @@ -853,7 +869,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = match &i.kind { AssocItemKind::Const(_, ty, expr) => { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type), true); ( hir::Generics::empty(), hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())), @@ -887,7 +904,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ImplItemKind::TyAlias(ty) } Some(ty) => { - let ty = this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy); + let ty = this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy, true); hir::ImplItemKind::TyAlias(ty) } }, @@ -1412,7 +1429,7 @@ impl<'hir> LoweringContext<'_, 'hir> { return None; } - let bounds = self.lower_param_bounds(bounds, itctx); + let bounds = self.lower_param_bounds(bounds, itctx, true); let ident = self.lower_ident(ident); let param_span = ident.span; @@ -1458,7 +1475,8 @@ impl<'hir> LoweringContext<'_, 'hir> { panic!("Missing resolution for lifetime {:?} at {:?}", id, ident.span) }); let lt_id = self.next_node_id(); - let lifetime = self.new_named_lifetime_with_res(lt_id, ident_span, ident, res); + let lifetime = + self.new_named_lifetime_with_res(lt_id, ident_span, ident, res, true); Some(hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { lifetime, span, @@ -1478,12 +1496,16 @@ impl<'hir> LoweringContext<'_, 'hir> { span, }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { bound_generic_params: self.lower_generic_params(bound_generic_params), - bounded_ty: self - .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + bounded_ty: self.lower_ty( + bounded_ty, + ImplTraitContext::Disallowed(ImplTraitPosition::Type), + true, + ), bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| { self.lower_param_bound( bound, ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + true, ) })), span: self.lower_span(span), @@ -1495,20 +1517,27 @@ impl<'hir> LoweringContext<'_, 'hir> { span, }) => hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { span: self.lower_span(span), - lifetime: self.lower_lifetime(lifetime), + lifetime: self.lower_lifetime(lifetime, true), bounds: self.lower_param_bounds( bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + true, ), in_where_clause: true, }), WherePredicate::EqPredicate(WhereEqPredicate { id, ref lhs_ty, ref rhs_ty, span }) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { hir_id: self.lower_node_id(id), - lhs_ty: self - .lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), - rhs_ty: self - .lower_ty(rhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + lhs_ty: self.lower_ty( + lhs_ty, + ImplTraitContext::Disallowed(ImplTraitPosition::Type), + true, + ), + rhs_ty: self.lower_ty( + rhs_ty, + ImplTraitContext::Disallowed(ImplTraitPosition::Type), + true, + ), span: self.lower_span(span), }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8fb29dcb67569..2749af72b68fd 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -957,7 +957,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let kind = match constraint.kind { AssocConstraintKind::Equality { ref term } => { let term = match term { - Term::Ty(ref ty) => self.lower_ty(ty, itctx).into(), + Term::Ty(ref ty) => self.lower_ty(ty, itctx, true).into(), Term::Const(ref c) => self.lower_anon_const(c).into(), }; hir::TypeBindingKind::Equality { term } @@ -1022,6 +1022,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { tokens: None, }, itctx, + true, ); hir::TypeBindingKind::Equality { term: ty.into() } @@ -1029,7 +1030,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { // Desugar `AssocTy: Bounds` into a type binding where the // later desugars into a trait predicate. - let bounds = self.lower_param_bounds(bounds, itctx); + let bounds = self.lower_param_bounds(bounds, itctx, true); hir::TypeBindingKind::Constraint { bounds } } @@ -1088,7 +1089,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx: ImplTraitContext, ) -> hir::GenericArg<'hir> { match arg { - ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), + ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<, true)), ast::GenericArg::Type(ty) => { match ty.kind { TyKind::Infer if self.tcx.features().generic_arg_infer => { @@ -1137,7 +1138,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } _ => {} } - GenericArg::Type(self.lower_ty_direct(&ty, itctx)) + GenericArg::Type(self.lower_ty_direct(&ty, itctx, true)) } ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg { value: self.lower_anon_const(&ct), @@ -1147,8 +1148,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "debug", skip(self))] - fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> { - self.arena.alloc(self.lower_ty_direct(t, itctx)) + fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext, captures: bool) -> &'hir hir::Ty<'hir> { + self.arena.alloc(self.lower_ty_direct(t, itctx, captures)) } fn lower_path_ty( @@ -1158,6 +1159,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { path: &Path, param_mode: ParamMode, itctx: ImplTraitContext, + captures: bool, ) -> hir::Ty<'hir> { // Check whether we should interpret this as a bare trait object. // This check mirrors the one in late resolution. We only introduce this special case in @@ -1177,6 +1179,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: t.span }, itctx, + captures, ); let bounds = this.arena.alloc_from_iter([bound]); let lifetime_bound = this.elided_dyn_bound(t.span); @@ -1187,7 +1190,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let id = self.lower_node_id(t.id); - let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx); + let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx, true); self.ty_path(id, t.span, qpath) } @@ -1199,11 +1202,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.ty(span, hir::TyKind::Tup(tys)) } - fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> { + fn lower_ty_direct( + &mut self, + t: &Ty, + itctx: ImplTraitContext, + captures: bool, + ) -> hir::Ty<'hir> { let kind = match t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => hir::TyKind::Err, - TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), + TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx, captures)), TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), TyKind::Rptr(ref region, ref mt) => { let region = region.unwrap_or_else(|| { @@ -1218,7 +1226,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let span = self.tcx.sess.source_map().next_point(t.span.shrink_to_lo()); Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id } }); - let lifetime = self.lower_lifetime(®ion); + let lifetime = self.lower_lifetime(®ion, captures); hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx)) } TyKind::BareFn(ref f) => { @@ -1233,14 +1241,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) } TyKind::Never => hir::TyKind::Never, - TyKind::Tup(ref tys) => hir::TyKind::Tup( - self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))), - ), + TyKind::Tup(ref tys) => { + hir::TyKind::Tup(self.arena.alloc_from_iter( + tys.iter().map(|ty| self.lower_ty_direct(ty, itctx, captures)), + )) + } TyKind::Paren(ref ty) => { - return self.lower_ty_direct(ty, itctx); + return self.lower_ty_direct(ty, itctx, captures); } TyKind::Path(ref qself, ref path) => { - return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx); + return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx, captures); } TyKind::ImplicitSelf => { let res = self.expect_full_res(t.id); @@ -1256,9 +1266,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), )) } - TyKind::Array(ref ty, ref length) => { - hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length)) - } + TyKind::Array(ref ty, ref length) => hir::TyKind::Array( + self.lower_ty(ty, itctx, captures), + self.lower_array_length(length), + ), TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)), TyKind::TraitObject(ref bounds, kind) => { let mut lifetime_bound = None; @@ -1269,7 +1280,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericBound::Trait( ref ty, TraitBoundModifier::None | TraitBoundModifier::MaybeConst, - ) => Some(this.lower_poly_trait_ref(ty, itctx)), + ) => Some(this.lower_poly_trait_ref(ty, itctx, captures)), // `~const ?Bound` will cause an error during AST validation // anyways, so treat it like `?Bound` as compilation proceeds. GenericBound::Trait( @@ -1278,7 +1289,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) => None, GenericBound::Outlives(ref lifetime) => { if lifetime_bound.is_none() { - lifetime_bound = Some(this.lower_lifetime(lifetime)); + lifetime_bound = Some(this.lower_lifetime(lifetime, true)); } None } @@ -1295,7 +1306,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { match itctx { ImplTraitContext::ReturnPositionOpaqueTy { origin } => self .lower_opaque_impl_trait(span, origin, def_node_id, |this| { - this.lower_param_bounds(bounds, itctx) + this.lower_param_bounds(bounds, itctx, true) }), ImplTraitContext::TypeAliasesOpaqueTy => { let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; @@ -1303,7 +1314,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, hir::OpaqueTyOrigin::TyAlias, def_node_id, - |this| this.lower_param_bounds(bounds, nested_itctx), + |this| this.lower_param_bounds(bounds, nested_itctx, true), ) } ImplTraitContext::Universal => { @@ -1417,7 +1428,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { |(_, (span, _, p_name, res))| { let id = self.next_node_id(); let ident = Ident::new(p_name.ident().name, span); - let l = self.new_named_lifetime_with_res(id, span, ident, res); + let l = self.new_named_lifetime_with_res(id, span, ident, res, true); hir::GenericArg::Lifetime(l) }, )); @@ -1495,7 +1506,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { if fn_node_id.is_some() { - self.lower_ty_direct(¶m.ty, ImplTraitContext::Universal) + self.lower_ty_direct(¶m.ty, ImplTraitContext::Universal, true) } else { self.lower_ty_direct( ¶m.ty, @@ -1509,6 +1520,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnDeclKind::Trait => ImplTraitPosition::TraitParam, FnDeclKind::Impl => ImplTraitPosition::ImplParam, }), + true, ) } })); @@ -1540,7 +1552,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnDeclKind::Impl => ImplTraitPosition::ImplReturn, }), }; - hir::FnRetTy::Return(self.lower_ty(ty, context)) + hir::FnRetTy::Return(self.lower_ty(ty, context, true)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)), } @@ -1746,7 +1758,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc_from_iter(captures.into_iter().map(|(_, (span, _, p_name, res))| { let id = self.next_node_id(); let ident = Ident::new(p_name.ident().name, span); - let l = self.new_named_lifetime_with_res(id, span, ident, res); + let l = self.new_named_lifetime_with_res(id, span, ident, res, true); hir::GenericArg::Lifetime(l) })); @@ -1776,7 +1788,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let context = ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), }; - self.lower_ty(ty, context) + self.lower_ty(ty, context, true) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; @@ -1803,23 +1815,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, tpb: &GenericBound, itctx: ImplTraitContext, + captures: bool, ) -> hir::GenericBound<'hir> { match tpb { GenericBound::Trait(p, modifier) => hir::GenericBound::Trait( - self.lower_poly_trait_ref(p, itctx), + self.lower_poly_trait_ref(p, itctx, captures), self.lower_trait_bound_modifier(*modifier), ), GenericBound::Outlives(lifetime) => { - hir::GenericBound::Outlives(self.lower_lifetime(lifetime)) + hir::GenericBound::Outlives(self.lower_lifetime(lifetime, captures)) } } } - fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { + fn lower_lifetime(&mut self, l: &Lifetime, captures: bool) -> hir::Lifetime { let span = self.lower_span(l.ident.span); let ident = self.lower_ident(l.ident); let res = self.resolver.get_lifetime_res(l.id).unwrap_or(LifetimeRes::Error); - self.new_named_lifetime_with_res(l.id, span, ident, res) + self.new_named_lifetime_with_res(l.id, span, ident, res, captures) } #[tracing::instrument(level = "debug", skip(self))] @@ -1829,55 +1842,60 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, ident: Ident, res: LifetimeRes, + captures: bool, ) -> hir::Lifetime { debug!(?self.captured_lifetimes); let name = match res { LifetimeRes::Param { mut param, binder } => { let p_name = ParamName::Plain(ident); - if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { - if !captured_lifetimes.binders_to_ignore.contains(&binder) { - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(o) => param = self.local_def_id(o.get().1), - Entry::Vacant(v) => { - let p_id = self.next_node_id(); - let p_def_id = self.create_def( - captured_lifetimes.parent_def_id, - p_id, - DefPathData::LifetimeNs(p_name.ident().name), - ); - - v.insert((span, p_id, p_name, res)); - param = p_def_id; + if captures { + if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { + if !captured_lifetimes.binders_to_ignore.contains(&binder) { + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(o) => param = self.local_def_id(o.get().1), + Entry::Vacant(v) => { + let p_id = self.next_node_id(); + let p_def_id = self.create_def( + captured_lifetimes.parent_def_id, + p_id, + DefPathData::LifetimeNs(p_name.ident().name), + ); + + v.insert((span, p_id, p_name, res)); + param = p_def_id; + } } } - } - self.captured_lifetimes = Some(captured_lifetimes); + self.captured_lifetimes = Some(captured_lifetimes); + } } hir::LifetimeName::Param(param, p_name) } LifetimeRes::Fresh { param, binder } => { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); let mut param = self.local_def_id(param); - if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { - if !captured_lifetimes.binders_to_ignore.contains(&binder) { - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(o) => param = self.local_def_id(o.get().1), - Entry::Vacant(v) => { - let p_id = self.next_node_id(); - let p_def_id = self.create_def( - captured_lifetimes.parent_def_id, - p_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ); - - v.insert((span, p_id, ParamName::Fresh, res)); - param = p_def_id; + if captures { + if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { + if !captured_lifetimes.binders_to_ignore.contains(&binder) { + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(o) => param = self.local_def_id(o.get().1), + Entry::Vacant(v) => { + let p_id = self.next_node_id(); + let p_def_id = self.create_def( + captured_lifetimes.parent_def_id, + p_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ); + + v.insert((span, p_id, ParamName::Fresh, res)); + param = p_def_id; + } } } - } - self.captured_lifetimes = Some(captured_lifetimes); + self.captured_lifetimes = Some(captured_lifetimes); + } } hir::LifetimeName::Param(param, ParamName::Fresh) } @@ -1941,7 +1959,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericParamKind::Type { ref default, .. } => { let kind = hir::GenericParamKind::Type { default: default.as_ref().map(|x| { - self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + self.lower_ty( + x, + ImplTraitContext::Disallowed(ImplTraitPosition::Type), + true, + ) }), synthetic: false, }; @@ -1949,7 +1971,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Plain(self.lower_ident(param.ident)), kind) } GenericParamKind::Const { ref ty, kw_span: _, ref default } => { - let ty = self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = + self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type), true); let default = default.as_ref().map(|def| self.lower_anon_const(def)); ( hir::ParamName::Plain(self.lower_ident(param.ident)), @@ -1959,8 +1982,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::TraitRef<'hir> { - let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) { + fn lower_trait_ref( + &mut self, + p: &TraitRef, + itctx: ImplTraitContext, + captures: bool, + ) -> hir::TraitRef<'hir> { + let path = match self.lower_qpath( + p.ref_id, + &None, + &p.path, + ParamMode::Explicit, + itctx, + captures, + ) { hir::QPath::Resolved(None, path) => path, qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath), }; @@ -1972,35 +2007,38 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, p: &PolyTraitRef, itctx: ImplTraitContext, + captures: bool, ) -> hir::PolyTraitRef<'hir> { self.with_lifetime_binder( p.trait_ref.ref_id, &p.bound_generic_params, |this, bound_generic_params| { - let trait_ref = this.lower_trait_ref(&p.trait_ref, itctx); + let trait_ref = this.lower_trait_ref(&p.trait_ref, itctx, captures); hir::PolyTraitRef { bound_generic_params, trait_ref, span: this.lower_span(p.span) } }, ) } fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { - hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl } + hir::MutTy { ty: self.lower_ty(&mt.ty, itctx, true), mutbl: mt.mutbl } } fn lower_param_bounds( &mut self, bounds: &[GenericBound], itctx: ImplTraitContext, + captures: bool, ) -> hir::GenericBounds<'hir> { - self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) + self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx, captures)) } fn lower_param_bounds_mut<'s>( &'s mut self, bounds: &'s [GenericBound], itctx: ImplTraitContext, + captures: bool, ) -> impl Iterator> + Captures<'s> + Captures<'a> { - bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) + bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx, captures)) } fn lower_generic_and_bounds( diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index bd2e76e5528da..b995b1b649d39 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -36,6 +36,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), + true, ); let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); break hir::PatKind::TupleStruct(qpath, pats, ddpos); @@ -52,6 +53,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), + true, ); break hir::PatKind::Path(qpath); } @@ -62,6 +64,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), + true, ); let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::PatField { diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 393be3b454c37..02e5816593cbd 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -24,9 +24,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p: &Path, param_mode: ParamMode, itctx: ImplTraitContext, + captures: bool, ) -> hir::QPath<'hir> { let qself_position = qself.as_ref().map(|q| q.position); - let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); + let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx, captures)); let partial_res = self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err)); @@ -72,6 +73,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode, parenthesized_generic_args, itctx, + captures, ) }, )), @@ -118,6 +120,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode, ParenthesizedGenericArgs::Err, itctx, + captures, )); let qpath = hir::QPath::TypeRelative(ty, hir_segment); @@ -158,6 +161,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode, ParenthesizedGenericArgs::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), + true, ) })), span: self.lower_span(p.span), @@ -182,6 +186,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode: ParamMode, parenthesized_generic_args: ParenthesizedGenericArgs, itctx: ImplTraitContext, + captures: bool, ) -> hir::PathSegment<'hir> { debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,); let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args { @@ -254,6 +259,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment.id, segment.ident.span, &mut generic_args, + captures, ); } @@ -283,6 +289,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment_id: NodeId, segment_ident_span: Span, generic_args: &mut GenericArgsCtor<'hir>, + captures: bool, ) { let (start, end) = match self.resolver.get_lifetime_res(segment_id) { Some(LifetimeRes::ElidedAnchor { start, end }) => (start, end), @@ -311,10 +318,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { 0, (start.as_u32()..end.as_u32()).map(|i| { let id = NodeId::from_u32(i); - let l = self.lower_lifetime(&Lifetime { - id, - ident: Ident::new(kw::UnderscoreLifetime, elided_lifetime_span), - }); + let l = self.lower_lifetime( + &Lifetime { + id, + ident: Ident::new(kw::UnderscoreLifetime, elided_lifetime_span), + }, + captures, + ); GenericArg::Lifetime(l) }), ); @@ -358,12 +368,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // we generally don't permit such things (see #51008). let ParenthesizedArgs { span, inputs, inputs_span, output } = data; let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| { - self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) + self.lower_ty_direct( + ty, + ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam), + true, + ) })); let output_ty = match output { - FnRetTy::Ty(ty) => { - self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) - } + FnRetTy::Ty(ty) => self.lower_ty( + &ty, + ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn), + true, + ), FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), }; let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))]; From 84a24a1b3c183066644be2db03c48545d796f01f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 19 Jul 2022 22:16:32 -0300 Subject: [PATCH 04/56] Unroll while_capturing_lifetimes into lower_opaque_impl_trait --- compiler/rustc_ast_lowering/src/lib.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 2749af72b68fd..72e0466761a05 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1376,11 +1376,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let hir_bounds = if origin == hir::OpaqueTyOrigin::TyAlias { lower_bounds(lctx) } else { - lctx.while_capturing_lifetimes( - opaque_ty_def_id, - &mut collected_lifetimes, - lower_bounds, - ) + let lifetime_stash = std::mem::replace( + &mut lctx.captured_lifetimes, + Some(LifetimeCaptureContext { + parent_def_id: opaque_ty_def_id, + captures: std::mem::take(&mut collected_lifetimes), + binders_to_ignore: Default::default(), + }), + ); + + let ret = lower_bounds(lctx); + + let ctxt = std::mem::replace(&mut lctx.captured_lifetimes, lifetime_stash).unwrap(); + collected_lifetimes = ctxt.captures; + + ret }; debug!(?collected_lifetimes); From cda2c04592850eb8248210beb8efd9c35de0dc19 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 20 Jul 2022 16:30:37 -0300 Subject: [PATCH 05/56] Explicitly gather lifetimes and definitions in RPIT --- compiler/rustc_ast/src/ast.rs | 61 +++++++- compiler/rustc_ast_lowering/src/lib.rs | 188 +++++++++++++++++++------ 2 files changed, 207 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 116497109f1dd..3503e5de8ccdb 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -25,7 +25,9 @@ pub use UnsafeSource::*; use crate::ptr::P; use crate::token::{self, CommentKind, Delimiter}; use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream}; +use crate::visit::{self, BoundKind, LifetimeCtxt, Visitor}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; @@ -64,7 +66,7 @@ impl fmt::Debug for Label { /// A "Lifetime" is an annotation of the scope in which variable /// can be used, e.g. `'a` in `&'a i32`. -#[derive(Clone, Encodable, Decodable, Copy)] +#[derive(Clone, Encodable, Decodable, Copy, PartialEq, Eq)] pub struct Lifetime { pub id: NodeId, pub ident: Ident, @@ -323,6 +325,63 @@ impl GenericBound { pub type GenericBounds = Vec; +struct LifetimeCollectVisitor<'ast> { + current_binders: Vec, + binders_to_ignore: FxHashMap>, + collected_lifetimes: Vec<&'ast Lifetime>, +} + +impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { + fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) { + if !self.collected_lifetimes.contains(&lifetime) { + self.collected_lifetimes.push(lifetime); + } + self.binders_to_ignore.insert(lifetime.id, self.current_binders.clone()); + } + + fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { + self.current_binders.push(t.trait_ref.ref_id); + + visit::walk_poly_trait_ref(self, t, m); + + self.current_binders.pop(); + } + + fn visit_ty(&mut self, t: &'ast Ty) { + if let TyKind::BareFn(_) = t.kind { + self.current_binders.push(t.id); + } + visit::walk_ty(self, t); + if let TyKind::BareFn(_) = t.kind { + self.current_binders.pop(); + } + } +} + +pub fn lifetimes_in_ret_ty(ret_ty: &FnRetTy) -> (Vec<&Lifetime>, FxHashMap>) { + let mut visitor = LifetimeCollectVisitor { + current_binders: Vec::new(), + binders_to_ignore: FxHashMap::default(), + collected_lifetimes: Vec::new(), + }; + visitor.visit_fn_ret_ty(ret_ty); + (visitor.collected_lifetimes, visitor.binders_to_ignore) +} + +pub fn lifetimes_in_bounds( + bounds: &GenericBounds, +) -> (Vec<&Lifetime>, FxHashMap>) { + let mut visitor = LifetimeCollectVisitor { + current_binders: Vec::new(), + binders_to_ignore: FxHashMap::default(), + collected_lifetimes: Vec::new(), + }; + for bound in bounds { + visitor.visit_param_bound(bound, BoundKind::Bound); + } + (visitor.collected_lifetimes, visitor.binders_to_ignore) +} + /// Specifies the enforced ordering for generic parameters. In the future, /// if we wanted to relax this order, we could override `PartialEq` and /// `PartialOrd`, to allow the kinds to be unordered. diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 72e0466761a05..dfd23dbd4d730 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1304,17 +1304,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::ImplTrait(def_node_id, ref bounds) => { let span = t.span; match itctx { - ImplTraitContext::ReturnPositionOpaqueTy { origin } => self - .lower_opaque_impl_trait(span, origin, def_node_id, |this| { - this.lower_param_bounds(bounds, itctx, true) - }), + ImplTraitContext::ReturnPositionOpaqueTy { origin } => { + self.lower_opaque_impl_trait(span, origin, def_node_id, bounds, itctx) + } ImplTraitContext::TypeAliasesOpaqueTy => { let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; self.lower_opaque_impl_trait( span, hir::OpaqueTyOrigin::TyAlias, def_node_id, - |this| this.lower_param_bounds(bounds, nested_itctx, true), + bounds, + nested_itctx, ) } ImplTraitContext::Universal => { @@ -1354,13 +1354,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) } } - #[tracing::instrument(level = "debug", skip(self, lower_bounds))] + #[tracing::instrument(level = "debug", skip(self))] fn lower_opaque_impl_trait( &mut self, span: Span, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, - lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>, + bounds: &GenericBounds, + itctx: ImplTraitContext, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop @@ -1374,23 +1375,122 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut collected_lifetimes = FxHashMap::default(); self.with_hir_id_owner(opaque_ty_node_id, |lctx| { let hir_bounds = if origin == hir::OpaqueTyOrigin::TyAlias { - lower_bounds(lctx) + lctx.lower_param_bounds(bounds, itctx, true) } else { - let lifetime_stash = std::mem::replace( - &mut lctx.captured_lifetimes, - Some(LifetimeCaptureContext { - parent_def_id: opaque_ty_def_id, - captures: std::mem::take(&mut collected_lifetimes), - binders_to_ignore: Default::default(), - }), - ); + if std::env::var("NEW_COLLECT_LIFETIMES").is_ok() { + let lifetime_stash = std::mem::replace( + &mut lctx.captured_lifetimes, + Some(LifetimeCaptureContext { + parent_def_id: opaque_ty_def_id, + captures: std::mem::take(&mut collected_lifetimes), + binders_to_ignore: Default::default(), + }), + ); + + let (lifetimes_in_bounds, binders_to_ignore) = ast::lifetimes_in_bounds(bounds); + + for lifetime in &lifetimes_in_bounds { + let ident = lifetime.ident; + let span = ident.span; + + let res = lctx + .resolver + .get_lifetime_res(lifetime.id) + .unwrap_or(LifetimeRes::Error); + + if let Some(mut captured_lifetimes) = lctx.captured_lifetimes.take() { + match res { + LifetimeRes::Param { param, binder } => { + if !captured_lifetimes.binders_to_ignore.contains(&binder) + && !binders_to_ignore + .get(&lifetime.id) + .unwrap_or(&Vec::new()) + .contains(&binder) + { + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(_) => {} + Entry::Vacant(v) => { + let node_id = lctx.next_node_id(); + let name = ParamName::Plain(ident); + + lctx.create_def( + captured_lifetimes.parent_def_id, + node_id, + DefPathData::LifetimeNs(name.ident().name), + ); + + v.insert((span, node_id, name, res)); + } + } + } + } + + LifetimeRes::Fresh { param, binder } => { + debug_assert_eq!(ident.name, kw::UnderscoreLifetime); + if !captured_lifetimes.binders_to_ignore.contains(&binder) + && !binders_to_ignore + .get(&lifetime.id) + .unwrap_or(&Vec::new()) + .contains(&binder) + { + let param = lctx.local_def_id(param); + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(_) => {} + Entry::Vacant(v) => { + let node_id = lctx.next_node_id(); + + let name = ParamName::Fresh; + + lctx.create_def( + captured_lifetimes.parent_def_id, + node_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ); + + v.insert((span, node_id, name, res)); + } + } + } + } + + LifetimeRes::Infer | LifetimeRes::Static | LifetimeRes::Error => {} + + res => panic!( + "Unexpected lifetime resolution {:?} for {:?} at {:?}", + res, lifetime.ident, lifetime.ident.span + ), + } + + lctx.captured_lifetimes = Some(captured_lifetimes); + } + } + + let ret = lctx.lower_param_bounds(bounds, itctx, false); + + let ctxt = + std::mem::replace(&mut lctx.captured_lifetimes, lifetime_stash).unwrap(); + + collected_lifetimes = ctxt.captures; + + ret + } else { + let lifetime_stash = std::mem::replace( + &mut lctx.captured_lifetimes, + Some(LifetimeCaptureContext { + parent_def_id: opaque_ty_def_id, + captures: std::mem::take(&mut collected_lifetimes), + binders_to_ignore: Default::default(), + }), + ); - let ret = lower_bounds(lctx); + let ret = lctx.lower_param_bounds(bounds, itctx, true); - let ctxt = std::mem::replace(&mut lctx.captured_lifetimes, lifetime_stash).unwrap(); - collected_lifetimes = ctxt.captures; + let ctxt = + std::mem::replace(&mut lctx.captured_lifetimes, lifetime_stash).unwrap(); + collected_lifetimes = ctxt.captures; - ret + ret + } }; debug!(?collected_lifetimes); @@ -1855,16 +1955,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { captures: bool, ) -> hir::Lifetime { debug!(?self.captured_lifetimes); + let name = match res { LifetimeRes::Param { mut param, binder } => { let p_name = ParamName::Plain(ident); - if captures { - if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { + if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { + if captures { if !captured_lifetimes.binders_to_ignore.contains(&binder) { match captured_lifetimes.captures.entry(param) { Entry::Occupied(o) => param = self.local_def_id(o.get().1), Entry::Vacant(v) => { let p_id = self.next_node_id(); + let p_def_id = self.create_def( captured_lifetimes.parent_def_id, p_id, @@ -1876,36 +1978,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } } - - self.captured_lifetimes = Some(captured_lifetimes); + } else { + if let Entry::Occupied(o) = captured_lifetimes.captures.entry(param) { + param = self.local_def_id(o.get().1); + } } + self.captured_lifetimes = Some(captured_lifetimes); } + hir::LifetimeName::Param(param, p_name) } LifetimeRes::Fresh { param, binder } => { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); + let mut param = self.local_def_id(param); - if captures { - if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { - if !captured_lifetimes.binders_to_ignore.contains(&binder) { - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(o) => param = self.local_def_id(o.get().1), - Entry::Vacant(v) => { - let p_id = self.next_node_id(); - let p_def_id = self.create_def( - captured_lifetimes.parent_def_id, - p_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ); + if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { + if !captured_lifetimes.binders_to_ignore.contains(&binder) { + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(o) => param = self.local_def_id(o.get().1), + Entry::Vacant(v) => { + let p_id = self.next_node_id(); + + let p_def_id = self.create_def( + captured_lifetimes.parent_def_id, + p_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ); - v.insert((span, p_id, ParamName::Fresh, res)); - param = p_def_id; - } + v.insert((span, p_id, ParamName::Fresh, res)); + param = p_def_id; } } - - self.captured_lifetimes = Some(captured_lifetimes); } + + self.captured_lifetimes = Some(captured_lifetimes); } hir::LifetimeName::Param(param, ParamName::Fresh) } From 399609e841f36f32d22d53df4c1633ff038f2ff7 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 26 Jul 2022 11:39:06 -0300 Subject: [PATCH 06/56] Add debug! calls --- compiler/rustc_ast_lowering/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index dfd23dbd4d730..b8383af521fde 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1378,6 +1378,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lctx.lower_param_bounds(bounds, itctx, true) } else { if std::env::var("NEW_COLLECT_LIFETIMES").is_ok() { + debug!(?lctx.captured_lifetimes); + let lifetime_stash = std::mem::replace( &mut lctx.captured_lifetimes, Some(LifetimeCaptureContext { @@ -1388,6 +1390,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); let (lifetimes_in_bounds, binders_to_ignore) = ast::lifetimes_in_bounds(bounds); + debug!(?lifetimes_in_bounds); + debug!(?binders_to_ignore); for lifetime in &lifetimes_in_bounds { let ident = lifetime.ident; @@ -1397,6 +1401,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .resolver .get_lifetime_res(lifetime.id) .unwrap_or(LifetimeRes::Error); + debug!(?res); if let Some(mut captured_lifetimes) = lctx.captured_lifetimes.take() { match res { From fac763168f35bc24b83c435d4d7009dca648432b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 26 Jul 2022 11:56:26 -0300 Subject: [PATCH 07/56] Remove NEW_COLLECT_LIFETIMES env var --- compiler/rustc_ast_lowering/src/lib.rs | 186 +++++++++++-------------- 1 file changed, 82 insertions(+), 104 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b8383af521fde..aa84373b6cf88 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1377,125 +1377,103 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let hir_bounds = if origin == hir::OpaqueTyOrigin::TyAlias { lctx.lower_param_bounds(bounds, itctx, true) } else { - if std::env::var("NEW_COLLECT_LIFETIMES").is_ok() { - debug!(?lctx.captured_lifetimes); - - let lifetime_stash = std::mem::replace( - &mut lctx.captured_lifetimes, - Some(LifetimeCaptureContext { - parent_def_id: opaque_ty_def_id, - captures: std::mem::take(&mut collected_lifetimes), - binders_to_ignore: Default::default(), - }), - ); - - let (lifetimes_in_bounds, binders_to_ignore) = ast::lifetimes_in_bounds(bounds); - debug!(?lifetimes_in_bounds); - debug!(?binders_to_ignore); - - for lifetime in &lifetimes_in_bounds { - let ident = lifetime.ident; - let span = ident.span; - - let res = lctx - .resolver - .get_lifetime_res(lifetime.id) - .unwrap_or(LifetimeRes::Error); - debug!(?res); - - if let Some(mut captured_lifetimes) = lctx.captured_lifetimes.take() { - match res { - LifetimeRes::Param { param, binder } => { - if !captured_lifetimes.binders_to_ignore.contains(&binder) - && !binders_to_ignore - .get(&lifetime.id) - .unwrap_or(&Vec::new()) - .contains(&binder) - { - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(_) => {} - Entry::Vacant(v) => { - let node_id = lctx.next_node_id(); - let name = ParamName::Plain(ident); - - lctx.create_def( - captured_lifetimes.parent_def_id, - node_id, - DefPathData::LifetimeNs(name.ident().name), - ); - - v.insert((span, node_id, name, res)); - } + debug!(?lctx.captured_lifetimes); + + let lifetime_stash = std::mem::replace( + &mut lctx.captured_lifetimes, + Some(LifetimeCaptureContext { + parent_def_id: opaque_ty_def_id, + captures: std::mem::take(&mut collected_lifetimes), + binders_to_ignore: Default::default(), + }), + ); + + let (lifetimes_in_bounds, binders_to_ignore) = ast::lifetimes_in_bounds(bounds); + debug!(?lifetimes_in_bounds); + debug!(?binders_to_ignore); + + for lifetime in &lifetimes_in_bounds { + let ident = lifetime.ident; + let span = ident.span; + + let res = + lctx.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error); + debug!(?res); + + if let Some(mut captured_lifetimes) = lctx.captured_lifetimes.take() { + match res { + LifetimeRes::Param { param, binder } => { + if !captured_lifetimes.binders_to_ignore.contains(&binder) + && !binders_to_ignore + .get(&lifetime.id) + .unwrap_or(&Vec::new()) + .contains(&binder) + { + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(_) => {} + Entry::Vacant(v) => { + let node_id = lctx.next_node_id(); + let name = ParamName::Plain(ident); + + lctx.create_def( + captured_lifetimes.parent_def_id, + node_id, + DefPathData::LifetimeNs(name.ident().name), + ); + + v.insert((span, node_id, name, res)); } } } + } - LifetimeRes::Fresh { param, binder } => { - debug_assert_eq!(ident.name, kw::UnderscoreLifetime); - if !captured_lifetimes.binders_to_ignore.contains(&binder) - && !binders_to_ignore - .get(&lifetime.id) - .unwrap_or(&Vec::new()) - .contains(&binder) - { - let param = lctx.local_def_id(param); - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(_) => {} - Entry::Vacant(v) => { - let node_id = lctx.next_node_id(); - - let name = ParamName::Fresh; - - lctx.create_def( - captured_lifetimes.parent_def_id, - node_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ); - - v.insert((span, node_id, name, res)); - } + LifetimeRes::Fresh { param, binder } => { + debug_assert_eq!(ident.name, kw::UnderscoreLifetime); + if !captured_lifetimes.binders_to_ignore.contains(&binder) + && !binders_to_ignore + .get(&lifetime.id) + .unwrap_or(&Vec::new()) + .contains(&binder) + { + let param = lctx.local_def_id(param); + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(_) => {} + Entry::Vacant(v) => { + let node_id = lctx.next_node_id(); + + let name = ParamName::Fresh; + + lctx.create_def( + captured_lifetimes.parent_def_id, + node_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ); + + v.insert((span, node_id, name, res)); } } } - - LifetimeRes::Infer | LifetimeRes::Static | LifetimeRes::Error => {} - - res => panic!( - "Unexpected lifetime resolution {:?} for {:?} at {:?}", - res, lifetime.ident, lifetime.ident.span - ), } - lctx.captured_lifetimes = Some(captured_lifetimes); - } - } - - let ret = lctx.lower_param_bounds(bounds, itctx, false); + LifetimeRes::Infer | LifetimeRes::Static | LifetimeRes::Error => {} - let ctxt = - std::mem::replace(&mut lctx.captured_lifetimes, lifetime_stash).unwrap(); + res => panic!( + "Unexpected lifetime resolution {:?} for {:?} at {:?}", + res, lifetime.ident, lifetime.ident.span + ), + } - collected_lifetimes = ctxt.captures; + lctx.captured_lifetimes = Some(captured_lifetimes); + } + } - ret - } else { - let lifetime_stash = std::mem::replace( - &mut lctx.captured_lifetimes, - Some(LifetimeCaptureContext { - parent_def_id: opaque_ty_def_id, - captures: std::mem::take(&mut collected_lifetimes), - binders_to_ignore: Default::default(), - }), - ); + let ret = lctx.lower_param_bounds(bounds, itctx, false); - let ret = lctx.lower_param_bounds(bounds, itctx, true); + let ctxt = std::mem::replace(&mut lctx.captured_lifetimes, lifetime_stash).unwrap(); - let ctxt = - std::mem::replace(&mut lctx.captured_lifetimes, lifetime_stash).unwrap(); - collected_lifetimes = ctxt.captures; + collected_lifetimes = ctxt.captures; - ret - } + ret }; debug!(?collected_lifetimes); From 25825cd4fa735c4b6d8b004940709bc066477c7c Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 26 Jul 2022 14:49:24 -0300 Subject: [PATCH 08/56] Extract create_and_capture_lifetime_defs function --- compiler/rustc_ast_lowering/src/lib.rs | 155 +++++++++++++------------ 1 file changed, 81 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index aa84373b6cf88..9009ae7a0510f 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1392,80 +1392,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?lifetimes_in_bounds); debug!(?binders_to_ignore); - for lifetime in &lifetimes_in_bounds { - let ident = lifetime.ident; - let span = ident.span; - - let res = - lctx.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error); - debug!(?res); - - if let Some(mut captured_lifetimes) = lctx.captured_lifetimes.take() { - match res { - LifetimeRes::Param { param, binder } => { - if !captured_lifetimes.binders_to_ignore.contains(&binder) - && !binders_to_ignore - .get(&lifetime.id) - .unwrap_or(&Vec::new()) - .contains(&binder) - { - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(_) => {} - Entry::Vacant(v) => { - let node_id = lctx.next_node_id(); - let name = ParamName::Plain(ident); - - lctx.create_def( - captured_lifetimes.parent_def_id, - node_id, - DefPathData::LifetimeNs(name.ident().name), - ); - - v.insert((span, node_id, name, res)); - } - } - } - } - - LifetimeRes::Fresh { param, binder } => { - debug_assert_eq!(ident.name, kw::UnderscoreLifetime); - if !captured_lifetimes.binders_to_ignore.contains(&binder) - && !binders_to_ignore - .get(&lifetime.id) - .unwrap_or(&Vec::new()) - .contains(&binder) - { - let param = lctx.local_def_id(param); - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(_) => {} - Entry::Vacant(v) => { - let node_id = lctx.next_node_id(); - - let name = ParamName::Fresh; - - lctx.create_def( - captured_lifetimes.parent_def_id, - node_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ); - - v.insert((span, node_id, name, res)); - } - } - } - } - - LifetimeRes::Infer | LifetimeRes::Static | LifetimeRes::Error => {} - - res => panic!( - "Unexpected lifetime resolution {:?} for {:?} at {:?}", - res, lifetime.ident, lifetime.ident.span - ), - } - - lctx.captured_lifetimes = Some(captured_lifetimes); - } - } + lctx.create_and_capture_lifetime_defs(&lifetimes_in_bounds, &binders_to_ignore); let ret = lctx.lower_param_bounds(bounds, itctx, false); @@ -1554,6 +1481,86 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item)) } + fn create_and_capture_lifetime_defs( + &mut self, + lifetimes_in_bounds: &[&Lifetime], + binders_to_ignore: &FxHashMap>, + ) { + for lifetime in lifetimes_in_bounds { + let ident = lifetime.ident; + let span = ident.span; + + let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error); + debug!(?res); + + if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { + match res { + LifetimeRes::Param { param, binder } => { + if !captured_lifetimes.binders_to_ignore.contains(&binder) + && !binders_to_ignore + .get(&lifetime.id) + .unwrap_or(&Vec::new()) + .contains(&binder) + { + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(_) => {} + Entry::Vacant(v) => { + let node_id = self.next_node_id(); + let name = ParamName::Plain(ident); + + self.create_def( + captured_lifetimes.parent_def_id, + node_id, + DefPathData::LifetimeNs(name.ident().name), + ); + + v.insert((span, node_id, name, res)); + } + } + } + } + + LifetimeRes::Fresh { param, binder } => { + debug_assert_eq!(ident.name, kw::UnderscoreLifetime); + if !captured_lifetimes.binders_to_ignore.contains(&binder) + && !binders_to_ignore + .get(&lifetime.id) + .unwrap_or(&Vec::new()) + .contains(&binder) + { + let param = self.local_def_id(param); + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(_) => {} + Entry::Vacant(v) => { + let node_id = self.next_node_id(); + + let name = ParamName::Fresh; + + self.create_def( + captured_lifetimes.parent_def_id, + node_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ); + + v.insert((span, node_id, name, res)); + } + } + } + } + + LifetimeRes::Infer | LifetimeRes::Static | LifetimeRes::Error => {} + + res => panic!( + "Unexpected lifetime resolution {:?} for {:?} at {:?}", + res, lifetime.ident, lifetime.ident.span + ), + } + + self.captured_lifetimes = Some(captured_lifetimes); + } + } + } + fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] { // Skip the `...` (`CVarArgs`) trailing arguments from the AST, // as they are not explicit in HIR/Ty function signatures. From 19dcbd151b9c8a061eb96a70c9a39a3f9796a701 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 26 Jul 2022 15:11:15 -0300 Subject: [PATCH 09/56] Explicitly gather lifetimes and definitions for bare async fns --- compiler/rustc_ast_lowering/src/lib.rs | 69 +++++++++++--------------- 1 file changed, 30 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9009ae7a0510f..bc4841eb36399 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -751,31 +751,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) } - /// Setup lifetime capture for and impl-trait. - /// The captures will be added to `captures`. - fn while_capturing_lifetimes( - &mut self, - parent_def_id: LocalDefId, - captures: &mut FxHashMap, - f: impl FnOnce(&mut Self) -> T, - ) -> T { - let lifetime_stash = std::mem::replace( - &mut self.captured_lifetimes, - Some(LifetimeCaptureContext { - parent_def_id, - captures: std::mem::take(captures), - binders_to_ignore: Default::default(), - }), - ); - - let ret = f(self); - - let ctxt = std::mem::replace(&mut self.captured_lifetimes, lifetime_stash).unwrap(); - *captures = ctxt.captures; - - ret - } - /// Register a binder to be ignored for lifetime capture. #[tracing::instrument(level = "debug", skip(self, f))] #[inline] @@ -1786,20 +1761,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?captures); self.with_hir_id_owner(opaque_ty_node_id, |this| { - let future_bound = - this.while_capturing_lifetimes(opaque_ty_def_id, &mut captures, |this| { - // We have to be careful to get elision right here. The - // idea is that we create a lifetime parameter for each - // lifetime in the return type. So, given a return type - // like `async fn foo(..) -> &[&u32]`, we lower to `impl - // Future`. - // - // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and - // hence the elision takes place at the fn site. - this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span) - }); - debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound); - debug!("lower_async_fn_ret_ty: captures={:#?}", captures); + let lifetime_stash = std::mem::replace( + &mut this.captured_lifetimes, + Some(LifetimeCaptureContext { + parent_def_id: opaque_ty_def_id, + captures: std::mem::take(&mut captures), + binders_to_ignore: Default::default(), + }), + ); + + let (lifetimes_in_bounds, binders_to_ignore) = ast::lifetimes_in_ret_ty(output); + debug!(?lifetimes_in_bounds); + debug!(?binders_to_ignore); + + this.create_and_capture_lifetime_defs(&lifetimes_in_bounds, &binders_to_ignore); + + // We have to be careful to get elision right here. The + // idea is that we create a lifetime parameter for each + // lifetime in the return type. So, given a return type + // like `async fn foo(..) -> &[&u32]`, we lower to `impl + // Future`. + // + // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and + // hence the elision takes place at the fn site. + let ret = this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span); + + let ctxt = std::mem::replace(&mut this.captured_lifetimes, lifetime_stash).unwrap(); + + captures = ctxt.captures; + + let future_bound = ret; let generic_params = this.arena.alloc_from_iter(captures.iter().map(|(_, &(span, p_id, p_name, _))| { From 5a184acfc6e5fc99993aae74d94e47ca5812dd08 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 26 Jul 2022 15:11:44 -0300 Subject: [PATCH 10/56] There's no need to check binders_to_ignore using the old code anymore --- compiler/rustc_ast_lowering/src/lib.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index bc4841eb36399..340f88e7540eb 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1471,11 +1471,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { match res { LifetimeRes::Param { param, binder } => { - if !captured_lifetimes.binders_to_ignore.contains(&binder) - && !binders_to_ignore - .get(&lifetime.id) - .unwrap_or(&Vec::new()) - .contains(&binder) + if !binders_to_ignore + .get(&lifetime.id) + .unwrap_or(&Vec::new()) + .contains(&binder) { match captured_lifetimes.captures.entry(param) { Entry::Occupied(_) => {} @@ -1497,11 +1496,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Fresh { param, binder } => { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); - if !captured_lifetimes.binders_to_ignore.contains(&binder) - && !binders_to_ignore - .get(&lifetime.id) - .unwrap_or(&Vec::new()) - .contains(&binder) + if !binders_to_ignore + .get(&lifetime.id) + .unwrap_or(&Vec::new()) + .contains(&binder) { let param = self.local_def_id(param); match captured_lifetimes.captures.entry(param) { From 9c0d9babd1c72a25f350a4e3c1277394ae80353e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 26 Jul 2022 15:23:26 -0300 Subject: [PATCH 11/56] Do not execute captures code for async fns --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 340f88e7540eb..6c0521da1ad4b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1877,7 +1877,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let context = ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), }; - self.lower_ty(ty, context, true) + self.lower_ty(ty, context, false) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; From 20c88a2a307f61441e797839d94058bfac152dc8 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 26 Jul 2022 15:30:58 -0300 Subject: [PATCH 12/56] Do not execute captures code when lowering lifetimes as GenericArg --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6c0521da1ad4b..bf1ced4f9630a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1423,7 +1423,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { |(_, (span, _, p_name, res))| { let id = self.next_node_id(); let ident = Ident::new(p_name.ident().name, span); - let l = self.new_named_lifetime_with_res(id, span, ident, res, true); + let l = self.new_named_lifetime_with_res(id, span, ident, res, false); hir::GenericArg::Lifetime(l) }, )); From 9f77688d1707dc6108803a3e1c4a6aa2747568a4 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 26 Jul 2022 15:50:25 -0300 Subject: [PATCH 13/56] Completely remove captures flag --- compiler/rustc_ast_lowering/src/asm.rs | 1 - compiler/rustc_ast_lowering/src/block.rs | 7 +- compiler/rustc_ast_lowering/src/expr.rs | 28 +--- compiler/rustc_ast_lowering/src/item.rs | 69 +++------ compiler/rustc_ast_lowering/src/lib.rs | 143 +++++++----------- compiler/rustc_ast_lowering/src/pat.rs | 3 - compiler/rustc_ast_lowering/src/path.rs | 34 ++--- .../rpit-assoc-pair-with-lifetime.rs | 7 + 8 files changed, 99 insertions(+), 193 deletions(-) create mode 100644 src/test/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 7d74007d1cb26..4166b4fc2e5bc 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -234,7 +234,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &sym.path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), - true, ); hir::InlineAsmOperand::SymStatic { path, def_id } } else { diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index d51393d88c032..7cbfe143b4d83 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -84,9 +84,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_local(&mut self, l: &Local) -> &'hir hir::Local<'hir> { - let ty = l.ty.as_ref().map(|t| { - self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable), true) - }); + let ty = l + .ty + .as_ref() + .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); let init = l.kind.init().map(|init| self.lower_expr(init)); let hir_id = self.lower_node_id(l.id); let pat = self.lower_pat(&l.pat); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b41140072418d..983efa48a4579 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -69,7 +69,6 @@ impl<'hir> LoweringContext<'_, 'hir> { ParamMode::Optional, ParenthesizedGenericArgs::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), - true, )); let args = self.lower_exprs(args); hir::ExprKind::MethodCall(hir_seg, args, self.lower_span(span)) @@ -90,20 +89,14 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Cast(ref expr, ref ty) => { let expr = self.lower_expr(expr); - let ty = self.lower_ty( - ty, - ImplTraitContext::Disallowed(ImplTraitPosition::Type), - true, - ); + let ty = + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ExprKind::Cast(expr, ty) } ExprKind::Type(ref expr, ref ty) => { let expr = self.lower_expr(expr); - let ty = self.lower_ty( - ty, - ImplTraitContext::Disallowed(ImplTraitPosition::Type), - true, - ); + let ty = + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ExprKind::Type(expr, ty) } ExprKind::AddrOf(k, m, ref ohs) => { @@ -233,7 +226,6 @@ impl<'hir> LoweringContext<'_, 'hir> { path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), - true, ); hir::ExprKind::Path(qpath) } @@ -272,7 +264,6 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), - true, )), self.arena .alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))), @@ -570,11 +561,9 @@ impl<'hir> LoweringContext<'_, 'hir> { body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> hir::ExprKind<'hir> { let output = match ret_ty { - Some(ty) => hir::FnRetTy::Return(self.lower_ty( - &ty, - ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock), - true, - )), + Some(ty) => hir::FnRetTy::Return( + self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)), + ), None => hir::FnRetTy::DefaultReturn(self.lower_span(span)), }; @@ -1178,7 +1167,6 @@ impl<'hir> LoweringContext<'_, 'hir> { path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), - true, ); // Destructure like a tuple struct. let tuple_struct_pat = @@ -1195,7 +1183,6 @@ impl<'hir> LoweringContext<'_, 'hir> { path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), - true, ); // Destructure like a unit struct. let unit_struct_pat = hir::PatKind::Path(qpath); @@ -1220,7 +1207,6 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), - true, ); let fields_omitted = match &se.rest { StructRest::Base(e) => { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 134876c2086f7..4cf0a8e0d2ed1 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -308,7 +308,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - |this| this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy, true), + |this| this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy), ); hir::ItemKind::TyAlias(ty, generics) } @@ -386,15 +386,11 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_trait_ref( trait_ref, ImplTraitContext::Disallowed(ImplTraitPosition::Trait), - true, ) }); - let lowered_ty = this.lower_ty( - ty, - ImplTraitContext::Disallowed(ImplTraitPosition::Type), - true, - ); + let lowered_ty = this + .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); (trait_ref, lowered_ty) }); @@ -438,7 +434,6 @@ impl<'hir> LoweringContext<'_, 'hir> { let bounds = this.lower_param_bounds( bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Bound), - true, ); let items = this.arena.alloc_from_iter( items.iter().map(|item| this.lower_trait_item_ref(item)), @@ -458,7 +453,6 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_param_bounds( bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Bound), - true, ) }, ); @@ -481,7 +475,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, body: Option<&Expr>, ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { - let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type), true); + let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); (ty, self.lower_const_body(span, body)) } @@ -667,11 +661,8 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) } ForeignItemKind::Static(ref t, m, _) => { - let ty = self.lower_ty( - t, - ImplTraitContext::Disallowed(ImplTraitPosition::Type), - true, - ); + let ty = + self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ForeignItemKind::Static(ty, m) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, @@ -740,11 +731,10 @@ impl<'hir> LoweringContext<'_, 'hir> { path, ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124) ImplTraitContext::Disallowed(ImplTraitPosition::Path), - true, ); self.arena.alloc(t) } else { - self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type), true) + self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) }; let hir_id = self.lower_node_id(f.id); self.lower_attrs(hir_id, &f.attrs); @@ -767,8 +757,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind, has_default) = match i.kind { AssocItemKind::Const(_, ref ty, ref default) => { - let ty = - self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type), true); + let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) } @@ -806,17 +795,12 @@ impl<'hir> LoweringContext<'_, 'hir> { ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let ty = ty.as_ref().map(|x| { - this.lower_ty( - x, - ImplTraitContext::Disallowed(ImplTraitPosition::Type), - true, - ) + this.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) }); hir::TraitItemKind::Type( this.lower_param_bounds( bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - true, ), ty, ) @@ -869,8 +853,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = match &i.kind { AssocItemKind::Const(_, ty, expr) => { - let ty = - self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type), true); + let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); ( hir::Generics::empty(), hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())), @@ -904,7 +887,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ImplItemKind::TyAlias(ty) } Some(ty) => { - let ty = this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy, true); + let ty = this.lower_ty(ty, ImplTraitContext::TypeAliasesOpaqueTy); hir::ImplItemKind::TyAlias(ty) } }, @@ -1429,7 +1412,7 @@ impl<'hir> LoweringContext<'_, 'hir> { return None; } - let bounds = self.lower_param_bounds(bounds, itctx, true); + let bounds = self.lower_param_bounds(bounds, itctx); let ident = self.lower_ident(ident); let param_span = ident.span; @@ -1475,8 +1458,7 @@ impl<'hir> LoweringContext<'_, 'hir> { panic!("Missing resolution for lifetime {:?} at {:?}", id, ident.span) }); let lt_id = self.next_node_id(); - let lifetime = - self.new_named_lifetime_with_res(lt_id, ident_span, ident, res, true); + let lifetime = self.new_named_lifetime_with_res(lt_id, ident_span, ident, res); Some(hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { lifetime, span, @@ -1496,16 +1478,12 @@ impl<'hir> LoweringContext<'_, 'hir> { span, }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { bound_generic_params: self.lower_generic_params(bound_generic_params), - bounded_ty: self.lower_ty( - bounded_ty, - ImplTraitContext::Disallowed(ImplTraitPosition::Type), - true, - ), + bounded_ty: self + .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| { self.lower_param_bound( bound, ImplTraitContext::Disallowed(ImplTraitPosition::Bound), - true, ) })), span: self.lower_span(span), @@ -1517,27 +1495,20 @@ impl<'hir> LoweringContext<'_, 'hir> { span, }) => hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { span: self.lower_span(span), - lifetime: self.lower_lifetime(lifetime, true), + lifetime: self.lower_lifetime(lifetime), bounds: self.lower_param_bounds( bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Bound), - true, ), in_where_clause: true, }), WherePredicate::EqPredicate(WhereEqPredicate { id, ref lhs_ty, ref rhs_ty, span }) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { hir_id: self.lower_node_id(id), - lhs_ty: self.lower_ty( - lhs_ty, - ImplTraitContext::Disallowed(ImplTraitPosition::Type), - true, - ), - rhs_ty: self.lower_ty( - rhs_ty, - ImplTraitContext::Disallowed(ImplTraitPosition::Type), - true, - ), + lhs_ty: self + .lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + rhs_ty: self + .lower_ty(rhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), span: self.lower_span(span), }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index bf1ced4f9630a..4ca771bf4738c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -932,7 +932,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let kind = match constraint.kind { AssocConstraintKind::Equality { ref term } => { let term = match term { - Term::Ty(ref ty) => self.lower_ty(ty, itctx, true).into(), + Term::Ty(ref ty) => self.lower_ty(ty, itctx).into(), Term::Const(ref c) => self.lower_anon_const(c).into(), }; hir::TypeBindingKind::Equality { term } @@ -997,7 +997,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { tokens: None, }, itctx, - true, ); hir::TypeBindingKind::Equality { term: ty.into() } @@ -1005,7 +1004,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { // Desugar `AssocTy: Bounds` into a type binding where the // later desugars into a trait predicate. - let bounds = self.lower_param_bounds(bounds, itctx, true); + let bounds = self.lower_param_bounds(bounds, itctx); hir::TypeBindingKind::Constraint { bounds } } @@ -1064,7 +1063,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx: ImplTraitContext, ) -> hir::GenericArg<'hir> { match arg { - ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<, true)), + ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), ast::GenericArg::Type(ty) => { match ty.kind { TyKind::Infer if self.tcx.features().generic_arg_infer => { @@ -1113,7 +1112,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } _ => {} } - GenericArg::Type(self.lower_ty_direct(&ty, itctx, true)) + GenericArg::Type(self.lower_ty_direct(&ty, itctx)) } ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg { value: self.lower_anon_const(&ct), @@ -1123,8 +1122,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "debug", skip(self))] - fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext, captures: bool) -> &'hir hir::Ty<'hir> { - self.arena.alloc(self.lower_ty_direct(t, itctx, captures)) + fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> { + self.arena.alloc(self.lower_ty_direct(t, itctx)) } fn lower_path_ty( @@ -1134,7 +1133,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { path: &Path, param_mode: ParamMode, itctx: ImplTraitContext, - captures: bool, ) -> hir::Ty<'hir> { // Check whether we should interpret this as a bare trait object. // This check mirrors the one in late resolution. We only introduce this special case in @@ -1154,7 +1152,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: t.span }, itctx, - captures, ); let bounds = this.arena.alloc_from_iter([bound]); let lifetime_bound = this.elided_dyn_bound(t.span); @@ -1165,7 +1162,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let id = self.lower_node_id(t.id); - let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx, true); + let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx); self.ty_path(id, t.span, qpath) } @@ -1177,16 +1174,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.ty(span, hir::TyKind::Tup(tys)) } - fn lower_ty_direct( - &mut self, - t: &Ty, - itctx: ImplTraitContext, - captures: bool, - ) -> hir::Ty<'hir> { + fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> { let kind = match t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => hir::TyKind::Err, - TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx, captures)), + TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), TyKind::Rptr(ref region, ref mt) => { let region = region.unwrap_or_else(|| { @@ -1201,7 +1193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let span = self.tcx.sess.source_map().next_point(t.span.shrink_to_lo()); Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id } }); - let lifetime = self.lower_lifetime(®ion, captures); + let lifetime = self.lower_lifetime(®ion); hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx)) } TyKind::BareFn(ref f) => { @@ -1216,16 +1208,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) } TyKind::Never => hir::TyKind::Never, - TyKind::Tup(ref tys) => { - hir::TyKind::Tup(self.arena.alloc_from_iter( - tys.iter().map(|ty| self.lower_ty_direct(ty, itctx, captures)), - )) - } + TyKind::Tup(ref tys) => hir::TyKind::Tup( + self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))), + ), TyKind::Paren(ref ty) => { - return self.lower_ty_direct(ty, itctx, captures); + return self.lower_ty_direct(ty, itctx); } TyKind::Path(ref qself, ref path) => { - return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx, captures); + return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx); } TyKind::ImplicitSelf => { let res = self.expect_full_res(t.id); @@ -1241,10 +1231,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), )) } - TyKind::Array(ref ty, ref length) => hir::TyKind::Array( - self.lower_ty(ty, itctx, captures), - self.lower_array_length(length), - ), + TyKind::Array(ref ty, ref length) => { + hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length)) + } TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)), TyKind::TraitObject(ref bounds, kind) => { let mut lifetime_bound = None; @@ -1255,7 +1244,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericBound::Trait( ref ty, TraitBoundModifier::None | TraitBoundModifier::MaybeConst, - ) => Some(this.lower_poly_trait_ref(ty, itctx, captures)), + ) => Some(this.lower_poly_trait_ref(ty, itctx)), // `~const ?Bound` will cause an error during AST validation // anyways, so treat it like `?Bound` as compilation proceeds. GenericBound::Trait( @@ -1264,7 +1253,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) => None, GenericBound::Outlives(ref lifetime) => { if lifetime_bound.is_none() { - lifetime_bound = Some(this.lower_lifetime(lifetime, true)); + lifetime_bound = Some(this.lower_lifetime(lifetime)); } None } @@ -1350,7 +1339,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut collected_lifetimes = FxHashMap::default(); self.with_hir_id_owner(opaque_ty_node_id, |lctx| { let hir_bounds = if origin == hir::OpaqueTyOrigin::TyAlias { - lctx.lower_param_bounds(bounds, itctx, true) + lctx.lower_param_bounds(bounds, itctx) } else { debug!(?lctx.captured_lifetimes); @@ -1369,7 +1358,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lctx.create_and_capture_lifetime_defs(&lifetimes_in_bounds, &binders_to_ignore); - let ret = lctx.lower_param_bounds(bounds, itctx, false); + let ret = lctx.lower_param_bounds(bounds, itctx); let ctxt = std::mem::replace(&mut lctx.captured_lifetimes, lifetime_stash).unwrap(); @@ -1423,7 +1412,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { |(_, (span, _, p_name, res))| { let id = self.next_node_id(); let ident = Ident::new(p_name.ident().name, span); - let l = self.new_named_lifetime_with_res(id, span, ident, res, false); + let l = self.new_named_lifetime_with_res(id, span, ident, res); hir::GenericArg::Lifetime(l) }, )); @@ -1579,7 +1568,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { if fn_node_id.is_some() { - self.lower_ty_direct(¶m.ty, ImplTraitContext::Universal, true) + self.lower_ty_direct(¶m.ty, ImplTraitContext::Universal) } else { self.lower_ty_direct( ¶m.ty, @@ -1593,7 +1582,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnDeclKind::Trait => ImplTraitPosition::TraitParam, FnDeclKind::Impl => ImplTraitPosition::ImplParam, }), - true, ) } })); @@ -1625,7 +1613,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnDeclKind::Impl => ImplTraitPosition::ImplReturn, }), }; - hir::FnRetTy::Return(self.lower_ty(ty, context, true)) + hir::FnRetTy::Return(self.lower_ty(ty, context)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)), } @@ -1847,7 +1835,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc_from_iter(captures.into_iter().map(|(_, (span, _, p_name, res))| { let id = self.next_node_id(); let ident = Ident::new(p_name.ident().name, span); - let l = self.new_named_lifetime_with_res(id, span, ident, res, true); + let l = self.new_named_lifetime_with_res(id, span, ident, res); hir::GenericArg::Lifetime(l) })); @@ -1877,7 +1865,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let context = ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), }; - self.lower_ty(ty, context, false) + self.lower_ty(ty, context) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; @@ -1904,24 +1892,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, tpb: &GenericBound, itctx: ImplTraitContext, - captures: bool, ) -> hir::GenericBound<'hir> { match tpb { GenericBound::Trait(p, modifier) => hir::GenericBound::Trait( - self.lower_poly_trait_ref(p, itctx, captures), + self.lower_poly_trait_ref(p, itctx), self.lower_trait_bound_modifier(*modifier), ), GenericBound::Outlives(lifetime) => { - hir::GenericBound::Outlives(self.lower_lifetime(lifetime, captures)) + hir::GenericBound::Outlives(self.lower_lifetime(lifetime)) } } } - fn lower_lifetime(&mut self, l: &Lifetime, captures: bool) -> hir::Lifetime { + fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { let span = self.lower_span(l.ident.span); let ident = self.lower_ident(l.ident); let res = self.resolver.get_lifetime_res(l.id).unwrap_or(LifetimeRes::Error); - self.new_named_lifetime_with_res(l.id, span, ident, res, captures) + self.new_named_lifetime_with_res(l.id, span, ident, res) } #[tracing::instrument(level = "debug", skip(self))] @@ -1931,7 +1918,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, ident: Ident, res: LifetimeRes, - captures: bool, ) -> hir::Lifetime { debug!(?self.captured_lifetimes); @@ -1939,29 +1925,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Param { mut param, binder } => { let p_name = ParamName::Plain(ident); if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { - if captures { - if !captured_lifetimes.binders_to_ignore.contains(&binder) { - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(o) => param = self.local_def_id(o.get().1), - Entry::Vacant(v) => { - let p_id = self.next_node_id(); + if !captured_lifetimes.binders_to_ignore.contains(&binder) { + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(o) => param = self.local_def_id(o.get().1), + Entry::Vacant(v) => { + let p_id = self.next_node_id(); - let p_def_id = self.create_def( - captured_lifetimes.parent_def_id, - p_id, - DefPathData::LifetimeNs(p_name.ident().name), - ); + let p_def_id = self.create_def( + captured_lifetimes.parent_def_id, + p_id, + DefPathData::LifetimeNs(p_name.ident().name), + ); - v.insert((span, p_id, p_name, res)); - param = p_def_id; - } + v.insert((span, p_id, p_name, res)); + param = p_def_id; } } - } else { - if let Entry::Occupied(o) = captured_lifetimes.captures.entry(param) { - param = self.local_def_id(o.get().1); - } } + self.captured_lifetimes = Some(captured_lifetimes); } @@ -2054,11 +2035,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericParamKind::Type { ref default, .. } => { let kind = hir::GenericParamKind::Type { default: default.as_ref().map(|x| { - self.lower_ty( - x, - ImplTraitContext::Disallowed(ImplTraitPosition::Type), - true, - ) + self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type)) }), synthetic: false, }; @@ -2066,8 +2043,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Plain(self.lower_ident(param.ident)), kind) } GenericParamKind::Const { ref ty, kw_span: _, ref default } => { - let ty = - self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type), true); + let ty = self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let default = default.as_ref().map(|def| self.lower_anon_const(def)); ( hir::ParamName::Plain(self.lower_ident(param.ident)), @@ -2077,20 +2053,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_trait_ref( - &mut self, - p: &TraitRef, - itctx: ImplTraitContext, - captures: bool, - ) -> hir::TraitRef<'hir> { - let path = match self.lower_qpath( - p.ref_id, - &None, - &p.path, - ParamMode::Explicit, - itctx, - captures, - ) { + fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext) -> hir::TraitRef<'hir> { + let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) { hir::QPath::Resolved(None, path) => path, qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath), }; @@ -2102,38 +2066,35 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, p: &PolyTraitRef, itctx: ImplTraitContext, - captures: bool, ) -> hir::PolyTraitRef<'hir> { self.with_lifetime_binder( p.trait_ref.ref_id, &p.bound_generic_params, |this, bound_generic_params| { - let trait_ref = this.lower_trait_ref(&p.trait_ref, itctx, captures); + let trait_ref = this.lower_trait_ref(&p.trait_ref, itctx); hir::PolyTraitRef { bound_generic_params, trait_ref, span: this.lower_span(p.span) } }, ) } fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { - hir::MutTy { ty: self.lower_ty(&mt.ty, itctx, true), mutbl: mt.mutbl } + hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl } } fn lower_param_bounds( &mut self, bounds: &[GenericBound], itctx: ImplTraitContext, - captures: bool, ) -> hir::GenericBounds<'hir> { - self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx, captures)) + self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) } fn lower_param_bounds_mut<'s>( &'s mut self, bounds: &'s [GenericBound], itctx: ImplTraitContext, - captures: bool, ) -> impl Iterator> + Captures<'s> + Captures<'a> { - bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx, captures)) + bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) } fn lower_generic_and_bounds( diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index b995b1b649d39..bd2e76e5528da 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -36,7 +36,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), - true, ); let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); break hir::PatKind::TupleStruct(qpath, pats, ddpos); @@ -53,7 +52,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), - true, ); break hir::PatKind::Path(qpath); } @@ -64,7 +62,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { path, ParamMode::Optional, ImplTraitContext::Disallowed(ImplTraitPosition::Path), - true, ); let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::PatField { diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 02e5816593cbd..393be3b454c37 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -24,10 +24,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p: &Path, param_mode: ParamMode, itctx: ImplTraitContext, - captures: bool, ) -> hir::QPath<'hir> { let qself_position = qself.as_ref().map(|q| q.position); - let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx, captures)); + let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); let partial_res = self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err)); @@ -73,7 +72,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode, parenthesized_generic_args, itctx, - captures, ) }, )), @@ -120,7 +118,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode, ParenthesizedGenericArgs::Err, itctx, - captures, )); let qpath = hir::QPath::TypeRelative(ty, hir_segment); @@ -161,7 +158,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode, ParenthesizedGenericArgs::Err, ImplTraitContext::Disallowed(ImplTraitPosition::Path), - true, ) })), span: self.lower_span(p.span), @@ -186,7 +182,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode: ParamMode, parenthesized_generic_args: ParenthesizedGenericArgs, itctx: ImplTraitContext, - captures: bool, ) -> hir::PathSegment<'hir> { debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,); let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args { @@ -259,7 +254,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment.id, segment.ident.span, &mut generic_args, - captures, ); } @@ -289,7 +283,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment_id: NodeId, segment_ident_span: Span, generic_args: &mut GenericArgsCtor<'hir>, - captures: bool, ) { let (start, end) = match self.resolver.get_lifetime_res(segment_id) { Some(LifetimeRes::ElidedAnchor { start, end }) => (start, end), @@ -318,13 +311,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { 0, (start.as_u32()..end.as_u32()).map(|i| { let id = NodeId::from_u32(i); - let l = self.lower_lifetime( - &Lifetime { - id, - ident: Ident::new(kw::UnderscoreLifetime, elided_lifetime_span), - }, - captures, - ); + let l = self.lower_lifetime(&Lifetime { + id, + ident: Ident::new(kw::UnderscoreLifetime, elided_lifetime_span), + }); GenericArg::Lifetime(l) }), ); @@ -368,18 +358,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // we generally don't permit such things (see #51008). let ParenthesizedArgs { span, inputs, inputs_span, output } = data; let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| { - self.lower_ty_direct( - ty, - ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam), - true, - ) + self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) })); let output_ty = match output { - FnRetTy::Ty(ty) => self.lower_ty( - &ty, - ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn), - true, - ), + FnRetTy::Ty(ty) => { + self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) + } FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), }; let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))]; diff --git a/src/test/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs b/src/test/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs new file mode 100644 index 0000000000000..a4e603de1ac24 --- /dev/null +++ b/src/test/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs @@ -0,0 +1,7 @@ +// check-pass + +pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { + v.into_iter() +} + +fn main() {} From 4f334f2b970c3149365d4d98f02090d52767e44f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 29 Jul 2022 22:38:07 -0300 Subject: [PATCH 14/56] Move LifetimeCollectVisitor to rustc_ast_lowering --- compiler/rustc_ast/src/ast.rs | 59 ------------------ compiler/rustc_ast_lowering/src/lib.rs | 7 ++- .../src/lifetime_collector.rs | 62 +++++++++++++++++++ 3 files changed, 67 insertions(+), 61 deletions(-) create mode 100644 compiler/rustc_ast_lowering/src/lifetime_collector.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 3503e5de8ccdb..870a7c0be33dc 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -25,9 +25,7 @@ pub use UnsafeSource::*; use crate::ptr::P; use crate::token::{self, CommentKind, Delimiter}; use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream}; -use crate::visit::{self, BoundKind, LifetimeCtxt, Visitor}; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; @@ -325,63 +323,6 @@ impl GenericBound { pub type GenericBounds = Vec; -struct LifetimeCollectVisitor<'ast> { - current_binders: Vec, - binders_to_ignore: FxHashMap>, - collected_lifetimes: Vec<&'ast Lifetime>, -} - -impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { - fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) { - if !self.collected_lifetimes.contains(&lifetime) { - self.collected_lifetimes.push(lifetime); - } - self.binders_to_ignore.insert(lifetime.id, self.current_binders.clone()); - } - - fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { - self.current_binders.push(t.trait_ref.ref_id); - - visit::walk_poly_trait_ref(self, t, m); - - self.current_binders.pop(); - } - - fn visit_ty(&mut self, t: &'ast Ty) { - if let TyKind::BareFn(_) = t.kind { - self.current_binders.push(t.id); - } - visit::walk_ty(self, t); - if let TyKind::BareFn(_) = t.kind { - self.current_binders.pop(); - } - } -} - -pub fn lifetimes_in_ret_ty(ret_ty: &FnRetTy) -> (Vec<&Lifetime>, FxHashMap>) { - let mut visitor = LifetimeCollectVisitor { - current_binders: Vec::new(), - binders_to_ignore: FxHashMap::default(), - collected_lifetimes: Vec::new(), - }; - visitor.visit_fn_ret_ty(ret_ty); - (visitor.collected_lifetimes, visitor.binders_to_ignore) -} - -pub fn lifetimes_in_bounds( - bounds: &GenericBounds, -) -> (Vec<&Lifetime>, FxHashMap>) { - let mut visitor = LifetimeCollectVisitor { - current_binders: Vec::new(), - binders_to_ignore: FxHashMap::default(), - collected_lifetimes: Vec::new(), - }; - for bound in bounds { - visitor.visit_param_bound(bound, BoundKind::Bound); - } - (visitor.collected_lifetimes, visitor.binders_to_ignore) -} - /// Specifies the enforced ordering for generic parameters. In the future, /// if we wanted to relax this order, we could override `PartialEq` and /// `PartialOrd`, to allow the kinds to be unordered. diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4ca771bf4738c..2883299291e3a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -77,6 +77,7 @@ mod block; mod expr; mod index; mod item; +mod lifetime_collector; mod pat; mod path; @@ -1352,7 +1353,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), ); - let (lifetimes_in_bounds, binders_to_ignore) = ast::lifetimes_in_bounds(bounds); + let (lifetimes_in_bounds, binders_to_ignore) = + lifetime_collector::lifetimes_in_bounds(bounds); debug!(?lifetimes_in_bounds); debug!(?binders_to_ignore); @@ -1756,7 +1758,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), ); - let (lifetimes_in_bounds, binders_to_ignore) = ast::lifetimes_in_ret_ty(output); + let (lifetimes_in_bounds, binders_to_ignore) = + lifetime_collector::lifetimes_in_ret_ty(output); debug!(?lifetimes_in_bounds); debug!(?binders_to_ignore); diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs new file mode 100644 index 0000000000000..1dab8799ae5f4 --- /dev/null +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -0,0 +1,62 @@ +use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor}; +use rustc_ast::{ + FnRetTy, GenericBounds, Lifetime, NodeId, PolyTraitRef, TraitBoundModifier, Ty, TyKind, +}; +use rustc_data_structures::fx::FxHashMap; + +struct LifetimeCollectVisitor<'ast> { + current_binders: Vec, + binders_to_ignore: FxHashMap>, + collected_lifetimes: Vec<&'ast Lifetime>, +} + +impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { + fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) { + if !self.collected_lifetimes.contains(&lifetime) { + self.collected_lifetimes.push(lifetime); + } + self.binders_to_ignore.insert(lifetime.id, self.current_binders.clone()); + } + + fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { + self.current_binders.push(t.trait_ref.ref_id); + + visit::walk_poly_trait_ref(self, t, m); + + self.current_binders.pop(); + } + + fn visit_ty(&mut self, t: &'ast Ty) { + if let TyKind::BareFn(_) = t.kind { + self.current_binders.push(t.id); + } + visit::walk_ty(self, t); + if let TyKind::BareFn(_) = t.kind { + self.current_binders.pop(); + } + } +} + +pub fn lifetimes_in_ret_ty(ret_ty: &FnRetTy) -> (Vec<&Lifetime>, FxHashMap>) { + let mut visitor = LifetimeCollectVisitor { + current_binders: Vec::new(), + binders_to_ignore: FxHashMap::default(), + collected_lifetimes: Vec::new(), + }; + visitor.visit_fn_ret_ty(ret_ty); + (visitor.collected_lifetimes, visitor.binders_to_ignore) +} + +pub fn lifetimes_in_bounds( + bounds: &GenericBounds, +) -> (Vec<&Lifetime>, FxHashMap>) { + let mut visitor = LifetimeCollectVisitor { + current_binders: Vec::new(), + binders_to_ignore: FxHashMap::default(), + collected_lifetimes: Vec::new(), + }; + for bound in bounds { + visitor.visit_param_bound(bound, BoundKind::Bound); + } + (visitor.collected_lifetimes, visitor.binders_to_ignore) +} From 05b989e16e7c6a7d4364f33f2612e540a50b1a27 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 1 Aug 2022 16:03:49 -0300 Subject: [PATCH 15/56] Skip lifetimes in binders when visiting --- compiler/rustc_ast_lowering/src/lib.rs | 92 ++++++++----------- .../src/lifetime_collector.rs | 53 ++++++----- compiler/rustc_hir/src/def.rs | 9 ++ 3 files changed, 76 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 2883299291e3a..c21afa26f4fe5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1353,12 +1353,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), ); - let (lifetimes_in_bounds, binders_to_ignore) = - lifetime_collector::lifetimes_in_bounds(bounds); + let lifetimes_in_bounds = + lifetime_collector::lifetimes_in_bounds(&lctx.resolver, bounds); debug!(?lifetimes_in_bounds); - debug!(?binders_to_ignore); - lctx.create_and_capture_lifetime_defs(&lifetimes_in_bounds, &binders_to_ignore); + lctx.create_and_capture_lifetime_defs(&lifetimes_in_bounds); let ret = lctx.lower_param_bounds(bounds, itctx); @@ -1447,11 +1446,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item)) } - fn create_and_capture_lifetime_defs( - &mut self, - lifetimes_in_bounds: &[&Lifetime], - binders_to_ignore: &FxHashMap>, - ) { + fn create_and_capture_lifetime_defs(&mut self, lifetimes_in_bounds: &[&Lifetime]) { for lifetime in lifetimes_in_bounds { let ident = lifetime.ident; let span = ident.span; @@ -1461,53 +1456,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { match res { - LifetimeRes::Param { param, binder } => { - if !binders_to_ignore - .get(&lifetime.id) - .unwrap_or(&Vec::new()) - .contains(&binder) - { - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(_) => {} - Entry::Vacant(v) => { - let node_id = self.next_node_id(); - let name = ParamName::Plain(ident); - - self.create_def( - captured_lifetimes.parent_def_id, - node_id, - DefPathData::LifetimeNs(name.ident().name), - ); - - v.insert((span, node_id, name, res)); - } + LifetimeRes::Param { param, binder: _ } => { + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(_) => {} + Entry::Vacant(v) => { + let node_id = self.next_node_id(); + let name = ParamName::Plain(ident); + + self.create_def( + captured_lifetimes.parent_def_id, + node_id, + DefPathData::LifetimeNs(name.ident().name), + ); + + v.insert((span, node_id, name, res)); } } } - LifetimeRes::Fresh { param, binder } => { + LifetimeRes::Fresh { param, binder: _ } => { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); - if !binders_to_ignore - .get(&lifetime.id) - .unwrap_or(&Vec::new()) - .contains(&binder) - { - let param = self.local_def_id(param); - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(_) => {} - Entry::Vacant(v) => { - let node_id = self.next_node_id(); - - let name = ParamName::Fresh; - - self.create_def( - captured_lifetimes.parent_def_id, - node_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ); - - v.insert((span, node_id, name, res)); - } + let param = self.local_def_id(param); + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(_) => {} + Entry::Vacant(v) => { + let node_id = self.next_node_id(); + + let name = ParamName::Fresh; + + self.create_def( + captured_lifetimes.parent_def_id, + node_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ); + + v.insert((span, node_id, name, res)); } } } @@ -1758,12 +1741,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), ); - let (lifetimes_in_bounds, binders_to_ignore) = - lifetime_collector::lifetimes_in_ret_ty(output); + let lifetimes_in_bounds = + lifetime_collector::lifetimes_in_ret_ty(&this.resolver, output); debug!(?lifetimes_in_bounds); - debug!(?binders_to_ignore); - this.create_and_capture_lifetime_defs(&lifetimes_in_bounds, &binders_to_ignore); + this.create_and_capture_lifetime_defs(&lifetimes_in_bounds); // We have to be careful to get elision right here. The // idea is that we create a lifetime parameter for each diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 1dab8799ae5f4..f67cbd69e4749 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -1,21 +1,32 @@ +use super::ResolverAstLoweringExt; use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor}; use rustc_ast::{ FnRetTy, GenericBounds, Lifetime, NodeId, PolyTraitRef, TraitBoundModifier, Ty, TyKind, }; -use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def::LifetimeRes; +use rustc_middle::ty::ResolverAstLowering; -struct LifetimeCollectVisitor<'ast> { +struct LifetimeCollectVisitor<'this, 'ast: 'this> { + resolver: &'this ResolverAstLowering, current_binders: Vec, - binders_to_ignore: FxHashMap>, collected_lifetimes: Vec<&'ast Lifetime>, } -impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { +impl<'this, 'ast: 'this> LifetimeCollectVisitor<'this, 'ast> { + fn new(resolver: &'this ResolverAstLowering) -> Self { + Self { resolver, current_binders: Vec::new(), collected_lifetimes: Vec::new() } + } +} + +impl<'this, 'ast: 'this> Visitor<'ast> for LifetimeCollectVisitor<'this, 'ast> { fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) { - if !self.collected_lifetimes.contains(&lifetime) { - self.collected_lifetimes.push(lifetime); + let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error); + + if res.binder().map_or(true, |b| !self.current_binders.contains(&b)) { + if !self.collected_lifetimes.contains(&lifetime) { + self.collected_lifetimes.push(lifetime); + } } - self.binders_to_ignore.insert(lifetime.id, self.current_binders.clone()); } fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { @@ -37,26 +48,22 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { } } -pub fn lifetimes_in_ret_ty(ret_ty: &FnRetTy) -> (Vec<&Lifetime>, FxHashMap>) { - let mut visitor = LifetimeCollectVisitor { - current_binders: Vec::new(), - binders_to_ignore: FxHashMap::default(), - collected_lifetimes: Vec::new(), - }; +pub fn lifetimes_in_ret_ty<'this, 'ast: 'this>( + resolver: &'this ResolverAstLowering, + ret_ty: &'ast FnRetTy, +) -> Vec<&'ast Lifetime> { + let mut visitor = LifetimeCollectVisitor::new(resolver); visitor.visit_fn_ret_ty(ret_ty); - (visitor.collected_lifetimes, visitor.binders_to_ignore) + visitor.collected_lifetimes } -pub fn lifetimes_in_bounds( - bounds: &GenericBounds, -) -> (Vec<&Lifetime>, FxHashMap>) { - let mut visitor = LifetimeCollectVisitor { - current_binders: Vec::new(), - binders_to_ignore: FxHashMap::default(), - collected_lifetimes: Vec::new(), - }; +pub fn lifetimes_in_bounds<'this, 'ast: 'this>( + resolver: &'this ResolverAstLowering, + bounds: &'ast GenericBounds, +) -> Vec<&'ast Lifetime> { + let mut visitor = LifetimeCollectVisitor::new(resolver); for bound in bounds { visitor.visit_param_bound(bound, BoundKind::Bound); } - (visitor.collected_lifetimes, visitor.binders_to_ignore) + visitor.collected_lifetimes } diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index be5b7eccbafb2..2a89947f92762 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -747,3 +747,12 @@ pub enum LifetimeRes { /// HACK: This is used to recover the NodeId of an elided lifetime. ElidedAnchor { start: NodeId, end: NodeId }, } + +impl LifetimeRes { + pub fn binder(&self) -> Option { + match self { + LifetimeRes::Param { binder, .. } | LifetimeRes::Fresh { binder, .. } => Some(*binder), + _ => None, + } + } +} From 81c4d2371aab4636c56ac5d61d391ae195d8bb0a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 11:00:34 -0300 Subject: [PATCH 16/56] Restructure visit_ty in a more clear way --- .../rustc_ast_lowering/src/lifetime_collector.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index f67cbd69e4749..586436240f124 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -38,12 +38,15 @@ impl<'this, 'ast: 'this> Visitor<'ast> for LifetimeCollectVisitor<'this, 'ast> { } fn visit_ty(&mut self, t: &'ast Ty) { - if let TyKind::BareFn(_) = t.kind { - self.current_binders.push(t.id); - } - visit::walk_ty(self, t); - if let TyKind::BareFn(_) = t.kind { - self.current_binders.pop(); + match t.kind { + TyKind::BareFn(_) => { + self.current_binders.push(t.id); + visit::walk_ty(self, t); + self.current_binders.pop(); + } + _ => { + visit::walk_ty(self, t); + } } } } From 1802d45b1238409d2c29cf7e8f25a96b94874fe2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 11:03:29 -0300 Subject: [PATCH 17/56] Record RPITs elided lifetimes in path segments --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- .../src/lifetime_collector.rs | 51 ++++++++++++------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c21afa26f4fe5..6cf938a242e54 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1446,7 +1446,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item)) } - fn create_and_capture_lifetime_defs(&mut self, lifetimes_in_bounds: &[&Lifetime]) { + fn create_and_capture_lifetime_defs(&mut self, lifetimes_in_bounds: &[Lifetime]) { for lifetime in lifetimes_in_bounds { let ident = lifetime.ident; let span = ident.span; diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 586436240f124..51fa7075d3450 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -1,25 +1,26 @@ use super::ResolverAstLoweringExt; use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor}; use rustc_ast::{ - FnRetTy, GenericBounds, Lifetime, NodeId, PolyTraitRef, TraitBoundModifier, Ty, TyKind, + FnRetTy, GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, TraitBoundModifier, Ty, + TyKind, }; use rustc_hir::def::LifetimeRes; use rustc_middle::ty::ResolverAstLowering; +use rustc_span::symbol::{kw, Ident}; +use rustc_span::Span; -struct LifetimeCollectVisitor<'this, 'ast: 'this> { - resolver: &'this ResolverAstLowering, +struct LifetimeCollectVisitor<'ast> { + resolver: &'ast ResolverAstLowering, current_binders: Vec, - collected_lifetimes: Vec<&'ast Lifetime>, + collected_lifetimes: Vec, } -impl<'this, 'ast: 'this> LifetimeCollectVisitor<'this, 'ast> { - fn new(resolver: &'this ResolverAstLowering) -> Self { +impl<'ast> LifetimeCollectVisitor<'ast> { + fn new(resolver: &'ast ResolverAstLowering) -> Self { Self { resolver, current_binders: Vec::new(), collected_lifetimes: Vec::new() } } -} -impl<'this, 'ast: 'this> Visitor<'ast> for LifetimeCollectVisitor<'this, 'ast> { - fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) { + fn record_lifetime_use(&mut self, lifetime: Lifetime) { let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error); if res.binder().map_or(true, |b| !self.current_binders.contains(&b)) { @@ -28,6 +29,25 @@ impl<'this, 'ast: 'this> Visitor<'ast> for LifetimeCollectVisitor<'this, 'ast> { } } } +} + +impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { + fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) { + self.record_lifetime_use(*lifetime); + } + + fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) { + if let Some(LifetimeRes::ElidedAnchor { start, end }) = + self.resolver.get_lifetime_res(path_segment.id) + { + for i in start..end { + let lifetime = + Lifetime { id: i, ident: Ident::new(kw::UnderscoreLifetime, path_span) }; + self.record_lifetime_use(lifetime); + } + } + visit::walk_path_segment(self, path_span, path_segment); + } fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { self.current_binders.push(t.trait_ref.ref_id); @@ -51,19 +71,16 @@ impl<'this, 'ast: 'this> Visitor<'ast> for LifetimeCollectVisitor<'this, 'ast> { } } -pub fn lifetimes_in_ret_ty<'this, 'ast: 'this>( - resolver: &'this ResolverAstLowering, - ret_ty: &'ast FnRetTy, -) -> Vec<&'ast Lifetime> { +pub fn lifetimes_in_ret_ty(resolver: &ResolverAstLowering, ret_ty: &FnRetTy) -> Vec { let mut visitor = LifetimeCollectVisitor::new(resolver); visitor.visit_fn_ret_ty(ret_ty); visitor.collected_lifetimes } -pub fn lifetimes_in_bounds<'this, 'ast: 'this>( - resolver: &'this ResolverAstLowering, - bounds: &'ast GenericBounds, -) -> Vec<&'ast Lifetime> { +pub fn lifetimes_in_bounds( + resolver: &ResolverAstLowering, + bounds: &GenericBounds, +) -> Vec { let mut visitor = LifetimeCollectVisitor::new(resolver); for bound in bounds { visitor.visit_param_bound(bound, BoundKind::Bound); From c390bda356905a2227591a1cf5cc49f618309ad6 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 15:06:12 -0300 Subject: [PATCH 18/56] Record RPITs elided lifetimes in Rptr Tys --- .../rustc_ast_lowering/src/lifetime_collector.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 51fa7075d3450..4a7106f8da0ad 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -64,6 +64,18 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { visit::walk_ty(self, t); self.current_binders.pop(); } + TyKind::Rptr(None, _) => { + if let Some(LifetimeRes::ElidedAnchor { start, end }) = + self.resolver.get_lifetime_res(t.id) + { + for i in start..end { + let lifetime = + Lifetime { id: i, ident: Ident::new(kw::UnderscoreLifetime, t.span) }; + self.record_lifetime_use(lifetime); + } + } + visit::walk_ty(self, t); + } _ => { visit::walk_ty(self, t); } From 14ea17858d0c222d24b0a7569d7a7aed933c57b9 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 11:39:40 -0300 Subject: [PATCH 19/56] Fail if LifetimeRes is Infer when creating def ids for lifetimes copies --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6cf938a242e54..a63badc897d28 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1495,7 +1495,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - LifetimeRes::Infer | LifetimeRes::Static | LifetimeRes::Error => {} + LifetimeRes::Static | LifetimeRes::Error => {} res => panic!( "Unexpected lifetime resolution {:?} for {:?} at {:?}", From 3030ab3074e3517e22d282bae8c2613ae0e1a54b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 15:14:42 -0300 Subject: [PATCH 20/56] new_named_lifetime_with_res's LifetimeRes::Param should have created def_id already --- compiler/rustc_ast_lowering/src/lib.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a63badc897d28..28b1527ca5f36 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1913,17 +1913,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if !captured_lifetimes.binders_to_ignore.contains(&binder) { match captured_lifetimes.captures.entry(param) { Entry::Occupied(o) => param = self.local_def_id(o.get().1), - Entry::Vacant(v) => { - let p_id = self.next_node_id(); - - let p_def_id = self.create_def( - captured_lifetimes.parent_def_id, - p_id, - DefPathData::LifetimeNs(p_name.ident().name), - ); - - v.insert((span, p_id, p_name, res)); - param = p_def_id; + Entry::Vacant(_) => { + panic!("Lifetime {:?} should have a def_id at this point", id); } } } From d9e6364755e7c332a904d23d2d8704e46f9bae79 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 15:14:53 -0300 Subject: [PATCH 21/56] new_named_lifetime_with_res's LifetimeRes::Fresh should have created def_id already --- compiler/rustc_ast_lowering/src/lib.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 28b1527ca5f36..163c84ae57b95 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1932,17 +1932,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if !captured_lifetimes.binders_to_ignore.contains(&binder) { match captured_lifetimes.captures.entry(param) { Entry::Occupied(o) => param = self.local_def_id(o.get().1), - Entry::Vacant(v) => { - let p_id = self.next_node_id(); - - let p_def_id = self.create_def( - captured_lifetimes.parent_def_id, - p_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ); - - v.insert((span, p_id, ParamName::Fresh, res)); - param = p_def_id; + Entry::Vacant(_) => { + panic!("Lifetime {:?} should have a def_id at this point", id); } } } From 6041ed077556bf26bb429ba8bdff8708aff70d14 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 15:27:46 -0300 Subject: [PATCH 22/56] No need to check binders to ignore on new_named_lifetime_with_res's LifetimeRes::Param --- compiler/rustc_ast_lowering/src/lib.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 163c84ae57b95..0ee2ffd271e01 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1907,16 +1907,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?self.captured_lifetimes); let name = match res { - LifetimeRes::Param { mut param, binder } => { + LifetimeRes::Param { mut param, .. } => { let p_name = ParamName::Plain(ident); if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { - if !captured_lifetimes.binders_to_ignore.contains(&binder) { - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(o) => param = self.local_def_id(o.get().1), - Entry::Vacant(_) => { - panic!("Lifetime {:?} should have a def_id at this point", id); - } - } + if let Entry::Occupied(o) = captured_lifetimes.captures.entry(param) { + param = self.local_def_id(o.get().1); } self.captured_lifetimes = Some(captured_lifetimes); From 552f6b0f81c7e2ad031695482d69776439a7935c Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 15:27:52 -0300 Subject: [PATCH 23/56] No need to check binders to ignore on new_named_lifetime_with_res's LifetimeRes::Fresh --- compiler/rustc_ast_lowering/src/lib.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0ee2ffd271e01..4359301881428 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1919,18 +1919,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::LifetimeName::Param(param, p_name) } - LifetimeRes::Fresh { param, binder } => { + LifetimeRes::Fresh { param, .. } => { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); let mut param = self.local_def_id(param); if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { - if !captured_lifetimes.binders_to_ignore.contains(&binder) { - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(o) => param = self.local_def_id(o.get().1), - Entry::Vacant(_) => { - panic!("Lifetime {:?} should have a def_id at this point", id); - } - } + if let Entry::Occupied(o) = captured_lifetimes.captures.entry(param) { + param = self.local_def_id(o.get().1); } self.captured_lifetimes = Some(captured_lifetimes); From 95158fdf3a1854a99cf6232538ca6c503be578cf Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 15:34:32 -0300 Subject: [PATCH 24/56] No need to store parent_def_id in LifetimeCaptureContext --- compiler/rustc_ast_lowering/src/lib.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4359301881428..26ab1f900e1d5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -136,8 +136,6 @@ struct LoweringContext<'a, 'hir> { /// to rebind the introduced lifetimes. #[derive(Debug)] struct LifetimeCaptureContext { - /// parent def_id for new definitions - parent_def_id: LocalDefId, /// Set of lifetimes to rebind. captures: FxHashMap< LocalDefId, // original parameter id @@ -1347,7 +1345,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lifetime_stash = std::mem::replace( &mut lctx.captured_lifetimes, Some(LifetimeCaptureContext { - parent_def_id: opaque_ty_def_id, captures: std::mem::take(&mut collected_lifetimes), binders_to_ignore: Default::default(), }), @@ -1357,7 +1354,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime_collector::lifetimes_in_bounds(&lctx.resolver, bounds); debug!(?lifetimes_in_bounds); - lctx.create_and_capture_lifetime_defs(&lifetimes_in_bounds); + lctx.create_and_capture_lifetime_defs(opaque_ty_def_id, &lifetimes_in_bounds); let ret = lctx.lower_param_bounds(bounds, itctx); @@ -1446,7 +1443,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item)) } - fn create_and_capture_lifetime_defs(&mut self, lifetimes_in_bounds: &[Lifetime]) { + fn create_and_capture_lifetime_defs( + &mut self, + parent_def_id: LocalDefId, + lifetimes_in_bounds: &[Lifetime], + ) { for lifetime in lifetimes_in_bounds { let ident = lifetime.ident; let span = ident.span; @@ -1464,7 +1465,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let name = ParamName::Plain(ident); self.create_def( - captured_lifetimes.parent_def_id, + parent_def_id, node_id, DefPathData::LifetimeNs(name.ident().name), ); @@ -1485,7 +1486,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let name = ParamName::Fresh; self.create_def( - captured_lifetimes.parent_def_id, + parent_def_id, node_id, DefPathData::LifetimeNs(kw::UnderscoreLifetime), ); @@ -1735,7 +1736,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lifetime_stash = std::mem::replace( &mut this.captured_lifetimes, Some(LifetimeCaptureContext { - parent_def_id: opaque_ty_def_id, captures: std::mem::take(&mut captures), binders_to_ignore: Default::default(), }), @@ -1745,7 +1745,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime_collector::lifetimes_in_ret_ty(&this.resolver, output); debug!(?lifetimes_in_bounds); - this.create_and_capture_lifetime_defs(&lifetimes_in_bounds); + this.create_and_capture_lifetime_defs(opaque_ty_def_id, &lifetimes_in_bounds); // We have to be careful to get elision right here. The // idea is that we create a lifetime parameter for each From 6c6a81e48ed15c27e80e17fe7db6905e15a61a22 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 15:46:03 -0300 Subject: [PATCH 25/56] Remove binders_to_ignore from LifetimeCaptureContext --- compiler/rustc_ast_lowering/src/lib.rs | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 26ab1f900e1d5..32ab34bfd2ac8 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -45,7 +45,7 @@ use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust; use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; @@ -146,8 +146,6 @@ struct LifetimeCaptureContext { LifetimeRes, // original resolution ), >, - /// Traversed binders. The ids in this set should *not* be rebound. - binders_to_ignore: FxHashSet, } trait ResolverAstLoweringExt { @@ -768,14 +766,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let generic_params = self.arena.alloc_from_iter(generic_params); debug!(?generic_params); - if let Some(ctxt) = &mut self.captured_lifetimes { - ctxt.binders_to_ignore.insert(binder); - } - let ret = f(self, generic_params); - if let Some(ctxt) = &mut self.captured_lifetimes { - ctxt.binders_to_ignore.remove(&binder); - } - ret + f(self, generic_params) } fn with_dyn_type_scope(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T { @@ -1346,7 +1337,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut lctx.captured_lifetimes, Some(LifetimeCaptureContext { captures: std::mem::take(&mut collected_lifetimes), - binders_to_ignore: Default::default(), }), ); @@ -1735,10 +1725,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.with_hir_id_owner(opaque_ty_node_id, |this| { let lifetime_stash = std::mem::replace( &mut this.captured_lifetimes, - Some(LifetimeCaptureContext { - captures: std::mem::take(&mut captures), - binders_to_ignore: Default::default(), - }), + Some(LifetimeCaptureContext { captures: std::mem::take(&mut captures) }), ); let lifetimes_in_bounds = From f6b4dd15417db0303da361a38531a45444948c55 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 17:17:34 -0300 Subject: [PATCH 26/56] Create new_mapping local structure and avoid checking def_ids on captures --- compiler/rustc_ast_lowering/src/lib.rs | 82 +++++++++++++++----------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 32ab34bfd2ac8..f804e09c49b15 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1327,6 +1327,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); let mut collected_lifetimes = FxHashMap::default(); + let mut new_remapping = FxHashMap::default(); + self.with_hir_id_owner(opaque_ty_node_id, |lctx| { let hir_bounds = if origin == hir::OpaqueTyOrigin::TyAlias { lctx.lower_param_bounds(bounds, itctx) @@ -1344,7 +1346,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime_collector::lifetimes_in_bounds(&lctx.resolver, bounds); debug!(?lifetimes_in_bounds); - lctx.create_and_capture_lifetime_defs(opaque_ty_def_id, &lifetimes_in_bounds); + lctx.create_and_capture_lifetime_defs( + opaque_ty_def_id, + &lifetimes_in_bounds, + &mut new_remapping, + ); let ret = lctx.lower_param_bounds(bounds, itctx); @@ -1437,6 +1443,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, parent_def_id: LocalDefId, lifetimes_in_bounds: &[Lifetime], + remapping: &mut FxHashMap, ) { for lifetime in lifetimes_in_bounds { let ident = lifetime.ident; @@ -1447,42 +1454,42 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { match res { - LifetimeRes::Param { param, binder: _ } => { - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(_) => {} - Entry::Vacant(v) => { - let node_id = self.next_node_id(); - let name = ParamName::Plain(ident); - - self.create_def( - parent_def_id, - node_id, - DefPathData::LifetimeNs(name.ident().name), - ); - - v.insert((span, node_id, name, res)); - } + LifetimeRes::Param { param: old_def_id, binder: _ } => { + if remapping.get(&old_def_id).is_none() { + let node_id = self.next_node_id(); + let name = ParamName::Plain(ident); + + let new_def_id = self.create_def( + parent_def_id, + node_id, + DefPathData::LifetimeNs(name.ident().name), + ); + + remapping.insert(old_def_id, new_def_id); + captured_lifetimes + .captures + .insert(old_def_id, (span, node_id, name, res)); } } LifetimeRes::Fresh { param, binder: _ } => { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); - let param = self.local_def_id(param); - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(_) => {} - Entry::Vacant(v) => { - let node_id = self.next_node_id(); - - let name = ParamName::Fresh; - - self.create_def( - parent_def_id, - node_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ); - - v.insert((span, node_id, name, res)); - } + let old_def_id = self.local_def_id(param); + if remapping.get(&old_def_id).is_none() { + let node_id = self.next_node_id(); + + let name = ParamName::Fresh; + + let new_def_id = self.create_def( + parent_def_id, + node_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ); + + remapping.insert(old_def_id, new_def_id); + captured_lifetimes + .captures + .insert(old_def_id, (span, node_id, name, res)); } } @@ -1691,6 +1698,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // lifetime parameters, including those defined in-band. let mut captures = FxHashMap::default(); + let mut new_remapping = FxHashMap::default(); let extra_lifetime_params = self.resolver.take_extra_lifetime_params(opaque_ty_node_id); debug!(?extra_lifetime_params); @@ -1700,7 +1708,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let inner_node_id = self.next_node_id(); // Add a definition for the in scope lifetime def. - self.create_def(opaque_ty_def_id, inner_node_id, DefPathData::LifetimeNs(name)); + let inner_def_id = + self.create_def(opaque_ty_def_id, inner_node_id, DefPathData::LifetimeNs(name)); + new_remapping.insert(outer_def_id, inner_def_id); let (p_name, inner_res) = match outer_res { // Input lifetime like `'a`: @@ -1732,7 +1742,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime_collector::lifetimes_in_ret_ty(&this.resolver, output); debug!(?lifetimes_in_bounds); - this.create_and_capture_lifetime_defs(opaque_ty_def_id, &lifetimes_in_bounds); + this.create_and_capture_lifetime_defs( + opaque_ty_def_id, + &lifetimes_in_bounds, + &mut new_remapping, + ); // We have to be careful to get elision right here. The // idea is that we create a lifetime parameter for each From 2d826e27c4bceec311dd6ec9ce5eb8eea78ebeff Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 18:04:37 -0300 Subject: [PATCH 27/56] Capture things as Lifetime object to simplify things --- compiler/rustc_ast_lowering/src/lib.rs | 108 ++++++++++++++----------- 1 file changed, 59 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f804e09c49b15..1e8978e6e83f4 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -140,9 +140,7 @@ struct LifetimeCaptureContext { captures: FxHashMap< LocalDefId, // original parameter id ( - Span, // Span - NodeId, // synthetized parameter id - ParamName, // parameter name + Lifetime, // Lifetime parameter LifetimeRes, // original resolution ), >, @@ -1363,20 +1361,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?collected_lifetimes); let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map( - |(_, &(span, p_id, p_name, _))| { - let hir_id = lctx.lower_node_id(p_id); - debug_assert_ne!(lctx.opt_local_def_id(p_id), None); + |(_, &(lifetime, _))| { + let hir_id = lctx.lower_node_id(lifetime.id); + debug_assert_ne!(lctx.opt_local_def_id(lifetime.id), None); - let kind = if p_name.ident().name == kw::UnderscoreLifetime { - hir::LifetimeParamKind::Elided + let (name, kind) = if lifetime.ident.name == kw::UnderscoreLifetime { + (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided) } else { - hir::LifetimeParamKind::Explicit + (hir::ParamName::Plain(lifetime.ident), hir::LifetimeParamKind::Explicit) }; hir::GenericParam { hir_id, - name: p_name, - span, + name, + span: lifetime.ident.span, pure_wrt_drop: false, kind: hir::GenericParamKind::Lifetime { kind }, colon_span: None, @@ -1403,9 +1401,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }); let lifetimes = self.arena.alloc_from_iter(collected_lifetimes.into_iter().map( - |(_, (span, _, p_name, res))| { + |(_, (lifetime, res))| { let id = self.next_node_id(); - let ident = Ident::new(p_name.ident().name, span); + let span = lifetime.ident.span; + + let ident = if lifetime.ident.name == kw::UnderscoreLifetime { + Ident::with_dummy_span(kw::UnderscoreLifetime) + } else { + lifetime.ident + }; + let l = self.new_named_lifetime_with_res(id, span, ident, res); hir::GenericArg::Lifetime(l) }, @@ -1446,9 +1451,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { remapping: &mut FxHashMap, ) { for lifetime in lifetimes_in_bounds { - let ident = lifetime.ident; - let span = ident.span; - let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error); debug!(?res); @@ -1457,39 +1459,34 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Param { param: old_def_id, binder: _ } => { if remapping.get(&old_def_id).is_none() { let node_id = self.next_node_id(); - let name = ParamName::Plain(ident); let new_def_id = self.create_def( parent_def_id, node_id, - DefPathData::LifetimeNs(name.ident().name), + DefPathData::LifetimeNs(lifetime.ident.name), ); - remapping.insert(old_def_id, new_def_id); - captured_lifetimes - .captures - .insert(old_def_id, (span, node_id, name, res)); + + let new_lifetime = Lifetime { id: node_id, ident: lifetime.ident }; + captured_lifetimes.captures.insert(old_def_id, (new_lifetime, res)); } } LifetimeRes::Fresh { param, binder: _ } => { - debug_assert_eq!(ident.name, kw::UnderscoreLifetime); + debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); let old_def_id = self.local_def_id(param); if remapping.get(&old_def_id).is_none() { let node_id = self.next_node_id(); - let name = ParamName::Fresh; - let new_def_id = self.create_def( parent_def_id, node_id, DefPathData::LifetimeNs(kw::UnderscoreLifetime), ); - remapping.insert(old_def_id, new_def_id); - captured_lifetimes - .captures - .insert(old_def_id, (span, node_id, name, res)); + + let new_lifetime = Lifetime { id: node_id, ident: lifetime.ident }; + captured_lifetimes.captures.insert(old_def_id, (new_lifetime, res)); } } @@ -1703,31 +1700,37 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let extra_lifetime_params = self.resolver.take_extra_lifetime_params(opaque_ty_node_id); debug!(?extra_lifetime_params); for (ident, outer_node_id, outer_res) in extra_lifetime_params { - let Ident { name, span } = ident; let outer_def_id = self.local_def_id(outer_node_id); let inner_node_id = self.next_node_id(); // Add a definition for the in scope lifetime def. - let inner_def_id = - self.create_def(opaque_ty_def_id, inner_node_id, DefPathData::LifetimeNs(name)); + let inner_def_id = self.create_def( + opaque_ty_def_id, + inner_node_id, + DefPathData::LifetimeNs(ident.name), + ); new_remapping.insert(outer_def_id, inner_def_id); - let (p_name, inner_res) = match outer_res { + let inner_res = match outer_res { // Input lifetime like `'a`: LifetimeRes::Param { param, .. } => { - (hir::ParamName::Plain(ident), LifetimeRes::Param { param, binder: fn_node_id }) + LifetimeRes::Param { param, binder: fn_node_id } } // Input lifetime like `'1`: LifetimeRes::Fresh { param, .. } => { - (hir::ParamName::Fresh, LifetimeRes::Fresh { param, binder: fn_node_id }) + LifetimeRes::Fresh { param, binder: fn_node_id } } LifetimeRes::Static | LifetimeRes::Error => continue, res => { - panic!("Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, span) + panic!( + "Unexpected lifetime resolution {:?} for {:?} at {:?}", + res, ident, ident.span + ) } }; - captures.insert(outer_def_id, (span, inner_node_id, p_name, inner_res)); + let new_lifetime = Lifetime { id: inner_node_id, ident }; + captures.insert(outer_def_id, (new_lifetime, inner_res)); } debug!(?captures); @@ -1765,20 +1768,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let future_bound = ret; let generic_params = - this.arena.alloc_from_iter(captures.iter().map(|(_, &(span, p_id, p_name, _))| { - let hir_id = this.lower_node_id(p_id); - debug_assert_ne!(this.opt_local_def_id(p_id), None); + this.arena.alloc_from_iter(captures.iter().map(|(_, &(lifetime, _))| { + let hir_id = this.lower_node_id(lifetime.id); + debug_assert_ne!(this.opt_local_def_id(lifetime.id), None); - let kind = if p_name.ident().name == kw::UnderscoreLifetime { - hir::LifetimeParamKind::Elided + let (name, kind) = if lifetime.ident.name == kw::UnderscoreLifetime { + (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided) } else { - hir::LifetimeParamKind::Explicit + (hir::ParamName::Plain(lifetime.ident), hir::LifetimeParamKind::Explicit) }; hir::GenericParam { hir_id, - name: p_name, - span, + name, + span: lifetime.ident.span, pure_wrt_drop: false, kind: hir::GenericParamKind::Lifetime { kind }, colon_span: None, @@ -1818,9 +1821,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // For the "output" lifetime parameters, we just want to // generate `'_`. let generic_args = - self.arena.alloc_from_iter(captures.into_iter().map(|(_, (span, _, p_name, res))| { + self.arena.alloc_from_iter(captures.into_iter().map(|(_, (lifetime, res))| { let id = self.next_node_id(); - let ident = Ident::new(p_name.ident().name, span); + let span = lifetime.ident.span; + + let ident = if lifetime.ident.name == kw::UnderscoreLifetime { + Ident::with_dummy_span(kw::UnderscoreLifetime) + } else { + lifetime.ident + }; + let l = self.new_named_lifetime_with_res(id, span, ident, res); hir::GenericArg::Lifetime(l) })); @@ -1912,7 +1922,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let p_name = ParamName::Plain(ident); if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { if let Entry::Occupied(o) = captured_lifetimes.captures.entry(param) { - param = self.local_def_id(o.get().1); + param = self.local_def_id(o.get().0.id); } self.captured_lifetimes = Some(captured_lifetimes); @@ -1926,7 +1936,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut param = self.local_def_id(param); if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { if let Entry::Occupied(o) = captured_lifetimes.captures.entry(param) { - param = self.local_def_id(o.get().1); + param = self.local_def_id(o.get().0.id); } self.captured_lifetimes = Some(captured_lifetimes); From f0db1d68e6fd0fe393a3c6b4c49167f9706a5479 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 23:20:15 -0300 Subject: [PATCH 28/56] Remove local_def_id from captured_lifetimes --- compiler/rustc_ast_lowering/src/lib.rs | 39 +++++++++++--------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1e8978e6e83f4..5ab95cf19562a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -137,13 +137,10 @@ struct LoweringContext<'a, 'hir> { #[derive(Debug)] struct LifetimeCaptureContext { /// Set of lifetimes to rebind. - captures: FxHashMap< - LocalDefId, // original parameter id - ( - Lifetime, // Lifetime parameter - LifetimeRes, // original resolution - ), - >, + captures: Vec<( + Lifetime, // Lifetime parameter + LifetimeRes, // original resolution + )>, } trait ResolverAstLoweringExt { @@ -1324,7 +1321,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); - let mut collected_lifetimes = FxHashMap::default(); + let mut collected_lifetimes = Vec::new(); let mut new_remapping = FxHashMap::default(); self.with_hir_id_owner(opaque_ty_node_id, |lctx| { @@ -1360,8 +1357,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; debug!(?collected_lifetimes); - let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map( - |(_, &(lifetime, _))| { + let lifetime_defs = + lctx.arena.alloc_from_iter(collected_lifetimes.iter().map(|&(lifetime, _)| { let hir_id = lctx.lower_node_id(lifetime.id); debug_assert_ne!(lctx.opt_local_def_id(lifetime.id), None); @@ -1379,8 +1376,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { kind: hir::GenericParamKind::Lifetime { kind }, colon_span: None, } - }, - )); + })); debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs); @@ -1400,8 +1396,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span) }); - let lifetimes = self.arena.alloc_from_iter(collected_lifetimes.into_iter().map( - |(_, (lifetime, res))| { + let lifetimes = + self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(lifetime, res)| { let id = self.next_node_id(); let span = lifetime.ident.span; @@ -1413,8 +1409,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let l = self.new_named_lifetime_with_res(id, span, ident, res); hir::GenericArg::Lifetime(l) - }, - )); + })); debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes); @@ -1468,7 +1463,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { remapping.insert(old_def_id, new_def_id); let new_lifetime = Lifetime { id: node_id, ident: lifetime.ident }; - captured_lifetimes.captures.insert(old_def_id, (new_lifetime, res)); + captured_lifetimes.captures.push((new_lifetime, res)); } } @@ -1486,7 +1481,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { remapping.insert(old_def_id, new_def_id); let new_lifetime = Lifetime { id: node_id, ident: lifetime.ident }; - captured_lifetimes.captures.insert(old_def_id, (new_lifetime, res)); + captured_lifetimes.captures.push((new_lifetime, res)); } } @@ -1694,7 +1689,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // by the opaque type. This should include all in-scope // lifetime parameters, including those defined in-band. - let mut captures = FxHashMap::default(); + let mut captures = Vec::new(); let mut new_remapping = FxHashMap::default(); let extra_lifetime_params = self.resolver.take_extra_lifetime_params(opaque_ty_node_id); @@ -1730,7 +1725,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; let new_lifetime = Lifetime { id: inner_node_id, ident }; - captures.insert(outer_def_id, (new_lifetime, inner_res)); + captures.push((new_lifetime, inner_res)); } debug!(?captures); @@ -1768,7 +1763,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let future_bound = ret; let generic_params = - this.arena.alloc_from_iter(captures.iter().map(|(_, &(lifetime, _))| { + this.arena.alloc_from_iter(captures.iter().map(|&(lifetime, _)| { let hir_id = this.lower_node_id(lifetime.id); debug_assert_ne!(this.opt_local_def_id(lifetime.id), None); @@ -1821,7 +1816,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // For the "output" lifetime parameters, we just want to // generate `'_`. let generic_args = - self.arena.alloc_from_iter(captures.into_iter().map(|(_, (lifetime, res))| { + self.arena.alloc_from_iter(captures.into_iter().map(|(lifetime, res)| { let id = self.next_node_id(); let span = lifetime.ident.span; From 1d6cebfd6bed99b1ef1671bcb1b6e0cd787953d5 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 20:01:40 -0300 Subject: [PATCH 29/56] Implement def_id based remapping --- compiler/rustc_ast_lowering/src/lib.rs | 240 ++++++++++++++----------- compiler/rustc_middle/src/ty/mod.rs | 2 + compiler/rustc_resolve/src/lib.rs | 5 + 3 files changed, 140 insertions(+), 107 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5ab95cf19562a..7c1bd6b4b199a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -151,6 +151,8 @@ trait ResolverAstLoweringExt { fn get_lifetime_res(&self, id: NodeId) -> Option; fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>; fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind; + fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId); + fn get_remapped_def_id(&self, local_def_id: LocalDefId) -> LocalDefId; } impl ResolverAstLoweringExt for ResolverAstLowering { @@ -218,6 +220,25 @@ impl ResolverAstLoweringExt for ResolverAstLowering { fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind { self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang) } + + /// Push a remapping into the top-most map. Panics if no map has been pushed. + #[tracing::instrument(level = "debug", skip(self))] + fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId) { + self.generics_def_id_map.last_mut().expect("no map pushed").insert(from, to); + } + + fn get_remapped_def_id(&self, mut local_def_id: LocalDefId) -> LocalDefId { + for map in &self.generics_def_id_map { + if let Some(r) = map.get(&local_def_id) { + debug!("def_id_remapper: remapping from `{local_def_id:?}` to `{r:?}`"); + local_def_id = *r; + } else { + debug!("def_id_remapper: no remapping for `{local_def_id:?}` found in map"); + } + } + + local_def_id + } } /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, @@ -474,7 +495,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn opt_local_def_id(&self, node: NodeId) -> Option { - self.resolver.node_id_to_def_id.get(&node).copied() + self.resolver + .node_id_to_def_id + .get(&node) + .map(|local_def_id| self.resolver.get_remapped_def_id(*local_def_id)) } fn local_def_id(&self, node: NodeId) -> LocalDefId { @@ -534,6 +558,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug_assert!(_old.is_none()) } + fn with_remapping( + &mut self, + remap: FxHashMap, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + self.resolver.generics_def_id_map.push(remap); + let res = f(self); + self.resolver.generics_def_id_map.pop(); + res + } + fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> { let attrs = std::mem::take(&mut self.attrs); let mut bodies = std::mem::take(&mut self.bodies); @@ -1325,9 +1360,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut new_remapping = FxHashMap::default(); self.with_hir_id_owner(opaque_ty_node_id, |lctx| { - let hir_bounds = if origin == hir::OpaqueTyOrigin::TyAlias { - lctx.lower_param_bounds(bounds, itctx) - } else { + if origin != hir::OpaqueTyOrigin::TyAlias { debug!(?lctx.captured_lifetimes); let lifetime_stash = std::mem::replace( @@ -1347,53 +1380,57 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut new_remapping, ); - let ret = lctx.lower_param_bounds(bounds, itctx); - let ctxt = std::mem::replace(&mut lctx.captured_lifetimes, lifetime_stash).unwrap(); collected_lifetimes = ctxt.captures; - - ret }; + debug!(?new_remapping); debug!(?collected_lifetimes); - let lifetime_defs = - lctx.arena.alloc_from_iter(collected_lifetimes.iter().map(|&(lifetime, _)| { - let hir_id = lctx.lower_node_id(lifetime.id); - debug_assert_ne!(lctx.opt_local_def_id(lifetime.id), None); + lctx.with_remapping(new_remapping, |lctx| { + let hir_bounds = lctx.lower_param_bounds(bounds, itctx); + + let lifetime_defs = + lctx.arena.alloc_from_iter(collected_lifetimes.iter().map(|&(lifetime, _)| { + let hir_id = lctx.lower_node_id(lifetime.id); + debug_assert_ne!(lctx.opt_local_def_id(lifetime.id), None); + + let (name, kind) = if lifetime.ident.name == kw::UnderscoreLifetime { + (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided) + } else { + ( + hir::ParamName::Plain(lifetime.ident), + hir::LifetimeParamKind::Explicit, + ) + }; - let (name, kind) = if lifetime.ident.name == kw::UnderscoreLifetime { - (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided) - } else { - (hir::ParamName::Plain(lifetime.ident), hir::LifetimeParamKind::Explicit) - }; + hir::GenericParam { + hir_id, + name, + span: lifetime.ident.span, + pure_wrt_drop: false, + kind: hir::GenericParamKind::Lifetime { kind }, + colon_span: None, + } + })); - hir::GenericParam { - hir_id, - name, - span: lifetime.ident.span, - pure_wrt_drop: false, - kind: hir::GenericParamKind::Lifetime { kind }, - colon_span: None, - } - })); - - debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs); - - let opaque_ty_item = hir::OpaqueTy { - generics: self.arena.alloc(hir::Generics { - params: lifetime_defs, - predicates: &[], - has_where_clause_predicates: false, - where_clause_span: lctx.lower_span(span), - span: lctx.lower_span(span), - }), - bounds: hir_bounds, - origin, - }; + debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs); + + let opaque_ty_item = hir::OpaqueTy { + generics: self.arena.alloc(hir::Generics { + params: lifetime_defs, + predicates: &[], + has_where_clause_predicates: false, + where_clause_span: lctx.lower_span(span), + span: lctx.lower_span(span), + }), + bounds: hir_bounds, + origin, + }; - trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id); - lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span) + trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id); + lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span) + }) }); let lifetimes = @@ -1746,58 +1783,62 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut new_remapping, ); - // We have to be careful to get elision right here. The - // idea is that we create a lifetime parameter for each - // lifetime in the return type. So, given a return type - // like `async fn foo(..) -> &[&u32]`, we lower to `impl - // Future`. - // - // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and - // hence the elision takes place at the fn site. - let ret = this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span); - let ctxt = std::mem::replace(&mut this.captured_lifetimes, lifetime_stash).unwrap(); captures = ctxt.captures; - let future_bound = ret; - - let generic_params = - this.arena.alloc_from_iter(captures.iter().map(|&(lifetime, _)| { - let hir_id = this.lower_node_id(lifetime.id); - debug_assert_ne!(this.opt_local_def_id(lifetime.id), None); - - let (name, kind) = if lifetime.ident.name == kw::UnderscoreLifetime { - (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided) - } else { - (hir::ParamName::Plain(lifetime.ident), hir::LifetimeParamKind::Explicit) - }; + this.with_remapping(new_remapping, |this| { + // We have to be careful to get elision right here. The + // idea is that we create a lifetime parameter for each + // lifetime in the return type. So, given a return type + // like `async fn foo(..) -> &[&u32]`, we lower to `impl + // Future`. + // + // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and + // hence the elision takes place at the fn site. + let future_bound = + this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span); + + let generic_params = + this.arena.alloc_from_iter(captures.iter().map(|&(lifetime, _)| { + let hir_id = this.lower_node_id(lifetime.id); + debug_assert_ne!(this.opt_local_def_id(lifetime.id), None); + + let (name, kind) = if lifetime.ident.name == kw::UnderscoreLifetime { + (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided) + } else { + ( + hir::ParamName::Plain(lifetime.ident), + hir::LifetimeParamKind::Explicit, + ) + }; - hir::GenericParam { - hir_id, - name, - span: lifetime.ident.span, - pure_wrt_drop: false, - kind: hir::GenericParamKind::Lifetime { kind }, - colon_span: None, - } - })); - debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params); - - let opaque_ty_item = hir::OpaqueTy { - generics: this.arena.alloc(hir::Generics { - params: generic_params, - predicates: &[], - has_where_clause_predicates: false, - where_clause_span: this.lower_span(span), - span: this.lower_span(span), - }), - bounds: arena_vec![this; future_bound], - origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), - }; + hir::GenericParam { + hir_id, + name, + span: lifetime.ident.span, + pure_wrt_drop: false, + kind: hir::GenericParamKind::Lifetime { kind }, + colon_span: None, + } + })); + debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params); + + let opaque_ty_item = hir::OpaqueTy { + generics: this.arena.alloc(hir::Generics { + params: generic_params, + predicates: &[], + has_where_clause_predicates: false, + where_clause_span: this.lower_span(span), + span: this.lower_span(span), + }), + bounds: arena_vec![this; future_bound], + origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), + }; - trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); - this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span) + trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); + this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span) + }) }); // As documented above, we need to create the lifetime @@ -1910,32 +1951,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ident: Ident, res: LifetimeRes, ) -> hir::Lifetime { - debug!(?self.captured_lifetimes); - let name = match res { - LifetimeRes::Param { mut param, .. } => { + LifetimeRes::Param { param, .. } => { let p_name = ParamName::Plain(ident); - if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { - if let Entry::Occupied(o) = captured_lifetimes.captures.entry(param) { - param = self.local_def_id(o.get().0.id); - } - - self.captured_lifetimes = Some(captured_lifetimes); - } + let param = self.resolver.get_remapped_def_id(param); hir::LifetimeName::Param(param, p_name) } LifetimeRes::Fresh { param, .. } => { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); + let param = self.local_def_id(param); - let mut param = self.local_def_id(param); - if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { - if let Entry::Occupied(o) = captured_lifetimes.captures.entry(param) { - param = self.local_def_id(o.get().0.id); - } - - self.captured_lifetimes = Some(captured_lifetimes); - } hir::LifetimeName::Param(param, ParamName::Fresh) } LifetimeRes::Infer => hir::LifetimeName::Infer, @@ -1943,7 +1969,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Error => hir::LifetimeName::Error, res => panic!("Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, span), }; - debug!(?self.captured_lifetimes); + debug!(?name); hir::Lifetime { hir_id: self.lower_node_id(id), span: self.lower_span(span), name } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 4b081316e2308..dfe0a4fd36448 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -177,6 +177,8 @@ pub struct ResolverAstLowering { pub label_res_map: NodeMap, /// Resolutions for lifetimes. pub lifetimes_res_map: NodeMap, + /// Mapping from generics def-id to RPIT copied generic def-id + pub generics_def_id_map: Vec>, /// Lifetime parameters that lowering will have to introduce. pub extra_lifetime_params_map: NodeMap>, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 31d10008efbfb..3e3c16f510000 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -913,6 +913,8 @@ pub struct Resolver<'a> { label_res_map: NodeMap, /// Resolutions for lifetimes. lifetimes_res_map: NodeMap, + /// Mapping from generics def-id to RPIT copied generic def-id + generics_def_id_map: Vec>, /// Lifetime parameters that lowering will have to introduce. extra_lifetime_params_map: NodeMap>, @@ -1277,6 +1279,7 @@ impl<'a> Resolver<'a> { import_res_map: Default::default(), label_res_map: Default::default(), lifetimes_res_map: Default::default(), + generics_def_id_map: Vec::new(), extra_lifetime_params_map: Default::default(), extern_crate_map: Default::default(), reexport_map: FxHashMap::default(), @@ -1444,6 +1447,7 @@ impl<'a> Resolver<'a> { import_res_map: self.import_res_map, label_res_map: self.label_res_map, lifetimes_res_map: self.lifetimes_res_map, + generics_def_id_map: self.generics_def_id_map, extra_lifetime_params_map: self.extra_lifetime_params_map, next_node_id: self.next_node_id, node_id_to_def_id: self.node_id_to_def_id, @@ -1488,6 +1492,7 @@ impl<'a> Resolver<'a> { import_res_map: self.import_res_map.clone(), label_res_map: self.label_res_map.clone(), lifetimes_res_map: self.lifetimes_res_map.clone(), + generics_def_id_map: self.generics_def_id_map.clone(), extra_lifetime_params_map: self.extra_lifetime_params_map.clone(), next_node_id: self.next_node_id.clone(), node_id_to_def_id: self.node_id_to_def_id.clone(), From 13800624de1c91cbb133c262086a0e5550686239 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 20:14:24 -0300 Subject: [PATCH 30/56] Remove captured_lifetimes and LifetimeCaptureContext and make create_lifetime_defs return the captures --- compiler/rustc_ast_lowering/src/item.rs | 1 - compiler/rustc_ast_lowering/src/lib.rs | 124 ++++++++---------------- 2 files changed, 43 insertions(+), 82 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 4cf0a8e0d2ed1..cffd025b1890c 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -80,7 +80,6 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { generator_kind: None, task_context: None, current_item: None, - captured_lifetimes: None, impl_trait_defs: Vec::new(), impl_trait_bounds: Vec::new(), allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 7c1bd6b4b199a..d2f9ea570fbc0 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -111,9 +111,6 @@ struct LoweringContext<'a, 'hir> { is_in_trait_impl: bool, is_in_dyn_type: bool, - /// Used to handle lifetimes appearing in impl-traits. - captured_lifetimes: Option, - current_hir_id_owner: LocalDefId, item_local_id_counter: hir::ItemLocalId, local_id_to_def_id: SortedMap, @@ -130,19 +127,6 @@ struct LoweringContext<'a, 'hir> { allow_into_future: Option>, } -/// When we lower a lifetime, it is inserted in `captures`, and the resolution is modified so -/// to point to the lifetime parameter impl-trait will generate. -/// When traversing `for<...>` binders, they are inserted in `binders_to_ignore` so we know *not* -/// to rebind the introduced lifetimes. -#[derive(Debug)] -struct LifetimeCaptureContext { - /// Set of lifetimes to rebind. - captures: Vec<( - Lifetime, // Lifetime parameter - LifetimeRes, // original resolution - )>, -} - trait ResolverAstLoweringExt { fn legacy_const_generic_args(&self, expr: &Expr) -> Option>; fn get_partial_res(&self, id: NodeId) -> Option; @@ -1361,28 +1345,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.with_hir_id_owner(opaque_ty_node_id, |lctx| { if origin != hir::OpaqueTyOrigin::TyAlias { - debug!(?lctx.captured_lifetimes); - - let lifetime_stash = std::mem::replace( - &mut lctx.captured_lifetimes, - Some(LifetimeCaptureContext { - captures: std::mem::take(&mut collected_lifetimes), - }), - ); - let lifetimes_in_bounds = lifetime_collector::lifetimes_in_bounds(&lctx.resolver, bounds); debug!(?lifetimes_in_bounds); - lctx.create_and_capture_lifetime_defs( + collected_lifetimes = lctx.create_and_capture_lifetime_defs( opaque_ty_def_id, &lifetimes_in_bounds, &mut new_remapping, ); - - let ctxt = std::mem::replace(&mut lctx.captured_lifetimes, lifetime_stash).unwrap(); - - collected_lifetimes = ctxt.captures; }; debug!(?new_remapping); debug!(?collected_lifetimes); @@ -1481,58 +1452,58 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { parent_def_id: LocalDefId, lifetimes_in_bounds: &[Lifetime], remapping: &mut FxHashMap, - ) { + ) -> Vec<(Lifetime, LifetimeRes)> { + let mut result = Vec::new(); + for lifetime in lifetimes_in_bounds { let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error); debug!(?res); - if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { - match res { - LifetimeRes::Param { param: old_def_id, binder: _ } => { - if remapping.get(&old_def_id).is_none() { - let node_id = self.next_node_id(); - - let new_def_id = self.create_def( - parent_def_id, - node_id, - DefPathData::LifetimeNs(lifetime.ident.name), - ); - remapping.insert(old_def_id, new_def_id); - - let new_lifetime = Lifetime { id: node_id, ident: lifetime.ident }; - captured_lifetimes.captures.push((new_lifetime, res)); - } - } + match res { + LifetimeRes::Param { param: old_def_id, binder: _ } => { + if remapping.get(&old_def_id).is_none() { + let node_id = self.next_node_id(); - LifetimeRes::Fresh { param, binder: _ } => { - debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); - let old_def_id = self.local_def_id(param); - if remapping.get(&old_def_id).is_none() { - let node_id = self.next_node_id(); - - let new_def_id = self.create_def( - parent_def_id, - node_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ); - remapping.insert(old_def_id, new_def_id); - - let new_lifetime = Lifetime { id: node_id, ident: lifetime.ident }; - captured_lifetimes.captures.push((new_lifetime, res)); - } + let new_def_id = self.create_def( + parent_def_id, + node_id, + DefPathData::LifetimeNs(lifetime.ident.name), + ); + remapping.insert(old_def_id, new_def_id); + + let new_lifetime = Lifetime { id: node_id, ident: lifetime.ident }; + result.push((new_lifetime, res)); } + } - LifetimeRes::Static | LifetimeRes::Error => {} + LifetimeRes::Fresh { param, binder: _ } => { + debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); + let old_def_id = self.local_def_id(param); + if remapping.get(&old_def_id).is_none() { + let node_id = self.next_node_id(); - res => panic!( - "Unexpected lifetime resolution {:?} for {:?} at {:?}", - res, lifetime.ident, lifetime.ident.span - ), + let new_def_id = self.create_def( + parent_def_id, + node_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ); + remapping.insert(old_def_id, new_def_id); + + let new_lifetime = Lifetime { id: node_id, ident: lifetime.ident }; + result.push((new_lifetime, res)); + } } - self.captured_lifetimes = Some(captured_lifetimes); + LifetimeRes::Static | LifetimeRes::Error => {} + + res => panic!( + "Unexpected lifetime resolution {:?} for {:?} at {:?}", + res, lifetime.ident, lifetime.ident.span + ), } } + + result } fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] { @@ -1768,24 +1739,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?captures); self.with_hir_id_owner(opaque_ty_node_id, |this| { - let lifetime_stash = std::mem::replace( - &mut this.captured_lifetimes, - Some(LifetimeCaptureContext { captures: std::mem::take(&mut captures) }), - ); - let lifetimes_in_bounds = lifetime_collector::lifetimes_in_ret_ty(&this.resolver, output); debug!(?lifetimes_in_bounds); - this.create_and_capture_lifetime_defs( + captures.extend(this.create_and_capture_lifetime_defs( opaque_ty_def_id, &lifetimes_in_bounds, &mut new_remapping, - ); - - let ctxt = std::mem::replace(&mut this.captured_lifetimes, lifetime_stash).unwrap(); - - captures = ctxt.captures; + )); this.with_remapping(new_remapping, |this| { // We have to be careful to get elision right here. The From cd3c388418c96fc801b29dd44e864c4590540c28 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 20:15:15 -0300 Subject: [PATCH 31/56] create_and_capture_lifetime_defs -> create_lifetime_defs --- compiler/rustc_ast_lowering/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d2f9ea570fbc0..b3a4844797994 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1349,7 +1349,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime_collector::lifetimes_in_bounds(&lctx.resolver, bounds); debug!(?lifetimes_in_bounds); - collected_lifetimes = lctx.create_and_capture_lifetime_defs( + collected_lifetimes = lctx.create_lifetime_defs( opaque_ty_def_id, &lifetimes_in_bounds, &mut new_remapping, @@ -1447,7 +1447,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item)) } - fn create_and_capture_lifetime_defs( + fn create_lifetime_defs( &mut self, parent_def_id: LocalDefId, lifetimes_in_bounds: &[Lifetime], @@ -1743,7 +1743,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime_collector::lifetimes_in_ret_ty(&this.resolver, output); debug!(?lifetimes_in_bounds); - captures.extend(this.create_and_capture_lifetime_defs( + captures.extend(this.create_lifetime_defs( opaque_ty_def_id, &lifetimes_in_bounds, &mut new_remapping, From 40bcbed3c7809fe779734d6a5c93e4b5e5d4b420 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 2 Aug 2022 23:06:38 -0300 Subject: [PATCH 32/56] Avoid explicitly handling res when is not needed --- compiler/rustc_ast_lowering/src/item.rs | 5 +- compiler/rustc_ast_lowering/src/lib.rs | 72 +++++++++++++++---------- 2 files changed, 46 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index cffd025b1890c..ee4c0036f7698 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1453,11 +1453,8 @@ impl<'hir> LoweringContext<'_, 'hir> { GenericParamKind::Lifetime => { let ident_span = self.lower_span(ident.span); let ident = self.lower_ident(ident); - let res = self.resolver.get_lifetime_res(id).unwrap_or_else(|| { - panic!("Missing resolution for lifetime {:?} at {:?}", id, ident.span) - }); let lt_id = self.next_node_id(); - let lifetime = self.new_named_lifetime_with_res(lt_id, ident_span, ident, res); + let lifetime = self.new_named_lifetime(id, lt_id, ident_span, ident); Some(hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { lifetime, span, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b3a4844797994..69398918f897e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1361,10 +1361,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lctx.with_remapping(new_remapping, |lctx| { let hir_bounds = lctx.lower_param_bounds(bounds, itctx); - let lifetime_defs = - lctx.arena.alloc_from_iter(collected_lifetimes.iter().map(|&(lifetime, _)| { - let hir_id = lctx.lower_node_id(lifetime.id); - debug_assert_ne!(lctx.opt_local_def_id(lifetime.id), None); + let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map( + |&(new_node_id, lifetime)| { + let hir_id = lctx.lower_node_id(new_node_id); + debug_assert_ne!(lctx.opt_local_def_id(new_node_id), None); let (name, kind) = if lifetime.ident.name == kw::UnderscoreLifetime { (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided) @@ -1383,7 +1383,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { kind: hir::GenericParamKind::Lifetime { kind }, colon_span: None, } - })); + }, + )); debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs); @@ -1405,7 +1406,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }); let lifetimes = - self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(lifetime, res)| { + self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(_, lifetime)| { let id = self.next_node_id(); let span = lifetime.ident.span; @@ -1415,7 +1416,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime.ident }; - let l = self.new_named_lifetime_with_res(id, span, ident, res); + let l = self.new_named_lifetime(lifetime.id, id, span, ident); hir::GenericArg::Lifetime(l) })); @@ -1452,7 +1453,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { parent_def_id: LocalDefId, lifetimes_in_bounds: &[Lifetime], remapping: &mut FxHashMap, - ) -> Vec<(Lifetime, LifetimeRes)> { + ) -> Vec<(NodeId, Lifetime)> { let mut result = Vec::new(); for lifetime in lifetimes_in_bounds { @@ -1471,8 +1472,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); remapping.insert(old_def_id, new_def_id); - let new_lifetime = Lifetime { id: node_id, ident: lifetime.ident }; - result.push((new_lifetime, res)); + result.push((node_id, *lifetime)); } } @@ -1489,8 +1489,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); remapping.insert(old_def_id, new_def_id); - let new_lifetime = Lifetime { id: node_id, ident: lifetime.ident }; - result.push((new_lifetime, res)); + result.push((node_id, *lifetime)); } } @@ -1732,8 +1731,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } }; - let new_lifetime = Lifetime { id: inner_node_id, ident }; - captures.push((new_lifetime, inner_res)); + let lifetime = Lifetime { id: outer_node_id, ident }; + captures.push((inner_node_id, lifetime, Some(inner_res))); } debug!(?captures); @@ -1743,11 +1742,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime_collector::lifetimes_in_ret_ty(&this.resolver, output); debug!(?lifetimes_in_bounds); - captures.extend(this.create_lifetime_defs( - opaque_ty_def_id, - &lifetimes_in_bounds, - &mut new_remapping, - )); + captures.extend( + this.create_lifetime_defs( + opaque_ty_def_id, + &lifetimes_in_bounds, + &mut new_remapping, + ) + .into_iter() + .map(|(new_node_id, lifetime)| (new_node_id, lifetime, None)), + ); this.with_remapping(new_remapping, |this| { // We have to be careful to get elision right here. The @@ -1761,10 +1764,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let future_bound = this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span); - let generic_params = - this.arena.alloc_from_iter(captures.iter().map(|&(lifetime, _)| { - let hir_id = this.lower_node_id(lifetime.id); - debug_assert_ne!(this.opt_local_def_id(lifetime.id), None); + let generic_params = this.arena.alloc_from_iter(captures.iter().map( + |&(new_node_id, lifetime, _)| { + let hir_id = this.lower_node_id(new_node_id); + debug_assert_ne!(this.opt_local_def_id(new_node_id), None); let (name, kind) = if lifetime.ident.name == kw::UnderscoreLifetime { (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided) @@ -1783,7 +1786,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { kind: hir::GenericParamKind::Lifetime { kind }, colon_span: None, } - })); + }, + )); debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params); let opaque_ty_item = hir::OpaqueTy { @@ -1819,7 +1823,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // For the "output" lifetime parameters, we just want to // generate `'_`. let generic_args = - self.arena.alloc_from_iter(captures.into_iter().map(|(lifetime, res)| { + self.arena.alloc_from_iter(captures.into_iter().map(|(_, lifetime, res)| { let id = self.next_node_id(); let span = lifetime.ident.span; @@ -1829,6 +1833,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime.ident }; + let res = res.unwrap_or( + self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error), + ); let l = self.new_named_lifetime_with_res(id, span, ident, res); hir::GenericArg::Lifetime(l) })); @@ -1901,8 +1908,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { let span = self.lower_span(l.ident.span); let ident = self.lower_ident(l.ident); - let res = self.resolver.get_lifetime_res(l.id).unwrap_or(LifetimeRes::Error); - self.new_named_lifetime_with_res(l.id, span, ident, res) + self.new_named_lifetime(l.id, l.id, span, ident) } #[tracing::instrument(level = "debug", skip(self))] @@ -1936,6 +1942,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::Lifetime { hir_id: self.lower_node_id(id), span: self.lower_span(span), name } } + #[tracing::instrument(level = "debug", skip(self))] + fn new_named_lifetime( + &mut self, + id: NodeId, + new_id: NodeId, + span: Span, + ident: Ident, + ) -> hir::Lifetime { + let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error); + self.new_named_lifetime_with_res(new_id, span, ident, res) + } + fn lower_generic_params_mut<'s>( &'s mut self, params: &'s [GenericParam], From 78585098b5914a978b1c11d770e13541b97bd11f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 3 Aug 2022 17:06:30 -0300 Subject: [PATCH 33/56] Add comments about lifetime collect and create lifetime defs for RPITs --- compiler/rustc_ast_lowering/src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 69398918f897e..e7a2065110790 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1345,10 +1345,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.with_hir_id_owner(opaque_ty_node_id, |lctx| { if origin != hir::OpaqueTyOrigin::TyAlias { + // When lowering `fn foo<'a>() -> impl Debug + 'a`, the `lifetime_collector` finds + // the set of lifetimes that appear in the bounds (in this case, 'a) and returns + // that set in the variable lifetimes_in_bounds. let lifetimes_in_bounds = lifetime_collector::lifetimes_in_bounds(&lctx.resolver, bounds); debug!(?lifetimes_in_bounds); + // For each captured lifetime (e.g., 'a), we create a new lifetime parameter that + // is a generic defined on the TAIT, so we have type Foo<'a1> = ... and we + // establish a mapping from the original parameter 'a to the new parameter 'a1. collected_lifetimes = lctx.create_lifetime_defs( opaque_ty_def_id, &lifetimes_in_bounds, @@ -1359,6 +1365,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?collected_lifetimes); lctx.with_remapping(new_remapping, |lctx| { + // Then when we lower the param bounds, references to 'a are remapped to 'a1, so we + // get back Debug + 'a1, which is suitable for use on the TAIT. let hir_bounds = lctx.lower_param_bounds(bounds, itctx); let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map( From 966269a46417bcd0f6db26d9e95bc265383f815a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 3 Aug 2022 17:16:33 -0300 Subject: [PATCH 34/56] Document generics_def_id_map field and record/get methods on it --- compiler/rustc_ast_lowering/src/lib.rs | 4 ++++ compiler/rustc_middle/src/ty/mod.rs | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e7a2065110790..52beb812f7891 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -135,7 +135,11 @@ trait ResolverAstLoweringExt { fn get_lifetime_res(&self, id: NodeId) -> Option; fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>; fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind; + /// Record the map from `from` local def id to `to` local def id, on `generics_def_id_map` + /// field. fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId); + /// Get the previously recorded `to` local def id given the `from` local def id, obtained using + /// `generics_def_id_map` field. fn get_remapped_def_id(&self, local_def_id: LocalDefId) -> LocalDefId; } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dfe0a4fd36448..02da02568d7e5 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -177,7 +177,10 @@ pub struct ResolverAstLowering { pub label_res_map: NodeMap, /// Resolutions for lifetimes. pub lifetimes_res_map: NodeMap, - /// Mapping from generics def-id to RPIT copied generic def-id + /// Mapping from generics `def_id`s to TAIT generics `def_id`s. + /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic + /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this + /// field from the original parameter 'a to the new parameter 'a1. pub generics_def_id_map: Vec>, /// Lifetime parameters that lowering will have to introduce. pub extra_lifetime_params_map: NodeMap>, From c946cdceb4213485ebbe7ab8c61c1f9f6a52f535 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 3 Aug 2022 17:26:38 -0300 Subject: [PATCH 35/56] Document opt_local_def_id --- compiler/rustc_ast_lowering/src/lib.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 52beb812f7891..0e701abd605ed 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -482,6 +482,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { start } + /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name + /// resolver (if any), after applying any remapping from `get_remapped_def_id`. + /// + /// For example: for each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic + /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping from the + /// original parameter 'a to the new parameter 'a1. + /// + /// This method will return, given `'a` node id, `'a1` def id, going through, as a mid step, + /// the def_id of `'a`. + /// For cases when there are no mappings, it will just return the def_id that correspond to the + /// given node_id. fn opt_local_def_id(&self, node: NodeId) -> Option { self.resolver .node_id_to_def_id From 11e00f502aa87cef30b715bb68f03ab4ca3208a7 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 3 Aug 2022 17:32:24 -0300 Subject: [PATCH 36/56] Add comments on with_remapping --- compiler/rustc_ast_lowering/src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0e701abd605ed..dc2d6d5883b70 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -557,6 +557,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug_assert!(_old.is_none()) } + /// Installs the remapping `remap` in scope while `f` is being executed. + /// This causes references to the `LocalDefId` keys to be changed to + /// refer to the values instead. + /// + /// The remapping is used when one piece of AST expands to multiple + /// pieces of HIR. For example, the function `fn foo<'a>(...) -> impl Debug + 'a`, + /// expands to both a function definition (`foo`) and a TAIT for the return value, + /// both of which have a lifetime parameter `'a`. The remapping allows us to + /// rewrite the `'a` in the return value to refer to the + /// `'a` declared on the TAIT, instead of the function. fn with_remapping( &mut self, remap: FxHashMap, From 6289d0eb538424f312d2d39f9ec83679e451c88a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 3 Aug 2022 19:09:14 -0300 Subject: [PATCH 37/56] with_lifetime_binder is now lower_lifetime_binder and doesn't need a closure --- compiler/rustc_ast_lowering/src/expr.rs | 63 ++++++++++++------------- compiler/rustc_ast_lowering/src/lib.rs | 44 +++++++++-------- 2 files changed, 52 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 983efa48a4579..fb6715ff17ee9 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -864,22 +864,21 @@ impl<'hir> LoweringContext<'_, 'hir> { (body_id, generator_option) }); - self.with_lifetime_binder(closure_id, generic_params, |this, bound_generic_params| { - // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = this.lower_fn_decl(decl, None, FnDeclKind::Closure, None); - - let c = self.arena.alloc(hir::Closure { - binder: binder_clause, - capture_clause, - bound_generic_params, - fn_decl, - body: body_id, - fn_decl_span: this.lower_span(fn_decl_span), - movability: generator_option, - }); + let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); + // Lower outside new scope to preserve `is_in_loop_condition`. + let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None); + + let c = self.arena.alloc(hir::Closure { + binder: binder_clause, + capture_clause, + bound_generic_params, + fn_decl, + body: body_id, + fn_decl_span: self.lower_span(fn_decl_span), + movability: generator_option, + }); - hir::ExprKind::Closure(c) - }) + hir::ExprKind::Closure(c) } fn generator_movability_for_fn( @@ -991,23 +990,23 @@ impl<'hir> LoweringContext<'_, 'hir> { body_id }); - self.with_lifetime_binder(closure_id, generic_params, |this, bound_generic_params| { - // We need to lower the declaration outside the new scope, because we - // have to conserve the state of being inside a loop condition for the - // closure argument types. - let fn_decl = this.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None); - - let c = self.arena.alloc(hir::Closure { - binder: binder_clause, - capture_clause, - bound_generic_params, - fn_decl, - body, - fn_decl_span: this.lower_span(fn_decl_span), - movability: None, - }); - hir::ExprKind::Closure(c) - }) + let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); + + // We need to lower the declaration outside the new scope, because we + // have to conserve the state of being inside a loop condition for the + // closure argument types. + let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None); + + let c = self.arena.alloc(hir::Closure { + binder: binder_clause, + capture_clause, + bound_generic_params, + fn_decl, + body, + fn_decl_span: self.lower_span(fn_decl_span), + movability: None, + }); + hir::ExprKind::Closure(c) } /// Destructure the LHS of complex assignments. diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index dc2d6d5883b70..418551fd8a588 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -787,15 +787,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) } - /// Register a binder to be ignored for lifetime capture. - #[tracing::instrument(level = "debug", skip(self, f))] + /// Lowers a lifetime binder that defines `generic_params`, returning the corresponding HIR + /// nodes. The returned list includes any "extra" lifetime parameters that were added by the + /// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id + /// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime + /// parameters will be successful. + #[tracing::instrument(level = "debug", skip(self))] #[inline] - fn with_lifetime_binder( + fn lower_lifetime_binder( &mut self, binder: NodeId, generic_params: &[GenericParam], - f: impl FnOnce(&mut Self, &'hir [hir::GenericParam<'hir>]) -> T, - ) -> T { + ) -> &'hir [hir::GenericParam<'hir>] { let mut generic_params: Vec<_> = self.lower_generic_params_mut(generic_params).collect(); let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder); debug!(?extra_lifetimes); @@ -805,7 +808,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let generic_params = self.arena.alloc_from_iter(generic_params); debug!(?generic_params); - f(self, generic_params) + generic_params } fn with_dyn_type_scope(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T { @@ -1226,15 +1229,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx)) } TyKind::BareFn(ref f) => { - self.with_lifetime_binder(t.id, &f.generic_params, |this, generic_params| { - hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy { - generic_params, - unsafety: this.lower_unsafety(f.unsafety), - abi: this.lower_extern(f.ext), - decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), - param_names: this.lower_fn_params_to_names(&f.decl), - })) - }) + let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); + hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy { + generic_params, + unsafety: self.lower_unsafety(f.unsafety), + abi: self.lower_extern(f.ext), + decl: self.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), + param_names: self.lower_fn_params_to_names(&f.decl), + })) } TyKind::Never => hir::TyKind::Never, TyKind::Tup(ref tys) => hir::TyKind::Tup( @@ -2069,14 +2071,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p: &PolyTraitRef, itctx: ImplTraitContext, ) -> hir::PolyTraitRef<'hir> { - self.with_lifetime_binder( - p.trait_ref.ref_id, - &p.bound_generic_params, - |this, bound_generic_params| { - let trait_ref = this.lower_trait_ref(&p.trait_ref, itctx); - hir::PolyTraitRef { bound_generic_params, trait_ref, span: this.lower_span(p.span) } - }, - ) + let bound_generic_params = + self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); + let trait_ref = self.lower_trait_ref(&p.trait_ref, itctx); + hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } } fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { From d85720a083baf48dbfb9cbb77613ef45fc32a20f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 3 Aug 2022 19:34:00 -0300 Subject: [PATCH 38/56] Document lower_opaque_impl_trait --- compiler/rustc_ast_lowering/src/lib.rs | 29 ++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 418551fd8a588..3af5945b80927 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1349,6 +1349,35 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) } } + /// Lowers a `ReturnPositionOpaqueTy` (`-> impl Trait`) or a `TypeAliasesOpaqueTy` (`type F = + /// impl Trait`): this creates the associated Opaque Type (TAIT) definition and then returns a + /// HIR type that references the TAIT. + /// + /// Given a function definition like: + /// + /// ```rust + /// fn test<'a, T: Debug>(x: &'a T) -> impl Debug + 'a { + /// x + /// } + /// ``` + /// + /// we will create a TAIT definition in the HIR like + /// + /// ``` + /// type TestReturn<'a, T, 'x> = impl Debug + 'x + /// ``` + /// + /// and return a type like `TestReturn<'static, T, 'a>`, so that the function looks like: + /// + /// ```rust + /// fn test<'a, T: Debug>(x: &'a T) -> TestReturn<'static, T, 'a> + /// ``` + /// + /// Note the subtely around type parameters! The new TAIT, `TestReturn`, inherits all the + /// type parameters from the function `test` (this is implemented in the query layer, they aren't + /// added explicitly in the HIR). But this includes all the lifetimes, and we only want to + /// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters + /// for the lifetimes that get captured (`'x`, in our example above) and reference those. #[tracing::instrument(level = "debug", skip(self))] fn lower_opaque_impl_trait( &mut self, From 76b518fc83d1ddd112ef721fa207d3a74be83010 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 3 Aug 2022 19:40:54 -0300 Subject: [PATCH 39/56] Document what collected_lifetimes vec containts --- compiler/rustc_ast_lowering/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3af5945b80927..99617cf5ab84d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1396,6 +1396,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); + // Contains the new lifetime definitions created for the TAIT (if any). let mut collected_lifetimes = Vec::new(); let mut new_remapping = FxHashMap::default(); @@ -1760,6 +1761,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // by the opaque type. This should include all in-scope // lifetime parameters, including those defined in-band. + // Contains the new lifetime definitions created for the TAIT (if any) generated for the + // return type. let mut captures = Vec::new(); let mut new_remapping = FxHashMap::default(); From 4b9b5838ac219aaca2cc7dbc93cda61555130006 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 3 Aug 2022 23:16:03 -0300 Subject: [PATCH 40/56] Move lifetimes_in_bounds call to outside with_hir_id_owner block in lower_opaque_impl_trait --- compiler/rustc_ast_lowering/src/lib.rs | 41 +++++++++++++++----------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 99617cf5ab84d..901284f3c1971 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1400,27 +1400,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut collected_lifetimes = Vec::new(); let mut new_remapping = FxHashMap::default(); + // If this came from a TAIT (as opposed to a function that returns an RPIT), we only want + // to capture the lifetimes that appear in the bounds. So visit the bounds to find out + // exactly which ones those are. + let lifetimes_to_remap = if origin == hir::OpaqueTyOrigin::TyAlias { + // in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't keep all the lifetime parameters + Vec::new() + } else { + // in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example, + // we only keep the lifetimes that appear in the `impl Debug` itself: + lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds) + }; + debug!(?lifetimes_to_remap); + self.with_hir_id_owner(opaque_ty_node_id, |lctx| { - if origin != hir::OpaqueTyOrigin::TyAlias { - // When lowering `fn foo<'a>() -> impl Debug + 'a`, the `lifetime_collector` finds - // the set of lifetimes that appear in the bounds (in this case, 'a) and returns - // that set in the variable lifetimes_in_bounds. - let lifetimes_in_bounds = - lifetime_collector::lifetimes_in_bounds(&lctx.resolver, bounds); - debug!(?lifetimes_in_bounds); - - // For each captured lifetime (e.g., 'a), we create a new lifetime parameter that - // is a generic defined on the TAIT, so we have type Foo<'a1> = ... and we - // establish a mapping from the original parameter 'a to the new parameter 'a1. - collected_lifetimes = lctx.create_lifetime_defs( - opaque_ty_def_id, - &lifetimes_in_bounds, - &mut new_remapping, - ); - }; - debug!(?new_remapping); + // If this opaque type is only capturing a subset of the lifetimes (those that appear + // in bounds), then create the new lifetime parameters required and create a mapping + // from the old `'a` (on the function) to the new `'a` (on the opaque type). + collected_lifetimes = lctx.create_lifetime_defs( + opaque_ty_def_id, + &lifetimes_to_remap, + &mut new_remapping, + ); debug!(?collected_lifetimes); + debug!(?new_remapping); + // Install the remapping from old to new (if any): lctx.with_remapping(new_remapping, |lctx| { // Then when we lower the param bounds, references to 'a are remapped to 'a1, so we // get back Debug + 'a1, which is suitable for use on the TAIT. From 12fa3393a587f17dcea70d62ca1ee66140fb3068 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 3 Aug 2022 23:24:13 -0300 Subject: [PATCH 41/56] Move lifetimes_in_bounds call to outside with_hir_id_owner block in lower_async_fn_ret_ty --- compiler/rustc_ast_lowering/src/lib.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 901284f3c1971..a82225850c4b1 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1809,21 +1809,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?captures); - self.with_hir_id_owner(opaque_ty_node_id, |this| { - let lifetimes_in_bounds = - lifetime_collector::lifetimes_in_ret_ty(&this.resolver, output); - debug!(?lifetimes_in_bounds); + // We only want to capture the lifetimes that appear in the bounds. So visit the bounds to + // find out exactly which ones those are. + // in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example, + // we only keep the lifetimes that appear in the `impl Debug` itself: + let lifetimes_to_remap = lifetime_collector::lifetimes_in_ret_ty(&self.resolver, output); + debug!(?lifetimes_to_remap); + self.with_hir_id_owner(opaque_ty_node_id, |this| { + // If this opaque type is only capturing a subset of the lifetimes (those that appear + // in bounds), then create the new lifetime parameters required and create a mapping + // from the old `'a` (on the function) to the new `'a` (on the opaque type). captures.extend( this.create_lifetime_defs( opaque_ty_def_id, - &lifetimes_in_bounds, + &lifetimes_to_remap, &mut new_remapping, ) .into_iter() .map(|(new_node_id, lifetime)| (new_node_id, lifetime, None)), ); + debug!(?captures); + debug!(?new_remapping); + // Install the remapping from old to new (if any): this.with_remapping(new_remapping, |this| { // We have to be careful to get elision right here. The // idea is that we create a lifetime parameter for each From 3f7db370efffa24143e6a2415e6fda314f3de058 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 3 Aug 2022 23:26:10 -0300 Subject: [PATCH 42/56] captures -> collected_lifetimes --- compiler/rustc_ast_lowering/src/lib.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a82225850c4b1..c245913a05b77 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1768,7 +1768,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Contains the new lifetime definitions created for the TAIT (if any) generated for the // return type. - let mut captures = Vec::new(); + let mut collected_lifetimes = Vec::new(); let mut new_remapping = FxHashMap::default(); let extra_lifetime_params = self.resolver.take_extra_lifetime_params(opaque_ty_node_id); @@ -1804,10 +1804,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; let lifetime = Lifetime { id: outer_node_id, ident }; - captures.push((inner_node_id, lifetime, Some(inner_res))); + collected_lifetimes.push((inner_node_id, lifetime, Some(inner_res))); } - debug!(?captures); + debug!(?collected_lifetimes); // We only want to capture the lifetimes that appear in the bounds. So visit the bounds to // find out exactly which ones those are. @@ -1820,7 +1820,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // If this opaque type is only capturing a subset of the lifetimes (those that appear // in bounds), then create the new lifetime parameters required and create a mapping // from the old `'a` (on the function) to the new `'a` (on the opaque type). - captures.extend( + collected_lifetimes.extend( this.create_lifetime_defs( opaque_ty_def_id, &lifetimes_to_remap, @@ -1829,7 +1829,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .into_iter() .map(|(new_node_id, lifetime)| (new_node_id, lifetime, None)), ); - debug!(?captures); + debug!(?collected_lifetimes); debug!(?new_remapping); // Install the remapping from old to new (if any): @@ -1845,7 +1845,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let future_bound = this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span); - let generic_params = this.arena.alloc_from_iter(captures.iter().map( + let generic_params = this.arena.alloc_from_iter(collected_lifetimes.iter().map( |&(new_node_id, lifetime, _)| { let hir_id = this.lower_node_id(new_node_id); debug_assert_ne!(this.opt_local_def_id(new_node_id), None); @@ -1903,8 +1903,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // For the "output" lifetime parameters, we just want to // generate `'_`. - let generic_args = - self.arena.alloc_from_iter(captures.into_iter().map(|(_, lifetime, res)| { + let generic_args = self.arena.alloc_from_iter(collected_lifetimes.into_iter().map( + |(_, lifetime, res)| { let id = self.next_node_id(); let span = lifetime.ident.span; @@ -1919,7 +1919,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); let l = self.new_named_lifetime_with_res(id, span, ident, res); hir::GenericArg::Lifetime(l) - })); + }, + )); // Create the `Foo<...>` reference itself. Note that the `type // Foo = impl Trait` is, internally, created as a child of the From 9c7de6fb3c4f81530e1172c354104d078930d088 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 09:44:18 -0300 Subject: [PATCH 43/56] Move hir_bounds after lifetime_defs --- compiler/rustc_ast_lowering/src/lib.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c245913a05b77..17e91b22e4b88 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1427,10 +1427,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Install the remapping from old to new (if any): lctx.with_remapping(new_remapping, |lctx| { - // Then when we lower the param bounds, references to 'a are remapped to 'a1, so we - // get back Debug + 'a1, which is suitable for use on the TAIT. - let hir_bounds = lctx.lower_param_bounds(bounds, itctx); - let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map( |&(new_node_id, lifetime)| { let hir_id = lctx.lower_node_id(new_node_id); @@ -1455,9 +1451,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } }, )); - debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs); + // Then when we lower the param bounds, references to 'a are remapped to 'a1, so we + // get back Debug + 'a1, which is suitable for use on the TAIT. + let hir_bounds = lctx.lower_param_bounds(bounds, itctx); + let opaque_ty_item = hir::OpaqueTy { generics: self.arena.alloc(hir::Generics { params: lifetime_defs, From a3bfdc77a7311287e1869c5bee5d9c2213963296 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 09:52:15 -0300 Subject: [PATCH 44/56] Add documentation about lifetime_defs --- compiler/rustc_ast_lowering/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 17e91b22e4b88..2608e3a5639df 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1427,6 +1427,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Install the remapping from old to new (if any): lctx.with_remapping(new_remapping, |lctx| { + // This creates HIR lifetime definitions as `hir::GenericParam`, in the given + // example `type TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection + // containing `&['x]`. let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map( |&(new_node_id, lifetime)| { let hir_id = lctx.lower_node_id(new_node_id); From cab67404a4b7ffbf5c323d663c20069c73316950 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 09:56:12 -0300 Subject: [PATCH 45/56] Add documentation about lifetime args --- compiler/rustc_ast_lowering/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 2608e3a5639df..b1224079c2c3e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1477,6 +1477,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }) }); + // This creates HIR lifetime arguments as `hir::GenericArg`, in the given example `type + // TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing `&['x]`. let lifetimes = self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(_, lifetime)| { let id = self.next_node_id(); From 2f353d1f72771183a32634593b1debf929903f41 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 09:58:37 -0300 Subject: [PATCH 46/56] Add more debug calls --- compiler/rustc_ast_lowering/src/lib.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b1224079c2c3e..037665f1e241b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1395,6 +1395,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); + debug!(?opaque_ty_def_id); // Contains the new lifetime definitions created for the TAIT (if any). let mut collected_lifetimes = Vec::new(); @@ -1454,11 +1455,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } }, )); - debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs); + debug!(?lifetime_defs); // Then when we lower the param bounds, references to 'a are remapped to 'a1, so we // get back Debug + 'a1, which is suitable for use on the TAIT. let hir_bounds = lctx.lower_param_bounds(bounds, itctx); + debug!(?hir_bounds); let opaque_ty_item = hir::OpaqueTy { generics: self.arena.alloc(hir::Generics { @@ -1471,8 +1473,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bounds: hir_bounds, origin, }; + debug!(?opaque_ty_item); - trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id); lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span) }) }); @@ -1493,8 +1495,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let l = self.new_named_lifetime(lifetime.id, id, span, ident); hir::GenericArg::Lifetime(l) })); - - debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes); + debug!(?lifetimes); // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) From 1ece866cf1752aff853bd582a62cf29ab403e2af Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 10:02:52 -0300 Subject: [PATCH 47/56] Add documentation for create_lifetime_defs --- compiler/rustc_ast_lowering/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 037665f1e241b..a0e448506db5d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1523,6 +1523,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item)) } + /// Given a `parent_def_id`, a list of `lifetimes_in_bounds and a `remapping` hash to be + /// filled, this function creates new definitions for `Param` and `Fresh` lifetimes, inserts the + /// new definition, adds it to the remapping with the definition of the given lifetime and + /// returns a list of lifetimes to be lowered afterwards. fn create_lifetime_defs( &mut self, parent_def_id: LocalDefId, From 9f10f589a78b0ed864884b6ab108fbd081ce2a8d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 10:05:04 -0300 Subject: [PATCH 48/56] Move new_remapping inside with_hir_id_owner --- compiler/rustc_ast_lowering/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a0e448506db5d..4a3e58b2f8e2e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1399,7 +1399,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Contains the new lifetime definitions created for the TAIT (if any). let mut collected_lifetimes = Vec::new(); - let mut new_remapping = FxHashMap::default(); // If this came from a TAIT (as opposed to a function that returns an RPIT), we only want // to capture the lifetimes that appear in the bounds. So visit the bounds to find out @@ -1415,6 +1414,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?lifetimes_to_remap); self.with_hir_id_owner(opaque_ty_node_id, |lctx| { + let mut new_remapping = FxHashMap::default(); + // If this opaque type is only capturing a subset of the lifetimes (those that appear // in bounds), then create the new lifetime parameters required and create a mapping // from the old `'a` (on the function) to the new `'a` (on the opaque type). From f8b1b2bdfb0baf687873af1bbcbb7292bc39a3f7 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 10:10:04 -0300 Subject: [PATCH 49/56] Extract record_elided_anchor --- .../src/lifetime_collector.rs | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 4a7106f8da0ad..1a9677919d07c 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -29,6 +29,17 @@ impl<'ast> LifetimeCollectVisitor<'ast> { } } } + + fn record_elided_anchor(&mut self, node_id: NodeId, span: Span) { + if let Some(LifetimeRes::ElidedAnchor { start, end }) = + self.resolver.get_lifetime_res(node_id) + { + for i in start..end { + let lifetime = Lifetime { id: i, ident: Ident::new(kw::UnderscoreLifetime, span) }; + self.record_lifetime_use(lifetime); + } + } + } } impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { @@ -37,15 +48,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { } fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) { - if let Some(LifetimeRes::ElidedAnchor { start, end }) = - self.resolver.get_lifetime_res(path_segment.id) - { - for i in start..end { - let lifetime = - Lifetime { id: i, ident: Ident::new(kw::UnderscoreLifetime, path_span) }; - self.record_lifetime_use(lifetime); - } - } + self.record_elided_anchor(path_segment.id, path_span); visit::walk_path_segment(self, path_span, path_segment); } @@ -65,15 +68,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { self.current_binders.pop(); } TyKind::Rptr(None, _) => { - if let Some(LifetimeRes::ElidedAnchor { start, end }) = - self.resolver.get_lifetime_res(t.id) - { - for i in start..end { - let lifetime = - Lifetime { id: i, ident: Ident::new(kw::UnderscoreLifetime, t.span) }; - self.record_lifetime_use(lifetime); - } - } + self.record_elided_anchor(t.id, t.span); visit::walk_ty(self, t); } _ => { From 5e716599837090cb280ef98b87d6a22fbbc89084 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 10:12:56 -0300 Subject: [PATCH 50/56] Add docs to record_elided_anchor --- compiler/rustc_ast_lowering/src/lifetime_collector.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 1a9677919d07c..d22b099dd2201 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -30,6 +30,9 @@ impl<'ast> LifetimeCollectVisitor<'ast> { } } + /// This collect lifetimes that are elided, for nodes like `Foo` where there are no explicit + /// lifetime nodes. Is equivalent to having "pseudo" nodes introduced for each of the node ids + /// in the list start..end. fn record_elided_anchor(&mut self, node_id: NodeId, span: Span) { if let Some(LifetimeRes::ElidedAnchor { start, end }) = self.resolver.get_lifetime_res(node_id) From c0923c893485be4deba7470e55d98fbf80f5c3d9 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 10:14:16 -0300 Subject: [PATCH 51/56] Add docs to generics_def_id_map --- compiler/rustc_resolve/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 3e3c16f510000..ef3c3da89c572 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -913,7 +913,10 @@ pub struct Resolver<'a> { label_res_map: NodeMap, /// Resolutions for lifetimes. lifetimes_res_map: NodeMap, - /// Mapping from generics def-id to RPIT copied generic def-id + /// Mapping from generics `def_id`s to TAIT generics `def_id`s. + /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic + /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this + /// field from the original parameter 'a to the new parameter 'a1. generics_def_id_map: Vec>, /// Lifetime parameters that lowering will have to introduce. extra_lifetime_params_map: NodeMap>, From 45991f9175604becdcf8592e22f41fa1acba58fe Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 12:07:03 -0300 Subject: [PATCH 52/56] Use span_bug instead of panic --- compiler/rustc_ast_lowering/src/lib.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4a3e58b2f8e2e..49f5470d18172 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -56,6 +56,7 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::definitions::DefPathData; use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; use rustc_index::vec::{Idx, IndexVec}; +use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::parse::feature_err; use rustc_span::hygiene::MacroKind; @@ -1575,10 +1576,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Static | LifetimeRes::Error => {} - res => panic!( - "Unexpected lifetime resolution {:?} for {:?} at {:?}", - res, lifetime.ident, lifetime.ident.span - ), + res => { + let bug_msg = format!( + "Unexpected lifetime resolution {:?} for {:?} at {:?}", + res, lifetime.ident, lifetime.ident.span + ); + span_bug!(lifetime.ident.span, "{}", bug_msg); + } } } From ece52451f6278bd4b3bdf02d82153ffb5c1b7f1d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 12:40:00 -0300 Subject: [PATCH 53/56] Do not collect lifetimes with Infer resolution --- .../src/lifetime_collector.rs | 26 +++++++++++++++---- compiler/rustc_hir/src/def.rs | 9 ------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index d22b099dd2201..81006e00fd4e5 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -5,6 +5,7 @@ use rustc_ast::{ TyKind, }; use rustc_hir::def::LifetimeRes; +use rustc_middle::span_bug; use rustc_middle::ty::ResolverAstLowering; use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; @@ -21,11 +22,26 @@ impl<'ast> LifetimeCollectVisitor<'ast> { } fn record_lifetime_use(&mut self, lifetime: Lifetime) { - let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error); - - if res.binder().map_or(true, |b| !self.current_binders.contains(&b)) { - if !self.collected_lifetimes.contains(&lifetime) { - self.collected_lifetimes.push(lifetime); + match self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error) { + LifetimeRes::Param { binder, .. } | LifetimeRes::Fresh { binder, .. } => { + if !self.current_binders.contains(&binder) { + if !self.collected_lifetimes.contains(&lifetime) { + self.collected_lifetimes.push(lifetime); + } + } + } + LifetimeRes::Static | LifetimeRes::Error => { + if !self.collected_lifetimes.contains(&lifetime) { + self.collected_lifetimes.push(lifetime); + } + } + LifetimeRes::Infer => {} + res => { + let bug_msg = format!( + "Unexpected lifetime resolution {:?} for {:?} at {:?}", + res, lifetime.ident, lifetime.ident.span + ); + span_bug!(lifetime.ident.span, "{}", bug_msg); } } } diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 2a89947f92762..be5b7eccbafb2 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -747,12 +747,3 @@ pub enum LifetimeRes { /// HACK: This is used to recover the NodeId of an elided lifetime. ElidedAnchor { start: NodeId, end: NodeId }, } - -impl LifetimeRes { - pub fn binder(&self) -> Option { - match self { - LifetimeRes::Param { binder, .. } | LifetimeRes::Fresh { binder, .. } => Some(*binder), - _ => None, - } - } -} From bf1c7da1476c8193a0e92262c3e4dd2d88392569 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 12:47:19 -0300 Subject: [PATCH 54/56] Improve record_def_id_remap docs --- compiler/rustc_ast_lowering/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 49f5470d18172..84388d3d65377 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -210,7 +210,10 @@ impl ResolverAstLoweringExt for ResolverAstLowering { self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang) } - /// Push a remapping into the top-most map. Panics if no map has been pushed. + /// Push a remapping into the top-most map. + /// Panics if no map has been pushed. + /// Remapping is used when creating lowering `-> impl Trait` return + /// types to create the resulting opaque type. #[tracing::instrument(level = "debug", skip(self))] fn record_def_id_remap(&mut self, from: LocalDefId, to: LocalDefId) { self.generics_def_id_map.last_mut().expect("no map pushed").insert(from, to); From 065e497630db6d9be3e1fd984270c9807408b55e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 12:47:58 -0300 Subject: [PATCH 55/56] Improve opt_local_def_id docs --- compiler/rustc_ast_lowering/src/lib.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 84388d3d65377..f86dcb9c4c881 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -489,14 +489,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name /// resolver (if any), after applying any remapping from `get_remapped_def_id`. /// - /// For example: for each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic - /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping from the - /// original parameter 'a to the new parameter 'a1. + /// For example, in a function like `fn foo<'a>(x: &'a u32)`, + /// invoking with the id from the `ast::Lifetime` node found inside + /// the `&'a u32` type would return the `LocalDefId` of the + /// `'a` parameter declared on `foo`. /// - /// This method will return, given `'a` node id, `'a1` def id, going through, as a mid step, - /// the def_id of `'a`. - /// For cases when there are no mappings, it will just return the def_id that correspond to the - /// given node_id. + /// This function also applies remapping from `get_remapped_def_id`. + /// These are used when synthesizing opaque types from `-> impl Trait` return types and so forth. + /// For example, in a function like `fn foo<'a>() -> impl Debug + 'a`, + /// we would create an opaque type `type FooReturn<'a1> = impl Debug + 'a1`. + /// When lowering the `Debug + 'a` bounds, we add a remapping to map `'a` to `'a1`. fn opt_local_def_id(&self, node: NodeId) -> Option { self.resolver .node_id_to_def_id From 4170d7390b90b5eee001d6292b3273dec6d67651 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Aug 2022 12:48:20 -0300 Subject: [PATCH 56/56] Fix typo --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f86dcb9c4c881..a5b089b032d8b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1379,7 +1379,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// fn test<'a, T: Debug>(x: &'a T) -> TestReturn<'static, T, 'a> /// ``` /// - /// Note the subtely around type parameters! The new TAIT, `TestReturn`, inherits all the + /// Note the subtlety around type parameters! The new TAIT, `TestReturn`, inherits all the /// type parameters from the function `test` (this is implemented in the query layer, they aren't /// added explicitly in the HIR). But this includes all the lifetimes, and we only want to /// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters