Auto merge of #78779 - LeSeulArtichaut:ty-visitor-return, r=oli-obk
Introduce `TypeVisitor::BreakTy` Implements MCP rust-lang/compiler-team#383. r? `@ghost` cc `@lcnr` `@oli-obk` ~~Blocked on FCP in rust-lang/compiler-team#383.~~
This commit is contained in:
commit
e0ef0fc392
@ -1498,7 +1498,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let Some((kind, def_id)) = TyCategory::from_ty(t) {
|
||||
let span = self.tcx.def_span(def_id);
|
||||
// Avoid cluttering the output when the "found" and error span overlap:
|
||||
|
@ -474,7 +474,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||
struct TraitObjectVisitor(Vec<DefId>);
|
||||
|
||||
impl TypeVisitor<'_> for TraitObjectVisitor {
|
||||
fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> {
|
||||
match t.kind() {
|
||||
ty::Dynamic(preds, RegionKind::ReStatic) => {
|
||||
if let Some(def_id) = preds.principal_def_id() {
|
||||
|
@ -1,5 +1,3 @@
|
||||
//! See the Book for more information.
|
||||
|
||||
pub use self::freshen::TypeFreshener;
|
||||
pub use self::LateBoundRegionConversionTime::*;
|
||||
pub use self::RegionVariableOrigin::*;
|
||||
@ -1334,9 +1332,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
let mut r = resolve::UnresolvedTypeFinder::new(self);
|
||||
value.visit_with(&mut r);
|
||||
r.first_unresolved
|
||||
value.visit_with(&mut resolve::UnresolvedTypeFinder::new(self)).break_value()
|
||||
}
|
||||
|
||||
pub fn probe_const_var(
|
||||
|
@ -741,7 +741,10 @@ struct ScopeInstantiator<'me, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ControlFlow<()> {
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(
|
||||
&mut self,
|
||||
t: &ty::Binder<T>,
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
self.target_index.shift_in(1);
|
||||
t.super_visit_with(self);
|
||||
self.target_index.shift_out(1);
|
||||
@ -749,7 +752,7 @@ impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
let ScopeInstantiator { bound_region_scope, next_region, .. } = self;
|
||||
|
||||
match r {
|
||||
|
@ -111,19 +111,17 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
|
||||
/// involve some hashing and so forth).
|
||||
pub struct UnresolvedTypeFinder<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
|
||||
/// Used to find the type parameter name and location for error reporting.
|
||||
pub first_unresolved: Option<(Ty<'tcx>, Option<Span>)>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> UnresolvedTypeFinder<'a, 'tcx> {
|
||||
pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
|
||||
UnresolvedTypeFinder { infcx, first_unresolved: None }
|
||||
UnresolvedTypeFinder { infcx }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> {
|
||||
type BreakTy = (Ty<'tcx>, Option<Span>);
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
let t = self.infcx.shallow_resolve(t);
|
||||
if t.has_infer_types() {
|
||||
if let ty::Infer(infer_ty) = *t.kind() {
|
||||
@ -144,8 +142,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.first_unresolved = Some((t, ty_var_span));
|
||||
ControlFlow::BREAK
|
||||
ControlFlow::Break((t, ty_var_span))
|
||||
} else {
|
||||
// Otherwise, visit its contents.
|
||||
t.super_visit_with(self)
|
||||
|
@ -69,7 +69,7 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.predicate.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
@ -1131,16 +1131,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
|
||||
struct ProhibitOpaqueTypes<'a, 'tcx> {
|
||||
cx: &'a LateContext<'tcx>,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
};
|
||||
|
||||
impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> {
|
||||
type BreakTy = Ty<'tcx>;
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match ty.kind() {
|
||||
ty::Opaque(..) => {
|
||||
self.ty = Some(ty);
|
||||
ControlFlow::BREAK
|
||||
}
|
||||
ty::Opaque(..) => ControlFlow::Break(ty),
|
||||
// Consider opaque types within projections FFI-safe if they do not normalize
|
||||
// to more opaque types.
|
||||
ty::Projection(..) => {
|
||||
@ -1159,9 +1157,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = ProhibitOpaqueTypes { cx: self.cx, ty: None };
|
||||
ty.visit_with(&mut visitor);
|
||||
if let Some(ty) = visitor.ty {
|
||||
if let Some(ty) = ty.visit_with(&mut ProhibitOpaqueTypes { cx: self.cx }).break_value() {
|
||||
self.emit_ffi_unsafe_type_lint(ty, sp, "opaque types have no C equivalent", None);
|
||||
true
|
||||
} else {
|
||||
|
@ -35,7 +35,7 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
|
||||
fn super_visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>(
|
||||
&self,
|
||||
__folder: &mut __F
|
||||
) -> ::std::ops::ControlFlow<()> {
|
||||
) -> ::std::ops::ControlFlow<__F::BreakTy> {
|
||||
match *self { #body_visit }
|
||||
::std::ops::ControlFlow::CONTINUE
|
||||
}
|
||||
|
@ -51,6 +51,7 @@
|
||||
#![feature(half_open_range_patterns)]
|
||||
#![feature(exclusive_range_pattern)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![recursion_limit = "512"]
|
||||
|
||||
#[macro_use]
|
||||
|
@ -62,7 +62,7 @@ macro_rules! TrivialTypeFoldableImpls {
|
||||
fn super_visit_with<F: $crate::ty::fold::TypeVisitor<$tcx>>(
|
||||
&self,
|
||||
_: &mut F)
|
||||
-> ::std::ops::ControlFlow<()>
|
||||
-> ::std::ops::ControlFlow<F::BreakTy>
|
||||
{
|
||||
::std::ops::ControlFlow::CONTINUE
|
||||
}
|
||||
@ -105,7 +105,7 @@ macro_rules! EnumTypeFoldableImpl {
|
||||
fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
|
||||
&self,
|
||||
visitor: &mut V,
|
||||
) -> ::std::ops::ControlFlow<()> {
|
||||
) -> ::std::ops::ControlFlow<V::BreakTy> {
|
||||
EnumTypeFoldableImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
|
||||
}
|
||||
}
|
||||
|
@ -2464,7 +2464,10 @@ impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> ControlFlow<()> {
|
||||
fn super_visit_with<Vs: TypeVisitor<'tcx>>(
|
||||
&self,
|
||||
visitor: &mut Vs,
|
||||
) -> ControlFlow<Vs::BreakTy> {
|
||||
self.base.visit_with(visitor)
|
||||
// Note: there's nothing in `self.proj` to visit.
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
|
||||
Terminator { source_info: self.source_info, kind }
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
use crate::mir::TerminatorKind::*;
|
||||
|
||||
match self.kind {
|
||||
@ -144,7 +144,7 @@ impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
|
||||
self
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
@ -154,7 +154,7 @@ impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
|
||||
Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) }
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.local.visit_with(visitor)?;
|
||||
self.projection.visit_with(visitor)
|
||||
}
|
||||
@ -165,7 +165,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
|
||||
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
@ -211,7 +211,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
use crate::mir::Rvalue::*;
|
||||
match *self {
|
||||
Use(ref op) => op.visit_with(visitor),
|
||||
@ -266,7 +266,7 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
match *self {
|
||||
Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
|
||||
Operand::Constant(ref c) => c.visit_with(visitor),
|
||||
@ -290,7 +290,10 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> ControlFlow<()> {
|
||||
fn super_visit_with<Vs: TypeVisitor<'tcx>>(
|
||||
&self,
|
||||
visitor: &mut Vs,
|
||||
) -> ControlFlow<Vs::BreakTy> {
|
||||
use crate::mir::ProjectionElem::*;
|
||||
|
||||
match self {
|
||||
@ -305,7 +308,7 @@ impl<'tcx> TypeFoldable<'tcx> for Field {
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
|
||||
self
|
||||
}
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
@ -314,7 +317,7 @@ impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
|
||||
self
|
||||
}
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
@ -323,7 +326,7 @@ impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
|
||||
self
|
||||
}
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
@ -336,7 +339,7 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
|
||||
literal: self.literal.fold_with(folder),
|
||||
}
|
||||
}
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.literal.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
@ -49,8 +49,8 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
|
||||
self.super_fold_with(folder)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()>;
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.super_visit_with(visitor)
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
|
||||
}
|
||||
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.visit_with(&mut HasTypeFlagsVisitor { flags }).is_break()
|
||||
self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags)
|
||||
}
|
||||
fn has_projections(&self) -> bool {
|
||||
self.has_type_flags(TypeFlags::HAS_PROJECTION)
|
||||
@ -142,26 +142,13 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
|
||||
fn still_further_specializable(&self) -> bool {
|
||||
self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE)
|
||||
}
|
||||
|
||||
/// A visitor that does not recurse into types, works like `fn walk_shallow` in `Ty`.
|
||||
fn visit_tys_shallow(&self, visit: impl FnMut(Ty<'tcx>) -> ControlFlow<()>) -> ControlFlow<()> {
|
||||
pub struct Visitor<F>(F);
|
||||
|
||||
impl<'tcx, F: FnMut(Ty<'tcx>) -> ControlFlow<()>> TypeVisitor<'tcx> for Visitor<F> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> {
|
||||
self.0(ty)
|
||||
}
|
||||
}
|
||||
|
||||
self.visit_with(&mut Visitor(visit))
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeFoldable<'tcx> for hir::Constness {
|
||||
fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self {
|
||||
self
|
||||
}
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
@ -195,23 +182,25 @@ pub trait TypeFolder<'tcx>: Sized {
|
||||
}
|
||||
|
||||
pub trait TypeVisitor<'tcx>: Sized {
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> ControlFlow<()> {
|
||||
type BreakTy = !;
|
||||
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> ControlFlow<Self::BreakTy> {
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
r.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
c.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
p.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
@ -329,14 +318,19 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
where
|
||||
F: FnMut(ty::Region<'tcx>) -> bool,
|
||||
{
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> ControlFlow<()> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(
|
||||
&mut self,
|
||||
t: &Binder<T>,
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
self.outer_index.shift_in(1);
|
||||
let result = t.as_ref().skip_binder().visit_with(self);
|
||||
self.outer_index.shift_out(1);
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match *r {
|
||||
ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => {
|
||||
ControlFlow::CONTINUE
|
||||
@ -351,7 +345,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// We're only interested in types involving regions
|
||||
if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
|
||||
ty.super_visit_with(self)
|
||||
@ -809,6 +803,9 @@ where
|
||||
value.fold_with(&mut Shifter::new(tcx, amount))
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
struct FoundEscapingVars;
|
||||
|
||||
/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a
|
||||
/// bound region or a bound type.
|
||||
///
|
||||
@ -840,93 +837,114 @@ struct HasEscapingVarsVisitor {
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> ControlFlow<()> {
|
||||
type BreakTy = FoundEscapingVars;
|
||||
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> ControlFlow<Self::BreakTy> {
|
||||
self.outer_index.shift_in(1);
|
||||
let result = t.super_visit_with(self);
|
||||
self.outer_index.shift_out(1);
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// If the outer-exclusive-binder is *strictly greater* than
|
||||
// `outer_index`, that means that `t` contains some content
|
||||
// bound at `outer_index` or above (because
|
||||
// `outer_exclusive_binder` is always 1 higher than the
|
||||
// content in `t`). Therefore, `t` has some escaping vars.
|
||||
if t.outer_exclusive_binder > self.outer_index {
|
||||
ControlFlow::BREAK
|
||||
ControlFlow::Break(FoundEscapingVars)
|
||||
} else {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// If the region is bound by `outer_index` or anything outside
|
||||
// of outer index, then it escapes the binders we have
|
||||
// visited.
|
||||
if r.bound_at_or_above_binder(self.outer_index) {
|
||||
ControlFlow::BREAK
|
||||
ControlFlow::Break(FoundEscapingVars)
|
||||
} else {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// we don't have a `visit_infer_const` callback, so we have to
|
||||
// hook in here to catch this case (annoying...), but
|
||||
// otherwise we do want to remember to visit the rest of the
|
||||
// const, as it has types/regions embedded in a lot of other
|
||||
// places.
|
||||
match ct.val {
|
||||
ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => ControlFlow::BREAK,
|
||||
ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => {
|
||||
ControlFlow::Break(FoundEscapingVars)
|
||||
}
|
||||
_ => ct.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if predicate.inner.outer_exclusive_binder > self.outer_index {
|
||||
ControlFlow::BREAK
|
||||
ControlFlow::Break(FoundEscapingVars)
|
||||
} else {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
struct FoundFlags;
|
||||
|
||||
// FIXME: Optimize for checking for infer flags
|
||||
struct HasTypeFlagsVisitor {
|
||||
flags: ty::TypeFlags,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
|
||||
fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<()> {
|
||||
type BreakTy = FoundFlags;
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!(
|
||||
"HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}",
|
||||
t,
|
||||
t.flags(),
|
||||
self.flags
|
||||
);
|
||||
if t.flags().intersects(self.flags) { ControlFlow::BREAK } else { ControlFlow::CONTINUE }
|
||||
if t.flags().intersects(self.flags) {
|
||||
ControlFlow::Break(FoundFlags)
|
||||
} else {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
let flags = r.type_flags();
|
||||
debug!("HasTypeFlagsVisitor: r={:?} r.flags={:?} self.flags={:?}", r, flags, self.flags);
|
||||
if flags.intersects(self.flags) { ControlFlow::BREAK } else { ControlFlow::CONTINUE }
|
||||
if flags.intersects(self.flags) {
|
||||
ControlFlow::Break(FoundFlags)
|
||||
} else {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
let flags = FlagComputation::for_const(c);
|
||||
debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
|
||||
if flags.intersects(self.flags) { ControlFlow::BREAK } else { ControlFlow::CONTINUE }
|
||||
if flags.intersects(self.flags) {
|
||||
ControlFlow::Break(FoundFlags)
|
||||
} else {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!(
|
||||
"HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
|
||||
predicate, predicate.inner.flags, self.flags
|
||||
);
|
||||
if predicate.inner.flags.intersects(self.flags) {
|
||||
ControlFlow::BREAK
|
||||
ControlFlow::Break(FoundFlags)
|
||||
} else {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
@ -960,14 +978,14 @@ impl LateBoundRegionsCollector {
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> ControlFlow<()> {
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> ControlFlow<Self::BreakTy> {
|
||||
self.current_index.shift_in(1);
|
||||
let result = t.super_visit_with(self);
|
||||
self.current_index.shift_out(1);
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// if we are only looking for "constrained" region, we have to
|
||||
// ignore the inputs to a projection, as they may not appear
|
||||
// in the normalized form
|
||||
@ -980,7 +998,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// if we are only looking for "constrained" region, we have to
|
||||
// ignore the inputs of an unevaluated const, as they may not appear
|
||||
// in the normalized form
|
||||
@ -993,7 +1011,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
|
||||
c.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::ReLateBound(debruijn, br) = *r {
|
||||
if debruijn == self.current_index {
|
||||
self.regions.insert(br);
|
||||
|
@ -1849,7 +1849,7 @@ impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
|
||||
ParamEnv::new(self.caller_bounds().fold_with(folder), self.reveal().fold_with(folder))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.caller_bounds().visit_with(visitor)?;
|
||||
self.reveal().visit_with(visitor)
|
||||
}
|
||||
|
@ -1796,7 +1796,7 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
|
||||
{
|
||||
struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet<Symbol>);
|
||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> {
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::ReLateBound(_, ty::BrNamed(_, name)) = *r {
|
||||
self.0.insert(name);
|
||||
}
|
||||
|
@ -729,7 +729,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef {
|
||||
self
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
@ -739,7 +739,7 @@ impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for
|
||||
(self.0.fold_with(folder), self.1.fold_with(folder))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.0.visit_with(visitor)?;
|
||||
self.1.visit_with(visitor)
|
||||
}
|
||||
@ -752,7 +752,7 @@ impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>>
|
||||
(self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.0.visit_with(visitor)?;
|
||||
self.1.visit_with(visitor)?;
|
||||
self.2.visit_with(visitor)
|
||||
@ -779,7 +779,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
|
||||
Rc::new((*self).clone().fold_with(folder))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
(**self).visit_with(visitor)
|
||||
}
|
||||
}
|
||||
@ -790,7 +790,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> {
|
||||
Arc::new((*self).clone().fold_with(folder))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
(**self).visit_with(visitor)
|
||||
}
|
||||
}
|
||||
@ -800,7 +800,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
|
||||
self.map_id(|value| value.fold_with(folder))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
(**self).visit_with(visitor)
|
||||
}
|
||||
}
|
||||
@ -810,7 +810,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
|
||||
self.map_id(|t| t.fold_with(folder))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
@ -820,7 +820,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> {
|
||||
self.map_id(|t| t.fold_with(folder))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
@ -834,11 +834,11 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
|
||||
folder.fold_binder(self)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.as_ref().skip_binder().visit_with(visitor)
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
visitor.visit_binder(self)
|
||||
}
|
||||
}
|
||||
@ -848,7 +848,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>>
|
||||
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_existential_predicates(v))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|p| p.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
@ -858,7 +858,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
|
||||
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
@ -868,7 +868,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> {
|
||||
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
@ -894,7 +894,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
use crate::ty::InstanceDef::*;
|
||||
self.substs.visit_with(visitor)?;
|
||||
match self.def {
|
||||
@ -920,7 +920,7 @@ impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> {
|
||||
Self { instance: self.instance.fold_with(folder), promoted: self.promoted }
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.instance.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
@ -969,7 +969,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
||||
folder.fold_ty(self)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
match self.kind() {
|
||||
ty::RawPtr(ref tm) => tm.visit_with(visitor),
|
||||
ty::Array(typ, sz) => {
|
||||
@ -1011,7 +1011,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
visitor.visit_ty(self)
|
||||
}
|
||||
}
|
||||
@ -1025,11 +1025,11 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
|
||||
folder.fold_region(self)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
visitor.visit_region(*self)
|
||||
}
|
||||
}
|
||||
@ -1040,11 +1040,11 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
|
||||
folder.tcx().reuse_or_mk_predicate(self, new)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
ty::PredicateKind::super_visit_with(&self.inner.kind, visitor)
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
visitor.visit_predicate(*self)
|
||||
}
|
||||
|
||||
@ -1062,7 +1062,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
|
||||
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_predicates(v))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|p| p.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
@ -1072,7 +1072,7 @@ impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T>
|
||||
self.map_id(|x| x.fold_with(folder))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
@ -1092,12 +1092,12 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
|
||||
folder.fold_const(self)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.ty.visit_with(visitor)?;
|
||||
self.val.visit_with(visitor)
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
visitor.visit_const(self)
|
||||
}
|
||||
}
|
||||
@ -1117,7 +1117,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
match *self {
|
||||
ty::ConstKind::Infer(ic) => ic.visit_with(visitor),
|
||||
ty::ConstKind::Param(p) => p.visit_with(visitor),
|
||||
@ -1135,7 +1135,7 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
|
||||
self
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
match self.unpack() {
|
||||
GenericArgKind::Lifetime(lt) => lt.visit_with(visitor),
|
||||
GenericArgKind::Type(ty) => ty.visit_with(visitor),
|
||||
@ -392,7 +392,7 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<()> {
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,9 @@ where
|
||||
};
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> {
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if !c.needs_subst() {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
@ -29,7 +31,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if !ty.needs_subst() {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!("visit_const: c={:?}", c);
|
||||
if !c.has_param_types_or_consts() {
|
||||
return ControlFlow::CONTINUE;
|
||||
@ -283,7 +283,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!("visit_ty: ty={:?}", ty);
|
||||
if !ty.has_param_types_or_consts() {
|
||||
return ControlFlow::CONTINUE;
|
||||
@ -318,7 +318,9 @@ struct HasUsedGenericParams<'a> {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
|
||||
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<()> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!("visit_const: c={:?}", c);
|
||||
if !c.has_param_types_or_consts() {
|
||||
return ControlFlow::CONTINUE;
|
||||
@ -336,7 +338,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!("visit_ty: ty={:?}", ty);
|
||||
if !ty.has_param_types_or_consts() {
|
||||
return ControlFlow::CONTINUE;
|
||||
|
@ -640,7 +640,7 @@ pub fn write_allocations<'tcx>(
|
||||
}
|
||||
struct CollectAllocIds(BTreeSet<AllocId>);
|
||||
impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds {
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::ConstKind::Value(val) = c.val {
|
||||
self.0.extend(alloc_ids_from_const(val));
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#![feature(or_patterns)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
use rustc_attr as attr;
|
||||
@ -44,6 +45,8 @@ use std::{cmp, fmt, mem};
|
||||
/// manually. Second, it doesn't visit some type components like signatures of fn types, or traits
|
||||
/// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`.
|
||||
trait DefIdVisitor<'tcx> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx>;
|
||||
fn shallow(&self) -> bool {
|
||||
false
|
||||
@ -56,7 +59,7 @@ trait DefIdVisitor<'tcx> {
|
||||
def_id: DefId,
|
||||
kind: &str,
|
||||
descr: &dyn fmt::Display,
|
||||
) -> ControlFlow<()>;
|
||||
) -> ControlFlow<Self::BreakTy>;
|
||||
|
||||
/// Not overridden, but used to actually visit types and traits.
|
||||
fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> {
|
||||
@ -66,13 +69,16 @@ trait DefIdVisitor<'tcx> {
|
||||
dummy: Default::default(),
|
||||
}
|
||||
}
|
||||
fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> ControlFlow<()> {
|
||||
fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
ty_fragment.visit_with(&mut self.skeleton())
|
||||
}
|
||||
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
self.skeleton().visit_trait(trait_ref)
|
||||
}
|
||||
fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_predicates(
|
||||
&mut self,
|
||||
predicates: ty::GenericPredicates<'tcx>,
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
self.skeleton().visit_predicates(predicates)
|
||||
}
|
||||
}
|
||||
@ -87,13 +93,13 @@ impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V>
|
||||
where
|
||||
V: DefIdVisitor<'tcx> + ?Sized,
|
||||
{
|
||||
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> {
|
||||
let TraitRef { def_id, substs } = trait_ref;
|
||||
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?;
|
||||
if self.def_id_visitor.shallow() { ControlFlow::CONTINUE } else { substs.visit_with(self) }
|
||||
}
|
||||
|
||||
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<V::BreakTy> {
|
||||
match predicate.skip_binders() {
|
||||
ty::PredicateAtom::Trait(ty::TraitPredicate { trait_ref }, _) => {
|
||||
self.visit_trait(trait_ref)
|
||||
@ -119,7 +125,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_predicates(
|
||||
&mut self,
|
||||
predicates: ty::GenericPredicates<'tcx>,
|
||||
) -> ControlFlow<V::BreakTy> {
|
||||
let ty::GenericPredicates { parent: _, predicates } = predicates;
|
||||
predicates.iter().try_for_each(|&(predicate, _span)| self.visit_predicate(predicate))
|
||||
}
|
||||
@ -129,7 +138,9 @@ impl<'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'tcx, V>
|
||||
where
|
||||
V: DefIdVisitor<'tcx> + ?Sized,
|
||||
{
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> {
|
||||
type BreakTy = V::BreakTy;
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> {
|
||||
let tcx = self.def_id_visitor.tcx();
|
||||
// InternalSubsts are not visited here because they are visited below in `super_visit_with`.
|
||||
match *ty.kind() {
|
||||
@ -283,7 +294,7 @@ impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'tcx> for FindMin<'a, 'tcx, VL>
|
||||
def_id: DefId,
|
||||
_kind: &str,
|
||||
_descr: &dyn fmt::Display,
|
||||
) -> ControlFlow<()> {
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
self.min = VL::new_min(self, def_id);
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
@ -902,7 +913,7 @@ impl DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
|
||||
def_id: DefId,
|
||||
_kind: &str,
|
||||
_descr: &dyn fmt::Display,
|
||||
) -> ControlFlow<()> {
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
if let Some(def_id) = def_id.as_local() {
|
||||
if let (ty::Visibility::Public, _) | (_, Some(AccessLevel::ReachableFromImplTrait)) =
|
||||
(self.tcx().visibility(def_id.to_def_id()), self.access_level)
|
||||
@ -1299,7 +1310,7 @@ impl DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||
def_id: DefId,
|
||||
kind: &str,
|
||||
descr: &dyn fmt::Display,
|
||||
) -> ControlFlow<()> {
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
if self.check_def_id(def_id, kind, descr) {
|
||||
ControlFlow::BREAK
|
||||
} else {
|
||||
@ -1799,7 +1810,7 @@ impl DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
||||
def_id: DefId,
|
||||
kind: &str,
|
||||
descr: &dyn fmt::Display,
|
||||
) -> ControlFlow<()> {
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
if self.check_def_id(def_id, kind, descr) {
|
||||
ControlFlow::BREAK
|
||||
} else {
|
||||
|
@ -692,12 +692,15 @@ impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<OP>
|
||||
where
|
||||
OP: FnMut(ty::Region<'tcx>),
|
||||
{
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ControlFlow<()> {
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(
|
||||
&mut self,
|
||||
t: &ty::Binder<T>,
|
||||
) -> ControlFlow<Self::BreakTy> {
|
||||
t.as_ref().skip_binder().visit_with(self);
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match *r {
|
||||
// ignore bound regions, keep visiting
|
||||
ty::ReLateBound(_, _) => ControlFlow::CONTINUE,
|
||||
@ -708,7 +711,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// We're only interested in types involving regions
|
||||
if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
|
||||
return ControlFlow::CONTINUE;
|
||||
|
@ -78,7 +78,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
Concrete,
|
||||
}
|
||||
let mut failure_kind = FailureKind::Concrete;
|
||||
walk_abstract_const(tcx, ct, |node| match node {
|
||||
walk_abstract_const::<!, _>(tcx, ct, |node| match node {
|
||||
Node::Leaf(leaf) => {
|
||||
let leaf = leaf.subst(tcx, ct.substs);
|
||||
if leaf.has_infer_types_or_consts() {
|
||||
@ -574,19 +574,19 @@ pub(super) fn try_unify_abstract_consts<'tcx>(
|
||||
// on `ErrorReported`.
|
||||
}
|
||||
|
||||
pub fn walk_abstract_const<'tcx, F>(
|
||||
pub fn walk_abstract_const<'tcx, R, F>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ct: AbstractConst<'tcx>,
|
||||
mut f: F,
|
||||
) -> ControlFlow<()>
|
||||
) -> ControlFlow<R>
|
||||
where
|
||||
F: FnMut(Node<'tcx>) -> ControlFlow<()>,
|
||||
F: FnMut(Node<'tcx>) -> ControlFlow<R>,
|
||||
{
|
||||
fn recurse<'tcx>(
|
||||
fn recurse<'tcx, R>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ct: AbstractConst<'tcx>,
|
||||
f: &mut dyn FnMut(Node<'tcx>) -> ControlFlow<()>,
|
||||
) -> ControlFlow<()> {
|
||||
f: &mut dyn FnMut(Node<'tcx>) -> ControlFlow<R>,
|
||||
) -> ControlFlow<R> {
|
||||
let root = ct.root();
|
||||
f(root)?;
|
||||
match root {
|
||||
|
@ -771,7 +771,9 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match t.kind() {
|
||||
ty::Param(_) => {
|
||||
if t == self.tcx.types.self_param {
|
||||
@ -812,7 +814,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, ct: &ty::Const<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_const(&mut self, ct: &ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// First check if the type of this constant references `Self`.
|
||||
self.visit_ty(ct.ty)?;
|
||||
|
||||
@ -844,7 +846,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::PredicateAtom::ConstEvaluatable(def, substs) = pred.skip_binders() {
|
||||
// FIXME(const_evaluatable_checked): We should probably deduplicate the logic for
|
||||
// `AbstractConst`s here, it might make sense to change `ConstEvaluatable` to
|
||||
|
@ -55,9 +55,7 @@ pub fn search_for_structural_match_violation<'tcx>(
|
||||
) -> Option<NonStructuralMatchTy<'tcx>> {
|
||||
// FIXME: we should instead pass in an `infcx` from the outside.
|
||||
tcx.infer_ctxt().enter(|infcx| {
|
||||
let mut search = Search { infcx, span, found: None, seen: FxHashSet::default() };
|
||||
ty.visit_with(&mut search);
|
||||
search.found
|
||||
ty.visit_with(&mut Search { infcx, span, seen: FxHashSet::default() }).break_value()
|
||||
})
|
||||
}
|
||||
|
||||
@ -116,9 +114,6 @@ struct Search<'a, 'tcx> {
|
||||
|
||||
infcx: InferCtxt<'a, 'tcx>,
|
||||
|
||||
/// Records first ADT that does not implement a structural-match trait.
|
||||
found: Option<NonStructuralMatchTy<'tcx>>,
|
||||
|
||||
/// Tracks ADTs previously encountered during search, so that
|
||||
/// we will not recur on them again.
|
||||
seen: FxHashSet<hir::def_id::DefId>,
|
||||
@ -135,38 +130,33 @@ impl Search<'a, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> {
|
||||
type BreakTy = NonStructuralMatchTy<'tcx>;
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!("Search visiting ty: {:?}", ty);
|
||||
|
||||
let (adt_def, substs) = match *ty.kind() {
|
||||
ty::Adt(adt_def, substs) => (adt_def, substs),
|
||||
ty::Param(_) => {
|
||||
self.found = Some(NonStructuralMatchTy::Param);
|
||||
return ControlFlow::BREAK;
|
||||
return ControlFlow::Break(NonStructuralMatchTy::Param);
|
||||
}
|
||||
ty::Dynamic(..) => {
|
||||
self.found = Some(NonStructuralMatchTy::Dynamic);
|
||||
return ControlFlow::BREAK;
|
||||
return ControlFlow::Break(NonStructuralMatchTy::Dynamic);
|
||||
}
|
||||
ty::Foreign(_) => {
|
||||
self.found = Some(NonStructuralMatchTy::Foreign);
|
||||
return ControlFlow::BREAK;
|
||||
return ControlFlow::Break(NonStructuralMatchTy::Foreign);
|
||||
}
|
||||
ty::Opaque(..) => {
|
||||
self.found = Some(NonStructuralMatchTy::Opaque);
|
||||
return ControlFlow::BREAK;
|
||||
return ControlFlow::Break(NonStructuralMatchTy::Opaque);
|
||||
}
|
||||
ty::Projection(..) => {
|
||||
self.found = Some(NonStructuralMatchTy::Projection);
|
||||
return ControlFlow::BREAK;
|
||||
return ControlFlow::Break(NonStructuralMatchTy::Projection);
|
||||
}
|
||||
ty::Generator(..) | ty::GeneratorWitness(..) => {
|
||||
self.found = Some(NonStructuralMatchTy::Generator);
|
||||
return ControlFlow::BREAK;
|
||||
return ControlFlow::Break(NonStructuralMatchTy::Generator);
|
||||
}
|
||||
ty::Closure(..) => {
|
||||
self.found = Some(NonStructuralMatchTy::Closure);
|
||||
return ControlFlow::BREAK;
|
||||
return ControlFlow::Break(NonStructuralMatchTy::Closure);
|
||||
}
|
||||
ty::RawPtr(..) => {
|
||||
// structural-match ignores substructure of
|
||||
@ -206,8 +196,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
|
||||
|
||||
ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => {
|
||||
// First check all contained types and then tell the caller to continue searching.
|
||||
ty.super_visit_with(self);
|
||||
return ControlFlow::CONTINUE;
|
||||
return ty.super_visit_with(self);
|
||||
}
|
||||
ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => {
|
||||
bug!("unexpected type during structural-match checking: {:?}", ty);
|
||||
@ -227,8 +216,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
|
||||
|
||||
if !self.type_marked_structural(ty) {
|
||||
debug!("Search found ty: {:?}", ty);
|
||||
self.found = Some(NonStructuralMatchTy::Adt(&adt_def));
|
||||
return ControlFlow::BREAK;
|
||||
return ControlFlow::Break(NonStructuralMatchTy::Adt(&adt_def));
|
||||
}
|
||||
|
||||
// structural-match does not care about the
|
||||
@ -244,20 +232,11 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
|
||||
// even though we skip super_visit_with, we must recur on
|
||||
// fields of ADT.
|
||||
let tcx = self.tcx();
|
||||
for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) {
|
||||
adt_def.all_fields().map(|field| field.ty(tcx, substs)).try_for_each(|field_ty| {
|
||||
let ty = self.tcx().normalize_erasing_regions(ty::ParamEnv::empty(), field_ty);
|
||||
debug!("structural-match ADT: field_ty={:?}, ty={:?}", field_ty, ty);
|
||||
|
||||
if ty.visit_with(self).is_break() {
|
||||
// found an ADT without structural-match; halt visiting!
|
||||
assert!(self.found.is_some());
|
||||
return ControlFlow::BREAK;
|
||||
}
|
||||
}
|
||||
|
||||
// Even though we do not want to recur on substs, we do
|
||||
// want our caller to continue its own search.
|
||||
ControlFlow::CONTINUE
|
||||
ty.visit_with(self)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -859,14 +859,14 @@ impl<'tcx> BoundVarsCollector<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> ControlFlow<()> {
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> ControlFlow<Self::BreakTy> {
|
||||
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<()> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match *t.kind() {
|
||||
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
|
||||
match self.parameters.entry(bound_ty.var.as_u32()) {
|
||||
@ -886,7 +886,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match r {
|
||||
ty::ReLateBound(index, br) if *index == self.binder_index => match br {
|
||||
ty::BoundRegion::BrNamed(def_id, _name) => {
|
||||
@ -1076,7 +1076,7 @@ impl PlaceholdersCollector {
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match t.kind() {
|
||||
ty::Placeholder(p) if p.universe == self.universe_index => {
|
||||
self.next_ty_placeholder = self.next_ty_placeholder.max(p.name.as_usize() + 1);
|
||||
@ -1088,7 +1088,7 @@ impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match r {
|
||||
ty::RePlaceholder(p) if p.universe == self.universe_index => {
|
||||
if let ty::BoundRegion::BrAnon(anon) = p.name {
|
||||
|
@ -446,24 +446,24 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
|
||||
struct ProhibitOpaqueVisitor<'tcx> {
|
||||
opaque_identity_ty: Ty<'tcx>,
|
||||
generics: &'tcx ty::Generics,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
};
|
||||
|
||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> {
|
||||
type BreakTy = Option<Ty<'tcx>>;
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t);
|
||||
if t != self.opaque_identity_ty && t.super_visit_with(self).is_break() {
|
||||
self.ty = Some(t);
|
||||
return ControlFlow::BREAK;
|
||||
return ControlFlow::Break(Some(t));
|
||||
}
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!("check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}", r);
|
||||
if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r {
|
||||
if *index < self.generics.parent_count as u32 {
|
||||
return ControlFlow::BREAK;
|
||||
return ControlFlow::Break(None);
|
||||
} else {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
@ -472,7 +472,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
|
||||
r.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::ConstKind::Unevaluated(..) = c.val {
|
||||
// FIXME(#72219) We currenctly don't detect lifetimes within substs
|
||||
// which would violate this check. Even though the particular substitution is not used
|
||||
@ -494,18 +494,17 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
|
||||
InternalSubsts::identity_for_item(tcx, def_id.to_def_id()),
|
||||
),
|
||||
generics: tcx.generics_of(def_id),
|
||||
ty: None,
|
||||
};
|
||||
let prohibit_opaque = tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
.iter()
|
||||
.any(|(predicate, _)| predicate.visit_with(&mut visitor).is_break());
|
||||
.try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor));
|
||||
debug!(
|
||||
"check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor={:?}",
|
||||
prohibit_opaque, visitor
|
||||
);
|
||||
|
||||
if prohibit_opaque {
|
||||
if let Some(ty) = prohibit_opaque.break_value() {
|
||||
let is_async = match item.kind {
|
||||
ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => match origin {
|
||||
hir::OpaqueTyOrigin::AsyncFn => true,
|
||||
@ -525,7 +524,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
|
||||
|
||||
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
|
||||
if snippet == "Self" {
|
||||
if let Some(ty) = visitor.ty {
|
||||
if let Some(ty) = ty {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"consider spelling out the type instead",
|
||||
@ -1455,7 +1454,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
|
||||
{
|
||||
struct VisitTypes(Vec<DefId>);
|
||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match *t.kind() {
|
||||
ty::Opaque(def, _) => {
|
||||
self.0.push(def);
|
||||
|
@ -983,7 +983,7 @@ fn suggest_constraining_param(
|
||||
struct TypeParamVisitor<'tcx>(Vec<Ty<'tcx>>);
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::Param(_) = ty.kind() {
|
||||
self.0.push(ty);
|
||||
}
|
||||
|
@ -800,18 +800,20 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
params: FxHashSet<u32>,
|
||||
}
|
||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::Param(param) = t.kind() {
|
||||
self.params.insert(param.index);
|
||||
}
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
ControlFlow::BREAK
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::ConstKind::Param(param) = c.val {
|
||||
self.params.insert(param.index);
|
||||
}
|
||||
|
@ -2062,7 +2062,7 @@ fn const_evaluatable_predicates_of<'tcx>(
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TypeVisitor<'tcx> for TyAliasVisitor<'a, 'tcx> {
|
||||
fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val {
|
||||
self.preds.insert((
|
||||
ty::PredicateAtom::ConstEvaluatable(def, substs).to_predicate(self.tcx),
|
||||
|
@ -57,7 +57,7 @@ struct ParameterCollector {
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match *t.kind() {
|
||||
ty::Projection(..) | ty::Opaque(..) if !self.include_nonconstraining => {
|
||||
// projections are not injective
|
||||
@ -72,14 +72,14 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if let ty::ReEarlyBound(data) = *r {
|
||||
self.parameters.push(Parameter::from(data));
|
||||
}
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> {
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match c.val {
|
||||
ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => {
|
||||
// Constant expressions are not injective
|
||||
|
@ -563,7 +563,9 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> {
|
||||
struct ContainsRegion;
|
||||
|
||||
impl TypeVisitor<'_> for ContainsRegion {
|
||||
fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<()> {
|
||||
type BreakTy = ();
|
||||
|
||||
fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<Self::BreakTy> {
|
||||
ControlFlow::BREAK
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user