TypeVisitor: use ControlFlow
in rustc_{mir,privacy,traits,typeck}
This commit is contained in:
parent
4fe735b320
commit
61f8182cec
@ -1,6 +1,7 @@
|
|||||||
use rustc_middle::mir::interpret::InterpResult;
|
use rustc_middle::mir::interpret::InterpResult;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
/// Returns `true` if a used generic parameter requires substitution.
|
/// Returns `true` if a used generic parameter requires substitution.
|
||||||
crate fn ensure_monomorphic_enough<'tcx, T>(tcx: TyCtxt<'tcx>, ty: T) -> InterpResult<'tcx>
|
crate fn ensure_monomorphic_enough<'tcx, T>(tcx: TyCtxt<'tcx>, ty: T) -> InterpResult<'tcx>
|
||||||
@ -17,24 +18,24 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> {
|
impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> {
|
||||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
|
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<(), ()> {
|
||||||
if !c.needs_subst() {
|
if !c.needs_subst() {
|
||||||
return false;
|
return ControlFlow::CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
match c.val {
|
match c.val {
|
||||||
ty::ConstKind::Param(..) => true,
|
ty::ConstKind::Param(..) => ControlFlow::BREAK,
|
||||||
_ => c.super_visit_with(self),
|
_ => c.super_visit_with(self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
|
||||||
if !ty.needs_subst() {
|
if !ty.needs_subst() {
|
||||||
return false;
|
return ControlFlow::CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
match *ty.kind() {
|
match *ty.kind() {
|
||||||
ty::Param(_) => true,
|
ty::Param(_) => ControlFlow::BREAK,
|
||||||
ty::Closure(def_id, substs)
|
ty::Closure(def_id, substs)
|
||||||
| ty::Generator(def_id, substs, ..)
|
| ty::Generator(def_id, substs, ..)
|
||||||
| ty::FnDef(def_id, substs) => {
|
| ty::FnDef(def_id, substs) => {
|
||||||
@ -50,11 +51,7 @@ where
|
|||||||
match (is_used, subst.needs_subst()) {
|
match (is_used, subst.needs_subst()) {
|
||||||
// Just in case there are closures or generators within this subst,
|
// Just in case there are closures or generators within this subst,
|
||||||
// recurse.
|
// recurse.
|
||||||
(true, true) if subst.super_visit_with(self) => {
|
(true, true) => return subst.super_visit_with(self),
|
||||||
// Only return when we find a parameter so the remaining substs
|
|
||||||
// are not skipped.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Confirm that polymorphization replaced the parameter with
|
// Confirm that polymorphization replaced the parameter with
|
||||||
// `ty::Param`/`ty::ConstKind::Param`.
|
// `ty::Param`/`ty::ConstKind::Param`.
|
||||||
(false, true) if cfg!(debug_assertions) => match subst.unpack() {
|
(false, true) if cfg!(debug_assertions) => match subst.unpack() {
|
||||||
@ -69,7 +66,7 @@ where
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
_ => ty.super_visit_with(self),
|
_ => ty.super_visit_with(self),
|
||||||
}
|
}
|
||||||
@ -77,7 +74,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut vis = UsedParamsNeedSubstVisitor { tcx };
|
let mut vis = UsedParamsNeedSubstVisitor { tcx };
|
||||||
if ty.visit_with(&mut vis) {
|
if ty.visit_with(&mut vis) == ControlFlow::BREAK {
|
||||||
throw_inval!(TooGeneric);
|
throw_inval!(TooGeneric);
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -27,6 +27,7 @@ Rust MIR: a lowered representation of Rust.
|
|||||||
#![feature(option_expect_none)]
|
#![feature(option_expect_none)]
|
||||||
#![feature(or_patterns)]
|
#![feature(or_patterns)]
|
||||||
#![feature(once_cell)]
|
#![feature(once_cell)]
|
||||||
|
#![feature(control_flow_enum)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -20,6 +20,7 @@ use rustc_middle::ty::{
|
|||||||
};
|
};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
/// Provide implementations of queries relating to polymorphization analysis.
|
/// Provide implementations of queries relating to polymorphization analysis.
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
@ -138,7 +139,7 @@ fn mark_used_by_predicates<'tcx>(
|
|||||||
// predicate is used.
|
// predicate is used.
|
||||||
let any_param_used = {
|
let any_param_used = {
|
||||||
let mut vis = HasUsedGenericParams { unused_parameters };
|
let mut vis = HasUsedGenericParams { unused_parameters };
|
||||||
predicate.visit_with(&mut vis)
|
predicate.visit_with(&mut vis) == ControlFlow::BREAK
|
||||||
};
|
};
|
||||||
|
|
||||||
if any_param_used {
|
if any_param_used {
|
||||||
@ -249,17 +250,17 @@ 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 visit_const(&mut self, c: &'tcx Const<'tcx>) -> bool {
|
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<(), ()> {
|
||||||
debug!("visit_const: c={:?}", c);
|
debug!("visit_const: c={:?}", c);
|
||||||
if !c.has_param_types_or_consts() {
|
if !c.has_param_types_or_consts() {
|
||||||
return false;
|
return ControlFlow::CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
match c.val {
|
match c.val {
|
||||||
ty::ConstKind::Param(param) => {
|
ty::ConstKind::Param(param) => {
|
||||||
debug!("visit_const: param={:?}", param);
|
debug!("visit_const: param={:?}", param);
|
||||||
self.unused_parameters.clear(param.index);
|
self.unused_parameters.clear(param.index);
|
||||||
false
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
ty::ConstKind::Unevaluated(def, _, Some(p))
|
ty::ConstKind::Unevaluated(def, _, Some(p))
|
||||||
// Avoid considering `T` unused when constants are of the form:
|
// Avoid considering `T` unused when constants are of the form:
|
||||||
@ -270,22 +271,22 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
|||||||
// the generic parameters, instead, traverse the promoted MIR.
|
// the generic parameters, instead, traverse the promoted MIR.
|
||||||
let promoted = self.tcx.promoted_mir(def.did);
|
let promoted = self.tcx.promoted_mir(def.did);
|
||||||
self.visit_body(&promoted[p]);
|
self.visit_body(&promoted[p]);
|
||||||
false
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
ty::ConstKind::Unevaluated(def, unevaluated_substs, None)
|
ty::ConstKind::Unevaluated(def, unevaluated_substs, None)
|
||||||
if self.tcx.def_kind(def.did) == DefKind::AnonConst =>
|
if self.tcx.def_kind(def.did) == DefKind::AnonConst =>
|
||||||
{
|
{
|
||||||
self.visit_child_body(def.did, unevaluated_substs);
|
self.visit_child_body(def.did, unevaluated_substs);
|
||||||
false
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
_ => c.super_visit_with(self),
|
_ => c.super_visit_with(self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
|
||||||
debug!("visit_ty: ty={:?}", ty);
|
debug!("visit_ty: ty={:?}", ty);
|
||||||
if !ty.has_param_types_or_consts() {
|
if !ty.has_param_types_or_consts() {
|
||||||
return false;
|
return ControlFlow::CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
match *ty.kind() {
|
match *ty.kind() {
|
||||||
@ -293,18 +294,18 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
|||||||
debug!("visit_ty: def_id={:?}", def_id);
|
debug!("visit_ty: def_id={:?}", def_id);
|
||||||
// Avoid cycle errors with generators.
|
// Avoid cycle errors with generators.
|
||||||
if def_id == self.def_id {
|
if def_id == self.def_id {
|
||||||
return false;
|
return ControlFlow::CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consider any generic parameters used by any closures/generators as used in the
|
// Consider any generic parameters used by any closures/generators as used in the
|
||||||
// parent.
|
// parent.
|
||||||
self.visit_child_body(def_id, substs);
|
self.visit_child_body(def_id, substs);
|
||||||
false
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
ty::Param(param) => {
|
ty::Param(param) => {
|
||||||
debug!("visit_ty: param={:?}", param);
|
debug!("visit_ty: param={:?}", param);
|
||||||
self.unused_parameters.clear(param.index);
|
self.unused_parameters.clear(param.index);
|
||||||
false
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
_ => ty.super_visit_with(self),
|
_ => ty.super_visit_with(self),
|
||||||
}
|
}
|
||||||
@ -317,28 +318,38 @@ struct HasUsedGenericParams<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
|
impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
|
||||||
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> bool {
|
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<(), ()> {
|
||||||
debug!("visit_const: c={:?}", c);
|
debug!("visit_const: c={:?}", c);
|
||||||
if !c.has_param_types_or_consts() {
|
if !c.has_param_types_or_consts() {
|
||||||
return false;
|
return ControlFlow::CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
match c.val {
|
match c.val {
|
||||||
ty::ConstKind::Param(param) => {
|
ty::ConstKind::Param(param) => {
|
||||||
!self.unused_parameters.contains(param.index).unwrap_or(false)
|
if self.unused_parameters.contains(param.index).unwrap_or(false) {
|
||||||
|
ControlFlow::CONTINUE
|
||||||
|
} else {
|
||||||
|
ControlFlow::BREAK
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => c.super_visit_with(self),
|
_ => c.super_visit_with(self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
|
||||||
debug!("visit_ty: ty={:?}", ty);
|
debug!("visit_ty: ty={:?}", ty);
|
||||||
if !ty.has_param_types_or_consts() {
|
if !ty.has_param_types_or_consts() {
|
||||||
return false;
|
return ControlFlow::CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
ty::Param(param) => !self.unused_parameters.contains(param.index).unwrap_or(false),
|
ty::Param(param) => {
|
||||||
|
if self.unused_parameters.contains(param.index).unwrap_or(false) {
|
||||||
|
ControlFlow::CONTINUE
|
||||||
|
} else {
|
||||||
|
ControlFlow::BREAK
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => ty.super_visit_with(self),
|
_ => ty.super_visit_with(self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ use rustc_middle::mir::visit::Visitor;
|
|||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::{self, TyCtxt, TypeFoldable, TypeVisitor};
|
use rustc_middle::ty::{self, TyCtxt, TypeFoldable, TypeVisitor};
|
||||||
use rustc_target::abi::Size;
|
use rustc_target::abi::Size;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
const INDENT: &str = " ";
|
const INDENT: &str = " ";
|
||||||
/// Alignment for lining up comments following MIR statements
|
/// Alignment for lining up comments following MIR statements
|
||||||
@ -639,7 +640,7 @@ 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 visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
|
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<(), ()> {
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(or_patterns)]
|
#![feature(or_patterns)]
|
||||||
|
#![feature(control_flow_enum)]
|
||||||
|
#![feature(try_blocks)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
use rustc_attr as attr;
|
use rustc_attr as attr;
|
||||||
@ -26,6 +28,7 @@ use rustc_span::symbol::{kw, Ident};
|
|||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
use std::{cmp, fmt, mem};
|
use std::{cmp, fmt, mem};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -48,7 +51,12 @@ trait DefIdVisitor<'tcx> {
|
|||||||
fn skip_assoc_tys(&self) -> bool {
|
fn skip_assoc_tys(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool;
|
fn visit_def_id(
|
||||||
|
&mut self,
|
||||||
|
def_id: DefId,
|
||||||
|
kind: &str,
|
||||||
|
descr: &dyn fmt::Display,
|
||||||
|
) -> ControlFlow<(), ()>;
|
||||||
|
|
||||||
/// Not overridden, but used to actually visit types and traits.
|
/// Not overridden, but used to actually visit types and traits.
|
||||||
fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> {
|
fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> {
|
||||||
@ -58,13 +66,13 @@ trait DefIdVisitor<'tcx> {
|
|||||||
dummy: Default::default(),
|
dummy: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> bool {
|
fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> ControlFlow<(), ()> {
|
||||||
ty_fragment.visit_with(&mut self.skeleton())
|
ty_fragment.visit_with(&mut self.skeleton())
|
||||||
}
|
}
|
||||||
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool {
|
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<(), ()> {
|
||||||
self.skeleton().visit_trait(trait_ref)
|
self.skeleton().visit_trait(trait_ref)
|
||||||
}
|
}
|
||||||
fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> bool {
|
fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> ControlFlow<(), ()> {
|
||||||
self.skeleton().visit_predicates(predicates)
|
self.skeleton().visit_predicates(predicates)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,25 +87,25 @@ impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V>
|
|||||||
where
|
where
|
||||||
V: DefIdVisitor<'tcx> + ?Sized,
|
V: DefIdVisitor<'tcx> + ?Sized,
|
||||||
{
|
{
|
||||||
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool {
|
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<(), ()> {
|
||||||
let TraitRef { def_id, substs } = trait_ref;
|
let TraitRef { def_id, substs } = trait_ref;
|
||||||
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())
|
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?;
|
||||||
|| (!self.def_id_visitor.shallow() && substs.visit_with(self))
|
if self.def_id_visitor.shallow() { ControlFlow::CONTINUE } else { substs.visit_with(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool {
|
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<(), ()> {
|
||||||
match predicate.skip_binders() {
|
match predicate.skip_binders() {
|
||||||
ty::PredicateAtom::Trait(ty::TraitPredicate { trait_ref }, _) => {
|
ty::PredicateAtom::Trait(ty::TraitPredicate { trait_ref }, _) => {
|
||||||
self.visit_trait(trait_ref)
|
self.visit_trait(trait_ref)
|
||||||
}
|
}
|
||||||
ty::PredicateAtom::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
|
ty::PredicateAtom::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
|
||||||
ty.visit_with(self)
|
ty.visit_with(self)?;
|
||||||
|| self.visit_trait(projection_ty.trait_ref(self.def_id_visitor.tcx()))
|
self.visit_trait(projection_ty.trait_ref(self.def_id_visitor.tcx()))
|
||||||
}
|
}
|
||||||
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => {
|
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => {
|
||||||
ty.visit_with(self)
|
ty.visit_with(self)
|
||||||
}
|
}
|
||||||
ty::PredicateAtom::RegionOutlives(..) => false,
|
ty::PredicateAtom::RegionOutlives(..) => ControlFlow::CONTINUE,
|
||||||
ty::PredicateAtom::ConstEvaluatable(..)
|
ty::PredicateAtom::ConstEvaluatable(..)
|
||||||
if self.def_id_visitor.tcx().features().const_evaluatable_checked =>
|
if self.def_id_visitor.tcx().features().const_evaluatable_checked =>
|
||||||
{
|
{
|
||||||
@ -105,20 +113,15 @@ where
|
|||||||
// private function we may have to do something here...
|
// private function we may have to do something here...
|
||||||
//
|
//
|
||||||
// For now, let's just pretend that everything is fine.
|
// For now, let's just pretend that everything is fine.
|
||||||
false
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
_ => bug!("unexpected predicate: {:?}", predicate),
|
_ => bug!("unexpected predicate: {:?}", predicate),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> bool {
|
fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> ControlFlow<(), ()> {
|
||||||
let ty::GenericPredicates { parent: _, predicates } = predicates;
|
let ty::GenericPredicates { parent: _, predicates } = predicates;
|
||||||
for &(predicate, _span) in predicates {
|
predicates.iter().try_for_each(|&(predicate, _span)| self.visit_predicate(predicate))
|
||||||
if self.visit_predicate(predicate) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +129,7 @@ impl<'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'tcx, V>
|
|||||||
where
|
where
|
||||||
V: DefIdVisitor<'tcx> + ?Sized,
|
V: DefIdVisitor<'tcx> + ?Sized,
|
||||||
{
|
{
|
||||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
|
||||||
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`.
|
||||||
match *ty.kind() {
|
match *ty.kind() {
|
||||||
@ -135,19 +138,15 @@ where
|
|||||||
| ty::FnDef(def_id, ..)
|
| ty::FnDef(def_id, ..)
|
||||||
| ty::Closure(def_id, ..)
|
| ty::Closure(def_id, ..)
|
||||||
| ty::Generator(def_id, ..) => {
|
| ty::Generator(def_id, ..) => {
|
||||||
if self.def_id_visitor.visit_def_id(def_id, "type", &ty) {
|
self.def_id_visitor.visit_def_id(def_id, "type", &ty)?;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if self.def_id_visitor.shallow() {
|
if self.def_id_visitor.shallow() {
|
||||||
return false;
|
return ControlFlow::CONTINUE;
|
||||||
}
|
}
|
||||||
// Default type visitor doesn't visit signatures of fn types.
|
// Default type visitor doesn't visit signatures of fn types.
|
||||||
// Something like `fn() -> Priv {my_func}` is considered a private type even if
|
// Something like `fn() -> Priv {my_func}` is considered a private type even if
|
||||||
// `my_func` is public, so we need to visit signatures.
|
// `my_func` is public, so we need to visit signatures.
|
||||||
if let ty::FnDef(..) = ty.kind() {
|
if let ty::FnDef(..) = ty.kind() {
|
||||||
if tcx.fn_sig(def_id).visit_with(self) {
|
tcx.fn_sig(def_id).visit_with(self)?;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Inherent static methods don't have self type in substs.
|
// Inherent static methods don't have self type in substs.
|
||||||
// Something like `fn() {my_method}` type of the method
|
// Something like `fn() {my_method}` type of the method
|
||||||
@ -155,9 +154,7 @@ where
|
|||||||
// so we need to visit the self type additionally.
|
// so we need to visit the self type additionally.
|
||||||
if let Some(assoc_item) = tcx.opt_associated_item(def_id) {
|
if let Some(assoc_item) = tcx.opt_associated_item(def_id) {
|
||||||
if let ty::ImplContainer(impl_def_id) = assoc_item.container {
|
if let ty::ImplContainer(impl_def_id) = assoc_item.container {
|
||||||
if tcx.type_of(impl_def_id).visit_with(self) {
|
tcx.type_of(impl_def_id).visit_with(self)?;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,7 +165,7 @@ where
|
|||||||
// as visible/reachable even if both `Type` and `Trait` are private.
|
// as visible/reachable even if both `Type` and `Trait` are private.
|
||||||
// Ideally, associated types should be substituted in the same way as
|
// Ideally, associated types should be substituted in the same way as
|
||||||
// free type aliases, but this isn't done yet.
|
// free type aliases, but this isn't done yet.
|
||||||
return false;
|
return ControlFlow::CONTINUE;
|
||||||
}
|
}
|
||||||
// This will also visit substs if necessary, so we don't need to recurse.
|
// This will also visit substs if necessary, so we don't need to recurse.
|
||||||
return self.visit_trait(proj.trait_ref(tcx));
|
return self.visit_trait(proj.trait_ref(tcx));
|
||||||
@ -185,9 +182,7 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let ty::ExistentialTraitRef { def_id, substs: _ } = trait_ref;
|
let ty::ExistentialTraitRef { def_id, substs: _ } = trait_ref;
|
||||||
if self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) {
|
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)?;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Opaque(def_id, ..) => {
|
ty::Opaque(def_id, ..) => {
|
||||||
@ -200,12 +195,10 @@ where
|
|||||||
// through the trait list (default type visitor doesn't visit those traits).
|
// through the trait list (default type visitor doesn't visit those traits).
|
||||||
// All traits in the list are considered the "primary" part of the type
|
// All traits in the list are considered the "primary" part of the type
|
||||||
// and are visited by shallow visitors.
|
// and are visited by shallow visitors.
|
||||||
if self.visit_predicates(ty::GenericPredicates {
|
self.visit_predicates(ty::GenericPredicates {
|
||||||
parent: None,
|
parent: None,
|
||||||
predicates: tcx.explicit_item_bounds(def_id),
|
predicates: tcx.explicit_item_bounds(def_id),
|
||||||
}) {
|
})?;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// These types don't have their own def-ids (but may have subcomponents
|
// These types don't have their own def-ids (but may have subcomponents
|
||||||
@ -231,7 +224,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
!self.def_id_visitor.shallow() && ty.super_visit_with(self)
|
if self.def_id_visitor.shallow() {
|
||||||
|
ControlFlow::CONTINUE
|
||||||
|
} else {
|
||||||
|
ty.super_visit_with(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,9 +278,14 @@ impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'tcx> for FindMin<'a, 'tcx, VL>
|
|||||||
fn skip_assoc_tys(&self) -> bool {
|
fn skip_assoc_tys(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool {
|
fn visit_def_id(
|
||||||
|
&mut self,
|
||||||
|
def_id: DefId,
|
||||||
|
_kind: &str,
|
||||||
|
_descr: &dyn fmt::Display,
|
||||||
|
) -> ControlFlow<(), ()> {
|
||||||
self.min = VL::new_min(self, def_id);
|
self.min = VL::new_min(self, def_id);
|
||||||
false
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -895,7 +897,12 @@ impl DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
|
|||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.ev.tcx
|
self.ev.tcx
|
||||||
}
|
}
|
||||||
fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool {
|
fn visit_def_id(
|
||||||
|
&mut self,
|
||||||
|
def_id: DefId,
|
||||||
|
_kind: &str,
|
||||||
|
_descr: &dyn fmt::Display,
|
||||||
|
) -> ControlFlow<(), ()> {
|
||||||
if let Some(def_id) = def_id.as_local() {
|
if let Some(def_id) = def_id.as_local() {
|
||||||
if let (ty::Visibility::Public, _) | (_, Some(AccessLevel::ReachableFromImplTrait)) =
|
if let (ty::Visibility::Public, _) | (_, Some(AccessLevel::ReachableFromImplTrait)) =
|
||||||
(self.tcx().visibility(def_id.to_def_id()), self.access_level)
|
(self.tcx().visibility(def_id.to_def_id()), self.access_level)
|
||||||
@ -904,7 +911,7 @@ impl DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
|
|||||||
self.ev.update(hir_id, self.access_level);
|
self.ev.update(hir_id, self.access_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1072,17 +1079,14 @@ impl<'tcx> TypePrivacyVisitor<'tcx> {
|
|||||||
fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
|
fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
|
||||||
self.span = span;
|
self.span = span;
|
||||||
let typeck_results = self.typeck_results();
|
let typeck_results = self.typeck_results();
|
||||||
if self.visit(typeck_results.node_type(id)) || self.visit(typeck_results.node_substs(id)) {
|
let result: ControlFlow<(), ()> = try {
|
||||||
return true;
|
self.visit(typeck_results.node_type(id))?;
|
||||||
}
|
self.visit(typeck_results.node_substs(id))?;
|
||||||
if let Some(adjustments) = typeck_results.adjustments().get(id) {
|
if let Some(adjustments) = typeck_results.adjustments().get(id) {
|
||||||
for adjustment in adjustments {
|
adjustments.iter().try_for_each(|adjustment| self.visit(adjustment.target))?;
|
||||||
if self.visit(adjustment.target) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
false
|
result == ControlFlow::BREAK
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
|
fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
|
||||||
@ -1124,14 +1128,14 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
|||||||
self.span = hir_ty.span;
|
self.span = hir_ty.span;
|
||||||
if let Some(typeck_results) = self.maybe_typeck_results {
|
if let Some(typeck_results) = self.maybe_typeck_results {
|
||||||
// Types in bodies.
|
// Types in bodies.
|
||||||
if self.visit(typeck_results.node_type(hir_ty.hir_id)) {
|
if self.visit(typeck_results.node_type(hir_ty.hir_id)) == ControlFlow::BREAK {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Types in signatures.
|
// Types in signatures.
|
||||||
// FIXME: This is very ineffective. Ideally each HIR type should be converted
|
// FIXME: This is very ineffective. Ideally each HIR type should be converted
|
||||||
// into a semantic type only once and the result should be cached somehow.
|
// into a semantic type only once and the result should be cached somehow.
|
||||||
if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty)) {
|
if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty)) == ControlFlow::BREAK {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1153,15 +1157,16 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
for (trait_predicate, _, _) in bounds.trait_bounds {
|
for (trait_predicate, _, _) in bounds.trait_bounds {
|
||||||
if self.visit_trait(trait_predicate.skip_binder()) {
|
if self.visit_trait(trait_predicate.skip_binder()) == ControlFlow::BREAK {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (poly_predicate, _) in bounds.projection_bounds {
|
for (poly_predicate, _) in bounds.projection_bounds {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
if self.visit(poly_predicate.skip_binder().ty)
|
if self.visit(poly_predicate.skip_binder().ty) == ControlFlow::BREAK
|
||||||
|| self.visit_trait(poly_predicate.skip_binder().projection_ty.trait_ref(tcx))
|
|| self.visit_trait(poly_predicate.skip_binder().projection_ty.trait_ref(tcx))
|
||||||
|
== ControlFlow::BREAK
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1188,7 +1193,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
|||||||
// Method calls have to be checked specially.
|
// Method calls have to be checked specially.
|
||||||
self.span = span;
|
self.span = span;
|
||||||
if let Some(def_id) = self.typeck_results().type_dependent_def_id(expr.hir_id) {
|
if let Some(def_id) = self.typeck_results().type_dependent_def_id(expr.hir_id) {
|
||||||
if self.visit(self.tcx.type_of(def_id)) {
|
if self.visit(self.tcx.type_of(def_id)) == ControlFlow::BREAK {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1286,8 +1291,17 @@ impl DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
|||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
|
fn visit_def_id(
|
||||||
self.check_def_id(def_id, kind, descr)
|
&mut self,
|
||||||
|
def_id: DefId,
|
||||||
|
kind: &str,
|
||||||
|
descr: &dyn fmt::Display,
|
||||||
|
) -> ControlFlow<(), ()> {
|
||||||
|
if self.check_def_id(def_id, kind, descr) {
|
||||||
|
ControlFlow::BREAK
|
||||||
|
} else {
|
||||||
|
ControlFlow::CONTINUE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1777,8 +1791,17 @@ impl DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
|||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
|
fn visit_def_id(
|
||||||
self.check_def_id(def_id, kind, descr)
|
&mut self,
|
||||||
|
def_id: DefId,
|
||||||
|
kind: &str,
|
||||||
|
descr: &dyn fmt::Display,
|
||||||
|
) -> ControlFlow<(), ()> {
|
||||||
|
if self.check_def_id(def_id, kind, descr) {
|
||||||
|
ControlFlow::BREAK
|
||||||
|
} else {
|
||||||
|
ControlFlow::CONTINUE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ use rustc_span::def_id::DefId;
|
|||||||
use chalk_ir::{FnSig, ForeignDefId};
|
use chalk_ir::{FnSig, ForeignDefId};
|
||||||
use rustc_hir::Unsafety;
|
use rustc_hir::Unsafety;
|
||||||
use std::collections::btree_map::{BTreeMap, Entry};
|
use std::collections::btree_map::{BTreeMap, Entry};
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
/// Essentially an `Into` with a `&RustInterner` parameter
|
/// Essentially an `Into` with a `&RustInterner` parameter
|
||||||
crate trait LowerInto<'tcx, T> {
|
crate trait LowerInto<'tcx, T> {
|
||||||
@ -897,14 +898,14 @@ impl<'tcx> BoundVarsCollector<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
|
impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
|
||||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
|
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> ControlFlow<(), ()> {
|
||||||
self.binder_index.shift_in(1);
|
self.binder_index.shift_in(1);
|
||||||
let result = t.super_visit_with(self);
|
let result = t.super_visit_with(self);
|
||||||
self.binder_index.shift_out(1);
|
self.binder_index.shift_out(1);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
|
||||||
match *t.kind() {
|
match *t.kind() {
|
||||||
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
|
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
|
||||||
match self.parameters.entry(bound_ty.var.as_u32()) {
|
match self.parameters.entry(bound_ty.var.as_u32()) {
|
||||||
@ -924,7 +925,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
|
|||||||
t.super_visit_with(self)
|
t.super_visit_with(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_region(&mut self, r: Region<'tcx>) -> bool {
|
fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<(), ()> {
|
||||||
match r {
|
match r {
|
||||||
ty::ReLateBound(index, br) if *index == self.binder_index => match br {
|
ty::ReLateBound(index, br) if *index == self.binder_index => match br {
|
||||||
ty::BoundRegion::BrNamed(def_id, _name) => {
|
ty::BoundRegion::BrNamed(def_id, _name) => {
|
||||||
@ -1114,7 +1115,7 @@ impl PlaceholdersCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
|
impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
|
||||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
|
||||||
match t.kind() {
|
match t.kind() {
|
||||||
ty::Placeholder(p) if p.universe == self.universe_index => {
|
ty::Placeholder(p) if p.universe == self.universe_index => {
|
||||||
self.next_ty_placeholder = self.next_ty_placeholder.max(p.name.as_usize() + 1);
|
self.next_ty_placeholder = self.next_ty_placeholder.max(p.name.as_usize() + 1);
|
||||||
@ -1126,7 +1127,7 @@ impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
|
|||||||
t.super_visit_with(self)
|
t.super_visit_with(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_region(&mut self, r: Region<'tcx>) -> bool {
|
fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<(), ()> {
|
||||||
match r {
|
match r {
|
||||||
ty::RePlaceholder(p) if p.universe == self.universe_index => {
|
ty::RePlaceholder(p) if p.universe == self.universe_index => {
|
||||||
if let ty::BoundRegion::BrAnon(anon) = p.name {
|
if let ty::BoundRegion::BrAnon(anon) = p.name {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
|
#![feature(control_flow_enum)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -24,6 +24,8 @@ use rustc_trait_selection::opaque_types::InferCtxtExt as _;
|
|||||||
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
|
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
|
||||||
use rustc_trait_selection::traits::{self, ObligationCauseCode};
|
use rustc_trait_selection::traits::{self, ObligationCauseCode};
|
||||||
|
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
pub fn check_wf_new(tcx: TyCtxt<'_>) {
|
pub fn check_wf_new(tcx: TyCtxt<'_>) {
|
||||||
let visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
|
let visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
|
||||||
tcx.hir().krate().par_visit_all_item_likes(&visit);
|
tcx.hir().krate().par_visit_all_item_likes(&visit);
|
||||||
@ -448,30 +450,34 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
|
|||||||
};
|
};
|
||||||
|
|
||||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
|
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
|
||||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
|
||||||
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 && t.super_visit_with(self) {
|
if t != self.opaque_identity_ty && t.super_visit_with(self) == ControlFlow::BREAK {
|
||||||
self.ty = Some(t);
|
self.ty = Some(t);
|
||||||
return true;
|
return ControlFlow::BREAK;
|
||||||
}
|
}
|
||||||
false
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<(), ()> {
|
||||||
debug!("check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}", r);
|
debug!("check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}", r);
|
||||||
if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r {
|
if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r {
|
||||||
return *index < self.generics.parent_count as u32;
|
if *index < self.generics.parent_count as u32 {
|
||||||
|
return ControlFlow::BREAK;
|
||||||
|
} else {
|
||||||
|
return ControlFlow::CONTINUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.super_visit_with(self)
|
r.super_visit_with(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
|
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<(), ()> {
|
||||||
if let ty::ConstKind::Unevaluated(..) = c.val {
|
if let ty::ConstKind::Unevaluated(..) = c.val {
|
||||||
// FIXME(#72219) We currenctly don't detect lifetimes within substs
|
// FIXME(#72219) We currenctly don't detect lifetimes within substs
|
||||||
// which would violate this check. Even though the particular substitution is not used
|
// which would violate this check. Even though the particular substitution is not used
|
||||||
// within the const, this should still be fixed.
|
// within the const, this should still be fixed.
|
||||||
return false;
|
return ControlFlow::CONTINUE;
|
||||||
}
|
}
|
||||||
c.super_visit_with(self)
|
c.super_visit_with(self)
|
||||||
}
|
}
|
||||||
@ -493,7 +499,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
|
|||||||
let prohibit_opaque = tcx
|
let prohibit_opaque = tcx
|
||||||
.explicit_item_bounds(def_id)
|
.explicit_item_bounds(def_id)
|
||||||
.iter()
|
.iter()
|
||||||
.any(|(predicate, _)| predicate.visit_with(&mut visitor));
|
.any(|(predicate, _)| predicate.visit_with(&mut visitor) == ControlFlow::BREAK);
|
||||||
debug!(
|
debug!(
|
||||||
"check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor={:?}",
|
"check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor={:?}",
|
||||||
prohibit_opaque, visitor
|
prohibit_opaque, visitor
|
||||||
@ -1449,11 +1455,11 @@ 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 visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
|
||||||
match *t.kind() {
|
match *t.kind() {
|
||||||
ty::Opaque(def, _) => {
|
ty::Opaque(def, _) => {
|
||||||
self.0.push(def);
|
self.0.push(def);
|
||||||
false
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
_ => t.super_visit_with(self),
|
_ => t.super_visit_with(self),
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ use rustc_span::symbol::{sym, Ident};
|
|||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
|
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
/// Checks a `a <op>= b`
|
/// Checks a `a <op>= b`
|
||||||
pub fn check_binop_assign(
|
pub fn check_binop_assign(
|
||||||
@ -981,7 +983,7 @@ fn suggest_constraining_param(
|
|||||||
struct TypeParamVisitor<'tcx>(Vec<Ty<'tcx>>);
|
struct TypeParamVisitor<'tcx>(Vec<Ty<'tcx>>);
|
||||||
|
|
||||||
impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> {
|
impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> {
|
||||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
|
||||||
if let ty::Param(_) = ty.kind() {
|
if let ty::Param(_) = ty.kind() {
|
||||||
self.0.push(ty);
|
self.0.push(ty);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@ use rustc_trait_selection::opaque_types::may_define_opaque_type;
|
|||||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
|
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
|
||||||
|
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
/// Helper type of a temporary returned by `.for_item(...)`.
|
/// Helper type of a temporary returned by `.for_item(...)`.
|
||||||
/// This is necessary because we can't write the following bound:
|
/// This is necessary because we can't write the following bound:
|
||||||
///
|
///
|
||||||
@ -798,18 +800,18 @@ fn check_where_clauses<'tcx, 'fcx>(
|
|||||||
params: FxHashSet<u32>,
|
params: FxHashSet<u32>,
|
||||||
}
|
}
|
||||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
|
impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
|
||||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
|
||||||
if let ty::Param(param) = t.kind() {
|
if let ty::Param(param) = t.kind() {
|
||||||
self.params.insert(param.index);
|
self.params.insert(param.index);
|
||||||
}
|
}
|
||||||
t.super_visit_with(self)
|
t.super_visit_with(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_region(&mut self, _: ty::Region<'tcx>) -> bool {
|
fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<(), ()> {
|
||||||
true
|
ControlFlow::BREAK
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
|
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<(), ()> {
|
||||||
if let ty::ConstKind::Param(param) = c.val {
|
if let ty::ConstKind::Param(param) = c.val {
|
||||||
self.params.insert(param.index);
|
self.params.insert(param.index);
|
||||||
}
|
}
|
||||||
@ -817,7 +819,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut param_count = CountParams::default();
|
let mut param_count = CountParams::default();
|
||||||
let has_region = pred.visit_with(&mut param_count);
|
let has_region = pred.visit_with(&mut param_count) == ControlFlow::BREAK;
|
||||||
let substituted_pred = pred.subst(fcx.tcx, substs);
|
let substituted_pred = pred.subst(fcx.tcx, substs);
|
||||||
// Don't check non-defaulted params, dependent defaults (including lifetimes)
|
// Don't check non-defaulted params, dependent defaults (including lifetimes)
|
||||||
// or preds with multiple params.
|
// or preds with multiple params.
|
||||||
|
@ -50,6 +50,8 @@ use rustc_span::{Span, DUMMY_SP};
|
|||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
|
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
|
||||||
|
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
mod item_bounds;
|
mod item_bounds;
|
||||||
mod type_of;
|
mod type_of;
|
||||||
|
|
||||||
@ -2060,14 +2062,14 @@ fn const_evaluatable_predicates_of<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> TypeVisitor<'tcx> for TyAliasVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> TypeVisitor<'tcx> for TyAliasVisitor<'a, 'tcx> {
|
||||||
fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> bool {
|
fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> ControlFlow<(), ()> {
|
||||||
if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val {
|
if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val {
|
||||||
self.preds.insert((
|
self.preds.insert((
|
||||||
ty::PredicateAtom::ConstEvaluatable(def, substs).to_predicate(self.tcx),
|
ty::PredicateAtom::ConstEvaluatable(def, substs).to_predicate(self.tcx),
|
||||||
self.span,
|
self.span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
false
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxHashSet;
|
|||||||
use rustc_middle::ty::fold::{TypeFoldable, TypeVisitor};
|
use rustc_middle::ty::fold::{TypeFoldable, TypeVisitor};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct Parameter(pub u32);
|
pub struct Parameter(pub u32);
|
||||||
@ -56,11 +57,11 @@ struct ParameterCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
|
impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
|
||||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
|
||||||
match *t.kind() {
|
match *t.kind() {
|
||||||
ty::Projection(..) | ty::Opaque(..) if !self.include_nonconstraining => {
|
ty::Projection(..) | ty::Opaque(..) if !self.include_nonconstraining => {
|
||||||
// projections are not injective
|
// projections are not injective
|
||||||
return false;
|
return ControlFlow::CONTINUE;
|
||||||
}
|
}
|
||||||
ty::Param(data) => {
|
ty::Param(data) => {
|
||||||
self.parameters.push(Parameter::from(data));
|
self.parameters.push(Parameter::from(data));
|
||||||
@ -71,14 +72,14 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
|
|||||||
t.super_visit_with(self)
|
t.super_visit_with(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<(), ()> {
|
||||||
if let ty::ReEarlyBound(data) = *r {
|
if let ty::ReEarlyBound(data) = *r {
|
||||||
self.parameters.push(Parameter::from(data));
|
self.parameters.push(Parameter::from(data));
|
||||||
}
|
}
|
||||||
false
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
|
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<(), ()> {
|
||||||
match c.val {
|
match c.val {
|
||||||
ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => {
|
ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => {
|
||||||
// Constant expressions are not injective
|
// Constant expressions are not injective
|
||||||
|
@ -66,6 +66,7 @@ This API is completely unstable and subject to change.
|
|||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(slice_partition_dedup)]
|
#![feature(slice_partition_dedup)]
|
||||||
|
#![feature(control_flow_enum)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
Loading…
Reference in New Issue
Block a user