X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_ast_lowering%2Fsrc%2Flib.rs;h=9009ae7a0510f2407a48fb1070205db6276aa975;hb=25825cd4fa735c4b6d8b004940709bc066477c7c;hp=a1bf0f94964bb70e8d342dd18b868482cb0bbb89;hpb=fe3342816a282949f014caa05ea2e669ff9d3d3c;p=rust.git diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a1bf0f94964..9009ae7a051 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -957,7 +957,7 @@ fn lower_assoc_ty_constraint( 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 @@ fn lower_assoc_ty_constraint( tokens: None, }, itctx, + true, ); hir::TypeBindingKind::Equality { term: ty.into() } @@ -1029,7 +1030,7 @@ fn lower_assoc_ty_constraint( } 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 @@ fn lower_generic_arg( 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 @@ fn lower_generic_arg( } _ => {} } - 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 @@ fn lower_generic_arg( } #[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 @@ fn lower_path_ty( 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 @@ fn lower_path_ty( 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 @@ fn lower_path_ty( } 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 @@ fn ty_tup(&mut self, span: Span, tys: &'hir [hir::Ty<'hir>]) -> hir::Ty<'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 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'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 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'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 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'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 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'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 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'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 } @@ -1293,17 +1304,17 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'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) - }), + 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), + bounds, + nested_itctx, ) } ImplTraitContext::Universal => { @@ -1343,13 +1354,14 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'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 @@ -1363,13 +1375,32 @@ fn lower_opaque_impl_trait( 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 { - lctx.while_capturing_lifetimes( - opaque_ty_def_id, - &mut collected_lifetimes, - lower_bounds, - ) + 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); + + lctx.create_and_capture_lifetime_defs(&lifetimes_in_bounds, &binders_to_ignore); + + 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 }; debug!(?collected_lifetimes); @@ -1417,7 +1448,7 @@ fn lower_opaque_impl_trait( |(_, (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) }, )); @@ -1450,6 +1481,86 @@ fn generate_opaque_type( 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. @@ -1495,7 +1606,7 @@ fn lower_fn_decl( } 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 +1620,7 @@ fn lower_fn_decl( FnDeclKind::Trait => ImplTraitPosition::TraitParam, FnDeclKind::Impl => ImplTraitPosition::ImplParam, }), + true, ) } })); @@ -1540,7 +1652,7 @@ fn lower_fn_decl( 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)), } @@ -1582,11 +1694,9 @@ fn lower_fn_decl( // // 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, @@ -1748,7 +1858,7 @@ fn lower_async_fn_ret_ty( 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) })); @@ -1778,7 +1888,7 @@ fn lower_async_fn_output_type_to_future_bound( 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, &[])), }; @@ -1805,23 +1915,24 @@ fn lower_param_bound( &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))] @@ -1831,35 +1942,45 @@ fn new_named_lifetime_with_res( 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 !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; + } } } + } 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 let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { if !captured_lifetimes.binders_to_ignore.contains(&binder) { @@ -1867,6 +1988,7 @@ fn new_named_lifetime_with_res( 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, @@ -1943,7 +2065,11 @@ fn lower_generic_param_kind( 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, }; @@ -1951,7 +2077,8 @@ fn lower_generic_param_kind( (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)), @@ -1961,8 +2088,20 @@ fn lower_generic_param_kind( } } - 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), }; @@ -1974,35 +2113,38 @@ fn lower_poly_trait_ref( &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( @@ -2015,7 +2157,6 @@ fn lower_generic_and_bounds( // 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), @@ -2030,7 +2171,8 @@ fn lower_generic_and_bounds( ident, node_id, &GenericParamKind::Type { default: None }, - hir_bounds, + bounds, + ImplTraitContext::Universal, hir::PredicateOrigin::ImplTrait, );