diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0d1aa39c5d956..1afe624240378 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1912,7 +1912,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { } let pred = obligation.predicate; // Match the existing behavior. - if pred.is_global() && !pred.has_late_bound_regions() { + if pred.is_global() && !pred.has_late_bound_vars() { let pred = self.normalize(span, None, pred); let hir_node = tcx.hir().find(self.body_id); diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index ffdac93bcd09a..9e4f90caab0b5 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -21,7 +21,7 @@ impl<'tcx> TyCtxt<'tcx> { T: TypeFoldable<'tcx>, { // If there's nothing to erase avoid performing the query at all - if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) { + if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) { return value; } debug!("erase_regions({:?})", value); diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 8306d670a65de..b7eafc4b43738 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -59,8 +59,18 @@ impl FlagComputation { { let mut computation = FlagComputation::new(); - if !value.bound_vars().is_empty() { - computation.flags = computation.flags | TypeFlags::HAS_RE_LATE_BOUND; + for bv in value.bound_vars() { + match bv { + ty::BoundVariableKind::Ty(_) => { + computation.flags |= TypeFlags::HAS_TY_LATE_BOUND; + } + ty::BoundVariableKind::Region(_) => { + computation.flags |= TypeFlags::HAS_RE_LATE_BOUND; + } + ty::BoundVariableKind::Const => { + computation.flags |= TypeFlags::HAS_CT_LATE_BOUND; + } + } } f(&mut computation, value.skip_binder()); @@ -131,6 +141,7 @@ impl FlagComputation { &ty::Bound(debruijn, _) => { self.add_bound_var(debruijn); + self.add_flags(TypeFlags::HAS_TY_LATE_BOUND); } &ty::Placeholder(..) => { @@ -303,6 +314,7 @@ impl FlagComputation { } ty::ConstKind::Bound(debruijn, _) => { self.add_bound_var(debruijn); + self.add_flags(TypeFlags::HAS_CT_LATE_BOUND); } ty::ConstKind::Param(_) => { self.add_flags(TypeFlags::HAS_CT_PARAM); diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index d5553f84f7517..ca44555813138 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -165,6 +165,14 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone { fn has_late_bound_regions(&self) -> bool { self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND) } + /// True if there are any late-bound non-region variables + fn has_non_region_late_bound(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_LATE_BOUND - TypeFlags::HAS_RE_LATE_BOUND) + } + /// True if there are any late-bound variables + fn has_late_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_LATE_BOUND) + } /// Indicates whether this value still has parameters/placeholders/inference variables /// which could be replaced later, in a way that would change the results of `impl` diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 9e8117c6a8536..0d446d654dc5c 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -206,6 +206,7 @@ impl<'tcx> SymbolMangler<'tcx> { where T: TypeVisitable<'tcx>, { + // FIXME(non-lifetime-binders): What to do here? let regions = if value.has_late_bound_regions() { self.tcx.collect_referenced_late_bound_regions(value) } else { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 760b4585f4e19..3f14491f8032f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -755,7 +755,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // contain the "'static" lifetime (any other lifetime // would either be late-bound or local), so it is guaranteed // to outlive any other lifetime - if pred.0.is_global() && !pred.0.has_late_bound_regions() { + if pred.0.is_global() && !pred.0.has_late_bound_vars() { Ok(EvaluatedToOk) } else { Ok(EvaluatedToOkModuloRegions) @@ -1785,9 +1785,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Check if a bound would previously have been removed when normalizing // the param_env so that it can be given the lowest priority. See // #50825 for the motivation for this. - let is_global = |cand: &ty::PolyTraitPredicate<'tcx>| { - cand.is_global() && !cand.has_late_bound_regions() - }; + let is_global = + |cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_late_bound_vars(); // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`, // `DiscriminantKindCandidate`, `ConstDestructCandidate` diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index fed070408f390..44004cb0be1e9 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -241,22 +241,30 @@ bitflags! { /// Basically anything but `ReLateBound` and `ReErased`. const HAS_FREE_REGIONS = 1 << 14; - /// Does this have any `ReLateBound` regions? Used to check - /// if a global bound is safe to evaluate. + /// Does this have any `ReLateBound` regions? const HAS_RE_LATE_BOUND = 1 << 15; + /// Does this have any `Bound` types? + const HAS_TY_LATE_BOUND = 1 << 16; + /// Does this have any `ConstKind::Bound` consts? + const HAS_CT_LATE_BOUND = 1 << 17; + /// Does this have any bound variables? + /// Used to check if a global bound is safe to evaluate. + const HAS_LATE_BOUND = TypeFlags::HAS_RE_LATE_BOUND.bits + | TypeFlags::HAS_TY_LATE_BOUND.bits + | TypeFlags::HAS_CT_LATE_BOUND.bits; /// Does this have any `ReErased` regions? - const HAS_RE_ERASED = 1 << 16; + const HAS_RE_ERASED = 1 << 18; /// Does this value have parameters/placeholders/inference variables which could be /// replaced later, in a way that would change the results of `impl` specialization? - const STILL_FURTHER_SPECIALIZABLE = 1 << 17; + const STILL_FURTHER_SPECIALIZABLE = 1 << 19; /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`? - const HAS_TY_FRESH = 1 << 18; + const HAS_TY_FRESH = 1 << 20; /// Does this value have `InferConst::Fresh`? - const HAS_CT_FRESH = 1 << 19; + const HAS_CT_FRESH = 1 << 21; } }