Skip to content

Commit

Permalink
TypeVisitor: use ControlFlow in rustc_{infer,lint,trait_selection}
Browse files Browse the repository at this point in the history
  • Loading branch information
LeSeulArtichaut committed Oct 30, 2020
1 parent 2c85b6f commit 4fe735b
Show file tree
Hide file tree
Showing 13 changed files with 106 additions and 82 deletions.
3 changes: 2 additions & 1 deletion compiler/rustc_infer/src/infer/error_reporting/mod.rs
Expand Up @@ -71,6 +71,7 @@ use rustc_middle::ty::{
};
use rustc_span::{BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
use std::ops::ControlFlow;
use std::{cmp, fmt};

mod note;
Expand Down Expand Up @@ -1497,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>) -> bool {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
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
Expand Up @@ -15,6 +15,8 @@ use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, T
use rustc_span::symbol::Ident;
use rustc_span::{MultiSpan, Span};

use std::ops::ControlFlow;

impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Print the error message for lifetime errors when the return type is a static `impl Trait`,
/// `dyn Trait` or if a method call on a trait object introduces a static requirement.
Expand Down Expand Up @@ -472,13 +474,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
struct TraitObjectVisitor(Vec<DefId>);

impl TypeVisitor<'_> for TraitObjectVisitor {
fn visit_ty(&mut self, t: Ty<'_>) -> bool {
fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<(), ()> {
match t.kind() {
ty::Dynamic(preds, RegionKind::ReStatic) => {
if let Some(def_id) = preds.principal_def_id() {
self.0.push(def_id);
}
false
ControlFlow::CONTINUE
}
_ => t.super_visit_with(self),
}
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_infer/src/infer/nll_relate/mod.rs
Expand Up @@ -30,6 +30,7 @@ use rustc_middle::ty::fold::{TypeFoldable, TypeVisitor};
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
use std::fmt::Debug;
use std::ops::ControlFlow;

#[derive(PartialEq)]
pub enum NormalizationStrategy {
Expand Down Expand Up @@ -740,15 +741,15 @@ 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>) -> bool {
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ControlFlow<(), ()> {
self.target_index.shift_in(1);
t.super_visit_with(self);
self.target_index.shift_out(1);

false
ControlFlow::CONTINUE
}

fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<(), ()> {
let ScopeInstantiator { bound_region_scope, next_region, .. } = self;

match r {
Expand All @@ -759,7 +760,7 @@ impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
_ => {}
}

false
ControlFlow::CONTINUE
}
}

Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_infer/src/infer/resolve.rs
Expand Up @@ -3,6 +3,8 @@ use super::{FixupError, FixupResult, InferCtxt, Span};
use rustc_middle::ty::fold::{TypeFolder, TypeVisitor};
use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable};

use std::ops::ControlFlow;

///////////////////////////////////////////////////////////////////////////
// OPPORTUNISTIC VAR RESOLVER

Expand Down Expand Up @@ -121,7 +123,7 @@ impl<'a, 'tcx> UnresolvedTypeFinder<'a, 'tcx> {
}

impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
let t = self.infcx.shallow_resolve(t);
if t.has_infer_types() {
if let ty::Infer(infer_ty) = *t.kind() {
Expand All @@ -143,15 +145,15 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
None
};
self.first_unresolved = Some((t, ty_var_span));
true // Halt visiting.
ControlFlow::BREAK
} else {
// Otherwise, visit its contents.
t.super_visit_with(self)
}
} else {
// All type variables in inference types must already be resolved,
// - no need to visit the contents, continue visiting.
false
ControlFlow::CONTINUE
}
}
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_infer/src/lib.rs
Expand Up @@ -22,6 +22,7 @@
#![feature(never_type)]
#![feature(or_patterns)]
#![feature(in_band_lifetimes)]
#![feature(control_flow_enum)]
#![recursion_limit = "512"] // For rustdoc

#[macro_use]
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_infer/src/traits/structural_impls.rs
Expand Up @@ -4,6 +4,7 @@ use rustc_middle::ty;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};

use std::fmt;
use std::ops::ControlFlow;

// Structural impls for the structs in `traits`.

Expand Down Expand Up @@ -68,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) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.predicate.visit_with(visitor)
}
}
1 change: 1 addition & 0 deletions compiler/rustc_lint/src/lib.rs
Expand Up @@ -37,6 +37,7 @@
#![feature(or_patterns)]
#![feature(half_open_range_patterns)]
#![feature(exclusive_range_pattern)]
#![feature(control_flow_enum)]
#![recursion_limit = "256"]

#[macro_use]
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_lint/src/types.rs
Expand Up @@ -18,6 +18,7 @@ use rustc_target::abi::{Integer, LayoutOf, TagEncoding, VariantIdx, Variants};
use rustc_target::spec::abi::Abi as SpecAbi;

use std::cmp;
use std::ops::ControlFlow;
use tracing::debug;

declare_lint! {
Expand Down Expand Up @@ -1135,11 +1136,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
};

impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
match ty.kind() {
ty::Opaque(..) => {
self.ty = Some(ty);
true
ControlFlow::BREAK
}
// Consider opaque types within projections FFI-safe if they do not normalize
// to more opaque types.
Expand All @@ -1148,7 +1149,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {

// If `ty` is a opaque type directly then `super_visit_with` won't invoke
// this function again.
if ty.has_opaque_types() { self.visit_ty(ty) } else { false }
if ty.has_opaque_types() {
self.visit_ty(ty)
} else {
ControlFlow::CONTINUE
}
}
_ => ty.super_visit_with(self),
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_trait_selection/src/lib.rs
Expand Up @@ -19,6 +19,7 @@
#![feature(never_type)]
#![feature(crate_visibility_modifier)]
#![feature(or_patterns)]
#![feature(control_flow_enum)]
#![recursion_limit = "512"] // For rustdoc

#[macro_use]
Expand Down
18 changes: 10 additions & 8 deletions compiler/rustc_trait_selection/src/opaque_types.rs
Expand Up @@ -15,6 +15,8 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::config::nightly_options;
use rustc_span::Span;

use std::ops::ControlFlow;

pub type OpaqueTypeMap<'tcx> = DefIdMap<OpaqueTypeDecl<'tcx>>;

/// Information about the opaque types whose values we
Expand Down Expand Up @@ -691,26 +693,26 @@ 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>) -> bool {
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ControlFlow<(), ()> {
t.as_ref().skip_binder().visit_with(self);
false // keep visiting
ControlFlow::CONTINUE
}

fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<(), ()> {
match *r {
// ignore bound regions, keep visiting
ty::ReLateBound(_, _) => false,
ty::ReLateBound(_, _) => ControlFlow::CONTINUE,
_ => {
(self.op)(r);
false
ControlFlow::CONTINUE
}
}
}

fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
// We're only interested in types involving regions
if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
return false; // keep visiting
return ControlFlow::CONTINUE;
}

match ty.kind() {
Expand Down Expand Up @@ -745,7 +747,7 @@ where
}
}

false
ControlFlow::CONTINUE
}
}

Expand Down
43 changes: 25 additions & 18 deletions compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
Expand Up @@ -24,6 +24,7 @@ use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::Span;

use std::cmp;
use std::ops::ControlFlow;

/// Check if a given constant can be evaluated.
pub fn is_const_evaluatable<'cx, 'tcx>(
Expand Down Expand Up @@ -86,9 +87,11 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
}

false
ControlFlow::CONTINUE
}
Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => {
ControlFlow::CONTINUE
}
Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => false,
});

match failure_kind {
Expand Down Expand Up @@ -564,29 +567,33 @@ pub(super) fn try_unify_abstract_consts<'tcx>(
// on `ErrorReported`.
}

// FIXME: Use `std::ops::ControlFlow` instead of `bool` here.
pub fn walk_abstract_const<'tcx, F>(tcx: TyCtxt<'tcx>, ct: AbstractConst<'tcx>, mut f: F) -> bool
pub fn walk_abstract_const<'tcx, F>(
tcx: TyCtxt<'tcx>,
ct: AbstractConst<'tcx>,
mut f: F,
) -> ControlFlow<(), ()>
where
F: FnMut(Node<'tcx>) -> bool,
F: FnMut(Node<'tcx>) -> ControlFlow<(), ()>,
{
fn recurse<'tcx>(
tcx: TyCtxt<'tcx>,
ct: AbstractConst<'tcx>,
f: &mut dyn FnMut(Node<'tcx>) -> bool,
) -> bool {
f: &mut dyn FnMut(Node<'tcx>) -> ControlFlow<(), ()>,
) -> ControlFlow<(), ()> {
let root = ct.root();
f(root)
|| match root {
Node::Leaf(_) => false,
Node::Binop(_, l, r) => {
recurse(tcx, ct.subtree(l), f) || recurse(tcx, ct.subtree(r), f)
}
Node::UnaryOp(_, v) => recurse(tcx, ct.subtree(v), f),
Node::FunctionCall(func, args) => {
recurse(tcx, ct.subtree(func), f)
|| args.iter().any(|&arg| recurse(tcx, ct.subtree(arg), f))
}
f(root)?;
match root {
Node::Leaf(_) => ControlFlow::CONTINUE,
Node::Binop(_, l, r) => {
recurse(tcx, ct.subtree(l), f)?;
recurse(tcx, ct.subtree(r), f)
}
Node::UnaryOp(_, v) => recurse(tcx, ct.subtree(v), f),
Node::FunctionCall(func, args) => {
recurse(tcx, ct.subtree(func), f)?;
args.iter().try_for_each(|&arg| recurse(tcx, ct.subtree(arg), f))
}
}
}

recurse(tcx, ct, &mut f)
Expand Down

0 comments on commit 4fe735b

Please sign in to comment.