Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce TypeVisitor::BreakTy #78779

Merged
merged 9 commits into from
Nov 17, 2020
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//! See the Book for more information.

pub use self::freshen::TypeFreshener;
pub use self::LateBoundRegionConversionTime::*;
pub use self::RegionVariableOrigin::*;
Expand Down Expand Up @@ -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(
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_infer/src/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -741,15 +741,18 @@ 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);

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 {
Expand Down
11 changes: 4 additions & 7 deletions compiler/rustc_infer/src/infer/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/traits/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
14 changes: 5 additions & 9 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..) => {
Expand All @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_macros/src/type_foldable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ macro_rules! CloneTypeFoldableImpls {
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
}
Expand Down Expand Up @@ -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())
}
}
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2477,7 +2477,10 @@ impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
UserTypeProjection { base, projs }
}

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.
}
Expand Down
25 changes: 14 additions & 11 deletions compiler/rustc_middle/src/mir/type_foldable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}
}
Expand All @@ -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)
}
Expand All @@ -166,7 +166,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
folder.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))
}
}
Expand Down Expand Up @@ -216,7 +216,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),
Expand Down Expand Up @@ -271,7 +271,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),
Expand All @@ -295,7 +295,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 {
Expand All @@ -310,7 +313,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
}
}
Expand All @@ -319,7 +322,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
}
}
Expand All @@ -328,7 +331,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.clone()
}
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
}
}
Expand All @@ -341,7 +344,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)
}
}
Loading