From 7ae301ec47ee6e3ed63a4f34eaad01d3d4b46755 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 14 Sep 2023 03:49:41 +0000 Subject: [PATCH] Properly consider binder vars in HasTypeFlagsVisitor --- compiler/rustc_middle/src/ty/flags.rs | 36 +++++++++++-------- compiler/rustc_middle/src/ty/visit.rs | 24 +++++++++++++ ...anonymize-unnamed-bound-vars-in-binders.rs | 27 ++++++++++++++ 3 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 tests/ui/lifetimes/anonymize-unnamed-bound-vars-in-binders.rs diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 3cafd9a8da913..231635c086e3b 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -34,6 +34,26 @@ impl FlagComputation { result.flags } + pub fn bound_var_flags(vars: &ty::List) -> FlagComputation { + let mut computation = FlagComputation::new(); + + for bv in 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; + } + } + } + + computation + } + fn add_flags(&mut self, flags: TypeFlags) { self.flags = self.flags | flags; } @@ -57,21 +77,7 @@ impl FlagComputation { where F: FnOnce(&mut Self, T), { - let mut computation = FlagComputation::new(); - - 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; - } - } - } + let mut computation = FlagComputation::bound_var_flags(value.bound_vars()); f(&mut computation, value.skip_binder()); diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index fb760654ea785..5deb5bfb19ee4 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -481,9 +481,33 @@ impl std::fmt::Debug for HasTypeFlagsVisitor { // `Ty`/`Const`/`Predicate`, but not within those types. This is because the // type flags at the outer layer are enough. So it's faster than it first // looks, particular for `Ty`/`Predicate` where it's just a field access. +// +// N.B. The only case where this isn't totally true is binders, which also +// add `HAS_{RE,TY,CT}_LATE_BOUND` flag depending on the *bound variables* that +// are present, regardless of whether those bound variables are used. This +// is important for anonymization of binders in `TyCtxt::erase_regions`. We +// specifically detect this case in `visit_binder`. impl<'tcx> TypeVisitor> for HasTypeFlagsVisitor { type BreakTy = FoundFlags; + fn visit_binder>>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { + // If we're looking for any of the HAS_*_LATE_BOUND flags, we need to + // additionally consider the bound vars on the binder itself, even if + // the contents of a the binder (e.g. a `TraitRef`) doesn't reference + // the bound vars. + if self.flags.intersects(TypeFlags::HAS_LATE_BOUND) { + let bound_var_flags = FlagComputation::bound_var_flags(t.bound_vars()); + if bound_var_flags.flags.intersects(self.flags) { + return ControlFlow::Break(FoundFlags); + } + } + + t.super_visit_with(self) + } + #[inline] fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { // Note: no `super_visit_with` call. diff --git a/tests/ui/lifetimes/anonymize-unnamed-bound-vars-in-binders.rs b/tests/ui/lifetimes/anonymize-unnamed-bound-vars-in-binders.rs new file mode 100644 index 0000000000000..05e3763e9d103 --- /dev/null +++ b/tests/ui/lifetimes/anonymize-unnamed-bound-vars-in-binders.rs @@ -0,0 +1,27 @@ +// build-pass +// issue: #115807 + +trait Chip: for<'a> TraitWithLifetime<'a> + SomeMarker { + fn compute(&self); +} + +trait SomeMarker {} + +trait TraitWithLifetime<'a>: SomeMarker {} + +trait Machine { + fn run(); +} + +struct BasicMachine; + +impl Machine for BasicMachine { + fn run() { + let chips: [&dyn Chip; 0] = []; + let _ = chips.map(|chip| chip.compute()); + } +} + +fn main() { + BasicMachine::run(); +}