1
Fork 0

require a tcx for TypeVisitor

This commit is contained in:
lcnr 2021-03-13 16:05:15 +01:00
parent 76e755cf4a
commit f4b606fd17
24 changed files with 182 additions and 50 deletions

View file

@ -1537,6 +1537,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} }
impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) { if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) {
let span = self.tcx.def_span(def_id); let span = self.tcx.def_span(def_id);

View file

@ -9,7 +9,9 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorRepor
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor};
use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind};
use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor}; use rustc_middle::ty::{
self, AssocItemContainer, RegionKind, Ty, TyCtxt, TypeFoldable, TypeVisitor,
};
use rustc_span::symbol::Ident; use rustc_span::symbol::Ident;
use rustc_span::{MultiSpan, Span}; use rustc_span::{MultiSpan, Span};
@ -476,8 +478,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Collect all the trait objects in a type that could have received an implicit `'static` lifetime. /// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
pub(super) struct TraitObjectVisitor(pub(super) FxHashSet<DefId>); pub(super) struct TraitObjectVisitor(pub(super) FxHashSet<DefId>);
impl TypeVisitor<'_> for TraitObjectVisitor { impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> { fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> {
bug!("tcx_for_anon_const_substs called for TraitObjectVisitor");
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() { match t.kind() {
ty::Dynamic(preds, RegionKind::ReStatic) => { ty::Dynamic(preds, RegionKind::ReStatic) => {
if let Some(def_id) = preds.principal_def_id() { if let Some(def_id) = preds.principal_def_id() {

View file

@ -202,6 +202,7 @@ where
}; };
value.skip_binder().visit_with(&mut ScopeInstantiator { value.skip_binder().visit_with(&mut ScopeInstantiator {
tcx: self.infcx.tcx,
next_region: &mut next_region, next_region: &mut next_region,
target_index: ty::INNERMOST, target_index: ty::INNERMOST,
bound_region_scope: &mut scope, bound_region_scope: &mut scope,
@ -757,6 +758,7 @@ where
/// `for<..`>. For each of those, it creates an entry in /// `for<..`>. For each of those, it creates an entry in
/// `bound_region_scope`. /// `bound_region_scope`.
struct ScopeInstantiator<'me, 'tcx> { struct ScopeInstantiator<'me, 'tcx> {
tcx: TyCtxt<'tcx>,
next_region: &'me mut dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx>, next_region: &'me mut dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
// The debruijn index of the scope we are instantiating. // The debruijn index of the scope we are instantiating.
target_index: ty::DebruijnIndex, target_index: ty::DebruijnIndex,
@ -764,6 +766,10 @@ struct ScopeInstantiator<'me, 'tcx> {
} }
impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> { impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_binder<T: TypeFoldable<'tcx>>( fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: &ty::Binder<'tcx, T>, t: &ty::Binder<'tcx, T>,

View file

@ -126,6 +126,11 @@ impl<'a, 'tcx> UnresolvedTypeFinder<'a, 'tcx> {
impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
type BreakTy = (Ty<'tcx>, Option<Span>); type BreakTy = (Ty<'tcx>, Option<Span>);
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
let t = self.infcx.shallow_resolve(t); let t = self.infcx.shallow_resolve(t);
if t.has_infer_types() { if t.has_infer_types() {

View file

@ -1160,6 +1160,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> { impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
type BreakTy = Ty<'tcx>; type BreakTy = Ty<'tcx>;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.cx.tcx
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match ty.kind() { match ty.kind() {

View file

@ -189,6 +189,12 @@ pub trait TypeFolder<'tcx>: Sized {
pub trait TypeVisitor<'tcx>: Sized { pub trait TypeVisitor<'tcx>: Sized {
type BreakTy = !; type BreakTy = !;
/// Supplies the `tcx` for an unevaluated anonymous constant in case its default substs
/// are not yet supplied.
///
/// Visitors which do not look into these substs may leave this unimplemented, so be
/// careful when calling this method elsewhere.
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx>;
fn visit_binder<T: TypeFoldable<'tcx>>( fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
@ -301,7 +307,8 @@ impl<'tcx> TyCtxt<'tcx> {
value: &impl TypeFoldable<'tcx>, value: &impl TypeFoldable<'tcx>,
callback: impl FnMut(ty::Region<'tcx>) -> bool, callback: impl FnMut(ty::Region<'tcx>) -> bool,
) -> bool { ) -> bool {
struct RegionVisitor<F> { struct RegionVisitor<'tcx, F> {
tcx: TyCtxt<'tcx>,
/// The index of a binder *just outside* the things we have /// The index of a binder *just outside* the things we have
/// traversed. If we encounter a bound region bound by this /// traversed. If we encounter a bound region bound by this
/// binder or one outer to it, it appears free. Example: /// binder or one outer to it, it appears free. Example:
@ -323,12 +330,16 @@ impl<'tcx> TyCtxt<'tcx> {
callback: F, callback: F,
} }
impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F> impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<'tcx, F>
where where
F: FnMut(ty::Region<'tcx>) -> bool, F: FnMut(ty::Region<'tcx>) -> bool,
{ {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_binder<T: TypeFoldable<'tcx>>( fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: &Binder<'tcx, T>, t: &Binder<'tcx, T>,
@ -364,7 +375,9 @@ impl<'tcx> TyCtxt<'tcx> {
} }
} }
value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback }).is_break() value
.visit_with(&mut RegionVisitor { tcx: self, outer_index: ty::INNERMOST, callback })
.is_break()
} }
} }
@ -708,7 +721,7 @@ impl<'tcx> TyCtxt<'tcx> {
where where
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,
{ {
let mut collector = LateBoundRegionsCollector::new(just_constraint); let mut collector = LateBoundRegionsCollector::new(self, just_constraint);
let result = value.as_ref().skip_binder().visit_with(&mut collector); let result = value.as_ref().skip_binder().visit_with(&mut collector);
assert!(result.is_continue()); // should never have stopped early assert!(result.is_continue()); // should never have stopped early
collector.regions collector.regions
@ -775,6 +788,10 @@ impl<'tcx> ValidateBoundVars<'tcx> {
impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> { impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("default anon const substs can't contain bound vars");
}
fn visit_binder<T: TypeFoldable<'tcx>>( fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: &Binder<'tcx, T>, t: &Binder<'tcx, T>,
@ -989,6 +1006,10 @@ struct HasEscapingVarsVisitor {
impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
type BreakTy = FoundEscapingVars; type BreakTy = FoundEscapingVars;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("tcx_for_anon_const_substs called for HasEscpaingVarsVisitor");
}
fn visit_binder<T: TypeFoldable<'tcx>>( fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: &Binder<'tcx, T>, t: &Binder<'tcx, T>,
@ -1059,6 +1080,9 @@ struct HasTypeFlagsVisitor {
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
type BreakTy = FoundFlags; type BreakTy = FoundFlags;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("tcx_for_anon_const_substs called for HasTypeFlagsVisitor");
}
#[inline] #[inline]
fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> {
@ -1113,7 +1137,8 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
/// Collects all the late-bound regions at the innermost binding level /// Collects all the late-bound regions at the innermost binding level
/// into a hash set. /// into a hash set.
struct LateBoundRegionsCollector { struct LateBoundRegionsCollector<'tcx> {
tcx: TyCtxt<'tcx>,
current_index: ty::DebruijnIndex, current_index: ty::DebruijnIndex,
regions: FxHashSet<ty::BoundRegionKind>, regions: FxHashSet<ty::BoundRegionKind>,
@ -1127,9 +1152,10 @@ struct LateBoundRegionsCollector {
just_constrained: bool, just_constrained: bool,
} }
impl LateBoundRegionsCollector { impl LateBoundRegionsCollector<'tcx> {
fn new(just_constrained: bool) -> Self { fn new(tcx: TyCtxt<'tcx>, just_constrained: bool) -> Self {
LateBoundRegionsCollector { LateBoundRegionsCollector {
tcx,
current_index: ty::INNERMOST, current_index: ty::INNERMOST,
regions: Default::default(), regions: Default::default(),
just_constrained, just_constrained,
@ -1137,7 +1163,11 @@ impl LateBoundRegionsCollector {
} }
} }
impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector<'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_binder<T: TypeFoldable<'tcx>>( fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: &Binder<'tcx, T>, t: &Binder<'tcx, T>,

View file

@ -2017,6 +2017,7 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
debug!("prepare_late_bound_region_info(value: {:?})", value); debug!("prepare_late_bound_region_info(value: {:?})", value);
struct LateBoundRegionNameCollector<'a, 'tcx> { struct LateBoundRegionNameCollector<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
used_region_names: &'a mut FxHashSet<Symbol>, used_region_names: &'a mut FxHashSet<Symbol>,
type_collector: SsoHashSet<Ty<'tcx>>, type_collector: SsoHashSet<Ty<'tcx>>,
} }
@ -2024,6 +2025,10 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("LateBoundRegionNameCollector::visit_region(r: {:?}, address: {:p})", r, &r); debug!("LateBoundRegionNameCollector::visit_region(r: {:?}, address: {:p})", r, &r);
if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r { if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
@ -2053,6 +2058,7 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
self.used_region_names.clear(); self.used_region_names.clear();
let mut collector = LateBoundRegionNameCollector { let mut collector = LateBoundRegionNameCollector {
tcx: self.tcx,
used_region_names: &mut self.used_region_names, used_region_names: &mut self.used_region_names,
type_collector: SsoHashSet::new(), type_collector: SsoHashSet::new(),
}; };

View file

@ -21,6 +21,10 @@ where
impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> { impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> {
type BreakTy = FoundParam; type BreakTy = FoundParam;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if !c.needs_subst() { if !c.needs_subst() {
return ControlFlow::CONTINUE; return ControlFlow::CONTINUE;

View file

@ -178,7 +178,7 @@ fn mark_used_by_predicates<'tcx>(
// Consider all generic params in a predicate as used if any other parameter in the // Consider all generic params in a predicate as used if any other parameter in the
// predicate is used. // predicate is used.
let any_param_used = { let any_param_used = {
let mut vis = HasUsedGenericParams { unused_parameters }; let mut vis = HasUsedGenericParams { tcx, unused_parameters };
predicate.visit_with(&mut vis).is_break() predicate.visit_with(&mut vis).is_break()
}; };
@ -283,6 +283,9 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
} }
impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
}
#[instrument(skip(self))] #[instrument(skip(self))]
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if !c.has_param_types_or_consts() { if !c.has_param_types_or_consts() {
@ -346,13 +349,18 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
} }
/// Visitor used to check if a generic parameter is used. /// Visitor used to check if a generic parameter is used.
struct HasUsedGenericParams<'a> { struct HasUsedGenericParams<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
unused_parameters: &'a FiniteBitSet<u32>, unused_parameters: &'a FiniteBitSet<u32>,
} }
impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> { impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
}
#[instrument(skip(self))] #[instrument(skip(self))]
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if !c.has_param_types_or_consts() { if !c.has_param_types_or_consts() {

View file

@ -682,6 +682,10 @@ pub fn write_allocations<'tcx>(
} }
struct CollectAllocIds(BTreeSet<AllocId>); struct CollectAllocIds(BTreeSet<AllocId>);
impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds { impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("tcx_for_anon_const_substs called for CollectAllocIds")
}
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::ConstKind::Value(val) = c.val { if let ty::ConstKind::Value(val) = c.val {
self.0.extend(alloc_ids_from_const(val)); self.0.extend(alloc_ids_from_const(val));

View file

@ -179,6 +179,10 @@ where
{ {
type BreakTy = V::BreakTy; type BreakTy = V::BreakTy;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.def_id_visitor.tcx()
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> {
let tcx = self.def_id_visitor.tcx(); let tcx = self.def_id_visitor.tcx();
// InternalSubsts are not visited here because they are visited below in `super_visit_with`. // InternalSubsts are not visited here because they are visited below in `super_visit_with`.

View file

@ -352,6 +352,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
if !required_region_bounds.is_empty() { if !required_region_bounds.is_empty() {
for required_region in required_region_bounds { for required_region in required_region_bounds {
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
tcx,
op: |r| self.sub_regions(infer::CallReturn(span), required_region, r), op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
}); });
} }
@ -427,6 +428,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
} }
} }
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
tcx,
op: |r| self.sub_regions(infer::CallReturn(span), least_region, r), op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
}); });
} }
@ -461,6 +463,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
); );
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
tcx: self.tcx,
op: |r| { op: |r| {
self.member_constraint( self.member_constraint(
opaque_type_key.def_id, opaque_type_key.def_id,
@ -546,14 +549,19 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// //
// We ignore any type parameters because impl trait values are assumed to // We ignore any type parameters because impl trait values are assumed to
// capture all the in-scope type parameters. // capture all the in-scope type parameters.
struct ConstrainOpaqueTypeRegionVisitor<OP> { struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP> {
tcx: TyCtxt<'tcx>,
op: OP, op: OP,
} }
impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<OP> impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
where where
OP: FnMut(ty::Region<'tcx>), OP: FnMut(ty::Region<'tcx>),
{ {
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_binder<T: TypeFoldable<'tcx>>( fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: &ty::Binder<'tcx, T>, t: &ty::Binder<'tcx, T>,

View file

@ -771,6 +771,9 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> { impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() { match t.kind() {

View file

@ -130,6 +130,9 @@ impl Search<'a, 'tcx> {
impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
type BreakTy = NonStructuralMatchTy<'tcx>; type BreakTy = NonStructuralMatchTy<'tcx>;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx()
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("Search visiting ty: {:?}", ty); debug!("Search visiting ty: {:?}", ty);

View file

@ -806,7 +806,7 @@ crate fn collect_bound_vars<'tcx, T: TypeFoldable<'tcx>>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
ty: Binder<'tcx, T>, ty: Binder<'tcx, T>,
) -> (T, chalk_ir::VariableKinds<RustInterner<'tcx>>, BTreeMap<DefId, u32>) { ) -> (T, chalk_ir::VariableKinds<RustInterner<'tcx>>, BTreeMap<DefId, u32>) {
let mut bound_vars_collector = BoundVarsCollector::new(); let mut bound_vars_collector = BoundVarsCollector::new(tcx);
ty.as_ref().skip_binder().visit_with(&mut bound_vars_collector); ty.as_ref().skip_binder().visit_with(&mut bound_vars_collector);
let mut parameters = bound_vars_collector.parameters; let mut parameters = bound_vars_collector.parameters;
let named_parameters: BTreeMap<DefId, u32> = bound_vars_collector let named_parameters: BTreeMap<DefId, u32> = bound_vars_collector
@ -836,14 +836,16 @@ crate fn collect_bound_vars<'tcx, T: TypeFoldable<'tcx>>(
} }
crate struct BoundVarsCollector<'tcx> { crate struct BoundVarsCollector<'tcx> {
tcx: TyCtxt<'tcx>,
binder_index: ty::DebruijnIndex, binder_index: ty::DebruijnIndex,
crate parameters: BTreeMap<u32, chalk_ir::VariableKind<RustInterner<'tcx>>>, crate parameters: BTreeMap<u32, chalk_ir::VariableKind<RustInterner<'tcx>>>,
crate named_parameters: Vec<DefId>, crate named_parameters: Vec<DefId>,
} }
impl<'tcx> BoundVarsCollector<'tcx> { impl<'tcx> BoundVarsCollector<'tcx> {
crate fn new() -> Self { crate fn new(tcx: TyCtxt<'tcx>) -> Self {
BoundVarsCollector { BoundVarsCollector {
tcx,
binder_index: ty::INNERMOST, binder_index: ty::INNERMOST,
parameters: BTreeMap::new(), parameters: BTreeMap::new(),
named_parameters: vec![], named_parameters: vec![],
@ -852,6 +854,10 @@ impl<'tcx> BoundVarsCollector<'tcx> {
} }
impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_binder<T: TypeFoldable<'tcx>>( fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: &Binder<'tcx, T>, t: &Binder<'tcx, T>,
@ -1070,6 +1076,10 @@ impl PlaceholdersCollector {
} }
impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector { impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("tcx_for_anon_const_substs called for PlaceholdersCollector");
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() { match t.kind() {
ty::Placeholder(p) if p.universe == self.universe_index => { ty::Placeholder(p) if p.universe == self.universe_index => {

View file

@ -54,6 +54,9 @@ impl<'tcx> BoundVarsCollector<'tcx> {
impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("default anon const substs can't be bound vars");
}
fn visit_binder<T: TypeFoldable<'tcx>>( fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: &Binder<'tcx, T>, t: &Binder<'tcx, T>,

View file

@ -470,14 +470,17 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
debug!(?item, ?span); debug!(?item, ?span);
struct FoundParentLifetime; struct FoundParentLifetime;
struct FindParentLifetimeVisitor<'tcx>(&'tcx ty::Generics); struct FindParentLifetimeVisitor<'tcx>(TyCtxt<'tcx>, &'tcx ty::Generics);
impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> {
type BreakTy = FoundParentLifetime; type BreakTy = FoundParentLifetime;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.0
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("FindParentLifetimeVisitor: r={:?}", r); debug!("FindParentLifetimeVisitor: r={:?}", r);
if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r { if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r {
if *index < self.0.parent_count as u32 { if *index < self.1.parent_count as u32 {
return ControlFlow::Break(FoundParentLifetime); return ControlFlow::Break(FoundParentLifetime);
} else { } else {
return ControlFlow::CONTINUE; return ControlFlow::CONTINUE;
@ -499,21 +502,24 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
} }
struct ProhibitOpaqueVisitor<'tcx> { struct ProhibitOpaqueVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
opaque_identity_ty: Ty<'tcx>, opaque_identity_ty: Ty<'tcx>,
generics: &'tcx ty::Generics, generics: &'tcx ty::Generics,
tcx: TyCtxt<'tcx>,
selftys: Vec<(Span, Option<String>)>, selftys: Vec<(Span, Option<String>)>,
} }
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
type BreakTy = Ty<'tcx>; type BreakTy = Ty<'tcx>;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t); debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t);
if t == self.opaque_identity_ty { if t == self.opaque_identity_ty {
ControlFlow::CONTINUE ControlFlow::CONTINUE
} else { } else {
t.super_visit_with(&mut FindParentLifetimeVisitor(self.generics)) t.super_visit_with(&mut FindParentLifetimeVisitor(self.tcx, self.generics))
.map_break(|FoundParentLifetime| t) .map_break(|FoundParentLifetime| t)
} }
} }
@ -1580,6 +1586,9 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
{ {
struct VisitTypes(Vec<DefId>); struct VisitTypes(Vec<DefId>);
impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes { impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("tcx_for_anon_const_substs called for VisitTypes");
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match *t.kind() { match *t.kind() {
ty::Opaque(def, _) => { ty::Opaque(def, _) => {

View file

@ -428,7 +428,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
if let Some(missing_trait) = missing_trait { if let Some(missing_trait) = missing_trait {
let mut visitor = TypeParamVisitor(vec![]); let mut visitor = TypeParamVisitor(self.tcx, vec![]);
visitor.visit_ty(lhs_ty); visitor.visit_ty(lhs_ty);
if op.node == hir::BinOpKind::Add if op.node == hir::BinOpKind::Add
@ -439,7 +439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// This has nothing here because it means we did string // This has nothing here because it means we did string
// concatenation (e.g., "Hello " + "World!"). This means // concatenation (e.g., "Hello " + "World!"). This means
// we don't want the note in the else clause to be emitted // we don't want the note in the else clause to be emitted
} else if let [ty] = &visitor.0[..] { } else if let [ty] = &visitor.1[..] {
if let ty::Param(p) = *ty.kind() { if let ty::Param(p) = *ty.kind() {
// Check if the method would be found if the type param wasn't // Check if the method would be found if the type param wasn't
// involved. If so, it means that adding a trait bound to the param is // involved. If so, it means that adding a trait bound to the param is
@ -1003,12 +1003,15 @@ fn suggest_constraining_param(
} }
} }
struct TypeParamVisitor<'tcx>(Vec<Ty<'tcx>>); struct TypeParamVisitor<'tcx>(TyCtxt<'tcx>, Vec<Ty<'tcx>>);
impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> { impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.0
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Param(_) = ty.kind() { if let ty::Param(_) = ty.kind() {
self.0.push(ty); self.1.push(ty);
} }
ty.super_visit_with(self) ty.super_visit_with(self)
} }

View file

@ -825,12 +825,15 @@ fn check_where_clauses<'tcx, 'fcx>(
.predicates .predicates
.iter() .iter()
.flat_map(|&(pred, sp)| { .flat_map(|&(pred, sp)| {
#[derive(Default)] struct CountParams<'tcx> {
struct CountParams { tcx: TyCtxt<'tcx>,
params: FxHashSet<u32>, params: FxHashSet<u32>,
} }
impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams<'tcx> {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Param(param) = t.kind() { if let ty::Param(param) = t.kind() {
@ -850,7 +853,7 @@ fn check_where_clauses<'tcx, 'fcx>(
c.super_visit_with(self) c.super_visit_with(self)
} }
} }
let mut param_count = CountParams::default(); let mut param_count = CountParams { tcx: fcx.tcx, params: FxHashSet::default() };
let has_region = pred.visit_with(&mut param_count).is_break(); let has_region = pred.visit_with(&mut param_count).is_break();
let substituted_pred = pred.subst(tcx, substs); let substituted_pred = pred.subst(tcx, substs);
// Don't check non-defaulted params, dependent defaults (including lifetimes) // Don't check non-defaulted params, dependent defaults (including lifetimes)

View file

@ -2320,7 +2320,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
tcx, tcx,
&mut predicates, &mut predicates,
trait_ref, trait_ref,
&mut cgp::parameters_for_impl(self_ty, trait_ref), &mut cgp::parameters_for_impl(tcx, self_ty, trait_ref),
); );
} }

View file

@ -27,12 +27,13 @@ impl From<ty::ParamConst> for Parameter {
/// Returns the set of parameters constrained by the impl header. /// Returns the set of parameters constrained by the impl header.
pub fn parameters_for_impl<'tcx>( pub fn parameters_for_impl<'tcx>(
tcx: TyCtxt<'tcx>,
impl_self_ty: Ty<'tcx>, impl_self_ty: Ty<'tcx>,
impl_trait_ref: Option<ty::TraitRef<'tcx>>, impl_trait_ref: Option<ty::TraitRef<'tcx>>,
) -> FxHashSet<Parameter> { ) -> FxHashSet<Parameter> {
let vec = match impl_trait_ref { let vec = match impl_trait_ref {
Some(tr) => parameters_for(&tr, false), Some(tr) => parameters_for(tcx, &tr, false),
None => parameters_for(&impl_self_ty, false), None => parameters_for(tcx, &impl_self_ty, false),
}; };
vec.into_iter().collect() vec.into_iter().collect()
} }
@ -43,20 +44,26 @@ pub fn parameters_for_impl<'tcx>(
/// of parameters whose values are needed in order to constrain `ty` - these /// of parameters whose values are needed in order to constrain `ty` - these
/// differ, with the latter being a superset, in the presence of projections. /// differ, with the latter being a superset, in the presence of projections.
pub fn parameters_for<'tcx>( pub fn parameters_for<'tcx>(
tcx: TyCtxt<'tcx>,
t: &impl TypeFoldable<'tcx>, t: &impl TypeFoldable<'tcx>,
include_nonconstraining: bool, include_nonconstraining: bool,
) -> Vec<Parameter> { ) -> Vec<Parameter> {
let mut collector = ParameterCollector { parameters: vec![], include_nonconstraining }; let mut collector = ParameterCollector { tcx, parameters: vec![], include_nonconstraining };
t.visit_with(&mut collector); t.visit_with(&mut collector);
collector.parameters collector.parameters
} }
struct ParameterCollector { struct ParameterCollector<'tcx> {
tcx: TyCtxt<'tcx>,
parameters: Vec<Parameter>, parameters: Vec<Parameter>,
include_nonconstraining: bool, include_nonconstraining: bool,
} }
impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { impl<'tcx> TypeVisitor<'tcx> for ParameterCollector<'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match *t.kind() { match *t.kind() {
ty::Projection(..) | ty::Opaque(..) if !self.include_nonconstraining => { ty::Projection(..) | ty::Opaque(..) if !self.include_nonconstraining => {
@ -198,12 +205,12 @@ pub fn setup_constraining_predicates<'tcx>(
// `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output` // `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
// Then the projection only applies if `T` is known, but it still // Then the projection only applies if `T` is known, but it still
// does not determine `U`. // does not determine `U`.
let inputs = parameters_for(&projection.projection_ty, true); let inputs = parameters_for(tcx, &projection.projection_ty, true);
let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(&p)); let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(&p));
if !relies_only_on_inputs { if !relies_only_on_inputs {
continue; continue;
} }
input_parameters.extend(parameters_for(&projection.ty, false)); input_parameters.extend(parameters_for(tcx, &projection.ty, false));
} else { } else {
continue; continue;
} }

View file

@ -119,7 +119,7 @@ fn enforce_impl_params_are_constrained(
let impl_predicates = tcx.predicates_of(impl_def_id); let impl_predicates = tcx.predicates_of(impl_def_id);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
let mut input_parameters = cgp::parameters_for_impl(impl_self_ty, impl_trait_ref); let mut input_parameters = cgp::parameters_for_impl(tcx, impl_self_ty, impl_trait_ref);
cgp::identify_constrained_generic_params( cgp::identify_constrained_generic_params(
tcx, tcx,
impl_predicates, impl_predicates,
@ -136,7 +136,7 @@ fn enforce_impl_params_are_constrained(
match item.kind { match item.kind {
ty::AssocKind::Type => { ty::AssocKind::Type => {
if item.defaultness.has_value() { if item.defaultness.has_value() {
cgp::parameters_for(&tcx.type_of(def_id), true) cgp::parameters_for(tcx, &tcx.type_of(def_id), true)
} else { } else {
Vec::new() Vec::new()
} }

View file

@ -207,15 +207,15 @@ fn unconstrained_parent_impl_substs<'tcx>(
continue; continue;
} }
unconstrained_parameters.extend(cgp::parameters_for(&projection_ty, true)); unconstrained_parameters.extend(cgp::parameters_for(tcx, &projection_ty, true));
for param in cgp::parameters_for(&projected_ty, false) { for param in cgp::parameters_for(tcx, &projected_ty, false) {
if !unconstrained_parameters.contains(&param) { if !unconstrained_parameters.contains(&param) {
constrained_params.insert(param.0); constrained_params.insert(param.0);
} }
} }
unconstrained_parameters.extend(cgp::parameters_for(&projected_ty, true)); unconstrained_parameters.extend(cgp::parameters_for(tcx, &projected_ty, true));
} }
} }
@ -249,7 +249,7 @@ fn check_duplicate_params<'tcx>(
parent_substs: &Vec<GenericArg<'tcx>>, parent_substs: &Vec<GenericArg<'tcx>>,
span: Span, span: Span,
) { ) {
let mut base_params = cgp::parameters_for(parent_substs, true); let mut base_params = cgp::parameters_for(tcx, parent_substs, true);
base_params.sort_by_key(|param| param.0); base_params.sort_by_key(|param| param.0);
if let (_, [duplicate, ..]) = base_params.partition_dedup() { if let (_, [duplicate, ..]) = base_params.partition_dedup() {
let param = impl1_substs[duplicate.0 as usize]; let param = impl1_substs[duplicate.0 as usize];

View file

@ -14,7 +14,7 @@ use rustc_middle::mir::{
visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _}, visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _},
Mutability, Mutability,
}; };
use rustc_middle::ty::{self, fold::TypeVisitor, Ty}; use rustc_middle::ty::{self, fold::TypeVisitor, Ty, TyCtxt};
use rustc_mir::dataflow::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor}; use rustc_mir::dataflow::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::{BytePos, Span}; use rustc_span::source_map::{BytePos, Span};
@ -576,7 +576,7 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> {
self.possible_borrower.add(borrowed.local, lhs); self.possible_borrower.add(borrowed.local, lhs);
}, },
other => { other => {
if ContainsRegion if ContainsRegion(self.cx.tcx)
.visit_ty(place.ty(&self.body.local_decls, self.cx.tcx).ty) .visit_ty(place.ty(&self.body.local_decls, self.cx.tcx).ty)
.is_continue() .is_continue()
{ {
@ -625,7 +625,7 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> {
.flat_map(HybridBitSet::iter) .flat_map(HybridBitSet::iter)
.collect(); .collect();
if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() { if ContainsRegion(self.cx.tcx).visit_ty(self.body.local_decls[*dest].ty).is_break() {
mutable_variables.push(*dest); mutable_variables.push(*dest);
} }
@ -701,12 +701,15 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleOriginVisitor<'a, 'tcx> {
} }
} }
struct ContainsRegion; struct ContainsRegion<'tcx>(TyCtxt<'tcx>);
impl TypeVisitor<'_> for ContainsRegion { impl<'tcx> TypeVisitor<'tcx> for ContainsRegion<'tcx> {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.0
}
fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
ControlFlow::BREAK ControlFlow::BREAK
} }
} }