diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 03af81ae02a6d..6317808e7fbe0 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -402,7 +402,7 @@ pub enum TraitBoundModifier { /// `typeck::collect::compute_bounds` matches these against /// the "special" built-in traits (see `middle::lang_items`) and /// detects `Copy`, `Send` and `Sync`. -#[derive(Debug, HashStable_Generic)] +#[derive(Clone, Debug, HashStable_Generic)] pub enum GenericBound<'hir> { Trait(PolyTraitRef<'hir>, TraitBoundModifier), // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem` @@ -2556,7 +2556,7 @@ pub enum UseKind { /// that the `ref_id` is for. Note that `ref_id`'s value is not the `HirId` of the /// trait being referred to but just a unique `HirId` that serves as a key /// within the resolution map. -#[derive(Debug, HashStable_Generic)] +#[derive(Clone, Debug, HashStable_Generic)] pub struct TraitRef<'hir> { pub path: &'hir Path<'hir>, // Don't hash the `ref_id`. It is tracked via the thing it is used to access. @@ -2575,7 +2575,7 @@ impl TraitRef<'_> { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Clone, Debug, HashStable_Generic)] pub struct PolyTraitRef<'hir> { /// The `'a` in `for<'a> Foo<&'a T>`. pub bound_generic_params: &'hir [GenericParam<'hir>], diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index aa4fd055d5ee0..c68705da413f8 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -293,7 +293,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { self.tcx } - fn fold_binder(&mut self, t: ty::Binder) -> ty::Binder + fn fold_binder(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> where T: TypeFoldable<'tcx>, { @@ -621,7 +621,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { let var = self.canonical_var(info, r.into()); - let br = ty::BoundRegion { kind: ty::BrAnon(var.as_u32()) }; + let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32()) }; let region = ty::ReLateBound(self.binder_index, br); self.tcx().mk_region(region) } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index f000d491b99a6..b8ecc949588fb 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -439,7 +439,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(debruijn, ty::INNERMOST); - opt_values[br.assert_bound_var()] = Some(*original_value); + opt_values[br.var] = Some(*original_value); } } GenericArgKind::Const(result_value) => { diff --git a/compiler/rustc_infer/src/infer/canonical/substitute.rs b/compiler/rustc_infer/src/infer/canonical/substitute.rs index 387f480814ae7..553a11d4393f9 100644 --- a/compiler/rustc_infer/src/infer/canonical/substitute.rs +++ b/compiler/rustc_infer/src/infer/canonical/substitute.rs @@ -71,11 +71,10 @@ where if var_values.var_values.is_empty() { value } else { - let fld_r = - |br: ty::BoundRegion| match var_values.var_values[br.assert_bound_var()].unpack() { - GenericArgKind::Lifetime(l) => l, - r => bug!("{:?} is a region but value is {:?}", br, r), - }; + let fld_r = |br: ty::BoundRegion| match var_values.var_values[br.var].unpack() { + GenericArgKind::Lifetime(l) => l, + r => bug!("{:?} is a region but value is {:?}", br, r), + }; let fld_t = |bound_ty: ty::BoundTy| match var_values.var_values[bound_ty.var].unpack() { GenericArgKind::Type(ty) => ty, diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index ffe947d209dd6..debf108253793 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -545,9 +545,9 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { @@ -840,9 +840,9 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 7c388b5503ee3..45ba50bb6349c 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -124,9 +124,9 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index a18c9569a8cd3..a91bd9ce2ff74 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -514,7 +514,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { fn print_dyn_existential( self, - _predicates: &'tcx ty::List>>, + _predicates: &'tcx ty::List>>, ) -> Result { Err(NonTrivialPath) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index 35b9bc96f1339..58eb1e9aa12cb 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -115,7 +115,7 @@ impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { // error. We will then search the function parameters for a bound // region at the right depth with the same index ( - Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), + Some(rl::Region::LateBoundAnon(debruijn_index, _, anon_index)), ty::BrAnon(br_index), ) => { debug!( @@ -143,7 +143,7 @@ impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { // error. We will then search the function parameters for a bound // region at the right depth with the same index ( - Some(rl::Region::LateBound(debruijn_index, id, _)), + Some(rl::Region::LateBound(debruijn_index, _, id, _)), ty::BrNamed(def_id, _), ) => { debug!( @@ -162,8 +162,8 @@ impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { rl::Region::Static | rl::Region::Free(_, _) | rl::Region::EarlyBound(_, _, _) - | rl::Region::LateBound(_, _, _) - | rl::Region::LateBoundAnon(_, _), + | rl::Region::LateBound(_, _, _, _) + | rl::Region::LateBoundAnon(_, _, _), ) | None, _, @@ -217,7 +217,10 @@ impl Visitor<'tcx> for TyPathVisitor<'tcx> { fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) { match (self.tcx.named_region(lifetime.hir_id), self.bound_region) { // the lifetime of the TyPath! - (Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => { + ( + Some(rl::Region::LateBoundAnon(debruijn_index, _, anon_index)), + ty::BrAnon(br_index), + ) => { if debruijn_index == self.current_index && anon_index == br_index { self.found_it = true; return; @@ -232,7 +235,7 @@ impl Visitor<'tcx> for TyPathVisitor<'tcx> { } } - (Some(rl::Region::LateBound(debruijn_index, id, _)), ty::BrNamed(def_id, _)) => { + (Some(rl::Region::LateBound(debruijn_index, _, id, _)), ty::BrNamed(def_id, _)) => { debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,); debug!("id={:?}", id); debug!("def_id={:?}", def_id); @@ -246,8 +249,8 @@ impl Visitor<'tcx> for TyPathVisitor<'tcx> { Some( rl::Region::Static | rl::Region::EarlyBound(_, _, _) - | rl::Region::LateBound(_, _, _) - | rl::Region::LateBoundAnon(_, _) + | rl::Region::LateBound(_, _, _, _) + | rl::Region::LateBoundAnon(_, _, _) | rl::Region::Free(_, _), ) | None, diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index ccba904df9e00..02662043dba79 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -85,9 +85,9 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index e794903fca3aa..d460222df8ad0 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -11,10 +11,10 @@ use rustc_middle::ty::{self, Binder, TypeFoldable}; impl<'a, 'tcx> CombineFields<'a, 'tcx> { pub fn higher_ranked_sub( &mut self, - a: Binder, - b: Binder, + a: Binder<'tcx, T>, + b: Binder<'tcx, T>, a_is_expected: bool, - ) -> RelateResult<'tcx, Binder> + ) -> RelateResult<'tcx, Binder<'tcx, T>> where T: Relate<'tcx>, { @@ -50,7 +50,10 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { debug!("higher_ranked_sub: OK result={:?}", result); - Ok(ty::Binder::bind(result)) + // We related `a_prime` and `b_prime`, which just had any bound vars + // replaced with placeholders or infer vars, respectively. Relating + // them should not introduce new bound vars. + Ok(ty::Binder::dummy(result)) }) } } @@ -66,7 +69,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// the [rustc dev guide]. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html - pub fn replace_bound_vars_with_placeholders(&self, binder: ty::Binder) -> T + pub fn replace_bound_vars_with_placeholders(&self, binder: ty::Binder<'tcx, T>) -> T where T: TypeFoldable<'tcx>, { diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index 9f43fac0916b5..4fa8f2f1a6a42 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -85,9 +85,9 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 9fb045e8e400b..eaec6b46bcd14 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1406,7 +1406,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &self, span: Span, lbrct: LateBoundRegionConversionTime, - value: ty::Binder, + value: ty::Binder<'tcx, T>, ) -> (T, BTreeMap>) where T: TypeFoldable<'tcx>, diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index e5eb771603cd7..fc9ea07866c21 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -157,7 +157,7 @@ where fn create_scope( &mut self, - value: ty::Binder>, + value: ty::Binder<'tcx, impl Relate<'tcx>>, universally_quantified: UniversallyQuantified, ) -> BoundRegionScope<'tcx> { let mut scope = BoundRegionScope::default(); @@ -608,9 +608,9 @@ where fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { @@ -744,7 +744,7 @@ struct ScopeInstantiator<'me, 'tcx> { impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> { fn visit_binder>( &mut self, - t: &ty::Binder, + t: &ty::Binder<'tcx, T>, ) -> ControlFlow { self.target_index.shift_in(1); t.super_visit_with(self); @@ -997,9 +997,9 @@ where fn binders( &mut self, - a: ty::Binder, - _: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + _: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 668719851583c..bf5f328233dfd 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -162,9 +162,9 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 0882d682e1537..a33234a91faff 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -128,7 +128,7 @@ impl<'tcx> FulfillmentError<'tcx> { } impl<'tcx> TraitObligation<'tcx> { - pub fn self_ty(&self) -> ty::Binder> { + pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> { self.predicate.map_bound(|p| p.self_ty()) } } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index e4403f879ffcd..14bd823ea2266 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -909,7 +909,7 @@ impl<'tcx> LateContext<'tcx> { fn print_dyn_existential( self, - _predicates: &'tcx ty::List>>, + _predicates: &'tcx ty::List>>, ) -> Result { Ok(()) } diff --git a/compiler/rustc_middle/src/ich/impls_ty.rs b/compiler/rustc_middle/src/ich/impls_ty.rs index 573b514e8445f..8e53e4ba94805 100644 --- a/compiler/rustc_middle/src/ich/impls_ty.rs +++ b/compiler/rustc_middle/src/ich/impls_ty.rs @@ -70,16 +70,16 @@ impl<'a> HashStable> for ty::RegionKind { ty::ReEmpty(universe) => { universe.hash_stable(hcx, hasher); } - ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i) }) => { + ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => { db.hash_stable(hcx, hasher); i.hash_stable(hcx, hasher); } - ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name) }) => { + ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name), .. }) => { db.hash_stable(hcx, hasher); def_id.hash_stable(hcx, hasher); name.hash_stable(hcx, hasher); } - ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv }) => { + ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv, .. }) => { db.hash_stable(hcx, hasher); } ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => { @@ -118,12 +118,13 @@ impl<'tcx> HashStable> for ty::BoundVar { } } -impl<'a, T> HashStable> for ty::Binder +impl<'a, 'tcx, T> HashStable> for ty::Binder<'tcx, T> where T: HashStable>, { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { self.as_ref().skip_binder().hash_stable(hcx, hasher); + self.bound_vars().hash_stable(hcx, hasher); } } diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 7ed4cbf034fe1..5df2f91f09fff 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -277,7 +277,7 @@ impl<'tcx, V> Canonical<'tcx, V> { } pub type QueryOutlivesConstraint<'tcx> = - ty::Binder, Region<'tcx>>>; + ty::Binder<'tcx, ty::OutlivesPredicate, Region<'tcx>>>; TrivialTypeFoldableAndLiftImpls! { for <'tcx> { @@ -314,7 +314,8 @@ impl<'tcx> CanonicalVarValues<'tcx> { tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into() } GenericArgKind::Lifetime(..) => { - let br = ty::BoundRegion { kind: ty::BrAnon(i) }; + let br = + ty::BoundRegion { var: ty::BoundVar::from_u32(i), kind: ty::BrAnon(i) }; tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into() } GenericArgKind::Const(ct) => tcx diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs index 32615f6c410c7..aa6488b329eba 100644 --- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs +++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs @@ -39,8 +39,13 @@ impl LifetimeDefOrigin { pub enum Region { Static, EarlyBound(/* index */ u32, /* lifetime decl */ DefId, LifetimeDefOrigin), - LateBound(ty::DebruijnIndex, /* lifetime decl */ DefId, LifetimeDefOrigin), - LateBoundAnon(ty::DebruijnIndex, /* anon index */ u32), + LateBound( + ty::DebruijnIndex, + /* late-bound index */ u32, + /* lifetime decl */ DefId, + LifetimeDefOrigin, + ), + LateBoundAnon(ty::DebruijnIndex, /* late-bound index */ u32, /* anon index */ u32), Free(DefId, /* lifetime decl */ DefId), } @@ -78,4 +83,6 @@ pub struct ResolveLifetimes { /// be late-bound if (a) it does NOT appear in a where-clause and /// (b) it DOES appear in the arguments. pub late_bound: FxHashMap>, + + pub late_bound_vars: FxHashMap>>, } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index fbd5af9d0a9e2..99d063c7eeafb 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1290,6 +1290,10 @@ rustc_queries! { -> Option> { desc { "looking up lifetime defaults for a region on an item" } } + query late_bound_vars_map(_: LocalDefId) + -> Option<&'tcx FxHashMap>> { + desc { "looking up late bound vars" } + } query visibility(def_id: DefId) -> ty::Visibility { eval_always diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 90b82020551c2..922d14bc2f574 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -341,7 +341,7 @@ impl ObligationCauseCode<'_> { // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(ObligationCauseCode<'_>, 32); +static_assert_size!(ObligationCauseCode<'_>, 40); #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum StatementAsExpression { diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index a5962e3b3ba57..8e2c79701af90 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -112,9 +112,9 @@ impl TypeRelation<'tcx> for Match<'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 59e1695cdb9d0..d7767dc39cb32 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -120,8 +120,9 @@ impl<'tcx, E: TyEncoder<'tcx>> Encodable for Ty<'tcx> { } } -impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Binder> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Binder<'tcx, ty::PredicateKind<'tcx>> { fn encode(&self, e: &mut E) -> Result<(), E::Error> { + self.bound_vars().encode(e)?; encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands) } } @@ -226,18 +227,22 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable for Ty<'tcx> { } } -impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Binder> { - fn decode(decoder: &mut D) -> Result>, D::Error> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Binder<'tcx, ty::PredicateKind<'tcx>> { + fn decode(decoder: &mut D) -> Result>, D::Error> { + let bound_vars = Decodable::decode(decoder)?; // Handle shorthands first, if we have an usize > 0x80. - Ok(ty::Binder::bind(if decoder.positioned_at_shorthand() { - let pos = decoder.read_usize()?; - assert!(pos >= SHORTHAND_OFFSET); - let shorthand = pos - SHORTHAND_OFFSET; - - decoder.with_position(shorthand, ty::PredicateKind::decode)? - } else { - ty::PredicateKind::decode(decoder)? - })) + Ok(ty::Binder::bind_with_vars( + if decoder.positioned_at_shorthand() { + let pos = decoder.read_usize()?; + assert!(pos >= SHORTHAND_OFFSET); + let shorthand = pos - SHORTHAND_OFFSET; + + decoder.with_position(shorthand, ty::PredicateKind::decode)? + } else { + ty::PredicateKind::decode(decoder)? + }, + bound_vars, + )) } } @@ -319,7 +324,7 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List> { } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> - for ty::List>> + for ty::List>> { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { let len = decoder.read_usize()?; @@ -379,15 +384,23 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::N } } +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List { + fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { + let len = decoder.read_usize()?; + Ok(decoder.tcx().mk_bound_variable_kinds((0..len).map(|_| Decodable::decode(decoder)))?) + } +} + impl_decodable_via_ref! { &'tcx ty::TypeckResults<'tcx>, &'tcx ty::List>, - &'tcx ty::List>>, + &'tcx ty::List>>, &'tcx Allocation, &'tcx mir::Body<'tcx>, &'tcx mir::UnsafetyCheckResult, &'tcx mir::BorrowCheckResult<'tcx>, - &'tcx mir::coverage::CodeRegion + &'tcx mir::coverage::CodeRegion, + &'tcx ty::List } #[macro_export] @@ -488,14 +501,16 @@ macro_rules! implement_ty_decoder { macro_rules! impl_binder_encode_decode { ($($t:ty),+ $(,)?) => { $( - impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Binder<$t> { + impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Binder<'tcx, $t> { fn encode(&self, e: &mut E) -> Result<(), E::Error> { + self.bound_vars().encode(e)?; self.as_ref().skip_binder().encode(e) } } - impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Binder<$t> { + impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Binder<'tcx, $t> { fn decode(decoder: &mut D) -> Result { - Ok(ty::Binder::bind(Decodable::decode(decoder)?)) + let bound_vars = Decodable::decode(decoder)?; + Ok(ty::Binder::bind_with_vars(Decodable::decode(decoder)?, bound_vars)) } } )* diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 94c1758b25c21..bb2b00cbaea81 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -87,7 +87,8 @@ pub struct CtxtInterners<'tcx> { substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List>>, region: InternedSet<'tcx, RegionKind>, - poly_existential_predicates: InternedSet<'tcx, List>>>, + poly_existential_predicates: + InternedSet<'tcx, List>>>, predicate: InternedSet<'tcx, PredicateInner<'tcx>>, predicates: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, @@ -95,6 +96,7 @@ pub struct CtxtInterners<'tcx> { const_: InternedSet<'tcx, Const<'tcx>>, /// Const allocations. allocation: InternedSet<'tcx, Allocation>, + bound_variable_kinds: InternedSet<'tcx, List>, } impl<'tcx> CtxtInterners<'tcx> { @@ -113,6 +115,7 @@ impl<'tcx> CtxtInterners<'tcx> { place_elems: Default::default(), const_: Default::default(), allocation: Default::default(), + bound_variable_kinds: Default::default(), } } @@ -136,7 +139,10 @@ impl<'tcx> CtxtInterners<'tcx> { } #[inline(never)] - fn intern_predicate(&self, kind: Binder>) -> &'tcx PredicateInner<'tcx> { + fn intern_predicate( + &self, + kind: Binder<'tcx, PredicateKind<'tcx>>, + ) -> &'tcx PredicateInner<'tcx> { self.predicate .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_predicate(kind); @@ -449,7 +455,7 @@ pub struct TypeckResults<'tcx> { /// Stores the type, expression, span and optional scope span of all types /// that are live across the yield of this generator (if a generator). - pub generator_interior_types: ty::Binder>>, + pub generator_interior_types: ty::Binder<'tcx, Vec>>, /// We sometimes treat byte string literals (which are of type `&[u8; N]`) /// as `&[u8]`, depending on the pattern in which they are used. @@ -804,7 +810,7 @@ impl CanonicalUserType<'tcx> { ty::ReLateBound(debruijn, br) => { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(*debruijn, ty::INNERMOST); - cvar == br.assert_bound_var() + cvar == br.var } _ => false, }, @@ -1616,10 +1622,11 @@ nop_lift! {allocation; &'a Allocation => &'tcx Allocation} nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>} nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>} -nop_list_lift! {poly_existential_predicates; ty::Binder> => ty::Binder>} +nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate<'a>> => ty::Binder<'tcx, ExistentialPredicate<'tcx>>} nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>} nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>} nop_list_lift! {projs; ProjectionKind => ProjectionKind} +nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind} // This is the impl for `&'a InternalSubsts<'a>`. nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>} @@ -1965,8 +1972,8 @@ impl<'tcx> Hash for Interned<'tcx, PredicateInner<'tcx>> { } } -impl<'tcx> Borrow>> for Interned<'tcx, PredicateInner<'tcx>> { - fn borrow<'a>(&'a self) -> &'a Binder> { +impl<'tcx> Borrow>> for Interned<'tcx, PredicateInner<'tcx>> { + fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> { &self.0.kind } } @@ -2072,10 +2079,11 @@ slice_interners!( substs: _intern_substs(GenericArg<'tcx>), canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>), poly_existential_predicates: - _intern_poly_existential_predicates(ty::Binder>), + _intern_poly_existential_predicates(ty::Binder<'tcx, ExistentialPredicate<'tcx>>), predicates: _intern_predicates(Predicate<'tcx>), projs: _intern_projs(ProjectionKind), place_elems: _intern_place_elems(PlaceElem<'tcx>), + bound_variable_kinds: _intern_bound_variable_kinds(ty::BoundVariableKind), ); impl<'tcx> TyCtxt<'tcx> { @@ -2158,7 +2166,7 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_predicate(self, binder: Binder>) -> Predicate<'tcx> { + pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { let inner = self.interners.intern_predicate(binder); Predicate { inner } } @@ -2167,7 +2175,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn reuse_or_mk_predicate( self, pred: Predicate<'tcx>, - binder: Binder>, + binder: Binder<'tcx, PredicateKind<'tcx>>, ) -> Predicate<'tcx> { if pred.kind() != binder { self.mk_predicate(binder) } else { pred } } @@ -2334,7 +2342,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_dynamic( self, - obj: &'tcx List>>, + obj: &'tcx List>>, reg: ty::Region<'tcx>, ) -> Ty<'tcx> { self.mk_ty(Dynamic(obj, reg)) @@ -2361,7 +2369,7 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_generator_witness(self, types: ty::Binder<&'tcx List>>) -> Ty<'tcx> { + pub fn mk_generator_witness(self, types: ty::Binder<'tcx, &'tcx List>>) -> Ty<'tcx> { self.mk_ty(GeneratorWitness(types)) } @@ -2466,8 +2474,8 @@ impl<'tcx> TyCtxt<'tcx> { pub fn intern_poly_existential_predicates( self, - eps: &[ty::Binder>], - ) -> &'tcx List>> { + eps: &[ty::Binder<'tcx, ExistentialPredicate<'tcx>>], + ) -> &'tcx List>> { assert!(!eps.is_empty()); assert!( eps.array_windows() @@ -2512,6 +2520,13 @@ impl<'tcx> TyCtxt<'tcx> { if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) } } + pub fn intern_bound_variable_kinds( + self, + ts: &[ty::BoundVariableKind], + ) -> &'tcx List { + if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) } + } + pub fn mk_fn_sig( self, inputs: I, @@ -2533,8 +2548,8 @@ impl<'tcx> TyCtxt<'tcx> { pub fn mk_poly_existential_predicates< I: InternAs< - [ty::Binder>], - &'tcx List>>, + [ty::Binder<'tcx, ExistentialPredicate<'tcx>>], + &'tcx List>>, >, >( self, @@ -2572,6 +2587,15 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_substs(iter::once(self_ty.into()).chain(rest.iter().cloned())) } + pub fn mk_bound_variable_kinds< + I: InternAs<[ty::BoundVariableKind], &'tcx List>, + >( + self, + iter: I, + ) -> I::Output { + iter.intern_with(|xs| self.intern_bound_variable_kinds(xs)) + } + /// Walks upwards from `id` to find a node which might change lint levels with attributes. /// It stops at `bound` and just returns it if reached. pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId { @@ -2648,6 +2672,17 @@ impl<'tcx> TyCtxt<'tcx> { pub fn object_lifetime_defaults(self, id: HirId) -> Option> { self.object_lifetime_defaults_map(id.owner) } + + pub fn late_bound_vars(self, id: HirId) -> &'tcx List { + self.mk_bound_variable_kinds( + self.late_bound_vars_map(id.owner) + .and_then(|map| map.get(&id.local_id).cloned()) + .unwrap_or_else(|| { + bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id) + }) + .iter(), + ) + } } impl TyCtxtAt<'tcx> { diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 4412ba9408c6c..79e88662f652d 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -43,7 +43,7 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> { if ty.needs_infer() { ty.super_fold_with(self) } else { self.tcx.erase_regions_ty(ty) } } - fn fold_binder(&mut self, t: ty::Binder) -> ty::Binder + fn fold_binder(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> where T: TypeFoldable<'tcx>, { diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index f19cc99844926..4767e5743c22e 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -57,7 +57,9 @@ pub enum TypeError<'tcx> { CyclicTy(Ty<'tcx>), CyclicConst(&'tcx ty::Const<'tcx>), ProjectionMismatched(ExpectedFound), - ExistentialMismatch(ExpectedFound<&'tcx ty::List>>>), + ExistentialMismatch( + ExpectedFound<&'tcx ty::List>>>, + ), ObjectUnsafeCoercion(DefId), ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>), diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index d6dc81c5b785d..01bc5cc761ca6 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -22,7 +22,7 @@ impl FlagComputation { result } - pub fn for_predicate(binder: ty::Binder>) -> FlagComputation { + pub fn for_predicate(binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) -> FlagComputation { let mut result = FlagComputation::new(); result.add_predicate(binder); result @@ -53,7 +53,7 @@ impl FlagComputation { /// Adds the flags/depth from a set of types that appear within the current type, but within a /// region binder. - fn bound_computation(&mut self, value: ty::Binder, f: F) + fn bound_computation(&mut self, value: ty::Binder<'_, T>, f: F) where F: FnOnce(&mut Self, T), { @@ -204,7 +204,7 @@ impl FlagComputation { } } - fn add_predicate(&mut self, binder: ty::Binder>) { + fn add_predicate(&mut self, binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) { self.bound_computation(binder, |computation, atom| computation.add_predicate_atom(atom)); } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index a6a1d1f73bb62..70f3ac3004042 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -35,6 +35,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::sso::SsoHashSet; use std::collections::BTreeMap; use std::fmt; use std::ops::ControlFlow; @@ -161,7 +162,7 @@ impl TypeFoldable<'tcx> for hir::Constness { pub trait TypeFolder<'tcx>: Sized { fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; - fn fold_binder(&mut self, t: Binder) -> Binder + fn fold_binder(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> where T: TypeFoldable<'tcx>, { @@ -184,7 +185,10 @@ pub trait TypeFolder<'tcx>: Sized { pub trait TypeVisitor<'tcx>: Sized { type BreakTy = !; - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { t.super_visit_with(self) } @@ -322,7 +326,7 @@ impl<'tcx> TyCtxt<'tcx> { fn visit_binder>( &mut self, - t: &Binder, + t: &Binder<'tcx, T>, ) -> ControlFlow { self.outer_index.shift_in(1); let result = t.as_ref().skip_binder().visit_with(self); @@ -400,7 +404,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { self.current_index.shift_in(1); let t = t.super_fold_with(self); self.current_index.shift_out(1); @@ -460,7 +467,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { self.current_index.shift_in(1); let t = t.super_fold_with(self); self.current_index.shift_out(1); @@ -538,7 +548,7 @@ impl<'tcx> TyCtxt<'tcx> { /// contain escaping bound types. pub fn replace_late_bound_regions( self, - value: Binder, + value: Binder<'tcx, T>, mut fld_r: F, ) -> (T, BTreeMap>) where @@ -588,7 +598,7 @@ impl<'tcx> TyCtxt<'tcx> { /// types. pub fn replace_bound_vars( self, - value: Binder, + value: Binder<'tcx, T>, mut fld_r: F, fld_t: G, fld_c: H, @@ -607,7 +617,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Replaces any late-bound regions bound in `value` with /// free variants attached to `all_outlive_scope`. - pub fn liberate_late_bound_regions(self, all_outlive_scope: DefId, value: ty::Binder) -> T + pub fn liberate_late_bound_regions( + self, + all_outlive_scope: DefId, + value: ty::Binder<'tcx, T>, + ) -> T where T: TypeFoldable<'tcx>, { @@ -620,13 +634,49 @@ impl<'tcx> TyCtxt<'tcx> { .0 } + pub fn shift_bound_var_indices(self, bound_vars: usize, value: T) -> T + where + T: TypeFoldable<'tcx>, + { + self.replace_escaping_bound_vars( + value, + |r| { + self.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { + var: ty::BoundVar::from_usize(r.var.as_usize() + bound_vars), + kind: r.kind, + }, + )) + }, + |t| { + self.mk_ty(ty::Bound( + ty::INNERMOST, + ty::BoundTy { + var: ty::BoundVar::from_usize(t.var.as_usize() + bound_vars), + kind: t.kind, + }, + )) + }, + |c, ty| { + self.mk_const(ty::Const { + val: ty::ConstKind::Bound( + ty::INNERMOST, + ty::BoundVar::from_usize(c.as_usize() + bound_vars), + ), + ty, + }) + }, + ) + } + /// Returns a set of all late-bound regions that are constrained /// by `value`, meaning that if we instantiate those LBR with /// variables and equate `value` with something else, those /// variables will also be equated. pub fn collect_constrained_late_bound_regions( self, - value: &Binder, + value: &Binder<'tcx, T>, ) -> FxHashSet where T: TypeFoldable<'tcx>, @@ -637,7 +687,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns a set of all late-bound regions that appear in `value` anywhere. pub fn collect_referenced_late_bound_regions( self, - value: &Binder, + value: &Binder<'tcx, T>, ) -> FxHashSet where T: TypeFoldable<'tcx>, @@ -647,7 +697,7 @@ impl<'tcx> TyCtxt<'tcx> { fn collect_late_bound_regions( self, - value: &Binder, + value: &Binder<'tcx, T>, just_constraint: bool, ) -> FxHashSet where @@ -661,7 +711,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also /// method lookup and a few other places where precise region relationships are not required. - pub fn erase_late_bound_regions(self, value: Binder) -> T + pub fn erase_late_bound_regions(self, value: Binder<'tcx, T>) -> T where T: TypeFoldable<'tcx>, { @@ -676,20 +726,205 @@ impl<'tcx> TyCtxt<'tcx> { /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become /// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization. - pub fn anonymize_late_bound_regions(self, sig: Binder) -> Binder + pub fn anonymize_late_bound_regions(self, sig: Binder<'tcx, T>) -> Binder<'tcx, T> where T: TypeFoldable<'tcx>, { let mut counter = 0; - Binder::bind( - self.replace_late_bound_regions(sig, |_| { - let br = ty::BoundRegion { kind: ty::BrAnon(counter) }; + let inner = self + .replace_late_bound_regions(sig, |_| { + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(counter), + kind: ty::BrAnon(counter), + }; let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br)); counter += 1; r }) - .0, - ) + .0; + let bound_vars = self.mk_bound_variable_kinds( + (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))), + ); + Binder::bind_with_vars(inner, bound_vars) + } +} + +pub struct BoundVarsCollector<'tcx> { + binder_index: ty::DebruijnIndex, + vars: BTreeMap, + // We may encounter the same variable at different levels of binding, so + // this can't just be `Ty` + visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>, +} + +impl<'tcx> BoundVarsCollector<'tcx> { + pub fn new() -> Self { + BoundVarsCollector { + binder_index: ty::INNERMOST, + vars: BTreeMap::new(), + visited: SsoHashSet::default(), + } + } + + pub fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List { + let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or_else(|| 0); + for i in 0..max { + if let None = self.vars.get(&i) { + panic!("Unknown variable: {:?}", i); + } + } + + tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v)) + } +} + +impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { + type BreakTy = (); + + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { + self.binder_index.shift_in(1); + let result = t.super_visit_with(self); + self.binder_index.shift_out(1); + result + } + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + if t.outer_exclusive_binder < self.binder_index + || !self.visited.insert((self.binder_index, t)) + { + return ControlFlow::CONTINUE; + } + use std::collections::btree_map::Entry; + match *t.kind() { + ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { + match self.vars.entry(bound_ty.var.as_u32()) { + Entry::Vacant(entry) => { + entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind)); + } + Entry::Occupied(entry) => match entry.get() { + ty::BoundVariableKind::Ty(_) => {} + _ => bug!("Conflicting bound vars"), + }, + } + } + + _ => (), + }; + + t.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + match r { + ty::ReLateBound(index, _br) if *index == self.binder_index => { + // If you hit this, you should be using `Binder::bind_with_vars` or `Binder::rebind` + bug!("Trying to collect bound vars with a bound region: {:?} {:?}", index, _br) + } + + _ => (), + }; + + r.super_visit_with(self) + } +} + +pub struct ValidateBoundVars<'tcx> { + bound_vars: &'tcx ty::List, + binder_index: ty::DebruijnIndex, + // We may encounter the same variable at different levels of binding, so + // this can't just be `Ty` + visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>, +} + +impl<'tcx> ValidateBoundVars<'tcx> { + pub fn new(bound_vars: &'tcx ty::List) -> Self { + ValidateBoundVars { + bound_vars, + binder_index: ty::INNERMOST, + visited: SsoHashSet::default(), + } + } +} + +impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> { + type BreakTy = (); + + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { + self.binder_index.shift_in(1); + let result = t.super_visit_with(self); + self.binder_index.shift_out(1); + result + } + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + if t.outer_exclusive_binder < self.binder_index + || !self.visited.insert((self.binder_index, t)) + { + return ControlFlow::BREAK; + } + match *t.kind() { + ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { + if self.bound_vars.len() <= bound_ty.var.as_usize() { + bug!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars); + } + let list_var = self.bound_vars[bound_ty.var.as_usize()]; + match list_var { + ty::BoundVariableKind::Ty(kind) => { + if kind != bound_ty.kind { + bug!( + "Mismatched type kinds: {:?} doesn't var in list {:?}", + bound_ty.kind, + list_var + ); + } + } + _ => { + bug!("Mismatched bound variable kinds! Expected type, found {:?}", list_var) + } + } + } + + _ => (), + }; + + t.super_visit_with(self) + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + match r { + ty::ReLateBound(index, br) if *index == self.binder_index => { + if self.bound_vars.len() <= br.var.as_usize() { + bug!("Not enough bound vars: {:?} not found in {:?}", *br, self.bound_vars); + } + let list_var = self.bound_vars[br.var.as_usize()]; + match list_var { + ty::BoundVariableKind::Region(kind) => { + if kind != br.kind { + bug!( + "Mismatched region kinds: {:?} doesn't match var ({:?}) in list ({:?})", + br.kind, + list_var, + self.bound_vars + ); + } + } + _ => bug!( + "Mismatched bound variable kinds! Expected region, found {:?}", + list_var + ), + } + } + + _ => (), + }; + + r.super_visit_with(self) } } @@ -719,7 +954,10 @@ impl TypeFolder<'tcx> for Shifter<'tcx> { self.tcx } - fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { self.current_index.shift_in(1); let t = t.super_fold_with(self); self.current_index.shift_out(1); @@ -828,7 +1066,10 @@ struct HasEscapingVarsVisitor { impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { type BreakTy = FoundEscapingVars; - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { self.outer_index.shift_in(1); let result = t.super_visit_with(self); self.outer_index.shift_out(1); @@ -974,7 +1215,10 @@ impl LateBoundRegionsCollector { } impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { self.current_index.shift_in(1); let result = t.super_visit_with(self); self.current_index.shift_out(1); diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0d03cf4575fcf..e7bbdc3ccebdf 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1,3 +1,4 @@ +// ignore-tidy-filelength use crate::ich::StableHashingContext; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; @@ -2481,21 +2482,42 @@ impl<'tcx> ty::Instance<'tcx> { ty::Closure(def_id, substs) => { let sig = substs.as_closure().sig(); - let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); - sig.map_bound(|sig| { + let bound_vars = tcx.mk_bound_variable_kinds( + sig.bound_vars() + .iter() + .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + ); + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind: ty::BoundRegionKind::BrEnv, + }; + let env_region = ty::ReLateBound(ty::INNERMOST, br); + let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap(); + + let sig = sig.skip_binder(); + ty::Binder::bind_with_vars( tcx.mk_fn_sig( - iter::once(env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), + iter::once(env_ty).chain(sig.inputs().iter().cloned()), sig.output(), sig.c_variadic, sig.unsafety, sig.abi, - ) - }) + ), + bound_vars, + ) } ty::Generator(_, substs, _) => { let sig = substs.as_generator().poly_sig(); - let br = ty::BoundRegion { kind: ty::BrEnv }; + let bound_vars = tcx.mk_bound_variable_kinds( + sig.bound_vars() + .iter() + .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + ); + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind: ty::BoundRegionKind::BrEnv, + }; let env_region = ty::ReLateBound(ty::INNERMOST, br); let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); @@ -2504,21 +2526,21 @@ impl<'tcx> ty::Instance<'tcx> { let pin_substs = tcx.intern_substs(&[env_ty.into()]); let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); - sig.map_bound(|sig| { - let state_did = tcx.require_lang_item(LangItem::GeneratorState, None); - let state_adt_ref = tcx.adt_def(state_did); - let state_substs = - tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]); - let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); - + let sig = sig.skip_binder(); + let state_did = tcx.require_lang_item(LangItem::GeneratorState, None); + let state_adt_ref = tcx.adt_def(state_did); + let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]); + let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); + ty::Binder::bind_with_vars( tcx.mk_fn_sig( [env_ty, sig.resume_ty].iter(), &ret_ty, false, hir::Unsafety::Normal, rustc_target::spec::abi::Abi::Rust, - ) - }) + ), + bound_vars, + ) } _ => bug!("unexpected type {:?} in Instance::fn_sig", ty), } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c0025cf3fc8a5..6574c9382604b 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -67,12 +67,12 @@ pub use self::sty::BoundRegionKind::*; pub use self::sty::RegionKind::*; pub use self::sty::TyKind::*; pub use self::sty::{ - Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, CanonicalPolyFnSig, - ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion, ExistentialPredicate, - ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, GeneratorSubsts, - GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection, PolyExistentialTraitRef, - PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef, - TyKind, TypeAndMut, UpvarSubsts, + Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind, + CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion, + ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, + GeneratorSubsts, GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection, + PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind, + RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, }; pub use self::trait_def::TraitDef; @@ -302,7 +302,7 @@ impl<'tcx> TyS<'tcx> { // `TyS` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(TyS<'_>, 32); +static_assert_size!(TyS<'_>, 40); impl<'tcx> Ord for TyS<'tcx> { fn cmp(&self, other: &TyS<'tcx>) -> Ordering { @@ -359,14 +359,14 @@ impl ty::EarlyBoundRegion { #[derive(Debug)] crate struct PredicateInner<'tcx> { - kind: Binder>, + kind: Binder<'tcx, PredicateKind<'tcx>>, flags: TypeFlags, /// See the comment for the corresponding field of [TyS]. outer_exclusive_binder: ty::DebruijnIndex, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(PredicateInner<'_>, 40); +static_assert_size!(PredicateInner<'_>, 48); #[derive(Clone, Copy, Lift)] pub struct Predicate<'tcx> { @@ -389,9 +389,9 @@ impl Hash for Predicate<'_> { impl<'tcx> Eq for Predicate<'tcx> {} impl<'tcx> Predicate<'tcx> { - /// Gets the inner `Binder>`. + /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. #[inline] - pub fn kind(self) -> Binder> { + pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { self.inner.kind } } @@ -543,10 +543,33 @@ impl<'tcx> Predicate<'tcx> { // substitution code expects equal binding levels in the values // from the substitution and the value being substituted into, and // this trick achieves that). - let substs = trait_ref.skip_binder().substs; - let pred = self.kind().skip_binder(); - let new = pred.subst(tcx, substs); - tcx.reuse_or_mk_predicate(self, ty::Binder::bind(new)) + + // Working through the second example: + // trait_ref: for<'x> T: Foo1<'^0.0>; substs: [T, '^0.0] + // predicate: for<'b> Self: Bar1<'a, '^0.0>; substs: [Self, 'a, '^0.0] + // We want to end up with: + // for<'x, 'b> T: Bar1<'^0.0, '^0.1> + // To do this: + // 1) We must shift all bound vars in predicate by the length + // of trait ref's bound vars. So, we would end up with predicate like + // Self: Bar1<'a, '^0.1> + // 2) We can then apply the trait substs to this, ending up with + // T: Bar1<'^0.0, '^0.1> + // 3) Finally, to create the final bound vars, we concatenate the bound + // vars of the trait ref with those of the predicate: + // ['x, 'b] + let bound_pred = self.kind(); + let pred_bound_vars = bound_pred.bound_vars(); + let trait_bound_vars = trait_ref.bound_vars(); + // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1> + let shifted_pred = + tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); + // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> + let new = shifted_pred.subst(tcx, trait_ref.skip_binder().substs); + // 3) ['x] + ['b] -> ['x, 'b] + let bound_vars = + tcx.mk_bound_variable_kinds(trait_bound_vars.iter().chain(pred_bound_vars)); + tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars)) } } @@ -556,7 +579,7 @@ pub struct TraitPredicate<'tcx> { pub trait_ref: TraitRef<'tcx>, } -pub type PolyTraitPredicate<'tcx> = ty::Binder>; +pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; impl<'tcx> TraitPredicate<'tcx> { pub fn def_id(self) -> DefId { @@ -574,7 +597,7 @@ impl<'tcx> PolyTraitPredicate<'tcx> { self.skip_binder().def_id() } - pub fn self_ty(self) -> ty::Binder> { + pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound(|trait_ref| trait_ref.self_ty()) } } @@ -584,8 +607,8 @@ impl<'tcx> PolyTraitPredicate<'tcx> { pub struct OutlivesPredicate(pub A, pub B); // `A: B` pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; -pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder>; -pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder>; +pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>; +pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>; #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable)] @@ -594,7 +617,7 @@ pub struct SubtypePredicate<'tcx> { pub a: Ty<'tcx>, pub b: Ty<'tcx>, } -pub type PolySubtypePredicate<'tcx> = ty::Binder>; +pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; /// This kind of predicate has no *direct* correspondent in the /// syntax, but it roughly corresponds to the syntactic forms: @@ -615,7 +638,7 @@ pub struct ProjectionPredicate<'tcx> { pub ty: Ty<'tcx>, } -pub type PolyProjectionPredicate<'tcx> = Binder>; +pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; impl<'tcx> PolyProjectionPredicate<'tcx> { /// Returns the `DefId` of the trait of the associated item being projected. @@ -637,7 +660,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) } - pub fn ty(&self) -> Binder> { + pub fn ty(&self) -> Binder<'tcx, Ty<'tcx>> { self.map_bound(|predicate| predicate.ty) } @@ -671,7 +694,7 @@ pub trait ToPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>; } -impl ToPredicate<'tcx> for Binder> { +impl ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { tcx.mk_predicate(self) @@ -694,11 +717,11 @@ impl<'tcx> ToPredicate<'tcx> for ConstnessAnd> { impl<'tcx> ToPredicate<'tcx> for ConstnessAnd> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ConstnessAnd { - value: self.value.map_bound(|trait_ref| ty::TraitPredicate { trait_ref }), - constness: self.constness, - } - .to_predicate(tcx) + self.value + .map_bound(|trait_ref| { + PredicateKind::Trait(ty::TraitPredicate { trait_ref }, self.constness) + }) + .to_predicate(tcx) } } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 9d97815a5f1b7..3b0cb8d421551 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -38,7 +38,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - /// If you have a `Binder`, you can do this to strip out the + /// If you have a `Binder<'tcx, T>`, you can do this to strip out the /// late-bound regions and then normalize the result, yielding up /// a `T` (with regions erased). This is appropriate when the /// binder is being instantiated at the call site. @@ -49,7 +49,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn normalize_erasing_late_bound_regions( self, param_env: ty::ParamEnv<'tcx>, - value: ty::Binder, + value: ty::Binder<'tcx, T>, ) -> T where T: TypeFoldable<'tcx>, diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index a47846828bd60..13e2122a619dc 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -63,7 +63,7 @@ pub trait Printer<'tcx>: Sized { fn print_dyn_existential( self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result; fn print_const(self, ct: &'tcx ty::Const<'tcx>) -> Result; @@ -346,7 +346,7 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> { } impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> - for &'tcx ty::List>> + for &'tcx ty::List>> { type Output = P::DynExistential; type Error = P::Error; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f23c64cb036cf..b8f39fce21d65 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -202,7 +202,7 @@ pub trait PrettyPrinter<'tcx>: self.print_def_path(def_id, substs) } - fn in_binder(self, value: &ty::Binder) -> Result + fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>, { @@ -211,7 +211,7 @@ pub trait PrettyPrinter<'tcx>: fn wrap_binder Result>( self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, f: F, ) -> Result where @@ -765,7 +765,7 @@ pub trait PrettyPrinter<'tcx>: fn pretty_print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { // Generate the main trait ref, including associated types. let mut first = true; @@ -1432,7 +1432,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { fn print_dyn_existential( self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { self.pretty_print_dyn_existential(predicates) } @@ -1571,7 +1571,7 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { Ok(self) } - fn in_binder(self, value: &ty::Binder) -> Result + fn in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>, { @@ -1580,7 +1580,7 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { fn wrap_binder Result>( self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, f: C, ) -> Result where @@ -1636,7 +1636,7 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { data.name != kw::Empty && data.name != kw::UnderscoreLifetime } - ty::ReLateBound(_, ty::BoundRegion { kind: br }) + ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { if let ty::BrNamed(_, name) = br { @@ -1715,7 +1715,7 @@ impl FmtPrinter<'_, '_, F> { return Ok(self); } } - ty::ReLateBound(_, ty::BoundRegion { kind: br }) + ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { if let ty::BrNamed(_, name) = br { @@ -1763,7 +1763,7 @@ impl FmtPrinter<'_, '_, F> { impl FmtPrinter<'_, 'tcx, F> { pub fn name_all_regions( mut self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, ) -> Result<(Self, (T, BTreeMap>)), fmt::Error> where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, @@ -1821,7 +1821,8 @@ impl FmtPrinter<'_, 'tcx, F> { ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) } }; - self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind })) + self.tcx + .mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })) }); start_or_continue(&mut self, "", "> ")?; @@ -1830,7 +1831,7 @@ impl FmtPrinter<'_, 'tcx, F> { Ok((self, new_value)) } - pub fn pretty_in_binder(self, value: &ty::Binder) -> Result + pub fn pretty_in_binder(self, value: &ty::Binder<'tcx, T>) -> Result where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { @@ -1844,7 +1845,7 @@ impl FmtPrinter<'_, 'tcx, F> { pub fn pretty_wrap_binder Result>( self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, f: C, ) -> Result where @@ -1858,14 +1859,14 @@ impl FmtPrinter<'_, 'tcx, F> { Ok(inner) } - fn prepare_late_bound_region_info(&mut self, value: &ty::Binder) + fn prepare_late_bound_region_info(&mut self, value: &ty::Binder<'tcx, T>) where T: TypeFoldable<'tcx>, { struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet); impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name) }) = *r { + if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r { self.0.insert(name); } r.super_visit_with(self) @@ -1879,7 +1880,7 @@ impl FmtPrinter<'_, 'tcx, F> { } } -impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder +impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T> where T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable<'tcx>, { @@ -1966,28 +1967,28 @@ impl ty::TraitRef<'tcx> { } } -impl ty::Binder> { - pub fn print_only_trait_path(self) -> ty::Binder> { +impl ty::Binder<'tcx, ty::TraitRef<'tcx>> { + pub fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> { self.map_bound(|tr| tr.print_only_trait_path()) } } forward_display_to_print! { Ty<'tcx>, - &'tcx ty::List>>, + &'tcx ty::List>>, &'tcx ty::Const<'tcx>, // HACK(eddyb) these are exhaustive instead of generic, // because `for<'tcx>` isn't possible yet. - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder, ty::Region<'tcx>>>, - ty::Binder, ty::Region<'tcx>>>, + ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>, + ty::Binder<'tcx, ty::TraitRef<'tcx>>, + ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + ty::Binder<'tcx, ty::FnSig<'tcx>>, + ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, + ty::Binder<'tcx, ty::SubtypePredicate<'tcx>>, + ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>, + ty::Binder<'tcx, ty::OutlivesPredicate, ty::Region<'tcx>>>, + ty::Binder<'tcx, ty::OutlivesPredicate, ty::Region<'tcx>>>, ty::OutlivesPredicate, ty::Region<'tcx>>, ty::OutlivesPredicate, ty::Region<'tcx>> diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index e2bbb31263a79..ca60339da0d00 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -93,9 +93,9 @@ pub trait TypeRelation<'tcx>: Sized { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>; } @@ -594,7 +594,7 @@ fn check_const_value_eq>( }) } -impl<'tcx> Relate<'tcx> for &'tcx ty::List>> { +impl<'tcx> Relate<'tcx> for &'tcx ty::List>> { fn relate>( relation: &mut R, a: Self, @@ -619,10 +619,9 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List Ok(ty::Binder::bind(Trait( - relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(), - ))), - (Projection(a), Projection(b)) => Ok(ty::Binder::bind(Projection( + (Trait(a), Trait(b)) => Ok(ep_a + .rebind(Trait(relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder()))), + (Projection(a), Projection(b)) => Ok(ep_a.rebind(Projection( relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(), ))), (AutoTrait(a), AutoTrait(b)) if a == b => Ok(ep_a.rebind(AutoTrait(a))), @@ -685,12 +684,12 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::Const<'tcx> { } } -impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder { +impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<'tcx, T> { fn relate>( relation: &mut R, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> { + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> { relation.binders(a, b) } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 2da23b331e0cb..a969626b370f5 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -454,10 +454,16 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> { } } -impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder { - type Lifted = ty::Binder; +impl<'a, 'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<'a, T> +where + >::Lifted: TypeFoldable<'tcx>, +{ + type Lifted = ty::Binder<'tcx, T::Lifted>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - self.map_bound(|v| tcx.lift(v)).transpose() + let bound_vars = tcx.lift(self.bound_vars()); + tcx.lift(self.skip_binder()) + .zip(bound_vars) + .map(|(value, vars)| ty::Binder::bind_with_vars(value, vars)) } } @@ -749,7 +755,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> { } } -impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { +impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> { fn super_fold_with>(self, folder: &mut F) -> Self { self.map_bound(|ty| ty.fold_with(folder)) } @@ -767,7 +773,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List>> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List>> { fn super_fold_with>(self, folder: &mut F) -> Self { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v)) } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index b8fe7aa7fd06a..e352d0bc75697 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -5,6 +5,8 @@ use self::TyKind::*; use crate::infer::canonical::Canonical; +use crate::ty::fold::BoundVarsCollector; +use crate::ty::fold::ValidateBoundVars; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::InferTy::{self, *}; use crate::ty::{ @@ -62,22 +64,10 @@ pub enum BoundRegionKind { #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)] #[derive(HashStable)] pub struct BoundRegion { + pub var: BoundVar, pub kind: BoundRegionKind, } -impl BoundRegion { - /// When canonicalizing, we replace unbound inference variables and free - /// regions with anonymous late bound regions. This method asserts that - /// we have an anonymous late bound region, which hence may refer to - /// a canonical variable. - pub fn assert_bound_var(&self) -> BoundVar { - match self.kind { - BoundRegionKind::BrAnon(var) => BoundVar::from_u32(var), - _ => bug!("bound region is not anonymous"), - } - } -} - impl BoundRegionKind { pub fn is_named(&self) -> bool { match *self { @@ -161,7 +151,7 @@ pub enum TyKind<'tcx> { FnPtr(PolyFnSig<'tcx>), /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. - Dynamic(&'tcx List>>, ty::Region<'tcx>), + Dynamic(&'tcx List>>, ty::Region<'tcx>), /// The anonymous type of a closure. Used to represent the type of /// `|a| a`. @@ -173,7 +163,7 @@ pub enum TyKind<'tcx> { /// A type representing the types stored inside a generator. /// This should only appear in GeneratorInteriors. - GeneratorWitness(Binder<&'tcx List>>), + GeneratorWitness(Binder<'tcx, &'tcx List>>), /// The never type `!`. Never, @@ -232,7 +222,7 @@ impl TyKind<'tcx> { // `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(TyKind<'_>, 24); +static_assert_size!(TyKind<'_>, 32); /// A closure can be modeled as a struct that looks like: /// @@ -747,7 +737,7 @@ impl<'tcx> ExistentialPredicate<'tcx> { } } -impl<'tcx> Binder> { +impl<'tcx> Binder<'tcx, ExistentialPredicate<'tcx>> { pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> { use crate::ty::ToPredicate; match self.skip_binder() { @@ -768,7 +758,7 @@ impl<'tcx> Binder> { } } -impl<'tcx> List>> { +impl<'tcx> List>> { /// Returns the "principal `DefId`" of this set of existential predicates. /// /// A Rust trait object type consists (in addition to a lifetime bound) @@ -794,7 +784,7 @@ impl<'tcx> List>> { /// is `{Send, Sync}`, while there is no principal. These trait objects /// have a "trivial" vtable consisting of just the size, alignment, /// and destructor. - pub fn principal(&self) -> Option>> { + pub fn principal(&self) -> Option>> { self[0] .map_bound(|this| match this { ExistentialPredicate::Trait(tr) => Some(tr), @@ -810,7 +800,7 @@ impl<'tcx> List>> { #[inline] pub fn projection_bounds<'a>( &'a self, - ) -> impl Iterator>> + 'a { + ) -> impl Iterator>> + 'a { self.iter().filter_map(|predicate| { predicate .map_bound(|pred| match pred { @@ -875,10 +865,10 @@ impl<'tcx> TraitRef<'tcx> { } } -pub type PolyTraitRef<'tcx> = Binder>; +pub type PolyTraitRef<'tcx> = Binder<'tcx, TraitRef<'tcx>>; impl<'tcx> PolyTraitRef<'tcx> { - pub fn self_ty(&self) -> Binder> { + pub fn self_ty(&self) -> Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|tr| tr.self_ty()) } @@ -931,7 +921,7 @@ impl<'tcx> ExistentialTraitRef<'tcx> { } } -pub type PolyExistentialTraitRef<'tcx> = Binder>; +pub type PolyExistentialTraitRef<'tcx> = Binder<'tcx, ExistentialTraitRef<'tcx>>; impl<'tcx> PolyExistentialTraitRef<'tcx> { pub fn def_id(&self) -> DefId { @@ -947,36 +937,56 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { } } +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable)] +pub enum BoundVariableKind { + Ty(BoundTyKind), + Region(BoundRegionKind), + Const, +} + /// Binder is a binder for higher-ranked lifetimes or types. It is part of the /// compiler's representation for things like `for<'a> Fn(&'a isize)` /// (which would be represented by the type `PolyTraitRef == -/// Binder`). Note that when we instantiate, +/// Binder<'tcx, TraitRef>`). Note that when we instantiate, /// erase, or otherwise "discharge" these bound vars, we change the -/// type from `Binder` to just `T` (see +/// type from `Binder<'tcx, T>` to just `T` (see /// e.g., `liberate_late_bound_regions`). /// /// `Decodable` and `Encodable` are implemented for `Binder` using the `impl_binder_encode_decode!` macro. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub struct Binder(T); +pub struct Binder<'tcx, T>(T, &'tcx List); -impl Binder { +impl<'tcx, T> Binder<'tcx, T> +where + T: TypeFoldable<'tcx>, +{ /// Wraps `value` in a binder, asserting that `value` does not /// contain any bound vars that would be bound by the /// binder. This is commonly used to 'inject' a value T into a /// different binding level. - pub fn dummy<'tcx>(value: T) -> Binder - where - T: TypeFoldable<'tcx>, - { + pub fn dummy(value: T) -> Binder<'tcx, T> { debug_assert!(!value.has_escaping_bound_vars()); - Binder(value) + Binder(value, ty::List::empty()) } /// Wraps `value` in a binder, binding higher-ranked vars (if any). - pub fn bind(value: T) -> Binder { - Binder(value) + pub fn bind(value: T, tcx: TyCtxt<'tcx>) -> Binder<'tcx, T> { + let mut collector = BoundVarsCollector::new(); + value.visit_with(&mut collector); + Binder(value, collector.into_vars(tcx)) + } + + pub fn bind_with_vars(value: T, vars: &'tcx List) -> Binder<'tcx, T> { + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(vars); + value.visit_with(&mut validator); + } + Binder(value, vars) } +} +impl<'tcx, T> Binder<'tcx, T> { /// Skips the binder and returns the "bound" value. This is a /// risky thing to do because it's easy to get confused about /// De Bruijn indices and the like. It is usually better to @@ -997,22 +1007,39 @@ impl Binder { self.0 } - pub fn as_ref(&self) -> Binder<&T> { - Binder(&self.0) + pub fn bound_vars(&self) -> &'tcx List { + self.1 + } + + pub fn as_ref(&self) -> Binder<'tcx, &T> { + Binder(&self.0, self.1) } - pub fn map_bound_ref(&self, f: F) -> Binder + pub fn map_bound_ref_unchecked(&self, f: F) -> Binder<'tcx, U> + where + F: FnOnce(&T) -> U, + { + let value = f(&self.0); + Binder(value, self.1) + } + + pub fn map_bound_ref>(&self, f: F) -> Binder<'tcx, U> where F: FnOnce(&T) -> U, { self.as_ref().map_bound(f) } - pub fn map_bound(self, f: F) -> Binder + pub fn map_bound>(self, f: F) -> Binder<'tcx, U> where F: FnOnce(T) -> U, { - Binder(f(self.0)) + let value = f(self.0); + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(self.1); + value.visit_with(&mut validator); + } + Binder(value, self.1) } /// Wraps a `value` in a binder, using the same bound variables as the @@ -1024,8 +1051,15 @@ impl Binder { /// don't actually track bound vars. However, semantically, it is different /// because bound vars aren't allowed to change here, whereas they are /// in `bind`. This may be (debug) asserted in the future. - pub fn rebind(&self, value: U) -> Binder { - Binder(value) + pub fn rebind(&self, value: U) -> Binder<'tcx, U> + where + U: TypeFoldable<'tcx>, + { + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(self.bound_vars()); + value.visit_with(&mut validator); + } + Binder(value, self.1) } /// Unwraps and returns the value within, but only if it contains @@ -1038,45 +1072,32 @@ impl Binder { /// binders, but that would require adjusting the debruijn /// indices, and given the shallow binding structure we often use, /// would not be that useful.) - pub fn no_bound_vars<'tcx>(self) -> Option + pub fn no_bound_vars(self) -> Option where T: TypeFoldable<'tcx>, { if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } - /// Given two things that have the same binder level, - /// and an operation that wraps on their contents, executes the operation - /// and then wraps its result. - /// - /// `f` should consider bound regions at depth 1 to be free, and - /// anything it produces with bound regions at depth 1 will be - /// bound in the resulting return value. - pub fn fuse(self, u: Binder, f: F) -> Binder - where - F: FnOnce(T, U) -> R, - { - Binder(f(self.0, u.0)) - } - /// Splits the contents into two things that share the same binder /// level as the original, returning two distinct binders. /// /// `f` should consider bound regions at depth 1 to be free, and /// anything it produces with bound regions at depth 1 will be /// bound in the resulting return values. - pub fn split(self, f: F) -> (Binder, Binder) + pub fn split(self, f: F) -> (Binder<'tcx, U>, Binder<'tcx, V>) where F: FnOnce(T) -> (U, V), { let (u, v) = f(self.0); - (Binder(u), Binder(v)) + (Binder(u, self.1), Binder(v, self.1)) } } -impl Binder> { - pub fn transpose(self) -> Option> { - self.0.map(Binder) +impl<'tcx, T> Binder<'tcx, Option> { + pub fn transpose(self) -> Option> { + let bound_vars = self.1; + self.0.map(|v| Binder(v, bound_vars)) } } @@ -1139,7 +1160,7 @@ pub struct GenSig<'tcx> { pub return_ty: Ty<'tcx>, } -pub type PolyGenSig<'tcx> = Binder>; +pub type PolyGenSig<'tcx> = Binder<'tcx, GenSig<'tcx>>; /// Signature of a function type, which we have arbitrarily /// decided to use to refer to the input/output types. @@ -1177,22 +1198,22 @@ impl<'tcx> FnSig<'tcx> { } } -pub type PolyFnSig<'tcx> = Binder>; +pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>; impl<'tcx> PolyFnSig<'tcx> { #[inline] - pub fn inputs(&self) -> Binder<&'tcx [Ty<'tcx>]> { - self.map_bound_ref(|fn_sig| fn_sig.inputs()) + pub fn inputs(&self) -> Binder<'tcx, &'tcx [Ty<'tcx>]> { + self.map_bound_ref_unchecked(|fn_sig| fn_sig.inputs()) } #[inline] - pub fn input(&self, index: usize) -> ty::Binder> { + pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) } - pub fn inputs_and_output(&self) -> ty::Binder<&'tcx List>> { + pub fn inputs_and_output(&self) -> ty::Binder<'tcx, &'tcx List>> { self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output) } #[inline] - pub fn output(&self) -> ty::Binder> { + pub fn output(&self) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.output()) } pub fn c_variadic(&self) -> bool { @@ -1206,7 +1227,7 @@ impl<'tcx> PolyFnSig<'tcx> { } } -pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder>>; +pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] #[derive(HashStable)] @@ -1450,7 +1471,7 @@ pub struct ExistentialProjection<'tcx> { pub ty: Ty<'tcx>, } -pub type PolyExistentialProjection<'tcx> = Binder>; +pub type PolyExistentialProjection<'tcx> = Binder<'tcx, ExistentialProjection<'tcx>>; impl<'tcx> ExistentialProjection<'tcx> { /// Extracts the underlying existential trait reference from this projection. diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 5d1b976ae973d..8352e8b4918f0 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -448,7 +448,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { self.binders_passed += 1; let t = t.super_fold_with(self); self.binders_passed -= 1; diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 9c7de250c29b1..7d09ca5152ffe 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -499,10 +499,9 @@ impl<'tcx> TyCtxt<'tcx> { self, closure_def_id: DefId, closure_substs: SubstsRef<'tcx>, - ) -> Option>> { + env_region: ty::RegionKind, + ) -> Option> { let closure_ty = self.mk_closure(closure_def_id, closure_substs); - let br = ty::BoundRegion { kind: ty::BrEnv }; - let env_region = ty::ReLateBound(ty::INNERMOST, br); let closure_kind_ty = closure_substs.as_closure().kind_ty(); let closure_kind = closure_kind_ty.to_opt_closure_kind()?; let env_ty = match closure_kind { @@ -510,7 +509,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty), ty::ClosureKind::FnOnce => closure_ty, }; - Some(ty::Binder::bind(env_ty)) + Some(env_ty) } /// Returns `true` if the node pointed to by `def_id` is a `static` item. diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs index 4f61b8d0910ff..6ea0ba0a8e1ba 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs @@ -502,7 +502,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // lifetimes without names with the value `'0`. match ty.kind() { ty::Ref( - ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br }) + ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }), _, _, @@ -523,7 +523,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let region = match ty.kind() { ty::Ref(region, _, _) => { match region { - ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br }) + ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { printer.region_highlight_mode.highlighting_bound_region(*br, counter) } diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index fddd140186883..3248554e20427 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -2028,7 +2028,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { traits::ObligationCauseCode::RepeatVec(is_const_fn), ), self.param_env, - ty::Binder::bind(ty::TraitRef::new( + ty::Binder::dummy(ty::TraitRef::new( self.tcx().require_lang_item( LangItem::Copy, Some(self.last_span), diff --git a/compiler/rustc_mir/src/borrow_check/universal_regions.rs b/compiler/rustc_mir/src/borrow_check/universal_regions.rs index 68fa9d8bf9858..c2ac1e289ce4e 100644 --- a/compiler/rustc_mir/src/borrow_check/universal_regions.rs +++ b/compiler/rustc_mir/src/borrow_check/universal_regions.rs @@ -589,31 +589,45 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { &self, indices: &UniversalRegionIndices<'tcx>, defining_ty: DefiningTy<'tcx>, - ) -> ty::Binder<&'tcx ty::List>> { + ) -> ty::Binder<'tcx, &'tcx ty::List>> { let tcx = self.infcx.tcx; match defining_ty { DefiningTy::Closure(def_id, substs) => { assert_eq!(self.mir_def.did.to_def_id(), def_id); let closure_sig = substs.as_closure().sig(); let inputs_and_output = closure_sig.inputs_and_output(); - let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap(); - ty::Binder::fuse(closure_ty, inputs_and_output, |closure_ty, inputs_and_output| { - // The "inputs" of the closure in the - // signature appear as a tuple. The MIR side - // flattens this tuple. - let (&output, tuplized_inputs) = inputs_and_output.split_last().unwrap(); - assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs"); - let inputs = match tuplized_inputs[0].kind() { - ty::Tuple(inputs) => inputs, - _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]), - }; + let bound_vars = tcx.mk_bound_variable_kinds( + inputs_and_output + .bound_vars() + .iter() + .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + ); + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind: ty::BrEnv, + }; + let env_region = ty::ReLateBound(ty::INNERMOST, br); + let closure_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap(); + + // The "inputs" of the closure in the + // signature appear as a tuple. The MIR side + // flattens this tuple. + let (&output, tuplized_inputs) = + inputs_and_output.skip_binder().split_last().unwrap(); + assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs"); + let inputs = match tuplized_inputs[0].kind() { + ty::Tuple(inputs) => inputs, + _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]), + }; + ty::Binder::bind_with_vars( tcx.mk_type_list( iter::once(closure_ty) .chain(inputs.iter().map(|k| k.expect_ty())) .chain(iter::once(output)), - ) - }) + ), + bound_vars, + ) } DefiningTy::Generator(def_id, substs, movability) => { @@ -657,7 +671,7 @@ trait InferCtxtExt<'tcx> { &self, origin: NllRegionVariableOrigin, all_outlive_scope: LocalDefId, - value: ty::Binder, + value: ty::Binder<'tcx, T>, indices: &mut UniversalRegionIndices<'tcx>, ) -> T where @@ -686,7 +700,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { &self, origin: NllRegionVariableOrigin, all_outlive_scope: LocalDefId, - value: ty::Binder, + value: ty::Binder<'tcx, T>, indices: &mut UniversalRegionIndices<'tcx>, ) -> T where diff --git a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs b/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs index e1ec4cc5e973c..ae5e78ee33f47 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs @@ -74,7 +74,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { fn print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { let mut first = true; for p in predicates { diff --git a/compiler/rustc_mir/src/monomorphize/mod.rs b/compiler/rustc_mir/src/monomorphize/mod.rs index d2586f0f84dff..9ca4b6687f1b5 100644 --- a/compiler/rustc_mir/src/monomorphize/mod.rs +++ b/compiler/rustc_mir/src/monomorphize/mod.rs @@ -8,14 +8,14 @@ pub mod collector; pub mod partitioning; pub mod polymorphize; -pub fn custom_coerce_unsize_info<'tcx>( +fn custom_coerce_unsize_info<'tcx>( tcx: TyCtxt<'tcx>, source_ty: Ty<'tcx>, target_ty: Ty<'tcx>, ) -> CustomCoerceUnsized { let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None); - let trait_ref = ty::Binder::bind(ty::TraitRef { + 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_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 1ad7b8fbbd5ed..ce5e41d3e7c86 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -850,9 +850,12 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { let obligation = Obligation::new( ObligationCause::dummy(), param_env, - Binder::bind(TraitPredicate { - trait_ref: TraitRef::from_method(tcx, trait_id, substs), - }), + Binder::bind( + TraitPredicate { + trait_ref: TraitRef::from_method(tcx, trait_id, substs), + }, + tcx, + ), ); let implsrc = tcx.infer_ctxt().enter(|infcx| { diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 9f1de3349a56e..c90f94c6d63fb 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -252,8 +252,13 @@ fn liberated_closure_env_ty( _ => bug!("closure expr does not have closure type: {:?}", closure_ty), }; - let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap(); - tcx.erase_late_bound_regions(closure_env_ty) + let bound_vars = + tcx.mk_bound_variable_kinds(std::iter::once(ty::BoundVariableKind::Region(ty::BrEnv))); + let br = + ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BrEnv }; + let env_region = ty::ReLateBound(ty::INNERMOST, br); + let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap(); + tcx.erase_late_bound_regions(ty::Binder::bind_with_vars(closure_env_ty, bound_vars)) } #[derive(Debug, PartialEq, Eq)] diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 698e5048f7bdd..b89ad867f46ee 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -30,7 +30,7 @@ use std::cell::Cell; use std::fmt; use std::mem::take; -use tracing::debug; +use tracing::{debug, span, Level}; // This counts the no of times a lifetime is used #[derive(Clone, Copy, Debug)] @@ -42,9 +42,9 @@ pub enum LifetimeUseSet<'tcx> { trait RegionExt { fn early(hir_map: &Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (ParamName, Region); - fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region); + fn late(index: u32, hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region); - fn late_anon(index: &Cell) -> Region; + fn late_anon(named_late_bound_vars: u32, index: &Cell) -> Region; fn id(&self) -> Option; @@ -67,7 +67,7 @@ impl RegionExt for Region { (param.name.normalize_to_macros_2_0(), Region::EarlyBound(i, def_id.to_def_id(), origin)) } - fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) { + fn late(idx: u32, hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) { let depth = ty::INNERMOST; let def_id = hir_map.local_def_id(param.hir_id); let origin = LifetimeDefOrigin::from_param(param); @@ -75,21 +75,24 @@ impl RegionExt for Region { "Region::late: param={:?} depth={:?} def_id={:?} origin={:?}", param, depth, def_id, origin, ); - (param.name.normalize_to_macros_2_0(), Region::LateBound(depth, def_id.to_def_id(), origin)) + ( + param.name.normalize_to_macros_2_0(), + Region::LateBound(depth, idx, def_id.to_def_id(), origin), + ) } - fn late_anon(index: &Cell) -> Region { + fn late_anon(named_late_bound_vars: u32, index: &Cell) -> Region { let i = index.get(); index.set(i + 1); let depth = ty::INNERMOST; - Region::LateBoundAnon(depth, i) + Region::LateBoundAnon(depth, named_late_bound_vars + i, i) } fn id(&self) -> Option { match *self { Region::Static | Region::LateBoundAnon(..) => None, - Region::EarlyBound(_, id, _) | Region::LateBound(_, id, _) | Region::Free(_, id) => { + Region::EarlyBound(_, id, _) | Region::LateBound(_, _, id, _) | Region::Free(_, id) => { Some(id) } } @@ -97,11 +100,11 @@ impl RegionExt for Region { fn shifted(self, amount: u32) -> Region { match self { - Region::LateBound(debruijn, id, origin) => { - Region::LateBound(debruijn.shifted_in(amount), id, origin) + Region::LateBound(debruijn, idx, id, origin) => { + Region::LateBound(debruijn.shifted_in(amount), idx, id, origin) } - Region::LateBoundAnon(debruijn, index) => { - Region::LateBoundAnon(debruijn.shifted_in(amount), index) + Region::LateBoundAnon(debruijn, index, anon_index) => { + Region::LateBoundAnon(debruijn.shifted_in(amount), index, anon_index) } _ => self, } @@ -109,11 +112,11 @@ impl RegionExt for Region { fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region { match self { - Region::LateBound(debruijn, id, origin) => { - Region::LateBound(debruijn.shifted_out_to_binder(binder), id, origin) + Region::LateBound(debruijn, index, id, origin) => { + Region::LateBound(debruijn.shifted_out_to_binder(binder), index, id, origin) } - Region::LateBoundAnon(debruijn, index) => { - Region::LateBoundAnon(debruijn.shifted_out_to_binder(binder), index) + Region::LateBoundAnon(debruijn, index, anon_index) => { + Region::LateBoundAnon(debruijn.shifted_out_to_binder(binder), index, anon_index) } _ => self, } @@ -147,6 +150,14 @@ struct NamedRegionMap { // be late-bound if (a) it does NOT appear in a where-clause and // (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>, } crate struct LifetimeContext<'a, 'tcx> { @@ -161,13 +172,21 @@ crate struct LifetimeContext<'a, 'tcx> { /// correct when representing these constraints, we should only introduce one /// scope. However, we want to support both locations for the quantifier and /// during lifetime resolution we want precise information (so we can't - /// desugar in an earlier phase). + /// desugar in an earlier phase). Moreso, an error here doesn't cause a bail + /// from type checking, so we need to be extra careful that we don't lose + /// 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: bool, + /// `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, /// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax. is_in_fn_syntax: bool, @@ -225,6 +244,17 @@ enum Scope<'a> { /// of the resulting opaque type. opaque_type_parent: bool, + /// 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 + /// queried later. However, if we enter an elision scope, we have to + /// later append the elided bound vars to the list and need to know what + /// to append to. + hir_id: hir::HirId, + s: ScopeRef<'a>, }, @@ -252,6 +282,50 @@ enum Scope<'a> { s: ScopeRef<'a>, }, + /// This is a particularly interesting consequence of how we handle poly + /// trait refs. See `trait_ref_hack` for additional info. This bit is + /// important w.r.t. querying late-bound vars. + /// + /// To completely understand why this is necessary, first it's important to + /// realize that `T: for<'a> U + for<'a, 'b> V` is actually two separate + /// trait refs: `T: for<'a> U` and `T: for<'b> V` and as such, the late + /// bound vars on each needs to be tracked separately. Also, in this case, + /// are *three* relevant `HirId`s: one for the entire bound and one + /// for each separate one. + /// + /// Next, imagine three different poly trait refs: + /// 1) `for<'a, 'b> T: U<'a, 'b>` + /// 2) `T: for<'a, 'b> U<'a, 'b>` + /// 3) `for<'a> T: for<'b> U<'a, 'b>` + /// + /// First, note that the third example is semantically invalid and an error, + /// but we *must* handle it as valid, since type checking isn't bailed out + /// of. Other than that, if ask for bound vars for each, we expect + /// `['a, 'b]`. If we *didn't* allow binders before `T`, then we would + /// always introduce a binder scope at the inner trait ref. This is great, + /// becauase later on during type-checking, we will ask "what are the late + /// bound vars on this trait ref". However, because we allow bound vars on + /// the bound itself, we have to have some way of keeping track of the fact + /// that we actually want to store the late bound vars as being associated + /// with the trait ref; this is that. + /// + /// One alternative way to handle this would be to just introduce a new + /// `Binder` scope, but that's semantically a bit different, since bound + /// vars from both `for<...>`s *do* share the same binder level. + TraitRefHackInner { + hir_id: hir::HirId, + s: ScopeRef<'a>, + }, + + /// When we have nested trait refs, we concanetate late bound vars for inner + /// trait refs from outer ones. But we also need to include any HRTB + /// lifetimes encountered when identifying the trait that an associated type + /// is declared on. + Supertrait { + lifetimes: Vec, + s: ScopeRef<'a>, + }, + Root, } @@ -266,6 +340,8 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { next_early_index, track_lifetime_uses, opaque_type_parent, + from_poly_trait_ref, + hir_id, s: _, } => f .debug_struct("Binder") @@ -273,6 +349,8 @@ 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("from_poly_trait_ref", from_poly_trait_ref) + .field("hir_id", hir_id) .field("s", &"..") .finish(), Scope::Body { id, s: _ } => { @@ -286,6 +364,16 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { .field("lifetime", lifetime) .field("s", &"..") .finish(), + Scope::TraitRefHackInner { hir_id, s: _ } => f + .debug_struct("TraitRefHackInner") + .field("hir_id", hir_id) + .field("s", &"..") + .finish(), + Scope::Supertrait { lifetimes, s: _ } => f + .debug_struct("Supertrait") + .field("lifetimes", lifetimes) + .field("s", &"..") + .finish(), Scope::Root => f.debug_struct("Root").finish(), } } @@ -294,8 +382,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { #[derive(Clone, Debug)] enum Elide { /// Use a fresh anonymous late-bound lifetime each time, by - /// incrementing the counter to generate sequential indices. - FreshLateAnon(Cell), + /// incrementing the counter to generate sequential indices. All + /// anonymous lifetimes must start *after* named bound vars. + FreshLateAnon(u32, Cell), /// Always use this one lifetime. Exact(Region), /// Less or more than one lifetime were found, error on unspecified. @@ -334,6 +423,7 @@ pub fn provide(providers: &mut ty::query::Providers) { _ => None, } }, + late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id), ..*providers }; @@ -391,13 +481,16 @@ fn do_resolve( trait_definition_only: bool, ) -> ResolveLifetimes { let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(local_def_id)); - let mut named_region_map = - NamedRegionMap { defs: Default::default(), late_bound: Default::default() }; + let mut named_region_map = NamedRegionMap { + defs: Default::default(), + late_bound: Default::default(), + late_bound_vars: Default::default(), + }; let mut visitor = LifetimeContext { tcx, map: &mut named_region_map, scope: ROOT_SCOPE, - trait_ref_hack: false, + trait_ref_hack: None, is_in_fn_syntax: false, is_in_const_generic: false, trait_definition_only, @@ -418,6 +511,10 @@ fn do_resolve( let map = rl.late_bound.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id); } + for (hir_id, v) in named_region_map.late_bound_vars { + let map = rl.late_bound_vars.entry(hir_id.owner).or_default(); + map.insert(hir_id.local_id, v); + } debug!(?rl.defs); rl @@ -503,6 +600,19 @@ fn sub_items_have_self_param(node: &hir::ItemKind<'_>) -> bool { matches!(*node, hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..)) } +fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::BoundVariableKind { + match region { + Region::LateBound(_, _, def_id, _) => { + let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local())); + ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name)) + } + Region::LateBoundAnon(_, _, anon_idx) => { + ty::BoundVariableKind::Region(ty::BrAnon(*anon_idx)) + } + _ => bug!("{:?} is not a late region", region), + } +} + impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { type Map = Map<'tcx>; @@ -530,11 +640,58 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.labels_in_fn = saved; } + fn visit_fn( + &mut self, + fk: intravisit::FnKind<'tcx>, + fd: &'tcx hir::FnDecl<'tcx>, + b: hir::BodyId, + s: rustc_span::Span, + hir_id: hir::HirId, + ) { + let name = match fk { + intravisit::FnKind::ItemFn(id, _, _, _) => id.as_str(), + intravisit::FnKind::Method(id, _, _) => id.as_str(), + intravisit::FnKind::Closure => Symbol::intern("closure").as_str(), + }; + let name: &str = &name; + let span = span!(Level::DEBUG, "visit_fn", name); + let _enter = span.enter(); + match fk { + // Any `Binders` are handled elsewhere + intravisit::FnKind::ItemFn(..) | intravisit::FnKind::Method(..) => { + intravisit::walk_fn(self, fk, fd, b, s, hir_id) + } + intravisit::FnKind::Closure => { + self.map.late_bound_vars.insert(hir_id, vec![]); + let scope = Scope::Binder { + hir_id, + lifetimes: FxHashMap::default(), + next_early_index: self.next_early_index(), + s: self.scope, + track_lifetime_uses: true, + opaque_type_parent: false, + from_poly_trait_ref: false, + }; + self.with(scope, move |_old_scope, this| { + intravisit::walk_fn(this, fk, fd, b, s, hir_id) + }); + } + } + } + fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { + match &item.kind { + hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => { + if let Some(of_trait) = of_trait { + self.map.late_bound_vars.insert(of_trait.hir_ref_id, Vec::default()); + } + } + _ => {} + } match item.kind { hir::ItemKind::Fn(ref sig, ref generics, _) => { self.missing_named_lifetime_spots.push(generics.into()); - self.visit_early_late(None, &sig.decl, generics, |this| { + self.visit_early_late(None, item.hir_id(), &sig.decl, generics, |this| { intravisit::walk_item(this, item); }); self.missing_named_lifetime_spots.pop(); @@ -582,6 +739,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.map.late_bound.insert(hir::HirId { owner, local_id }); }); } + for (&owner, late_bound_vars) in + resolved_lifetimes.late_bound_vars.iter() + { + late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| { + self.map.late_bound_vars.insert( + hir::HirId { owner, local_id }, + late_bound_vars.clone(), + ); + }); + } break; } hir::Node::Crate(_) => bug!("No Item about an OpaqueTy"), @@ -621,11 +788,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } }) .collect(); + self.map.late_bound_vars.insert(item.hir_id(), vec![]); let scope = Scope::Binder { + hir_id: item.hir_id(), lifetimes, next_early_index: index + non_lifetime_count, opaque_type_parent: true, track_lifetime_uses, + from_poly_trait_ref: false, s: ROOT_SCOPE, }; self.with(scope, |old_scope, this| { @@ -640,7 +810,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { match item.kind { hir::ForeignItemKind::Fn(ref decl, _, ref generics) => { - self.visit_early_late(None, decl, generics, |this| { + self.visit_early_late(None, item.hir_id(), decl, generics, |this| { intravisit::walk_foreign_item(this, item); }) } @@ -672,21 +842,29 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }; self.missing_named_lifetime_spots .push(MissingLifetimeSpot::HigherRanked { span, span_type }); + let (lifetimes, binders): (FxHashMap, Vec<_>) = c + .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(ty.hir_id, binders); let scope = Scope::Binder { - lifetimes: c - .generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir(), param)) - } - _ => None, - }) - .collect(), + hir_id: ty.hir_id, + lifetimes, s: self.scope, next_early_index, track_lifetime_uses: true, opaque_type_parent: false, + from_poly_trait_ref: false, }; self.with(scope, |old_scope, this| { // a bare fn has no bounds, so everything @@ -721,7 +899,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // resolved the same as the `'_` in `&'_ Foo`. // // cc #48468 - self.resolve_elided_lifetimes(vec![lifetime]) + self.resolve_elided_lifetimes(&[lifetime]) } LifetimeName::Param(_) | LifetimeName::Static => { // If the user wrote an explicit name, use that. @@ -784,7 +962,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // well-supported at the moment, so this doesn't work. // In the future, this should be fixed and this error should be removed. let def = self.map.defs.get(&lifetime.hir_id).cloned(); - if let Some(Region::LateBound(_, def_id, _)) = def { + if let Some(Region::LateBound(_, _, def_id, _)) = def { if let Some(def_id) = def_id.as_local() { let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); // Ensure that the parent of the def is an item, not HRTB @@ -863,17 +1041,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } let next_early_index = index + non_lifetime_count; + self.map.late_bound_vars.insert(ty.hir_id, vec![]); if let Some(elision_region) = elision { let scope = Scope::Elision { elide: Elide::Exact(elision_region), s: self.scope }; self.with(scope, |_old_scope, this| { let scope = Scope::Binder { + hir_id: ty.hir_id, lifetimes, next_early_index, s: this.scope, track_lifetime_uses: true, opaque_type_parent: false, + from_poly_trait_ref: false, }; this.with(scope, |_old_scope, this| { this.visit_generics(generics); @@ -884,11 +1065,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }); } else { let scope = Scope::Binder { + hir_id: ty.hir_id, lifetimes, next_early_index, s: self.scope, track_lifetime_uses: true, opaque_type_parent: false, + from_poly_trait_ref: false, }; self.with(scope, |_old_scope, this| { this.visit_generics(generics); @@ -910,6 +1093,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let tcx = self.tcx; self.visit_early_late( Some(tcx.hir().get_parent_item(trait_item.hir_id())), + trait_item.hir_id(), &sig.decl, &trait_item.generics, |this| intravisit::walk_trait_item(this, trait_item), @@ -935,12 +1119,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } }) .collect(); + self.map.late_bound_vars.insert(trait_item.hir_id(), vec![]); let scope = Scope::Binder { + hir_id: trait_item.hir_id(), lifetimes, next_early_index: index + non_lifetime_count, s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, + from_poly_trait_ref: false, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -972,6 +1159,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let tcx = self.tcx; self.visit_early_late( Some(tcx.hir().get_parent_item(impl_item.hir_id())), + impl_item.hir_id(), &sig.decl, &impl_item.generics, |this| intravisit::walk_impl_item(this, impl_item), @@ -984,7 +1172,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let mut index = self.next_early_index(); let mut non_lifetime_count = 0; debug!("visit_ty: index = {}", index); - let lifetimes = generics + let lifetimes: FxHashMap = generics .params .iter() .filter_map(|param| match param.kind { @@ -997,12 +1185,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } }) .collect(); + self.map.late_bound_vars.insert(ty.hir_id, vec![]); let scope = Scope::Binder { + hir_id: ty.hir_id, lifetimes, next_early_index: index + non_lifetime_count, s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, + from_poly_trait_ref: false, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1024,7 +1215,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { #[tracing::instrument(level = "debug", skip(self))] fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { if lifetime_ref.is_elided() { - self.resolve_elided_lifetimes(vec![lifetime_ref]); + self.resolve_elided_lifetimes(&[lifetime_ref]); return; } if lifetime_ref.is_static() { @@ -1085,30 +1276,39 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { ref bound_generic_params, .. }) => { - let lifetimes: FxHashMap<_, _> = bound_generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir(), param)) - } - _ => None, - }) - .collect(); + let (lifetimes, binders): (FxHashMap, 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(); let scope = Scope::Binder { + hir_id: bounded_ty.hir_id, lifetimes, s: self.scope, next_early_index, track_lifetime_uses: true, opaque_type_parent: false, + 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 = true; + this.trait_ref_hack = Some(bounded_ty.hir_id); walk_list!(this, visit_param_bound, bounds); - this.trait_ref_hack = false; + this.trait_ref_hack = None; }); result } else { @@ -1138,13 +1338,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) { match bound { - hir::GenericBound::LangItemTrait { .. } if !self.trait_ref_hack => { + hir::GenericBound::LangItemTrait(_, _, hir_id, _) if self.trait_ref_hack.is_none() => { + self.map.late_bound_vars.insert(*hir_id, vec![]); let scope = Scope::Binder { + hir_id: *hir_id, lifetimes: FxHashMap::default(), s: self.scope, next_early_index: self.next_early_index(), track_lifetime_uses: true, opaque_type_parent: false, + from_poly_trait_ref: false, }; self.with(scope, |_, this| { intravisit::walk_param_bound(this, bound); @@ -1163,38 +1366,128 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let should_pop_missing_lt = self.is_trait_ref_fn_scope(trait_ref); - let trait_ref_hack = take(&mut self.trait_ref_hack); - if !trait_ref_hack - || trait_ref + let trait_ref_hack = self.trait_ref_hack.take(); + let next_early_index = self.next_early_index(); + // See note on `trait_ref_hack`. If `for<..>` has been defined in both + // the outer and inner part of the trait ref, emit an error. + let has_lifetimes = trait_ref.bound_generic_params.iter().any(|param| match param.kind { + GenericParamKind::Lifetime { .. } => true, + _ => false, + }); + if trait_ref_hack.is_some() && has_lifetimes { + struct_span_err!( + self.tcx.sess, + trait_ref.span, + E0316, + "nested quantification of lifetimes" + ) + .emit(); + } + + 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 = FxHashMap::default(); + let binders_iter = trait_ref .bound_generic_params .iter() - .any(|param| matches!(param.kind, GenericParamKind::Lifetime { .. })) - { - if trait_ref_hack { - struct_span_err!( - self.tcx.sess, - trait_ref.span, - E0316, - "nested quantification of lifetimes" - ) - .emit(); - } - let next_early_index = self.next_early_index(); - let scope = Scope::Binder { - lifetimes: trait_ref - .bound_generic_params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir(), param)) + .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); + + (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::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { + 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::Supertrait { s, lifetimes } => { + supertrait_lifetimes = lifetimes.clone(); + scope = s; + } + + 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, 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(); + + outer_binders.extend(local_binders.into_iter()); + + (outer_binders, lifetimes) + }; + + debug!(?binders); + self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders); + + if trait_ref_hack.is_none() || has_lifetimes { + let scope = Scope::Binder { + hir_id: trait_ref.trait_ref.hir_ref_id, + lifetimes, s: self.scope, next_early_index, track_lifetime_uses: true, opaque_type_parent: false, + from_poly_trait_ref: true, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); @@ -1202,7 +1495,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { this.visit_trait_ref(&trait_ref.trait_ref); }); } else { - self.visit_trait_ref(&trait_ref.trait_ref); + 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); + }); } self.trait_ref_hack = trait_ref_hack; if should_pop_missing_lt { @@ -1354,7 +1651,9 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) { match *scope { Scope::Body { s, .. } | Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } => { + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::TraitRefHackInner { s, .. } + | Scope::Supertrait { s, .. } => { scope = s; } @@ -1543,11 +1842,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let labels_in_fn = take(&mut self.labels_in_fn); let xcrate_object_lifetime_defaults = take(&mut self.xcrate_object_lifetime_defaults); let missing_named_lifetime_spots = take(&mut self.missing_named_lifetime_spots); + let trait_ref_hack = take(&mut self.trait_ref_hack); let mut this = LifetimeContext { tcx: *tcx, map, scope: &wrap_scope, - trait_ref_hack: self.trait_ref_hack, + trait_ref_hack, is_in_fn_syntax: self.is_in_fn_syntax, is_in_const_generic: self.is_in_const_generic, trait_definition_only: self.trait_definition_only, @@ -1567,6 +1867,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { self.labels_in_fn = this.labels_in_fn; self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults; self.missing_named_lifetime_spots = this.missing_named_lifetime_spots; + self.trait_ref_hack = this.trait_ref_hack; } /// helper method to determine the span to remove when suggesting the @@ -1715,7 +2016,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .values() .flat_map(|region| match region { Region::EarlyBound(_, def_id, _) - | Region::LateBound(_, def_id, _) + | Region::LateBound(_, _, def_id, _) | Region::Free(_, def_id) => Some(*def_id), Region::LateBoundAnon(..) | Region::Static => None, @@ -1861,6 +2162,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn visit_early_late( &mut self, parent_id: Option, + hir_id: hir::HirId, decl: &'tcx hir::FnDecl<'tcx>, generics: &'tcx hir::Generics<'tcx>, walk: F, @@ -1870,31 +2172,34 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { insert_late_bound_lifetimes(self.map, decl, generics); // Find the start of nested early scopes, e.g., in methods. - let mut index = 0; + let mut next_early_index = 0; if let Some(parent_id) = parent_id { let parent = self.tcx.hir().expect_item(parent_id); if sub_items_have_self_param(&parent.kind) { - index += 1; // Self comes before lifetimes + next_early_index += 1; // Self comes before lifetimes } match parent.kind { hir::ItemKind::Trait(_, _, ref generics, ..) | hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => { - index += generics.params.len() as u32; + next_early_index += generics.params.len() as u32; } _ => {} } } let mut non_lifetime_count = 0; - let lifetimes = generics + let mut named_late_bound_vars = 0; + let lifetimes: FxHashMap = generics .params .iter() .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { if self.map.late_bound.contains(¶m.hir_id) { - Some(Region::late(&self.tcx.hir(), param)) + let late_bound_idx = named_late_bound_vars; + named_late_bound_vars += 1; + Some(Region::late(late_bound_idx, &self.tcx.hir(), param)) } else { - Some(Region::early(&self.tcx.hir(), &mut index, param)) + Some(Region::early(&self.tcx.hir(), &mut next_early_index, param)) } } GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { @@ -1903,14 +2208,35 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } }) .collect(); - let next_early_index = index + non_lifetime_count; + let next_early_index = next_early_index + non_lifetime_count; + let binders: Vec<_> = generics + .params + .iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } + if self.map.late_bound.contains(¶m.hir_id) => + { + 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); + r + }) + .collect(); + self.map.late_bound_vars.insert(hir_id, binders); let scope = Scope::Binder { + hir_id, lifetimes, next_early_index, s: self.scope, opaque_type_parent: true, track_lifetime_uses: false, + from_poly_trait_ref: false, }; self.with(scope, move |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1933,7 +2259,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Binder { s, .. } | Scope::Body { s, .. } | Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } => scope = s, + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::TraitRefHackInner { s, .. } + | Scope::Supertrait { s, .. } => scope = s, } } } @@ -1965,6 +2293,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // given name or we run out of scopes. // search. let mut late_depth = 0; + let mut in_poly_trait_ref = false; let mut scope = self.scope; let mut outermost_body = None; let result = loop { @@ -1982,7 +2311,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { break None; } - Scope::Binder { ref lifetimes, s, .. } => { + Scope::Binder { ref lifetimes, from_poly_trait_ref, s, .. } => { match lifetime_ref.name { LifetimeName::Param(param_name) => { if let Some(&def) = lifetimes.get(¶m_name.normalize_to_macros_2_0()) @@ -1993,11 +2322,35 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { _ => bug!("expected LifetimeName::Param"), } - late_depth += 1; + match (from_poly_trait_ref, in_poly_trait_ref) { + // This is the first binder we see that is a poly trait ref; add one to the + // late depth and mark that we're potentially in nested trait refs. + (true, false) => { + in_poly_trait_ref = true; + late_depth += 1; + } + // We've already seen a binder that is a poly trait ref and this one is too, + // that means that they are nested and we are concatenating the bound vars; + // don't increase the late depth. + (true, true) => {} + // We've exited nested poly trait refs; add one to the late depth and mark + // that we are no longer in nested trait refs + (false, true) => { + in_poly_trait_ref = false; + late_depth += 1; + } + // Any other kind of nested binders: just increase late depth. + (false, false) => { + late_depth += 1; + } + } scope = s; } - Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { + Scope::Elision { s, .. } + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::TraitRefHackInner { s, .. } + | Scope::Supertrait { s, .. } => { scope = s; } } @@ -2025,7 +2378,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { if !self.trait_definition_only && self.is_in_fn_syntax { match def { Region::EarlyBound(_, _, LifetimeDefOrigin::InBand) - | Region::LateBound(_, _, LifetimeDefOrigin::InBand) => { + | Region::LateBound(_, _, _, LifetimeDefOrigin::InBand) => { struct_span_err!( self.tcx.sess, lifetime_ref.span, @@ -2044,6 +2397,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { LifetimeDefOrigin::ExplicitOrElided | LifetimeDefOrigin::Error, ) | Region::LateBound( + _, _, _, LifetimeDefOrigin::ExplicitOrElided | LifetimeDefOrigin::Error, @@ -2079,7 +2433,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } let mut elide_lifetimes = true; - let lifetimes = generic_args + let lifetimes: Vec<_> = generic_args .args .iter() .filter_map(|arg| match arg { @@ -2092,8 +2446,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { _ => None, }) .collect(); + // We short-circuit here if all are elided in order to pluralize + // possible errors if elide_lifetimes { - self.resolve_elided_lifetimes(lifetimes); + self.resolve_elided_lifetimes(&lifetimes); } else { lifetimes.iter().for_each(|lt| self.visit_lifetime(lt)); } @@ -2146,7 +2502,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Binder { s, .. } | Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } => { + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::TraitRefHackInner { s, .. } + | Scope::Supertrait { s, .. } => { scope = s; } } @@ -2245,13 +2603,84 @@ 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. - for b in generic_args.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, }; - self.with(scope, |_, this| this.visit_assoc_type_binding(b)); + if let Some(type_def_id) = type_def_id { + 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)); + } + } + } + + /// 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> { + 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 = 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, + } + }); + + let obligations = obligations.filter(|o| visited.insert(o.0)); + stack.extend(obligations); } } @@ -2261,7 +2690,37 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { inputs: &'tcx [hir::Ty<'tcx>], output: Option<&'tcx hir::Ty<'tcx>>, ) { - let arg_scope = Scope::Elision { elide: Elide::FreshLateAnon(Cell::new(0)), s: self.scope }; + debug!("visit_fn_like_elision: enter"); + let mut scope = &*self.scope; + let hir_id = loop { + match scope { + Scope::Binder { hir_id, .. } | Scope::TraitRefHackInner { hir_id, .. } => { + break *hir_id; + } + Scope::Body { id, .. } => break id.hir_id, + Scope::ObjectLifetimeDefault { ref s, .. } + | Scope::Elision { ref s, .. } + | Scope::Supertrait { ref s, .. } => { + scope = *s; + } + 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); + } + 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 { + elide: Elide::FreshLateAnon(named_late_bound_vars, Cell::new(0)), + s: self.scope, + }; self.with(arg_scope, |_, this| { for input in inputs { this.visit_ty(input); @@ -2516,7 +2975,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) { if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.hir_id) { match lifetime { - Region::LateBound(debruijn, _, _) | Region::LateBoundAnon(debruijn, _) + Region::LateBound(debruijn, _, _, _) + | Region::LateBoundAnon(debruijn, _, _) if debruijn < self.outer_index => { self.have_bound_regions = true; @@ -2528,9 +2988,46 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } } + + struct GatherAnonLifetimes { + anon_count: u32, + } + impl<'v> Visitor<'v> for GatherAnonLifetimes { + type Map = intravisit::ErasedMap<'v>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } + + 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; + } + intravisit::walk_ty(self, ty); + } + + fn visit_generic_args( + &mut self, + path_span: Span, + generic_args: &'v hir::GenericArgs<'v>, + ) { + // parenthesized args enter a new elison scope + if generic_args.parenthesized { + return; + } + intravisit::walk_generic_args(self, path_span, generic_args) + } + + fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) { + if lifetime_ref.is_elided() { + self.anon_count += 1; + } + } + } } - fn resolve_elided_lifetimes(&mut self, lifetime_refs: Vec<&'tcx hir::Lifetime>) { + fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) { debug!("resolve_elided_lifetimes(lifetime_refs={:?})", lifetime_refs); if lifetime_refs.is_empty() { @@ -2539,6 +3036,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let span = lifetime_refs[0].span; let mut late_depth = 0; + let mut in_poly_trait_ref = false; let mut scope = self.scope; let mut lifetime_names = FxHashSet::default(); let mut lifetime_spans = vec![]; @@ -2549,7 +3047,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Root => break None, - Scope::Binder { s, ref lifetimes, .. } => { + Scope::Binder { s, ref lifetimes, from_poly_trait_ref, .. } => { // collect named lifetimes for suggestions for name in lifetimes.keys() { if let hir::ParamName::Plain(name) = name { @@ -2557,15 +3055,31 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { lifetime_spans.push(name.span); } } - late_depth += 1; + // See comments in `resolve_lifetime_ref` + match (from_poly_trait_ref, in_poly_trait_ref) { + (true, false) => { + in_poly_trait_ref = true; + late_depth += 1; + } + (true, true) => {} + (false, true) => { + in_poly_trait_ref = false; + late_depth += 1; + } + (false, false) => { + late_depth += 1; + } + } scope = s; } Scope::Elision { ref elide, ref s, .. } => { let lifetime = match *elide { - Elide::FreshLateAnon(ref counter) => { + Elide::FreshLateAnon(named_late_bound_vars, ref counter) => { for lifetime_ref in lifetime_refs { - let lifetime = Region::late_anon(counter).shifted(late_depth); + let lifetime = Region::late_anon(named_late_bound_vars, counter) + .shifted(late_depth); + self.insert_lifetime(lifetime_ref, lifetime); } return; @@ -2602,7 +3116,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { return; } - Scope::ObjectLifetimeDefault { s, .. } => { + Scope::ObjectLifetimeDefault { s, .. } + | Scope::TraitRefHackInner { s, .. } + | Scope::Supertrait { s, .. } => { scope = s; } } @@ -2708,11 +3224,25 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) { debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref); let mut late_depth = 0; + let mut in_poly_trait_ref = false; let mut scope = self.scope; let lifetime = loop { match *scope { - Scope::Binder { s, .. } => { - late_depth += 1; + Scope::Binder { s, from_poly_trait_ref, .. } => { + match (from_poly_trait_ref, in_poly_trait_ref) { + (true, false) => { + in_poly_trait_ref = true; + late_depth += 1; + } + (true, true) => {} + (false, true) => { + in_poly_trait_ref = false; + late_depth += 1; + } + (false, false) => { + late_depth += 1; + } + } scope = s; } @@ -2721,6 +3251,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return, Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l, + + Scope::TraitRefHackInner { s, .. } | Scope::Supertrait { s, .. } => { + scope = s; + } } }; self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth)); @@ -2844,7 +3378,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { match *old_scope { Scope::Body { s, .. } | Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } => { + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::TraitRefHackInner { s, .. } + | Scope::Supertrait { s, .. } => { old_scope = s; } @@ -2890,7 +3426,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // A lifetime only used in a fn argument could as well // be replaced with `'_`, as that would generate a // fresh name, too. - Scope::Elision { elide: Elide::FreshLateAnon(_), .. } => break true, + Scope::Elision { elide: Elide::FreshLateAnon(..), .. } => break true, // In the return type or other such place, `'_` is not // going to make a fresh name, so we cannot @@ -2900,7 +3436,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { elide: Elide::Exact(_) | Elide::Error(_) | Elide::Forbid, .. } => break false, - Scope::ObjectLifetimeDefault { s, .. } => scope = s, + Scope::ObjectLifetimeDefault { s, .. } + | Scope::TraitRefHackInner { s, .. } + | Scope::Supertrait { s, .. } => scope = s, } } } @@ -2919,7 +3457,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } Region::Free(_, def_id) - | Region::LateBound(_, def_id, _) + | Region::LateBound(_, _, def_id, _) | Region::EarlyBound(_, def_id, _) => { // A lifetime declared by the user. let track_lifetime_uses = self.track_lifetime_uses(); diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index b0d5f34090241..7d186c330ba3f 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -230,7 +230,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { fn print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { let mut first = true; for p in predicates { diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 12c0a147990fa..37a834043f624 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -181,7 +181,7 @@ impl SymbolMangler<'tcx> { fn in_binder( mut self, - value: &ty::Binder, + value: &ty::Binder<'tcx, T>, print_value: impl FnOnce(Self, &T) -> Result, ) -> Result where @@ -318,7 +318,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { // Late-bound lifetimes use indices starting at 1, // see `BinderLevel` for more details. - ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i) }) => { + ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i), .. }) => { let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; let depth = binder.lifetime_depths.start + i; @@ -483,7 +483,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { fn print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>>, ) -> Result { for predicate in predicates { self = self.in_binder(&predicate, |mut cx, predicate| { diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index d6a585e626c48..b6c3768d8876a 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -697,7 +697,7 @@ where { fn visit_binder>( &mut self, - t: &ty::Binder, + t: &ty::Binder<'tcx, T>, ) -> ControlFlow { t.as_ref().skip_binder().visit_with(self); ControlFlow::CONTINUE diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index b38e3fbaab407..f54eb0914a5a7 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -84,7 +84,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) }; - let trait_pred = ty::Binder::bind(trait_ref); + let trait_pred = ty::Binder::dummy(trait_ref); let bail_out = tcx.infer_ctxt().enter(|infcx| { let mut selcx = SelectionContext::with_negative(&infcx, true); @@ -280,7 +280,7 @@ impl AutoTraitFinder<'tcx> { let mut already_visited = FxHashSet::default(); let mut predicates = VecDeque::new(); - predicates.push_back(ty::Binder::bind(ty::TraitPredicate { + predicates.push_back(ty::Binder::dummy(ty::TraitPredicate { trait_ref: ty::TraitRef { def_id: trait_did, substs: infcx.tcx.mk_substs_trait(ty, &[]), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index c1b105f1d8489..326b85e1013d6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -65,7 +65,7 @@ pub trait InferCtxtExt<'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, ); @@ -73,7 +73,7 @@ pub trait InferCtxtExt<'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: &ty::Binder>, + trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, has_custom_message: bool, ) -> bool; @@ -82,14 +82,14 @@ pub trait InferCtxtExt<'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ); fn suggest_change_mut( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, ); @@ -98,7 +98,7 @@ pub trait InferCtxtExt<'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, span: Span, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ); fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option; @@ -108,7 +108,7 @@ pub trait InferCtxtExt<'tcx> { err: &mut DiagnosticBuilder<'_>, span: Span, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) -> bool; fn point_at_returns_when_relevant( @@ -170,7 +170,7 @@ pub trait InferCtxtExt<'tcx> { &self, err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, span: Span, ); } @@ -583,7 +583,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, ) { let self_ty = match trait_ref.self_ty().no_bound_vars() { @@ -676,7 +676,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: &ty::Binder>, + trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, has_custom_message: bool, ) -> bool { @@ -761,7 +761,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) { let span = obligation.cause.span; @@ -824,7 +824,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, points_at_arg: bool, ) { let span = obligation.cause.span; @@ -896,10 +896,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, span: Span, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) { let is_empty_tuple = - |ty: ty::Binder>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty()); + |ty: ty::Binder<'tcx, Ty<'_>>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty()); let hir = self.tcx.hir(); let parent_node = hir.get_parent_node(obligation.cause.body_id); @@ -948,7 +948,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'_>, span: Span, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) -> bool { match obligation.cause.code.peel_derives() { // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`. @@ -2190,7 +2190,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder>, + trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, span: Span, ) { debug!( diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 79f65669479c8..fc9739f70d40d 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -684,7 +684,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { /// Returns the set of inference variables contained in `substs`. fn substs_infer_vars<'a, 'tcx>( selcx: &mut SelectionContext<'a, 'tcx>, - substs: ty::Binder>, + substs: ty::Binder<'tcx, SubstsRef<'tcx>>, ) -> impl Iterator> { selcx .infcx() diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 7de20e477fe04..b5a458db6075f 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -757,7 +757,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( struct IllegalSelfTypeVisitor<'tcx> { tcx: TyCtxt<'tcx>, trait_def_id: DefId, - supertraits: Option>>, + supertraits: Option>, } impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> { @@ -778,8 +778,10 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( // Compute supertraits of current trait lazily. if self.supertraits.is_none() { let trait_ref = - ty::Binder::bind(ty::TraitRef::identity(self.tcx, self.trait_def_id)); - self.supertraits = Some(traits::supertraits(self.tcx, trait_ref).collect()); + ty::Binder::dummy(ty::TraitRef::identity(self.tcx, self.trait_def_id)); + self.supertraits = Some( + traits::supertraits(self.tcx, trait_ref).map(|t| t.def_id()).collect(), + ); } // Determine whether the trait reference `Foo as @@ -790,9 +792,11 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( // direct equality here because all of these types // are part of the formal parameter listing, and // hence there should be no inference variables. - let projection_trait_ref = ty::Binder::bind(data.trait_ref(self.tcx)); - let is_supertrait_of_current_trait = - self.supertraits.as_ref().unwrap().contains(&projection_trait_ref); + let is_supertrait_of_current_trait = self + .supertraits + .as_ref() + .unwrap() + .contains(&data.trait_ref(self.tcx).def_id); if is_supertrait_of_current_trait { ControlFlow::CONTINUE // do not walk contained types, do not report error, do collect $200 diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 0af6d6459159e..b3e5df4da0a9f 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1275,6 +1275,9 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>( let tcx = selcx.tcx(); let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty()); + // We get here from `poly_project_and_unify_type` which replaces bound vars + // with placeholders + debug_assert!(!self_ty.has_escaping_bound_vars()); let substs = tcx.mk_substs([self_ty.into()].iter()); let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None); @@ -1306,7 +1309,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>( ty: self_ty.ptr_metadata_ty(tcx), }; - confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate), false) + confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate, tcx), false) } fn confirm_fn_pointer_candidate<'cx, 'tcx>( diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 272930f6bb9ca..31685a012ca2f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -272,7 +272,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, trait_def_id: DefId, - nested: ty::Binder>>, + nested: ty::Binder<'tcx, Vec>>, ) -> ImplSourceAutoImplData> { debug!(?nested, "vtable_auto_impl"); ensure_sufficient_stack(|| { @@ -748,7 +748,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { cause, obligation.recursion_depth + 1, obligation.param_env, - ty::Binder::bind(outlives).to_predicate(tcx), + obligation.predicate.rebind(outlives).to_predicate(tcx), )); } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 45680c90cdc17..1c51597fff2a8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -204,7 +204,7 @@ struct EvaluatedCandidate<'tcx> { /// When does the builtin impl for `T: Trait` apply? enum BuiltinImplConditions<'tcx> { /// The impl is conditional on `T1, T2, ...: Trait`. - Where(ty::Binder>>), + Where(ty::Binder<'tcx, Vec>>), /// There is no built-in impl. There may be some other /// candidate (a where-clause or user-defined impl). None, @@ -1673,7 +1673,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Bar where struct Bar { x: T, y: u32 } -> [i32, u32] /// Zed where enum Zed { A(T), B(u32) } -> [i32, u32] /// ``` - fn constituent_types_for_ty(&self, t: ty::Binder>) -> ty::Binder>> { + fn constituent_types_for_ty( + &self, + t: ty::Binder<'tcx, Ty<'tcx>>, + ) -> ty::Binder<'tcx, Vec>> { match *t.skip_binder().kind() { ty::Uint(_) | ty::Int(_) @@ -1746,7 +1749,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { cause: ObligationCause<'tcx>, recursion_depth: usize, trait_def_id: DefId, - types: ty::Binder>>, + types: ty::Binder<'tcx, Vec>>, ) -> Vec> { // Because the types were potentially derived from // higher-ranked obligations they may reference late-bound @@ -1767,7 +1770,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .skip_binder() // binder moved -\ .iter() .flat_map(|ty| { - let ty: ty::Binder> = types.rebind(ty); // <----/ + let ty: ty::Binder<'tcx, Ty<'tcx>> = types.rebind(ty); // <----/ self.infcx.commit_unconditionally(|_| { let placeholder_ty = self.infcx.replace_bound_vars_with_placeholders(ty); diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 8888ea2c8490c..fd94f9f799847 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -328,7 +328,7 @@ pub fn closure_trait_ref_and_return_type( self_ty: Ty<'tcx>, sig: ty::PolyFnSig<'tcx>, tuple_arguments: TupleArgumentsFlag, -) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> { +) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>)> { let arguments_tuple = match tuple_arguments { TupleArgumentsFlag::No => sig.skip_binder().inputs()[0], TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()), @@ -346,7 +346,7 @@ pub fn generator_trait_ref_and_outputs( fn_trait_def_id: DefId, self_ty: Ty<'tcx>, sig: ty::PolyGenSig<'tcx>, -) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> { +) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> { debug_assert!(!self_ty.has_escaping_bound_vars()); let trait_ref = ty::TraitRef { def_id: fn_trait_def_id, diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 3d5f8d128dc4b..f592cf1cd249d 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -704,7 +704,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { fn from_object_ty( &mut self, ty: Ty<'tcx>, - data: &'tcx ty::List>>, + data: &'tcx ty::List>>, region: ty::Region<'tcx>, ) { // Imagine a type like this: @@ -767,7 +767,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { /// `infer::required_region_bounds`, see that for more information. pub fn object_region_bounds<'tcx>( tcx: TyCtxt<'tcx>, - existential_predicates: &'tcx ty::List>>, + existential_predicates: &'tcx ty::List>>, ) -> Vec> { // Since we don't actually *know* the self type for an object, // this "open(err)" serves as a kind of dummy standin -- basically diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 5c0cb2fb83578..8c97e606c569f 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -735,7 +735,10 @@ fn bound_vars_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { .into(), ty::GenericParamDefKind::Lifetime => { - let br = ty::BoundRegion { kind: ty::BrAnon(substs.len() as u32) }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(substs.len()), + kind: ty::BrAnon(substs.len() as u32), + }; tcx.mk_region(ty::RegionKind::ReLateBound(ty::INNERMOST, br)).into() } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index fdf5f697e6117..39890fd5b0574 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -434,17 +434,11 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime>> for Region<'t ReEarlyBound(_) => { panic!("Should have already been substituted."); } - ReLateBound(db, br) => match br.kind { - ty::BoundRegionKind::BrAnon(var) => { - chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new( - chalk_ir::DebruijnIndex::new(db.as_u32()), - var as usize, - )) - .intern(interner) - } - ty::BoundRegionKind::BrNamed(_def_id, _name) => unimplemented!(), - ty::BrEnv => unimplemented!(), - }, + ReLateBound(db, br) => chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new( + chalk_ir::DebruijnIndex::new(db.as_u32()), + br.var.as_usize(), + )) + .intern(interner), ReFree(_) => unimplemented!(), ReStatic => chalk_ir::LifetimeData::Static.intern(interner), ReVar(_) => unimplemented!(), @@ -467,7 +461,10 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime ty::RegionKind::ReLateBound( ty::DebruijnIndex::from_u32(var.debruijn.depth()), - ty::BoundRegion { kind: ty::BrAnon(var.index as u32) }, + ty::BoundRegion { + var: ty::BoundVar::from_usize(var.index), + kind: ty::BrAnon(var.index as u32), + }, ), chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(), chalk_ir::LifetimeData::Placeholder(p) => { @@ -606,7 +603,7 @@ impl<'tcx> LowerInto<'tcx, Option LowerInto<'tcx, chalk_ir::Binders>>> - for &'tcx ty::List>> + for &'tcx ty::List>> { fn lower_into( self, @@ -677,7 +674,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders LowerInto<'tcx, chalk_ir::FnSig>> for ty::Binder> { +impl<'tcx> LowerInto<'tcx, chalk_ir::FnSig>> + for ty::Binder<'tcx, ty::FnSig<'tcx>> +{ fn lower_into(self, _interner: &RustInterner<'_>) -> FnSig> { chalk_ir::FnSig { abi: self.abi(), @@ -801,7 +800,7 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound crate fn collect_bound_vars<'tcx, T: TypeFoldable<'tcx>>( interner: &RustInterner<'tcx>, tcx: TyCtxt<'tcx>, - ty: Binder, + ty: Binder<'tcx, T>, ) -> (T, chalk_ir::VariableKinds>, BTreeMap) { let mut bound_vars_collector = BoundVarsCollector::new(); ty.as_ref().skip_binder().visit_with(&mut bound_vars_collector); @@ -849,7 +848,10 @@ impl<'tcx> BoundVarsCollector<'tcx> { } impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { self.binder_index.shift_in(1); let result = t.super_visit_with(self); self.binder_index.shift_out(1); @@ -895,7 +897,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { }, }, - ty::BrEnv => unimplemented!(), + ty::BoundRegionKind::BrEnv => unimplemented!(), }, ty::ReEarlyBound(_re) => { @@ -931,7 +933,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: Binder) -> Binder { + fn fold_binder>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> { self.binder_index.shift_in(1); let result = t.super_fold_with(self); self.binder_index.shift_out(1); @@ -943,7 +945,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> { ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind { ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) { Some(idx) => { - let new_br = ty::BoundRegion { kind: ty::BrAnon(*idx) }; + let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx) }; return self.tcx.mk_region(RegionKind::ReLateBound(*index, new_br)); } None => panic!("Missing `BrNamed`."), @@ -987,7 +989,7 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> { self.tcx } - fn fold_binder>(&mut self, t: Binder) -> Binder { + fn fold_binder>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> { self.binder_index.shift_in(1); let result = t.super_fold_with(self); self.binder_index.shift_out(1); @@ -1026,12 +1028,16 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> { // This covers any region variables in a goal, right? ty::ReEarlyBound(_re) => match self.named_regions.get(&_re.def_id) { Some(idx) => { - let br = ty::BoundRegion { kind: ty::BrAnon(*idx) }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(*idx), + kind: ty::BrAnon(*idx), + }; self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)) } None => { let idx = self.named_regions.len() as u32; - let br = ty::BoundRegion { kind: ty::BrAnon(idx) }; + let br = + ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) }; self.named_regions.insert(_re.def_id, idx); self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)) } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 6b9d46ee0af80..874289d02938d 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -115,7 +115,7 @@ fn resolve_associated_item<'tcx>( ); let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); - let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)))?; + let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref, tcx)))?; // Now that we know which impl is being used, we can dispatch to // the actual function: diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 9625211109d10..845375f3e322b 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -166,7 +166,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { parent_substs: &[subst::GenericArg<'tcx>], has_self: bool, self_ty: Option>, - arg_count: GenericArgCountResult, + arg_count: &GenericArgCountResult, ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>, ) -> SubstsRef<'tcx> { // Collect the segments of the path; we need to substitute arguments diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index dbc518da8c83a..b6de491911ab7 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -210,14 +210,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let r = match tcx.named_region(lifetime.hir_id) { Some(rl::Region::Static) => tcx.lifetimes.re_static, - Some(rl::Region::LateBound(debruijn, id, _)) => { - let name = lifetime_name(id.expect_local()); - let br = ty::BoundRegion { kind: ty::BrNamed(id, name) }; + Some(rl::Region::LateBound(debruijn, index, def_id, _)) => { + let name = lifetime_name(def_id.expect_local()); + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(index), + kind: ty::BrNamed(def_id, name), + }; tcx.mk_region(ty::ReLateBound(debruijn, br)) } - Some(rl::Region::LateBoundAnon(debruijn, index)) => { - let br = ty::BoundRegion { kind: ty::BrAnon(index) }; + Some(rl::Region::LateBoundAnon(debruijn, index, anon_index)) => { + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(index), + kind: ty::BrAnon(anon_index), + }; tcx.mk_region(ty::ReLateBound(debruijn, br)) } @@ -266,7 +272,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def_id: DefId, item_segment: &hir::PathSegment<'_>, ) -> SubstsRef<'tcx> { - let (substs, assoc_bindings, _) = self.create_substs_for_ast_path( + let (substs, _) = self.create_substs_for_ast_path( span, def_id, &[], @@ -275,6 +281,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment.infer_args, None, ); + let assoc_bindings = self.create_assoc_bindings_for_generic_args(item_segment.args()); if let Some(b) = assoc_bindings.first() { Self::prohibit_assoc_ty_binding(self.tcx(), b.span); @@ -314,6 +321,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// `[Vec, u8]` and `generic_args` are the arguments for the associated /// type itself: `['a]`. The returned `SubstsRef` concatenates these two /// lists: `[Vec, u8, 'a]`. + #[tracing::instrument(level = "debug", skip(self, span))] fn create_substs_for_ast_path<'a>( &self, span: Span, @@ -323,15 +331,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generic_args: &'a hir::GenericArgs<'_>, infer_args: bool, self_ty: Option>, - ) -> (SubstsRef<'tcx>, Vec>, GenericArgCountResult) { + ) -> (SubstsRef<'tcx>, GenericArgCountResult) { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). - debug!( - "create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \ - generic_args={:?})", - def_id, self_ty, generic_args - ); let tcx = self.tcx(); let generics = tcx.generics_of(def_id); @@ -367,7 +370,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // here and so associated type bindings will be handled regardless of whether there are any // non-`Self` generic parameters. if generics.params.len() == 0 { - return (tcx.intern_substs(&[]), vec![], arg_count); + return (tcx.intern_substs(&[]), arg_count); } let is_object = self_ty.map_or(false, |ty| ty == self.tcx().types.trait_object_dummy_self); @@ -540,7 +543,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { parent_substs, self_ty.is_some(), self_ty, - arg_count.clone(), + &arg_count, &mut substs_ctx, ); @@ -551,6 +554,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generic_args.args.is_empty(), ); + debug!( + "create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}", + generics, self_ty, substs + ); + + (substs, arg_count) + } + + fn create_assoc_bindings_for_generic_args<'a>( + &self, + generic_args: &'a hir::GenericArgs<'_>, + ) -> Vec> { // Convert associated-type bindings or constraints into a separate vector. // Example: Given this: // @@ -581,12 +596,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) .collect(); - debug!( - "create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}", - generics, self_ty, substs - ); - - (substs, assoc_bindings, arg_count) + assoc_bindings } crate fn create_substs_for_associated_item( @@ -636,8 +646,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) } - /// The given trait-ref must actually be a trait. - pub(super) fn instantiate_poly_trait_ref_inner( + /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct + /// a full trait reference. The resulting trait reference is returned. This may also generate + /// auxiliary bounds, which are added to `bounds`. + /// + /// Example: + /// + /// ``` + /// poly_trait_ref = Iterator + /// self_ty = Foo + /// ``` + /// + /// this would return `Foo: Iterator` and add `::Item = u32` into `bounds`. + /// + /// **A note on binders:** against our usual convention, there is an implied bounder around + /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions. + /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>` + /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be + /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, + /// however. + #[tracing::instrument(level = "debug", skip(self, span, constness, bounds, speculative))] + pub fn instantiate_poly_trait_ref( &self, trait_ref: &hir::TraitRef<'_>, span: Span, @@ -648,18 +677,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) -> GenericArgCountResult { let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); - debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id); - self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1); - let (substs, assoc_bindings, arg_count) = self.create_substs_for_ast_trait_ref( + let tcx = self.tcx(); + let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id); + debug!(?bound_vars); + + let (substs, arg_count) = self.create_substs_for_ast_trait_ref( trait_ref.path.span, trait_def_id, self_ty, trait_ref.path.segments.last().unwrap(), ); - let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs)); + let assoc_bindings = self + .create_assoc_bindings_for_generic_args(trait_ref.path.segments.last().unwrap().args()); + let poly_trait_ref = + ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); + + debug!(?poly_trait_ref, ?assoc_bindings); bounds.trait_bounds.push((poly_trait_ref, span, constness)); let mut dup_bindings = FxHashMap::default(); @@ -677,50 +713,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Okay to ignore `Err` because of `ErrorReported` (see above). } - debug!( - "instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}", - trait_ref, bounds, poly_trait_ref - ); - arg_count } - /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct - /// a full trait reference. The resulting trait reference is returned. This may also generate - /// auxiliary bounds, which are added to `bounds`. - /// - /// Example: - /// - /// ``` - /// poly_trait_ref = Iterator - /// self_ty = Foo - /// ``` - /// - /// this would return `Foo: Iterator` and add `::Item = u32` into `bounds`. - /// - /// **A note on binders:** against our usual convention, there is an implied bounder around - /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions. - /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>` - /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be - /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, - /// however. - pub fn instantiate_poly_trait_ref( - &self, - poly_trait_ref: &hir::PolyTraitRef<'_>, - constness: Constness, - self_ty: Ty<'tcx>, - bounds: &mut Bounds<'tcx>, - ) -> GenericArgCountResult { - self.instantiate_poly_trait_ref_inner( - &poly_trait_ref.trait_ref, - poly_trait_ref.span, - constness, - self_ty, - bounds, - false, - ) - } - pub fn instantiate_lang_item_trait_ref( &self, lang_item: hir::LangItem, @@ -732,7 +727,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) { let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span)); - let (substs, assoc_bindings, _) = self.create_substs_for_ast_path( + let (substs, _) = self.create_substs_for_ast_path( span, trait_def_id, &[], @@ -741,7 +736,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { false, Some(self_ty), ); - let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs)); + let assoc_bindings = self.create_assoc_bindings_for_generic_args(args); + let tcx = self.tcx(); + let bound_vars = tcx.late_bound_vars(hir_id); + let poly_trait_ref = + ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst)); let mut dup_bindings = FxHashMap::default(); @@ -765,23 +764,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment<'_>, ) -> ty::TraitRef<'tcx> { - let (substs, assoc_bindings, _) = + let (substs, _) = self.create_substs_for_ast_trait_ref(span, trait_def_id, self_ty, trait_segment); + let assoc_bindings = self.create_assoc_bindings_for_generic_args(trait_segment.args()); if let Some(b) = assoc_bindings.first() { Self::prohibit_assoc_ty_binding(self.tcx(), b.span); } ty::TraitRef::new(trait_def_id, substs) } + #[tracing::instrument(level = "debug", skip(self, span))] fn create_substs_for_ast_trait_ref<'a>( &self, span: Span, trait_def_id: DefId, self_ty: Ty<'tcx>, trait_segment: &'a hir::PathSegment<'a>, - ) -> (SubstsRef<'tcx>, Vec>, GenericArgCountResult) { - debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment); - + ) -> (SubstsRef<'tcx>, GenericArgCountResult) { self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment); self.create_substs_for_ast_path( @@ -803,7 +802,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } // Returns `true` if a bounds list includes `?Sized`. - pub fn is_unsized(&self, ast_bounds: &[&hir::GenericBound<'_>], span: Span) -> bool { + pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool { let tcx = self.tcx(); // Try to find an unbound in bounds. @@ -858,29 +857,46 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// **A note on binders:** there is an implied binder around /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` /// for more details. + #[tracing::instrument(level = "debug", skip(self, bounds))] fn add_bounds( &self, param_ty: Ty<'tcx>, - ast_bounds: &[&hir::GenericBound<'_>], + ast_bounds: &[hir::GenericBound<'_>], bounds: &mut Bounds<'tcx>, + bound_vars: &'tcx ty::List, ) { let constness = self.default_constness_for_trait_bounds(); for ast_bound in ast_bounds { match *ast_bound { hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => { - self.instantiate_poly_trait_ref(b, constness, param_ty, bounds); + self.instantiate_poly_trait_ref( + &b.trait_ref, + b.span, + constness, + param_ty, + bounds, + false, + ); } hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => { - self.instantiate_poly_trait_ref(b, Constness::NotConst, param_ty, bounds); + self.instantiate_poly_trait_ref( + &b.trait_ref, + b.span, + Constness::NotConst, + param_ty, + bounds, + false, + ); } hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {} hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self .instantiate_lang_item_trait_ref( - *lang_item, *span, *hir_id, args, param_ty, bounds, + lang_item, span, hir_id, args, param_ty, bounds, ), - hir::GenericBound::Outlives(ref l) => bounds - .region_bounds - .push((ty::Binder::bind(self.ast_region_to_region(l, None)), l.span)), + hir::GenericBound::Outlives(ref l) => bounds.region_bounds.push(( + ty::Binder::bind_with_vars(self.ast_region_to_region(l, None), bound_vars), + l.span, + )), } } } @@ -908,7 +924,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { sized_by_default: SizedByDefault, span: Span, ) -> Bounds<'tcx> { - let ast_bounds: Vec<_> = ast_bounds.iter().collect(); self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span) } @@ -928,7 +943,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(trait_ref) = ast_bound.trait_ref() { if let Some(trait_did) = trait_ref.trait_def_id() { if self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) { - result.push(ast_bound); + result.push(ast_bound.clone()); } } } @@ -940,13 +955,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn compute_bounds_inner( &self, param_ty: Ty<'tcx>, - ast_bounds: &[&hir::GenericBound<'_>], + ast_bounds: &[hir::GenericBound<'_>], sized_by_default: SizedByDefault, span: Span, ) -> Bounds<'tcx> { let mut bounds = Bounds::default(); - self.add_bounds(param_ty, ast_bounds, &mut bounds); + self.add_bounds(param_ty, ast_bounds, &mut bounds, ty::List::empty()); bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default { if !self.is_unsized(ast_bounds, span) { Some(span) } else { None } @@ -963,6 +978,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// **A note on binders:** given something like `T: for<'a> Iterator`, the /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside* /// the binder (e.g., `&'a u32`) and hence may reference bound regions. + #[tracing::instrument( + level = "debug", + skip(self, bounds, speculative, dup_bindings, path_span) + )] fn add_predicates_for_ast_type_binding( &self, hir_ref_id: hir::HirId, @@ -989,7 +1008,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // // We want to produce `>::T == foo`. - debug!(?hir_ref_id, ?trait_ref, ?binding, ?bounds, "add_predicates_for_ast_type_binding",); let tcx = self.tcx(); let candidate = @@ -1090,7 +1108,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let late_bound_in_trait_ref = tcx.collect_constrained_late_bound_regions(&projection_ty); let late_bound_in_ty = - tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty)); + tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty)); debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref); debug!("late_bound_in_ty = {:?}", late_bound_in_ty); @@ -1139,10 +1157,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` // parameter to have a skipped binder. - let param_ty = - tcx.mk_projection(assoc_ty.def_id, projection_ty.skip_binder().substs); - let ast_bounds: Vec<_> = ast_bounds.iter().collect(); - self.add_bounds(param_ty, &ast_bounds, bounds); + let param_ty = tcx.mk_ty(ty::Projection(projection_ty.skip_binder())); + self.add_bounds(param_ty, ast_bounds, bounds, candidate.bound_vars()); } } Ok(()) @@ -1176,10 +1192,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }), .. } = self.instantiate_poly_trait_ref( - trait_bound, + &trait_bound.trait_ref, + trait_bound.span, Constness::NotConst, dummy_self, &mut bounds, + false, ) { potential_assoc_types.extend(cur_potential_assoc_types); } @@ -1664,7 +1682,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; self.one_bound_for_assoc_type( - || traits::supertraits(tcx, ty::Binder::bind(trait_ref)), + || traits::supertraits(tcx, ty::Binder::bind(trait_ref, tcx)), || "Self".to_string(), assoc_ident, span, @@ -2199,6 +2217,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); tcx.mk_fn_ptr(self.ty_of_fn( + ast_ty.hir_id, bf.unsafety, bf.abi, &bf.decl, @@ -2241,7 +2260,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => { let def_id = tcx.require_lang_item(lang_item, Some(span)); - let (substs, _, _) = self.create_substs_for_ast_path( + let (substs, _) = self.create_substs_for_ast_path( span, def_id, &[], @@ -2278,7 +2297,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { result_ty } - pub fn impl_trait_ty_to_ty( + fn impl_trait_ty_to_ty( &self, def_id: DefId, lifetimes: &[hir::GenericArg<'_>], @@ -2339,6 +2358,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub fn ty_of_fn( &self, + hir_id: hir::HirId, unsafety: hir::Unsafety, abi: abi::Abi, decl: &hir::FnDecl<'_>, @@ -2349,6 +2369,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("ty_of_fn"); let tcx = self.tcx(); + let bound_vars = tcx.late_bound_vars(hir_id); + debug!(?bound_vars); // We proactively collect all the inferred type params to emit a single error per fn def. let mut visitor = PlaceholderHirTyCollector::default(); @@ -2368,8 +2390,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("ty_of_fn: output_ty={:?}", output_ty); - let bare_fn_ty = - ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi)); + let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi); + let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); if !self.allow_ty_infer() { // We always collect the spans for placeholder types when evaluating `fn`s, but we @@ -2450,7 +2472,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn compute_object_lifetime_bound( &self, span: Span, - existential_predicates: &'tcx ty::List>>, + existential_predicates: &'tcx ty::List>>, ) -> Option> // if None, use the default { let tcx = self.tcx(); diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_typeck/src/bounds.rs index 7ba90ad88193f..5d20064072263 100644 --- a/compiler/rustc_typeck/src/bounds.rs +++ b/compiler/rustc_typeck/src/bounds.rs @@ -26,7 +26,7 @@ pub struct Bounds<'tcx> { /// A list of region bounds on the (implicit) self type. So if you /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but /// the `T` is not explicitly included). - pub region_bounds: Vec<(ty::Binder>, Span)>, + pub region_bounds: Vec<(ty::Binder<'tcx, ty::Region<'tcx>>, Span)>, /// A list of trait bounds. So if you had `T: Debug` this would be /// `T: Debug`. Note that the self-type is explicit here. @@ -57,7 +57,7 @@ impl<'tcx> Bounds<'tcx> { // If it could be sized, and is, add the `Sized` predicate. let sized_predicate = self.implicitly_sized.and_then(|span| { tcx.lang_items().sized_trait().map(|sized| { - let trait_ref = ty::Binder::bind(ty::TraitRef { + let trait_ref = ty::Binder::dummy(ty::TraitRef { def_id: sized, substs: tcx.mk_substs_trait(param_ty, &[]), }); diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 4099ecd435d51..22d3dc6bdc0c0 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expr_def_id = self.tcx.hir().local_def_id(expr.hir_id); let ClosureSignatures { bound_sig, liberated_sig } = - self.sig_of_closure(expr_def_id.to_def_id(), decl, body, expected_sig); + self.sig_of_closure(expr.hir_id, expr_def_id.to_def_id(), decl, body, expected_sig); debug!("check_closure: ty_of_closure returns {:?}", liberated_sig); @@ -288,15 +288,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, expected_sig: Option>, ) -> ClosureSignatures<'tcx> { if let Some(e) = expected_sig { - self.sig_of_closure_with_expectation(expr_def_id, decl, body, e) + self.sig_of_closure_with_expectation(hir_id, expr_def_id, decl, body, e) } else { - self.sig_of_closure_no_expectation(expr_def_id, decl, body) + self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body) } } @@ -304,13 +305,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// types that the user gave into a signature. fn sig_of_closure_no_expectation( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, ) -> ClosureSignatures<'tcx> { debug!("sig_of_closure_no_expectation()"); - let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); + let bound_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body); self.closure_sigs(expr_def_id, body, bound_sig) } @@ -364,6 +366,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// regions with depth 1, which are bound then by the closure. fn sig_of_closure_with_expectation( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, @@ -375,7 +378,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // expectation if things don't see to match up with what we // expect. if expected_sig.sig.c_variadic() != decl.c_variadic { - return self.sig_of_closure_no_expectation(expr_def_id, decl, body); + return self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body); } else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 { return self.sig_of_closure_with_mismatched_number_of_arguments( expr_def_id, @@ -411,9 +414,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Along the way, it also writes out entries for types that the user // wrote into our typeck results, which are then later used by the privacy // check. - match self.check_supplied_sig_against_expectation(expr_def_id, decl, body, &closure_sigs) { + match self.check_supplied_sig_against_expectation( + hir_id, + expr_def_id, + decl, + body, + &closure_sigs, + ) { Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok), - Err(_) => return self.sig_of_closure_no_expectation(expr_def_id, decl, body), + Err(_) => return self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body), } closure_sigs @@ -460,6 +469,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// strategy. fn check_supplied_sig_against_expectation( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, @@ -469,7 +479,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // (See comment on `sig_of_closure_with_expectation` for the // meaning of these letters.) - let supplied_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); + let supplied_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body); debug!("check_supplied_sig_against_expectation: supplied_sig={:?}", supplied_sig); @@ -534,6 +544,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Also, record this closure signature for later. fn supplied_sig_of_closure( &self, + hir_id: hir::HirId, expr_def_id: DefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, @@ -545,6 +556,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { decl, body.generator_kind, ); + let bound_vars = self.tcx.late_bound_vars(hir_id); + // First, convert the types that the user supplied (if any). let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a)); let supplied_return = match decl.output { @@ -571,13 +584,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, }; - let result = ty::Binder::bind(self.tcx.mk_fn_sig( - supplied_arguments, - supplied_return, - decl.c_variadic, - hir::Unsafety::Normal, - Abi::RustCall, - )); + let result = ty::Binder::bind_with_vars( + self.tcx.mk_fn_sig( + supplied_arguments, + supplied_return, + decl.c_variadic, + hir::Unsafety::Normal, + Abi::RustCall, + ), + bound_vars, + ); debug!("supplied_sig_of_closure: result={:?}", result); diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 94aee87364a69..68a923a55eb0f 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1487,7 +1487,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { if let (Some((expr, _)), Some((fn_decl, _, _))) = (expression, fcx.get_node_fn_decl(parent_item)) { - fcx.suggest_missing_return_expr(&mut err, expr, fn_decl, expected, found); + fcx.suggest_missing_return_expr(&mut err, expr, fn_decl, expected, found, parent_id); } if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.get(), fn_output) { diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 70f850084a89f..f044daa450918 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -225,7 +225,7 @@ fn compare_predicate_entailment<'tcx>( let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars( impl_m_span, infer::HigherRankedType, - ty::Binder::bind(impl_m_own_bounds.predicates), + ty::Binder::bind(impl_m_own_bounds.predicates, tcx), ); for predicate in impl_m_own_bounds { let traits::Normalized { value: predicate, obligations } = @@ -258,14 +258,14 @@ fn compare_predicate_entailment<'tcx>( ); let impl_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, impl_sig); - let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig)); + let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig, tcx)); debug!("compare_impl_method: impl_fty={:?}", impl_fty); let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id)); let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs); let trait_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig); - let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig)); + let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig, tcx)); debug!("compare_impl_method: trait_fty={:?}", trait_fty); diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index 4d74962d28ed3..de6336b254b3f 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -354,9 +354,9 @@ impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> { fn binders( &mut self, - a: ty::Binder, - b: ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> where T: Relate<'tcx>, { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index a7a412f06becc..9ace455042103 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1462,7 +1462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &[][..], has_self, self_ty, - arg_count, + &arg_count, &mut CreateCtorSubstsContext { fcx: self, span, diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index bd89c7274e77b..6112a5fdc91d6 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -55,7 +55,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { pointing_at_return_type = self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest); - self.suggest_missing_return_expr(err, expr, &fn_decl, expected, found); + let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap(); + self.suggest_missing_return_expr(err, expr, &fn_decl, expected, found, fn_id); } pointing_at_return_type } @@ -479,6 +480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn_decl: &hir::FnDecl<'_>, expected: Ty<'tcx>, found: Ty<'tcx>, + id: hir::HirId, ) { if !expected.is_unit() { return; @@ -486,7 +488,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let found = self.resolve_vars_with_obligations(found); if let hir::FnRetTy::Return(ty) = fn_decl.output { let ty = >::ast_ty_to_ty(self, ty); - let ty = self.tcx.erase_late_bound_regions(Binder::bind(ty)); + let bound_vars = self.tcx.late_bound_vars(id); + let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); let ty = self.normalize_associated_types_in(expr.span, ty); if self.can_coerce(found, ty) { err.multipart_suggestion( diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index 91708465b3f60..e40aa91485858 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -186,7 +186,10 @@ pub fn resolve_interior<'a, 'tcx>( // which means that none of the regions inside relate to any other, even if // typeck had previously found constraints that would cause them to be related. let folded = fcx.tcx.fold_regions(erased, &mut false, |_, current_depth| { - let br = ty::BoundRegion { kind: ty::BrAnon(counter) }; + let br = ty::BoundRegion { + var: ty::BoundVar::from_u32(counter), + kind: ty::BrAnon(counter), + }; let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br)); counter += 1; r @@ -202,11 +205,15 @@ pub fn resolve_interior<'a, 'tcx>( // Extract type components to build the witness type. let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty)); - let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list)); + let bound_vars = fcx.tcx.mk_bound_variable_kinds( + (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))), + ); + let witness = + fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone())); // Store the generator types and spans into the typeck results for this generator. visitor.fcx.inh.typeck_results.borrow_mut().generator_interior_types = - ty::Binder::bind(type_causes); + ty::Binder::bind_with_vars(type_causes, bound_vars); debug!( "types in generator after region replacement {:?}, span = {:?}", diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 990ed5abdbfcb..303a77507cf7b 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -101,12 +101,21 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let intrinsic_name = tcx.item_name(it.def_id.to_def_id()); let name_str = intrinsic_name.as_str(); + let bound_vars = tcx.mk_bound_variable_kinds( + [ty::BoundVariableKind::Region(ty::BrAnon(0)), ty::BoundVariableKind::Region(ty::BrEnv)] + .iter() + .copied(), + ); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { - let region = tcx - .mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrAnon(0) })); - let env_region = - tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrEnv })); + let region = tcx.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }, + )); + let env_region = tcx.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv }, + )); let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]); (tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty) }) @@ -305,7 +314,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap()); let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id; - let br = ty::BoundRegion { kind: ty::BrAnon(0) }; + let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0) }; ( 1, vec![ @@ -366,7 +375,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { (n_tps, inputs, output, unsafety) }; let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic); - let sig = ty::Binder::bind(sig); + let sig = ty::Binder::bind_with_vars(sig, bound_vars); equate_intrinsic_type(tcx, it, n_tps, sig) } diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index fff659a91adfc..f546a0d896354 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -119,7 +119,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // We won't add these if we encountered an illegal sized bound, so that we can use // a custom error in that case. if illegal_sized_bound.is_none() { - let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig)); + let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig, self.tcx)); self.add_obligations(method_ty, all_substs, method_predicates); } @@ -381,7 +381,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { parent_substs, false, None, - arg_count_correct, + &arg_count_correct, &mut MethodSubstsCtxt { cfcx: self, pick, seg }, ) } @@ -550,7 +550,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { upcast_trait_refs.into_iter().next().unwrap() } - fn replace_bound_vars_with_fresh_vars(&self, value: ty::Binder) -> T + fn replace_bound_vars_with_fresh_vars(&self, value: ty::Binder<'tcx, T>) -> T where T: TypeFoldable<'tcx>, { diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index c74fd25f76d37..bd7ffd057b466 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -399,7 +399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds)); // Also add an obligation for the method type being well-formed. - let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig)); + let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig, tcx)); debug!( "lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}", method_ty, obligation diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 0742549f8904e..bfaf36e702fdb 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -1753,7 +1753,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /// region got replaced with the same variable, which requires a bit more coordination /// and/or tracking the substitution and /// so forth. - fn erase_late_bound_regions(&self, value: ty::Binder) -> T + fn erase_late_bound_regions(&self, value: ty::Binder<'tcx, T>) -> T where T: TypeFoldable<'tcx>, { diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index ad9bb70377968..0760d59875c70 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -497,6 +497,7 @@ fn typeck_with_fallback<'tcx>( let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); >::ty_of_fn( &fcx, + id, header.unsafety, header.abi, decl, diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index e7e603c8bd510..887cc42a1dd27 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1067,13 +1067,14 @@ fn check_method_receiver<'fcx, 'tcx>( debug!("check_method_receiver: sig={:?}", sig); let self_ty = fcx.normalize_associated_types_in(span, self_ty); - let self_ty = fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(self_ty)); + let self_ty = + fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(self_ty, fcx.tcx)); let receiver_ty = sig.inputs()[0]; let receiver_ty = fcx.normalize_associated_types_in(span, receiver_ty); let receiver_ty = - fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(receiver_ty)); + fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(receiver_ty, fcx.tcx)); if fcx.tcx.features().arbitrary_self_types { if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) { diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 0ef5f4d1c180c..afe52c977334d 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1244,7 +1244,8 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option {} Some( - rl::Region::LateBound(debruijn, _, _) | rl::Region::LateBoundAnon(debruijn, _), + rl::Region::LateBound(debruijn, _, _, _) + | rl::Region::LateBoundAnon(debruijn, _, _), ) if debruijn < self.outer_index => {} Some( rl::Region::LateBound(..) @@ -1707,10 +1708,11 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { } diag.emit(); - ty::Binder::bind(fn_sig) + ty::Binder::bind(fn_sig, tcx) } None => >::ty_of_fn( &icx, + hir_id, sig.header.unsafety, sig.header.abi, &sig.decl, @@ -1728,6 +1730,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { .. }) => >::ty_of_fn( &icx, + hir_id, header.unsafety, header.abi, decl, @@ -1749,13 +1752,10 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id).to_def_id()); let inputs = data.fields().iter().map(|f| tcx.type_of(tcx.hir().local_def_id(f.hir_id))); - ty::Binder::bind(tcx.mk_fn_sig( - inputs, - ty, - false, - hir::Unsafety::Normal, - abi::Abi::Rust, - )) + ty::Binder::bind( + tcx.mk_fn_sig(inputs, ty, false, hir::Unsafety::Normal, abi::Abi::Rust), + tcx, + ) } Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => { @@ -2039,7 +2039,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP param.bounds.iter().for_each(|bound| match bound { hir::GenericBound::Outlives(lt) => { let bound = >::ast_region_to_region(&icx, <, None); - let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound)); + let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound), tcx); predicates.insert((outlives.to_predicate(tcx), lt.span)); } _ => bug!(), @@ -2084,6 +2084,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP match predicate { hir::WherePredicate::BoundPredicate(bound_pred) => { let ty = icx.to_ty(&bound_pred.bounded_ty); + let bound_vars = icx.tcx.late_bound_vars(bound_pred.bounded_ty.hir_id); // Keep the type around in a dummy predicate, in case of no bounds. // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` @@ -2099,9 +2100,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } else { let span = bound_pred.bounded_ty.span; let re_root_empty = tcx.lifetimes.re_root_empty; - let predicate = ty::Binder::bind(ty::PredicateKind::TypeOutlives( - ty::OutlivesPredicate(ty, re_root_empty), - )); + let predicate = ty::Binder::bind_with_vars( + ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( + ty, + re_root_empty, + )), + bound_vars, + ); predicates.insert((predicate.to_predicate(tcx), span)); } } @@ -2118,10 +2123,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP let mut bounds = Bounds::default(); let _ = >::instantiate_poly_trait_ref( &icx, - &poly_trait_ref, + &poly_trait_ref.trait_ref, + poly_trait_ref.span, constness, ty, &mut bounds, + false, ); predicates.extend(bounds.predicates(tcx, ty)); } @@ -2144,9 +2151,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP let region = >::ast_region_to_region(&icx, lifetime, None); predicates.insert(( - ty::Binder::bind(ty::PredicateKind::TypeOutlives( - ty::OutlivesPredicate(ty, region), - )) + ty::Binder::bind_with_vars( + ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( + ty, region, + )), + bound_vars, + ) .to_predicate(tcx), lifetime.span, )); @@ -2368,7 +2378,14 @@ fn predicates_from_bound<'tcx>( }; let mut bounds = Bounds::default(); - let _ = astconv.instantiate_poly_trait_ref(tr, constness, param_ty, &mut bounds); + let _ = astconv.instantiate_poly_trait_ref( + &tr.trait_ref, + tr.span, + constness, + param_ty, + &mut bounds, + false, + ); bounds.predicates(astconv.tcx(), param_ty) } hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { @@ -2404,8 +2421,10 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( } else { hir::Unsafety::Unsafe }; + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let fty = >::ty_of_fn( &ItemCtxt::new(tcx, def_id), + hir_id, unsafety, abi, decl, diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index cb442344fa21c..190744fe6f1d8 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -430,7 +430,7 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> { let env_node_id = tcx.hir().get_parent_item(hir_ty.hir_id); let env_def_id = tcx.hir().local_def_id(env_node_id); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); - item_cx.to_ty(hir_ty) + >::ast_ty_to_ty(&item_cx, hir_ty) } pub fn hir_trait_to_predicates<'tcx>( @@ -445,7 +445,7 @@ pub fn hir_trait_to_predicates<'tcx>( let env_def_id = tcx.hir().local_def_id(env_hir_id); let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.to_def_id()); let mut bounds = Bounds::default(); - let _ = >::instantiate_poly_trait_ref_inner( + let _ = >::instantiate_poly_trait_ref( &item_cx, hir_trait, DUMMY_SP, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4d33a1e69612f..217e899001ef9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -352,7 +352,7 @@ impl Clean for hir::Lifetime { match def { Some( rl::Region::EarlyBound(_, node_id, _) - | rl::Region::LateBound(_, node_id, _) + | rl::Region::LateBound(_, _, node_id, _) | rl::Region::Free(_, node_id), ) => { if let Some(lt) = cx.lt_substs.get(&node_id).cloned() { @@ -411,7 +411,7 @@ impl Clean> for ty::RegionKind { fn clean(&self, _cx: &mut DocContext<'_>) -> Option { match *self { ty::ReStatic => Some(Lifetime::statik()), - ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name) }) => { + ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => { Some(Lifetime(name)) } ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)), diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 32bac53e8f51b..60cbe9f376f01 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -97,7 +97,7 @@ fn external_generic_args( .iter() .filter_map(|kind| match kind.unpack() { GenericArgKind::Lifetime(lt) => match lt { - ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrAnon(_) }) => { + ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrAnon(_), .. }) => { Some(GenericArg::Lifetime(Lifetime::elided())) } _ => lt.clean(cx).map(GenericArg::Lifetime), diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index ed67b2dcb0480..c8530c70f78d2 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -118,7 +118,7 @@ pub fn type_parameter() {} pub fn lifetime_parameter() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn lifetime_parameter<'a>() {} @@ -150,7 +150,7 @@ pub fn lifetime_bound<'a, T>() {} #[cfg(not(cfail1))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" + except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] pub fn lifetime_bound<'a, T: 'a>() {} @@ -183,7 +183,7 @@ pub fn second_lifetime_bound<'a, 'b, T: 'a>() {} #[cfg(not(cfail1))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" + except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index ae8f2ace217dc..ee7b258cec4ed 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -312,7 +312,7 @@ impl Foo { // if we lower generics before the body, then the `HirId` for // things in the body will be affected. So if you start to see // `typeck` appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig")] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_parameter_to_method<'a>(&self) { } } @@ -360,7 +360,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of" + except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } @@ -388,7 +388,7 @@ impl Foo { // body will be affected. So if you start to see `typeck` // appear dirty, that might be the cause. -nmatsakis #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,\ - type_of")] + type_of,fn_sig")] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { } } diff --git a/src/test/ui/associated-type-bounds/hrtb.rs b/src/test/ui/associated-type-bounds/hrtb.rs new file mode 100644 index 0000000000000..7ab3836493b01 --- /dev/null +++ b/src/test/ui/associated-type-bounds/hrtb.rs @@ -0,0 +1,65 @@ +// check-pass + +#![feature(associated_type_bounds)] + +trait A<'a> {} +trait B<'b> {} +fn foo() +where + for<'a> T: A<'a> + 'a, +{ +} +trait C<'c>: for<'a> A<'a> + for<'b> B<'b> { + type As; +} +struct D +where + T: for<'c> C<'c, As: A<'c>>, +{ + t: std::marker::PhantomData, +} + +trait E<'e> { + type As; +} +trait F<'f>: for<'a> A<'a> + for<'e> E<'e> {} +struct G +where + for<'f> T: F<'f, As: E<'f>> + 'f, +{ + t: std::marker::PhantomData, +} + +trait I<'a, 'b, 'c> { + type As; +} +trait H<'d, 'e>: for<'f> I<'d, 'f, 'e> + 'd {} +fn foo2() +where + T: for<'g> H<'g, 'g, As: for<'h> H<'h, 'g> + 'g>, +{ +} + +fn foo3() +where + T: for<'i> H<'i, 'i, As: for<'j> H<'j, 'i, As: for<'k> I<'i, 'k, 'j> + 'j> + 'i>, +{ +} +fn foo4() +where + T: for<'l, 'i> H<'l, 'i, As: for<'j> H<'j, 'i, As: for<'k> I<'l, 'k, 'j> + 'j> + 'i>, +{ +} + +struct X<'x, 'y> { + x: std::marker::PhantomData<&'x ()>, + y: std::marker::PhantomData<&'y ()>, +} + +fn foo5() +where + T: for<'l, 'i> H<'l, 'i, As: for<'j> H<'j, 'i, As: for<'k> H<'j, 'k, As = X<'j, 'k>> + 'j> + 'i> +{ +} + +fn main() {} diff --git a/src/test/ui/hrtb/complex.rs b/src/test/ui/hrtb/complex.rs new file mode 100644 index 0000000000000..8cdfe247e025e --- /dev/null +++ b/src/test/ui/hrtb/complex.rs @@ -0,0 +1,28 @@ +// check-pass + +trait A<'a> {} +trait B<'b> {} +fn foo() where for<'a> T: A<'a> + 'a {} +trait C<'c>: for<'a> A<'a> + for<'b> B<'b> { + type As; +} +struct D where T: for<'c> C<'c, As=&'c ()> { + t: std::marker::PhantomData, +} +trait E<'e, 'g> { + type As; +} +trait F<'f>: for<'a> A<'a> + for<'e> E<'e, 'f> {} +struct G where T: for<'f> F<'f, As=&'f ()> { + t: std::marker::PhantomData, +} +trait H<'a, 'b> { + type As; +} +trait I<'a>: for<'b> H<'a, 'b> {} + +struct J where T: for<'i> I<'i, As=&'i ()> { + t: std::marker::PhantomData, +} + +fn main() {} diff --git a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.rs b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.rs index 3b407871e37e1..c1c40afdbab55 100644 --- a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.rs +++ b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.rs @@ -7,7 +7,7 @@ fn foo(x: &u32) { fn foo2(x: &u32) {} fn bar() { - let y: fn(&'test u32) = foo2; + let y: fn(&'test u32) = foo2; //~ ERROR use of undeclared lifetime } fn main() {} diff --git a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr index 7ecb6ff0c9da9..a43b49041ec2a 100644 --- a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr +++ b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr @@ -6,6 +6,22 @@ LL | fn foo(x: &u32) { LL | let y: &'test u32 = x; | ^^^^^ undeclared lifetime -error: aborting due to previous error +error[E0261]: use of undeclared lifetime name `'test` + --> $DIR/no_introducing_in_band_in_locals.rs:10:16 + | +LL | let y: fn(&'test u32) = foo2; + | ^^^^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider introducing lifetime `'test` here + | +LL | fn bar<'test>() { + | ^^^^^^^ +help: consider making the type lifetime-generic with a new `'test` lifetime + | +LL | let y: for<'test> fn(&'test u32) = foo2; + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/methods/method-call-lifetime-args-unresolved.rs b/src/test/ui/methods/method-call-lifetime-args-unresolved.rs index d7760985ec6f0..d16ba3df47b63 100644 --- a/src/test/ui/methods/method-call-lifetime-args-unresolved.rs +++ b/src/test/ui/methods/method-call-lifetime-args-unresolved.rs @@ -1,5 +1,3 @@ fn main() { 0.clone::<'a>(); //~ ERROR use of undeclared lifetime name `'a` - //~^ WARNING cannot specify lifetime arguments - //~| WARNING this was previously accepted } diff --git a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr index 5a958bc4b9c31..93c0384fcc266 100644 --- a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr +++ b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr @@ -1,18 +1,3 @@ -warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/method-call-lifetime-args-unresolved.rs:2:15 - | -LL | 0.clone::<'a>(); - | ^^ - | - ::: $SRC_DIR/core/src/clone.rs:LL:COL - | -LL | fn clone(&self) -> Self; - | - the late bound lifetime parameter is introduced here - | - = note: `#[warn(late_bound_lifetime_arguments)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #42868 - error[E0261]: use of undeclared lifetime name `'a` --> $DIR/method-call-lifetime-args-unresolved.rs:2:15 | @@ -23,6 +8,6 @@ LL | 0.clone::<'a>(); | = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr index 4e122d930fc4e..ff16bf0e078fc 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure substs [ i16, - for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) i32)), + for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) i32)), (), ] diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr index 44d1d2327fcdb..22398f0857255 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32)), + for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32)), (), ] diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index fa9f994c4fae3..11420efaa066e 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -10,7 +10,7 @@ LL | | }, | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)), + for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), (), ] = note: late-bound region is '_#4r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr index 0555f79bcb03b..98c3c28fb43ff 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -11,7 +11,7 @@ LL | | }); | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)), + for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index 0932f9415480c..30ef343b26123 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -10,7 +10,7 @@ LL | | }) | = note: defining type: case1::{closure#0} with closure substs [ i32, - for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>)), + for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>)), (), ] @@ -49,7 +49,7 @@ LL | | }) | = note: defining type: case2::{closure#0} with closure substs [ i32, - for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>)), + for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>)), (), ] = note: number of external vids: 2 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index bf6e2a922ed08..29993b129c71a 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -12,7 +12,7 @@ LL | | }); | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) u32>)), + for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) u32>)), (), ] = note: late-bound region is '_#2r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index a3d993848cbaa..cb505d8b1eceb 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -12,7 +12,7 @@ LL | | }); | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)), + for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr index 60dca1baa40e7..2ec9d4d8db1a6 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -11,7 +11,7 @@ LL | | }); | = note: defining type: test::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)), + for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr index cbb10eb187ed8..21e4232c788fb 100644 --- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -10,7 +10,7 @@ LL | | }, | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)), + for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index f9f1d8bb6fffa..8b9b043542057 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -11,7 +11,7 @@ LL | | }); | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)), + for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)), (), ] = note: late-bound region is '_#2r diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 1587c28e1bef3..060ce690f0306 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -11,7 +11,7 @@ LL | | }); | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)), + for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr index 44f743310b483..5fc1d5c436181 100644 --- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -6,7 +6,7 @@ LL | expect_sig(|a, b| b); // ought to return `a` | = note: defining type: test::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) i32, + for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) i32, (), ] diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index dbf76cd1329cb..baf223b786b08 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -6,7 +6,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic::::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) T)), + for<'r, 's> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)), (), ] = note: number of external vids: 2 @@ -31,7 +31,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic_fail::::{closure#0} with closure substs [ i16, - for<'r, 's> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) T)), + for<'r, 's> extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)), (), ] = note: late-bound region is '_#2r diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr index 92208231b1735..fa59d7a031397 100644 --- a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr +++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr @@ -1,4 +1,4 @@ -error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,)))` +error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,)), [])` --> $DIR/repeated_projection_type.rs:19:1 | LL | / impl> X for V { diff --git a/src/test/ui/symbol-names/basic.legacy.stderr b/src/test/ui/symbol-names/basic.legacy.stderr index 7155d88be9632..3dd2b19fbf987 100644 --- a/src/test/ui/symbol-names/basic.legacy.stderr +++ b/src/test/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17hfcf1daab33c43a6aE) +error: symbol-name(_ZN5basic4main17h6c535bbea2051f85E) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::hfcf1daab33c43a6a) +error: demangling(basic::main::h6c535bbea2051f85) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr index 9575875f5a8ac..65cc62b4d1dd6 100644 --- a/src/test/ui/symbol-names/issue-60925.legacy.stderr +++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hb8ca3eb2682b1b51E) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h6244e5288326926aE) --> $DIR/issue-60925.rs:22:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::hb8ca3eb2682b1b51) +error: demangling(issue_60925::foo::Foo::foo::h6244e5288326926a) --> $DIR/issue-60925.rs:22:9 | LL | #[rustc_symbol_name] diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs index bad3e488bb6d5..4c13941f66599 100644 --- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs +++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs @@ -44,7 +44,7 @@ fn get_trait_predicates_for_trait_id<'tcx>( for (pred, _) in generics.predicates { if_chain! { if let PredicateKind::Trait(poly_trait_pred, _) = pred.kind().skip_binder(); - let trait_pred = cx.tcx.erase_late_bound_regions(ty::Binder::bind(poly_trait_pred)); + let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred)); if let Some(trait_def_id) = trait_id; if trait_def_id == trait_pred.trait_ref.def_id; then { @@ -58,12 +58,12 @@ fn get_trait_predicates_for_trait_id<'tcx>( fn get_projection_pred<'tcx>( cx: &LateContext<'tcx>, generics: GenericPredicates<'tcx>, - pred: TraitPredicate<'tcx>, + trait_pred: TraitPredicate<'tcx>, ) -> Option> { generics.predicates.iter().find_map(|(proj_pred, _)| { - if let ty::PredicateKind::Projection(proj_pred) = proj_pred.kind().skip_binder() { - let projection_pred = cx.tcx.erase_late_bound_regions(ty::Binder::bind(proj_pred)); - if projection_pred.projection_ty.substs == pred.trait_ref.substs { + if let ty::PredicateKind::Projection(pred) = proj_pred.kind().skip_binder() { + let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.kind().rebind(pred)); + if projection_pred.projection_ty.substs == trait_pred.trait_ref.substs { return Some(projection_pred); } }