diff options
| author | Jack Huey <jack.huey@umassmed.edu> | 2021-03-26 17:40:15 -0400 |
|---|---|---|
| committer | Jack Huey <jack.huey@umassmed.edu> | 2021-03-31 10:16:37 -0400 |
| commit | 7108918db6f59fca6656849c3e360045354e8a42 (patch) | |
| tree | 124e089444740f2ac65eef217e221cd832033ef7 /compiler | |
| parent | 0c98dc66fdc1bd5a2ff56bc72c67b03c2d376cd0 (diff) | |
| download | rust-7108918db6f59fca6656849c3e360045354e8a42.tar.gz rust-7108918db6f59fca6656849c3e360045354e8a42.zip | |
Cleanups and comments
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_middle/src/ty/util.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/monomorphize/mod.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/lifetimes.rs | 407 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/supertraits.rs | 60 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/auto_trait.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/astconv/mod.rs | 5 |
7 files changed, 214 insertions, 265 deletions
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index b211ac2a79f..7d09ca5152f 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -504,7 +504,6 @@ impl<'tcx> TyCtxt<'tcx> { let closure_ty = self.mk_closure(closure_def_id, closure_substs); let closure_kind_ty = closure_substs.as_closure().kind_ty(); let closure_kind = closure_kind_ty.to_opt_closure_kind()?; - debug_assert!(!closure_ty.has_escaping_bound_vars()); let env_ty = match closure_kind { ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty), ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty), diff --git a/compiler/rustc_mir/src/monomorphize/mod.rs b/compiler/rustc_mir/src/monomorphize/mod.rs index fd3f3b3a080..9ca4b6687f1 100644 --- a/compiler/rustc_mir/src/monomorphize/mod.rs +++ b/compiler/rustc_mir/src/monomorphize/mod.rs @@ -1,6 +1,6 @@ use rustc_middle::traits; use rustc_middle::ty::adjustment::CustomCoerceUnsized; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_hir::lang_items::LangItem; @@ -15,8 +15,6 @@ fn custom_coerce_unsize_info<'tcx>( ) -> CustomCoerceUnsized { let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None); - debug_assert!(!source_ty.has_escaping_bound_vars()); - debug_assert!(!target_ty.has_escaping_bound_vars()); let trait_ref = ty::Binder::dummy(ty::TraitRef { def_id, substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]), diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 25acbd478bf..1377bb781d0 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -34,7 +34,6 @@ use tracing::debug; mod diagnostics; crate mod lifetimes; -crate mod supertraits; type Res = def::Res<NodeId>; diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 79d81ef047e..b89ad867f46 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -151,6 +151,12 @@ struct NamedRegionMap { // (b) it DOES appear in the arguments. late_bound: HirIdSet, + // Maps relevant hir items to the bound vars on them. These include: + // - function defs + // - function pointers + // - closures + // - trait refs + // - bound types (like `T` in `for<'a> T<'a>: Foo`) late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>, } @@ -171,10 +177,16 @@ crate struct LifetimeContext<'a, 'tcx> { /// any bound var information. /// /// So, if we encounter a quantifier at the outer scope, we set - /// `trait_ref_hack` to `true` (and introduce a scope), and then if we encounter - /// a quantifier at the inner scope, we error. If `trait_ref_hack` is `false`, - /// then we introduce the scope at the inner quantifier. - trait_ref_hack: Option<(Vec<ty::BoundVariableKind>, u32)>, + /// `trait_ref_hack` to the hir id of the bounded type (and introduce a scope). + /// Then, if we encounter a quantifier at the inner scope, then we know to + /// emit an error. Importantly though, we do have to track the lifetimes + /// defined on the outer scope (i.e. the bounded ty), since we continue + /// to type check after emitting an error; we therefore assume that the bound + /// vars on the inner trait refs come from both quantifiers. + /// + /// If we encounter a quantifier in the inner scope `trait_ref_hack` being + /// `None`, then we just introduce the scope at the inner quantifier as normal. + trait_ref_hack: Option<hir::HirId>, /// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax. is_in_fn_syntax: bool, @@ -232,11 +244,9 @@ enum Scope<'a> { /// of the resulting opaque type. opaque_type_parent: bool, - /// We need to keep track of the number of named late bound vars, since - /// we may have elided lifetimes that have an index starting *after* - /// these. - named_late_bound_vars: u32, - + /// True only if this `Binder` scope is from the quantifiers on a + /// `PolyTraitRef`. This is necessary for `assocated_type_bounds`, which + /// requires binders of nested trait refs to be merged. from_poly_trait_ref: bool, /// The late bound vars for a given item are stored by `HirId` to be @@ -304,7 +314,6 @@ enum Scope<'a> { /// vars from both `for<...>`s *do* share the same binder level. TraitRefHackInner { hir_id: hir::HirId, - named_late_bound_vars: u32, s: ScopeRef<'a>, }, @@ -331,7 +340,6 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { next_early_index, track_lifetime_uses, opaque_type_parent, - named_late_bound_vars, from_poly_trait_ref, hir_id, s: _, @@ -341,7 +349,6 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { .field("next_early_index", next_early_index) .field("track_lifetime_uses", track_lifetime_uses) .field("opaque_type_parent", opaque_type_parent) - .field("named_late_bound_vars", named_late_bound_vars) .field("from_poly_trait_ref", from_poly_trait_ref) .field("hir_id", hir_id) .field("s", &"..") @@ -357,10 +364,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { .field("lifetime", lifetime) .field("s", &"..") .finish(), - Scope::TraitRefHackInner { hir_id, named_late_bound_vars, s: _ } => f + Scope::TraitRefHackInner { hir_id, s: _ } => f .debug_struct("TraitRefHackInner") .field("hir_id", hir_id) - .field("named_late_bound_vars", named_late_bound_vars) .field("s", &"..") .finish(), Scope::Supertrait { lifetimes, s: _ } => f @@ -664,7 +670,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: false, - named_late_bound_vars: 0, from_poly_trait_ref: false, }; self.with(scope, move |_old_scope, this| { @@ -790,7 +795,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index: index + non_lifetime_count, opaque_type_parent: true, track_lifetime_uses, - named_late_bound_vars: 0, from_poly_trait_ref: false, s: ROOT_SCOPE, }; @@ -838,21 +842,19 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }; self.missing_named_lifetime_spots .push(MissingLifetimeSpot::HigherRanked { span, span_type }); - let mut named_late_bound_vars = 0; let (lifetimes, binders): (FxHashMap<hir::ParamName, Region>, Vec<_>) = c .generic_params .iter() .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - let late_bound_idx = named_late_bound_vars; - named_late_bound_vars += 1; - let pair = Region::late(late_bound_idx, &self.tcx.hir(), param); - let r = pair.1.clone(); - let r = late_region_as_bound_region(self.tcx, &r); - Some((pair, r)) - } + GenericParamKind::Lifetime { .. } => Some(param), _ => None, }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param); + let r = late_region_as_bound_region(self.tcx, &pair.1); + (pair, r) + }) .unzip(); self.map.late_bound_vars.insert(ty.hir_id, binders); let scope = Scope::Binder { @@ -862,7 +864,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index, track_lifetime_uses: true, opaque_type_parent: false, - named_late_bound_vars, from_poly_trait_ref: false, }; self.with(scope, |old_scope, this| { @@ -1053,7 +1054,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: this.scope, track_lifetime_uses: true, opaque_type_parent: false, - named_late_bound_vars: 0, from_poly_trait_ref: false, }; this.with(scope, |_old_scope, this| { @@ -1071,7 +1071,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: false, - named_late_bound_vars: 0, from_poly_trait_ref: false, }; self.with(scope, |_old_scope, this| { @@ -1128,7 +1127,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, - named_late_bound_vars: 0, from_poly_trait_ref: false, }; self.with(scope, |old_scope, this| { @@ -1195,7 +1193,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, - named_late_bound_vars: 0, from_poly_trait_ref: false, }; self.with(scope, |old_scope, this| { @@ -1279,21 +1276,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { ref bound_generic_params, .. }) => { - let mut named_late_bound_vars = 0; - let (lifetimes, binders): (FxHashMap<_, _>, Vec<_>) = bound_generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - let late_bound_idx = named_late_bound_vars; - named_late_bound_vars += 1; - let pair = Region::late(late_bound_idx, &self.tcx.hir(), param); - let r = pair.1.clone(); - let r = late_region_as_bound_region(self.tcx, &r); - Some((pair, r)) - } - _ => None, - }) - .unzip(); + let (lifetimes, binders): (FxHashMap<hir::ParamName, Region>, Vec<_>) = + bound_generic_params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some(param), + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = + Region::late(late_bound_idx as u32, &self.tcx.hir(), param); + let r = late_region_as_bound_region(self.tcx, &pair.1); + (pair, r) + }) + .unzip(); self.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone()); if !lifetimes.is_empty() { let next_early_index = self.next_early_index(); @@ -1304,13 +1301,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index, track_lifetime_uses: true, opaque_type_parent: false, - named_late_bound_vars, from_poly_trait_ref: true, }; let result = self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &bound_generic_params); this.visit_ty(&bounded_ty); - this.trait_ref_hack = Some((binders, named_late_bound_vars)); + this.trait_ref_hack = Some(bounded_ty.hir_id); walk_list!(this, visit_param_bound, bounds); this.trait_ref_hack = None; }); @@ -1351,7 +1347,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index: self.next_early_index(), track_lifetime_uses: true, opaque_type_parent: false, - named_late_bound_vars: 0, from_poly_trait_ref: false, }; self.with(scope, |_, this| { @@ -1389,112 +1384,97 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { .emit(); } - let (binders, named_late_bound_vars, lifetimes) = - if let Some((mut binders, mut named_late_bound_vars)) = trait_ref_hack.clone() { - let initial_binders = named_late_bound_vars; - binders.extend(trait_ref.bound_generic_params.iter().filter_map(|param| { - match param.kind { - GenericParamKind::Lifetime { .. } => { - let late_bound_idx = named_late_bound_vars; - named_late_bound_vars += 1; - let region = Region::late(late_bound_idx, &self.tcx.hir(), param).1; - Some(late_region_as_bound_region(self.tcx, ®ion)) - } - GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, - } - })); - - let mut named_late_bound_vars = initial_binders; - let lifetimes: FxHashMap<hir::ParamName, Region> = trait_ref - .bound_generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - let late_bound_idx = named_late_bound_vars; - named_late_bound_vars += 1; - Some(Region::late(late_bound_idx, &self.tcx.hir(), param)) - } - _ => None, - }) - .collect(); - - (binders, named_late_bound_vars, lifetimes) - } else { - let mut supertrait_lifetimes = vec![]; - let mut scope = self.scope; - let mut binders = loop { - match scope { - Scope::Body { .. } | Scope::Root => { - break vec![]; - } + let (binders, lifetimes) = if let Some(hir_id) = trait_ref_hack { + let mut binders = self.map.late_bound_vars.entry(hir_id).or_default().clone(); + let initial_bound_vars = binders.len() as u32; + let mut lifetimes: FxHashMap<hir::ParamName, Region> = FxHashMap::default(); + let binders_iter = trait_ref + .bound_generic_params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some(param), + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = Region::late( + initial_bound_vars + late_bound_idx as u32, + &self.tcx.hir(), + param, + ); + let r = late_region_as_bound_region(self.tcx, &pair.1); + lifetimes.insert(pair.0, pair.1); + r + }); + binders.extend(binders_iter); - Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { - scope = s; - } + (binders, lifetimes) + } else { + let mut supertrait_lifetimes = vec![]; + let mut scope = self.scope; + let mut outer_binders = loop { + match scope { + Scope::Body { .. } | Scope::Root => { + break vec![]; + } - Scope::TraitRefHackInner { hir_id, .. } => { - // Nested poly trait refs have the binders concatenated - // If we reach `TraitRefHackInner`, then there is only one more `Binder` above us, - // over all the bounds. We don't want this, since all the lifetimes we care about - // are here anyways. - let mut full_binders = - self.map.late_bound_vars.entry(*hir_id).or_default().clone(); - full_binders.extend(supertrait_lifetimes.into_iter()); - break full_binders; - } + Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { + scope = s; + } - Scope::Supertrait { s, lifetimes } => { - supertrait_lifetimes = lifetimes.clone(); - scope = s; - } + Scope::TraitRefHackInner { hir_id, .. } => { + // Nested poly trait refs have the binders concatenated + // If we reach `TraitRefHackInner`, then there is only one more `Binder` above us, + // over all the bounds. We don't want this, since all the lifetimes we care about + // are here anyways. + let mut full_binders = + self.map.late_bound_vars.entry(*hir_id).or_default().clone(); + full_binders.extend(supertrait_lifetimes.into_iter()); + break full_binders; + } - Scope::Binder { hir_id, from_poly_trait_ref, .. } => { - if !from_poly_trait_ref { - // We should only see super trait lifetimes if there is a `Binder` above - assert!(supertrait_lifetimes.is_empty()); - break vec![]; - } - // Nested poly trait refs have the binders concatenated - let mut full_binders = - self.map.late_bound_vars.entry(*hir_id).or_default().clone(); - full_binders.extend(supertrait_lifetimes.into_iter()); - break full_binders; - } + Scope::Supertrait { s, lifetimes } => { + supertrait_lifetimes = lifetimes.clone(); + scope = s; } - }; - let mut named_late_bound_vars = binders.len() as u32; - let local_binders: Vec<_> = trait_ref - .bound_generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - let late_bound_idx = named_late_bound_vars; - named_late_bound_vars += 1; - let region = Region::late(late_bound_idx, &self.tcx.hir(), param).1; - Some(late_region_as_bound_region(self.tcx, ®ion)) - } - GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, - }) - .collect(); - let mut named_late_bound_vars = binders.len() as u32; - let lifetimes: FxHashMap<hir::ParamName, Region> = trait_ref - .bound_generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - let late_bound_idx = named_late_bound_vars; - named_late_bound_vars += 1; - Some(Region::late(late_bound_idx, &self.tcx.hir(), param)) + Scope::Binder { hir_id, from_poly_trait_ref, .. } => { + if !from_poly_trait_ref { + // We should only see super trait lifetimes if there is a `Binder` above + assert!(supertrait_lifetimes.is_empty()); + break vec![]; } - _ => None, - }) - .collect(); + // Nested poly trait refs have the binders concatenated + let mut full_binders = + self.map.late_bound_vars.entry(*hir_id).or_default().clone(); + full_binders.extend(supertrait_lifetimes.into_iter()); + break full_binders; + } + } + }; + let (lifetimes, local_binders): (FxHashMap<hir::ParamName, Region>, Vec<_>) = trait_ref + .bound_generic_params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some(param), + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = Region::late( + outer_binders.len() as u32 + late_bound_idx as u32, + &self.tcx.hir(), + param, + ); + let r = late_region_as_bound_region(self.tcx, &pair.1); + (pair, r) + }) + .unzip(); - binders.extend(local_binders.into_iter()); + outer_binders.extend(local_binders.into_iter()); - (binders, named_late_bound_vars, lifetimes) - }; + (outer_binders, lifetimes) + }; debug!(?binders); self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders); @@ -1507,7 +1487,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index, track_lifetime_uses: true, opaque_type_parent: false, - named_late_bound_vars: named_late_bound_vars as u32, from_poly_trait_ref: true, }; self.with(scope, |old_scope, this| { @@ -1516,11 +1495,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { this.visit_trait_ref(&trait_ref.trait_ref); }); } else { - let scope = Scope::TraitRefHackInner { - hir_id: trait_ref.trait_ref.hir_ref_id, - named_late_bound_vars: named_late_bound_vars as u32, - s: self.scope, - }; + let scope = + Scope::TraitRefHackInner { hir_id: trait_ref.trait_ref.hir_ref_id, s: self.scope }; self.with(scope, |_old_scope, this| { this.visit_trait_ref(&trait_ref.trait_ref); }); @@ -2234,23 +2210,22 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .collect(); let next_early_index = next_early_index + non_lifetime_count; - let mut named_late_bound_vars = 0; let binders: Vec<_> = generics .params .iter() .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - if self.map.late_bound.contains(¶m.hir_id) { - let late_bound_idx = named_late_bound_vars; - named_late_bound_vars += 1; - let r = Region::late(late_bound_idx, &self.tcx.hir(), param).1; - let r = late_region_as_bound_region(self.tcx, &r); - Some(r) - } else { - None - } + GenericParamKind::Lifetime { .. } + if self.map.late_bound.contains(¶m.hir_id) => + { + Some(param) } - GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, + _ => None, + }) + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = Region::late(late_bound_idx as u32, &self.tcx.hir(), param); + let r = late_region_as_bound_region(self.tcx, &pair.1); + r }) .collect(); self.map.late_bound_vars.insert(hir_id, binders); @@ -2261,7 +2236,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { s: self.scope, opaque_type_parent: true, track_lifetime_uses: false, - named_late_bound_vars: named_late_bound_vars as u32, from_poly_trait_ref: false, }; self.with(scope, move |old_scope, this| { @@ -2629,49 +2603,85 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let has_lifetime_parameter = generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))); - // Resolve lifetimes found in the type `XX` from `Item = XX` bindings. + // Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or + // in the trait ref `YY<...>` in `Item: YY<...>`. for binding in generic_args.bindings { let scope = Scope::ObjectLifetimeDefault { lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) }, s: self.scope, }; if let Some(type_def_id) = type_def_id { - let lifetimes = - LifetimeContext::supertrait_bounds(self.tcx, type_def_id, binding.ident); - if let Some(lifetimes) = lifetimes { - self.with(scope, |_, this| { - let scope = Scope::Supertrait { lifetimes, s: this.scope }; - this.with(scope, |_, this| this.visit_assoc_type_binding(binding)); - }); - } else { - self.with(scope, |_, this| this.visit_assoc_type_binding(binding)); - } + let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes( + self.tcx, + type_def_id, + binding.ident, + ); + self.with(scope, |_, this| { + let scope = + Scope::Supertrait { lifetimes: lifetimes.unwrap_or(vec![]), s: this.scope }; + this.with(scope, |_, this| this.visit_assoc_type_binding(binding)); + }); } else { self.with(scope, |_, this| this.visit_assoc_type_binding(binding)); } } } - fn trait_defines_associated_type_named( - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, - assoc_name: Ident, - ) -> bool { - tcx.associated_items(trait_def_id) - .find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id) - .is_some() - } - - fn supertrait_bounds( + /// Returns all the late-bound vars that come into scope from supertrait HRTBs, based on the + /// associated type name and starting trait. + /// For example, imagine we have + /// ```rust + /// trait Foo<'a, 'b> { + /// type As; + /// } + /// trait Bar<'b>: for<'a> Foo<'a, 'b> {} + /// trait Bar: for<'b> Bar<'b> {} + /// ``` + /// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on + /// the starting trait `Bar`, we would return `Some(['b, 'a])`. + fn supertrait_hrtb_lifetimes( tcx: TyCtxt<'tcx>, def_id: DefId, assoc_name: Ident, ) -> Option<Vec<ty::BoundVariableKind>> { - let all_candidates = super::supertraits::supertraits(tcx, def_id); - let mut matching_candidates = all_candidates - .filter(|r| LifetimeContext::trait_defines_associated_type_named(tcx, r.0, assoc_name)); + let trait_defines_associated_type_named = |trait_def_id: DefId| { + tcx.associated_items(trait_def_id) + .find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id) + .is_some() + }; + + use smallvec::{smallvec, SmallVec}; + let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> = + smallvec![(def_id, smallvec![])]; + let mut visited: FxHashSet<DefId> = FxHashSet::default(); + loop { + let (def_id, bound_vars) = match stack.pop() { + Some(next) => next, + None => break None, + }; + if trait_defines_associated_type_named(def_id) { + break Some(bound_vars.into_iter().collect()); + } + let predicates = + tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name))); + let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| { + let bound_predicate = pred.kind(); + match bound_predicate.skip_binder() { + ty::PredicateKind::Trait(data, _) => { + // The order here needs to match what we would get from `subst_supertrait` + let pred_bound_vars = bound_predicate.bound_vars(); + let mut all_bound_vars = bound_vars.clone(); + all_bound_vars.extend(pred_bound_vars.iter()); + let super_def_id = data.trait_ref.def_id; + Some((super_def_id, all_bound_vars)) + } + _ => None, + } + }); - matching_candidates.next().map(|c| c.1.into_iter().collect()) + let obligations = obligations.filter(|o| visited.insert(o.0)); + stack.extend(obligations); + } } #[tracing::instrument(level = "debug", skip(self))] @@ -2682,13 +2692,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { ) { debug!("visit_fn_like_elision: enter"); let mut scope = &*self.scope; - let (hir_id, named_late_bound_vars) = loop { + let hir_id = loop { match scope { - Scope::Binder { hir_id, named_late_bound_vars, .. } - | Scope::TraitRefHackInner { hir_id, named_late_bound_vars, .. } => { - break (*hir_id, *named_late_bound_vars); + Scope::Binder { hir_id, .. } | Scope::TraitRefHackInner { hir_id, .. } => { + break *hir_id; } - Scope::Body { id, .. } => break (id.hir_id, 0), + Scope::Body { id, .. } => break id.hir_id, Scope::ObjectLifetimeDefault { ref s, .. } | Scope::Elision { ref s, .. } | Scope::Supertrait { ref s, .. } => { @@ -2697,11 +2706,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Root => bug!("In fn_like_elision without appropriate scope above"), } }; + // While not strictly necessary, we gather anon lifetimes *before* actually + // visiting the argument types. let mut gather = GatherAnonLifetimes { anon_count: 0 }; for input in inputs { gather.visit_ty(input); } - self.map.late_bound_vars.entry(hir_id).or_default().extend( + let late_bound_vars = self.map.late_bound_vars.entry(hir_id).or_default(); + let named_late_bound_vars = late_bound_vars.len() as u32; + late_bound_vars.extend( (0..gather.anon_count).map(|var| ty::BoundVariableKind::Region(ty::BrAnon(var))), ); let arg_scope = Scope::Elision { @@ -2987,6 +3000,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } fn visit_ty(&mut self, ty: &hir::Ty<'_>) { + // If we enter a `BareFn`, then we enter a *new* binding scope if let hir::TyKind::BareFn(_) = ty.kind { return; } @@ -2998,6 +3012,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { path_span: Span, generic_args: &'v hir::GenericArgs<'v>, ) { + // parenthesized args enter a new elison scope if generic_args.parenthesized { return; } diff --git a/compiler/rustc_resolve/src/late/supertraits.rs b/compiler/rustc_resolve/src/late/supertraits.rs deleted file mode 100644 index 2130c33bd77..00000000000 --- a/compiler/rustc_resolve/src/late/supertraits.rs +++ /dev/null @@ -1,60 +0,0 @@ -use smallvec::{smallvec, SmallVec}; - -use rustc_data_structures::fx::FxHashSet; -use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, TyCtxt}; - -pub struct Elaborator<'tcx> { - tcx: TyCtxt<'tcx>, - stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]>, - visited: FxHashSet<DefId>, -} - -#[allow(dead_code)] -pub fn supertraits<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Elaborator<'tcx> { - Elaborator { tcx, stack: smallvec![(def_id, smallvec![])], visited: Default::default() } -} - -impl<'tcx> Elaborator<'tcx> { - fn elaborate(&mut self, def_id: DefId, bound_vars: &SmallVec<[ty::BoundVariableKind; 8]>) { - let tcx = self.tcx; - - let predicates = tcx.super_predicates_of(def_id); - let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| { - let bound_predicate = pred.kind(); - match bound_predicate.skip_binder() { - ty::PredicateKind::Trait(data, _) => { - // The order here needs to match what we would get from `subst_supertrait` - let pred_bound_vars = bound_predicate.bound_vars(); - let mut all_bound_vars = bound_vars.clone(); - all_bound_vars.extend(pred_bound_vars.iter()); - let super_def_id = data.trait_ref.def_id; - Some((super_def_id, all_bound_vars)) - } - _ => None, - } - }); - - let visited = &mut self.visited; - let obligations = obligations.filter(|o| visited.insert(o.0)); - self.stack.extend(obligations); - } -} - -impl<'tcx> Iterator for Elaborator<'tcx> { - type Item = (DefId, SmallVec<[ty::BoundVariableKind; 8]>); - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.stack.len(), None) - } - - fn next(&mut self) -> Option<Self::Item> { - match self.stack.pop() { - Some((def_id, bound_vars)) => { - self.elaborate(def_id, &bound_vars); - Some((def_id, bound_vars)) - } - None => None, - } - } -} diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index cb66dc7e5d9..f54eb0914a5 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -82,7 +82,6 @@ impl<'tcx> AutoTraitFinder<'tcx> { ) -> AutoTraitResult<A> { let tcx = self.tcx; - debug_assert!(!ty.has_escaping_bound_vars()); let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) }; let trait_pred = ty::Binder::dummy(trait_ref); diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 8d55bc8f2f3..b6de491911a 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2186,13 +2186,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } + /// Parses the programmer's textual representation of a type into our + /// internal notion of a type. pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { self.ast_ty_to_ty_inner(ast_ty, false) } - /// Parses the programmer's textual representation of a type into our - /// internal notion of a type. - /// /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors. #[tracing::instrument(level = "debug", skip(self))] |
