diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 7cd55951cdaf4..abe3b50ffdab9 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -284,11 +284,13 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> { } impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder + fn fold_binder(&mut self, t: &ty::Binder) -> Result, !> where T: TypeFoldable<'tcx> { self.binder_index.shift_in(1); @@ -297,8 +299,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> t } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { + Ok(match *r { ty::ReLateBound(index, ..) => { if index >= self.binder_index { bug!("escaping late bound region during canonicalization") @@ -333,10 +335,10 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> ty::ReClosureBound(..) => { bug!("closure bound region encountered during canonicalization") } - } + }) } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result, !> { match t.sty { ty::Infer(ty::TyVar(vid)) => { debug!("canonical: type var found with vid {:?}", vid); @@ -354,29 +356,29 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> // FIXME: perf problem described in #55921. ui = ty::UniverseIndex::ROOT; } - self.canonicalize_ty_var( + Ok(self.canonicalize_ty_var( CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) }, t - ) + )) } } } - ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var( + ty::Infer(ty::IntVar(_)) => Ok(self.canonicalize_ty_var( CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) }, t - ), + )), - ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var( + ty::Infer(ty::FloatVar(_)) => Ok(self.canonicalize_ty_var( CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) }, t - ), + )), ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) @@ -384,18 +386,18 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> bug!("encountered a fresh type during canonicalization") } - ty::Placeholder(placeholder) => self.canonicalize_ty_var( + ty::Placeholder(placeholder) => Ok(self.canonicalize_ty_var( CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderTy(placeholder) }, t - ), + )), ty::Bound(debruijn, _) => { if debruijn >= self.binder_index { bug!("escaping bound type during canonicalization") } else { - t + Ok(t) } } @@ -427,7 +429,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> if t.flags.intersects(self.needs_canonical_flags) { t.super_fold_with(self) } else { - t + Ok(t) } } } @@ -485,7 +487,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { indices: FxHashMap::default(), binder_index: ty::INNERMOST, }; - let out_value = value.fold_with(&mut canonicalizer); + let Ok(out_value) = value.fold_with(&mut canonicalizer); // Once we have canonicalized `out_value`, it should not // contain anything that ties it to this inference context @@ -627,7 +629,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { let infcx = self.infcx.expect("encountered ty-var without infcx"); let bound_to = infcx.shallow_resolve(ty_var); if bound_to != ty_var { - self.fold_ty(bound_to) + self.fold_ty(bound_to).unwrap_or_else(|e: !| e) } else { let var = self.canonical_var(info, ty_var.into()); self.tcx().mk_ty(ty::Bound(self.binder_index, var.into())) diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 6ef902a47dc8d..27c41d80b5cc1 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -29,13 +29,13 @@ use super::lub::Lub; use super::sub::Sub; use super::type_variable::TypeVariableValue; -use crate::hir::def_id::DefId; use crate::ty::{IntType, UintType}; use crate::ty::{self, Ty, TyCtxt}; +use crate::ty::fold::{TypeFoldable, TypeFolder}; use crate::ty::error::TypeError; -use crate::ty::relate::{self, Relate, RelateResult, TypeRelation}; -use crate::ty::subst::SubstsRef; +use crate::ty::relate::{RelateResult, TypeRelation}; use crate::traits::{Obligation, PredicateObligations}; +use crate::util::common::ErrorReported; use syntax::ast; use syntax_pos::Span; @@ -278,7 +278,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { root_ty: ty, }; - let ty = match generalize.relate(&ty, &ty) { + let ty = match ty.fold_with(&mut generalize) { Ok(ty) => ty, Err(e) => { debug!("generalize: failure {:?}", e); @@ -351,60 +351,41 @@ struct Generalization<'tcx> { needs_wf: bool, } -impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> { - fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> { - self.infcx.tcx - } - - fn tag(&self) -> &'static str { - "Generalizer" - } +impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> { + type Error = TypeError<'tcx>; - fn a_is_expected(&self) -> bool { - true - } - - fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) - -> RelateResult<'tcx, ty::Binder> - where T: Relate<'tcx> - { - Ok(ty::Binder::bind(self.relate(a.skip_binder(), b.skip_binder())?)) + fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> { + self.infcx.tcx } - fn relate_item_substs(&mut self, - item_def_id: DefId, - a_subst: SubstsRef<'tcx>, - b_subst: SubstsRef<'tcx>) - -> RelateResult<'tcx, SubstsRef<'tcx>> - { + fn use_variances(&self) -> bool { if self.ambient_variance == ty::Variance::Invariant { // Avoid fetching the variance if we are in an invariant // context; no need, and it can induce dependency cycles // (e.g., #41849). - relate::relate_substs(self, None, a_subst, b_subst) + false } else { - let opt_variances = self.tcx().variances_of(item_def_id); - relate::relate_substs(self, Some(&opt_variances), a_subst, b_subst) + true } } - fn relate_with_variance>(&mut self, - variance: ty::Variance, - a: &T, - b: &T) - -> RelateResult<'tcx, T> + fn fold_with_variance>(&mut self, + variance: ty::Variance, + a: &T) + -> RelateResult<'tcx, T> { let old_ambient_variance = self.ambient_variance; + debug!("Generalize: fold_with_variance({:?}, {:?}, old_variance={:?})", + variance, a, old_ambient_variance); self.ambient_variance = self.ambient_variance.xform(variance); - let result = self.relate(a, b); + let result = a.fold_with(self); self.ambient_variance = old_ambient_variance; result } - fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be == - + fn fold_ty(&mut self, t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + debug!("Generalize: fold_ty({:?}, variance={:?})", t, self.ambient_variance); debug!("generalize: t={:?}", t); // Check to see whether the type we are genealizing references @@ -425,7 +406,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' TypeVariableValue::Known { value: u } => { drop(variables); debug!("generalize: known value {:?}", u); - self.relate(&u, &u) + u.fold_with(self) } TypeVariableValue::Unknown { universe } => { match self.ambient_variance { @@ -449,7 +430,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' let origin = *variables.var_origin(vid); let new_var_id = variables.new_var(self.for_universe, false, origin); - let u = self.tcx().mk_var(new_var_id); + let u = self.infcx.tcx.mk_var(new_var_id); debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); return Ok(u); @@ -459,21 +440,33 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' } ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) => { - // No matter what mode we are in, - // integer/floating-point types must be equal to be - // relatable. Ok(t) } + ty::Array(_, sz) => { + // HACK, not sure how desirable this is: propagate errors from + // array lengths to the array type itself. This makes error + // messages a bit nicer, and used to be the case before because + // we used `ty::relate` instead of `TypeFoldable`, so I'll keep + // it here. + // + // This does not serve any functional purpose, but it does + // avoid some "duplicate" errors. + match self.infcx.tcx.force_eval_array_length(*sz) { + Ok(_) => t.super_fold_with(self), + Err(ErrorReported) => { + Ok(self.infcx.tcx.types.err) + } + } + } _ => { - relate::super_relate_tys(self, t, t) + t.super_fold_with(self) } } } - fn regions(&mut self, r: ty::Region<'tcx>, r2: ty::Region<'tcx>) + fn fold_region(&mut self, r: ty::Region<'tcx>) -> RelateResult<'tcx, ty::Region<'tcx>> { - assert_eq!(r, r2); // we are abusing TypeRelation here; both LHS and RHS ought to be == - + debug!("Generalize: fold_region({:?}, variance={:?})", r, self.ambient_variance); debug!("generalize: regions r={:?}", r); match *r { diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 201717b34ee41..62467bef56c38 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -64,7 +64,7 @@ impl<'a, 'gcx, 'tcx> TypeFreshener<'a, 'gcx, 'tcx> { F: FnOnce(u32) -> ty::InferTy, { if let Some(ty) = opt_ty { - return ty.fold_with(self); + return ty.fold_with(self).unwrap_or_else(|e: !| e); } match self.freshen_map.entry(key) { @@ -81,12 +81,14 @@ impl<'a, 'gcx, 'tcx> TypeFreshener<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { + Ok(match *r { ty::ReLateBound(..) => { // leave bound regions alone r @@ -110,18 +112,18 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { r, ); } - } + }) } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result, !> { if !t.needs_infer() && !t.has_erasable_regions() && !(t.has_closure_types() && self.infcx.in_progress_tables.is_some()) { - return t; + return Ok(t); } let tcx = self.infcx.tcx; - match t.sty { + Ok(match t.sty { ty::Infer(ty::TyVar(v)) => { let opt_ty = self.infcx.type_variables.borrow_mut().probe(v).known(); self.freshen( @@ -185,11 +187,11 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ty::Closure(..) | ty::GeneratorWitness(..) | ty::Opaque(..) => { - t.super_fold_with(self) + t.super_fold_with(self)? } ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t), - } + }) } } diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index 5f6a8802b4def..4b45aaaf72fe7 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -95,7 +95,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { origin, }; - Ok(value.fold_with(&mut fudger)) + value.fold_with(&mut fudger).map_err(|e| e) } } @@ -107,11 +107,13 @@ pub struct RegionFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result, !> { match ty.sty { ty::Infer(ty::InferTy::TyVar(vid)) => { match self.type_variables.get(&vid) { @@ -124,14 +126,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> { debug_assert!(self.infcx.type_variables.borrow_mut() .probe(vid) .is_unknown()); - ty + Ok(ty) } Some(&origin) => { // This variable was created during the // fudging. Recreate it with a fresh variable // here. - self.infcx.next_ty_var(origin) + Ok(self.infcx.next_ty_var(origin)) } } } @@ -139,14 +141,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> { } } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { + Ok(match *r { ty::ReVar(v) if self.region_vars.contains(&v) => { self.infcx.next_region_var(self.origin.clone()) } _ => { r } - } + }) } } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 84ad742d3c972..437318d37829f 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -604,7 +604,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } pub fn freshen>(&self, t: T) -> T { - t.fold_with(&mut self.freshener()) + t.fold_with(&mut self.freshener()).unwrap_or_else(|e: !| e) } pub fn type_var_diverges(&'a self, ty: Ty<'_>) -> bool { @@ -1298,7 +1298,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return value.clone(); // avoid duplicated subst-folding } let mut r = resolve::OpportunisticTypeResolver::new(self); - value.fold_with(&mut r) + value.fold_with(&mut r).unwrap_or_else(|e: !| e) } /// Returns `true` if `T` contains unresolved type variables. In the @@ -1311,7 +1311,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { T: TypeFoldable<'tcx>, { let mut r = resolve::UnresolvedTypeFinder::new(self); - value.visit_with(&mut r) + value.visit_with(&mut r).is_err() } pub fn fully_resolve>(&self, value: &T) -> FixupResult { diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index f37e24b292e03..97179fc0539bd 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -22,8 +22,8 @@ //! constituents) use crate::infer::InferCtxt; -use crate::ty::fold::{TypeFoldable, TypeVisitor}; -use crate::ty::relate::{self, Relate, RelateResult, TypeRelation}; +use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use crate::ty::relate::{Relate, RelateResult, TypeRelation}; use crate::ty::subst::Kind; use crate::ty::{self, Ty, TyCtxt}; use crate::ty::error::TypeError; @@ -196,7 +196,7 @@ where } }; - value.skip_binder().visit_with(&mut ScopeInstantiator { + let Ok(_) = value.skip_binder().visit_with(&mut ScopeInstantiator { next_region: &mut next_region, target_index: ty::INNERMOST, bound_region_scope: &mut scope, @@ -344,7 +344,7 @@ where result } - fn generalize_value>( + fn generalize_value>( &mut self, value: T, for_vid: ty::TyVid @@ -360,7 +360,7 @@ where universe, }; - generalizer.relate(&value, &value) + value.fold_with(&mut generalizer) } } @@ -604,15 +604,17 @@ struct ScopeInstantiator<'me, 'tcx: 'me> { } impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> { - fn visit_binder>(&mut self, t: &ty::Binder) -> bool { + type Error = !; + + fn visit_binder>(&mut self, t: &ty::Binder) -> Result<(), !> { self.target_index.shift_in(1); - t.super_visit_with(self); + t.super_visit_with(self)?; self.target_index.shift_out(1); - false + Ok(()) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Result<(), !> { let ScopeInstantiator { bound_region_scope, next_region, @@ -630,7 +632,7 @@ impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> { _ => {} } - false + Ok(()) } } @@ -678,54 +680,58 @@ where universe: ty::UniverseIndex, } -impl TypeRelation<'me, 'gcx, 'tcx> for TypeGeneralizer<'me, 'gcx, 'tcx, D> +impl TypeFolder<'gcx, 'tcx> for TypeGeneralizer<'me, 'gcx, 'tcx, D> where D: TypeRelatingDelegate<'tcx>, { - fn tcx(&self) -> TyCtxt<'me, 'gcx, 'tcx> { - self.infcx.tcx - } + type Error = TypeError<'tcx>; - fn tag(&self) -> &'static str { - "nll::generalizer" + fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> { + self.infcx.tcx } - fn a_is_expected(&self) -> bool { - true + fn use_variances(&self) -> bool { + if self.ambient_variance == ty::Variance::Invariant { + // Avoid fetching the variance if we are in an invariant + // context; no need, and it can induce dependency cycles + // (e.g., #41849). + false + } else { + true + } } - fn relate_with_variance>( + fn fold_with_variance>( &mut self, variance: ty::Variance, a: &T, - b: &T, ) -> RelateResult<'tcx, T> { debug!( - "TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})", - variance, a, b + "TypeGeneralizer::fold_with_variance(variance={:?}, a={:?})", + variance, a ); let old_ambient_variance = self.ambient_variance; self.ambient_variance = self.ambient_variance.xform(variance); debug!( - "TypeGeneralizer::relate_with_variance: ambient_variance = {:?}", + "TypeGeneralizer::fold_with_variance: ambient_variance = {:?}", self.ambient_variance ); - let r = self.relate(a, b)?; + let r = a.super_fold_with(self)?; self.ambient_variance = old_ambient_variance; - debug!("TypeGeneralizer::relate_with_variance: r={:?}", r); + debug!("TypeGeneralizer::fold_with_variance: r={:?}", r); Ok(r) } - fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + fn fold_ty(&mut self, a: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { use crate::infer::type_variable::TypeVariableValue; - debug!("TypeGeneralizer::tys(a={:?})", a,); + debug!("TypeGeneralizer::fold_ty(a={:?})", a,); match a.sty { ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) @@ -744,13 +750,13 @@ where if sub_vid == self.for_vid_sub_root { // If sub-roots are equal, then `for_vid` and // `vid` are related via subtyping. - debug!("TypeGeneralizer::tys: occurs check failed"); + debug!("TypeGeneralizer::fold_ty: occurs check failed"); return Err(TypeError::Mismatch); } else { match variables.probe(vid) { TypeVariableValue::Known { value: u } => { drop(variables); - self.relate(&u, &u) + u.fold_with(self) } TypeVariableValue::Unknown { universe: _universe } => { if self.ambient_variance == ty::Bivariant { @@ -787,7 +793,7 @@ where ty::Placeholder(placeholder) => { if self.universe.cannot_name(placeholder.universe) { debug!( - "TypeGeneralizer::tys: root universe {:?} cannot name\ + "TypeGeneralizer::fold_ty: root universe {:?} cannot name\ placeholder in universe {:?}", self.universe, placeholder.universe @@ -799,17 +805,16 @@ where } _ => { - relate::super_relate_tys(self, a, a) + a.super_fold_with(self) } } } - fn regions( + fn fold_region( &mut self, a: ty::Region<'tcx>, - _: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { - debug!("TypeGeneralizer::regions(a={:?})", a,); + debug!("TypeGeneralizer::fold_region(a={:?})", a,); if let ty::ReLateBound(debruijn, _) = a { if *debruijn < self.first_free_index { @@ -838,18 +843,17 @@ where Ok(replacement_region_vid) } - fn binders( + fn fold_binder( &mut self, a: &ty::Binder, - _: &ty::Binder, ) -> RelateResult<'tcx, ty::Binder> where - T: Relate<'tcx>, + T: TypeFoldable<'tcx>, { - debug!("TypeGeneralizer::binders(a={:?})", a,); + debug!("TypeGeneralizer::fold_binder(a={:?})", a,); self.first_free_index.shift_in(1); - let result = self.relate(a.skip_binder(), a.skip_binder())?; + let result = a.skip_binder().fold_with(self)?; self.first_free_index.shift_out(1); Ok(ty::Binder::bind(result)) } diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 159bc1ceae26c..28624f968bf5e 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -448,7 +448,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Convert the type from the function into a type valid outside // the function, by replacing invalid regions with 'static, // after producing an error for each of them. - let definition_ty = + let Ok(definition_ty) = instantiated_ty.fold_with(&mut ReverseMapper::new( self.tcx, self.is_tainted_by_errors(), @@ -506,23 +506,25 @@ impl<'cx, 'gcx, 'tcx> ReverseMapper<'cx, 'gcx, 'tcx> { fn fold_kind_mapping_missing_regions_to_empty(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> { assert!(!self.map_missing_regions_to_empty); self.map_missing_regions_to_empty = true; - let kind = kind.fold_with(self); + let Ok(kind) = kind.fold_with(self); self.map_missing_regions_to_empty = false; kind } fn fold_kind_normally(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> { assert!(!self.map_missing_regions_to_empty); - kind.fold_with(self) + kind.fold_with(self).unwrap_or_else(|e: !| e) } } impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> { + type Error = !; + fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> { self.tcx } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { match r { // ignore bound regions that appear in the type (e.g., this // would ignore `'r` in a type like `for<'r> fn(&'r u32)`. @@ -533,13 +535,13 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> // ignore `ReScope`, as that can appear anywhere // See `src/test/run-pass/issue-49556.rs` for example. - ty::ReScope(..) => return r, + ty::ReScope(..) => return Ok(r), _ => { } } match self.map.get(&r.into()).map(|k| k.unpack()) { - Some(UnpackedKind::Lifetime(r1)) => r1, + Some(UnpackedKind::Lifetime(r1)) => Ok(r1), Some(u) => panic!("region mapped to unexpected kind: {:?}", u), None => { if !self.map_missing_regions_to_empty && !self.tainted_by_errors { @@ -576,12 +578,12 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> err.emit(); } } - self.tcx.types.re_empty + Ok(self.tcx.types.re_empty) }, } } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result, !> { match ty.sty { ty::Closure(def_id, substs) => { // I am a horrible monster and I pray for death. When @@ -621,7 +623,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> }, )); - self.tcx.mk_closure(def_id, ty::ClosureSubsts { substs }) + Ok(self.tcx.mk_closure(def_id, ty::ClosureSubsts { substs })) } _ => ty.super_fold_with(self), @@ -733,7 +735,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> { ty }, - }) + }).unwrap_or_else(|e: !| e) } fn fold_opaque_ty( diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs index 4a8f0c34ead11..03dafefe926cb 100644 --- a/src/librustc/infer/resolve.rs +++ b/src/librustc/infer/resolve.rs @@ -22,13 +22,15 @@ impl<'a, 'gcx, 'tcx> OpportunisticTypeResolver<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticTypeResolver<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result, !> { if !t.has_infer_types() { - t // micro-optimize -- if there is nothing in this type that this fold affects... + Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects... } else { let t0 = self.infcx.shallow_resolve(t); t0.super_fold_with(self) @@ -50,27 +52,29 @@ impl<'a, 'gcx, 'tcx> OpportunisticTypeAndRegionResolver<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticTypeAndRegionResolver<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result, !> { if !t.needs_infer() { - t // micro-optimize -- if there is nothing in this type that this fold affects... + Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects... } else { let t0 = self.infcx.shallow_resolve(t); t0.super_fold_with(self) } } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { + Ok(match *r { ty::ReVar(rid) => self.infcx.borrow_region_constraints() .opportunistic_resolve_var(self.tcx(), rid), _ => r, - } + }) } } @@ -92,13 +96,15 @@ impl<'a, 'gcx, 'tcx> UnresolvedTypeFinder<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'gcx, 'tcx> { - fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { + type Error = (); + + fn visit_ty(&mut self, t: Ty<'tcx>) -> Result<(), ()> { let t = self.infcx.shallow_resolve(t); if t.has_infer_types() { if let ty::Infer(_) = t.sty { // Since we called `shallow_resolve` above, this must // be an (as yet...) unresolved inference variable. - true + Err(()) } else { // Otherwise, visit its contents. t.super_visit_with(self) @@ -106,7 +112,7 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'gcx, 'tcx> } else { // Micro-optimize: no inference types at all Can't have unresolved type // variables, no need to visit the contents. - false + Ok(()) } } } @@ -122,7 +128,7 @@ pub fn fully_resolve<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, where T : TypeFoldable<'tcx> { let mut full_resolver = FullTypeResolver { infcx: infcx, err: None }; - let result = value.fold_with(&mut full_resolver); + let Ok(result) = value.fold_with(&mut full_resolver); match full_resolver.err { None => Ok(result), Some(e) => Err(e), @@ -137,29 +143,32 @@ struct FullTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for FullTypeResolver<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result, !> { if !t.needs_infer() && !ty::keep_local(&t) { - t // micro-optimize -- if there is nothing in this type that this fold affects... - // ^ we need to have the `keep_local` check to un-default - // defaulted tuples. + Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects... + // ^ we need to have the `keep_local` check to un-default + // defaulted tuples. } else { let t = self.infcx.shallow_resolve(t); + // FIXME: use the error propagation support. match t.sty { ty::Infer(ty::TyVar(vid)) => { self.err = Some(FixupError::UnresolvedTy(vid)); - self.tcx().types.err + Ok(self.tcx().types.err) } ty::Infer(ty::IntVar(vid)) => { self.err = Some(FixupError::UnresolvedIntTy(vid)); - self.tcx().types.err + Ok(self.tcx().types.err) } ty::Infer(ty::FloatVar(vid)) => { self.err = Some(FixupError::UnresolvedFloatTy(vid)); - self.tcx().types.err + Ok(self.tcx().types.err) } ty::Infer(_) => { bug!("Unexpected type in full type resolver: {:?}", t); @@ -171,14 +180,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for FullTypeResolver<'a, 'gcx, 'tcx> } } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { + Ok(match *r { ty::ReVar(rid) => self.infcx.lexical_region_resolutions .borrow() .as_ref() .expect("region resolution not performed") .resolve_var(rid), _ => r, - } + }) } } diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs index 8d9d1db5756b8..6de718f4f7a01 100644 --- a/src/librustc/macros.rs +++ b/src/librustc/macros.rs @@ -221,16 +221,16 @@ macro_rules! CloneTypeFoldableImpls { fn super_fold_with<'gcx: $tcx, F: $crate::ty::fold::TypeFolder<'gcx, $tcx>>( &self, _: &mut F - ) -> $ty { - Clone::clone(self) + ) -> Result<$ty, F::Error> { + Ok(Clone::clone(self)) } fn super_visit_with>( &self, _: &mut F) - -> bool + -> Result<(), F::Error> { - false + Ok(()) } } )+ @@ -335,17 +335,21 @@ macro_rules! BraceStructTypeFoldableImpl { fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>( &self, folder: &mut V, - ) -> Self { + ) -> Result { let $s { $($field,)* } = self; - $s { $($field: $crate::ty::fold::TypeFoldable::fold_with($field, folder),)* } + // FIXME(#58274): investigate parser bug + Ok({ $s { + $($field: $crate::ty::fold::TypeFoldable::fold_with($field, folder)?),* + }}) } fn super_visit_with>( &self, visitor: &mut V, - ) -> bool { + ) -> Result<(), V::Error> { let $s { $($field,)* } = self; - false $(|| $crate::ty::fold::TypeFoldable::visit_with($field, visitor))* + $($crate::ty::fold::TypeFoldable::visit_with($field, visitor)?;)*; + Ok(()) } } }; @@ -362,17 +366,20 @@ macro_rules! TupleStructTypeFoldableImpl { fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>( &self, folder: &mut V, - ) -> Self { + ) -> Result { let $s($($field,)*)= self; - $s($($crate::ty::fold::TypeFoldable::fold_with($field, folder),)*) + Ok($s( + $($crate::ty::fold::TypeFoldable::fold_with($field, folder)?),* + )) } fn super_visit_with>( &self, visitor: &mut V, - ) -> bool { + ) -> Result<(), V::Error> { let $s($($field,)*) = self; - false $(|| $crate::ty::fold::TypeFoldable::visit_with($field, visitor))* + $($crate::ty::fold::TypeFoldable::visit_with($field, visitor)?;)*; + Ok(()) } } }; @@ -389,14 +396,14 @@ macro_rules! EnumTypeFoldableImpl { fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>( &self, folder: &mut V, - ) -> Self { + ) -> Result { EnumTypeFoldableImpl!(@FoldVariants(self, folder) input($($variants)*) output()) } fn super_visit_with>( &self, visitor: &mut V, - ) -> bool { + ) -> Result<(), V::Error> { EnumTypeFoldableImpl!(@VisitVariants(self, visitor) input($($variants)*) output()) } } @@ -416,9 +423,9 @@ macro_rules! EnumTypeFoldableImpl { input($($input)*) output( $variant ( $($variant_arg),* ) => { - $variant ( - $($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)),* - ) + Ok($variant ( + $($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)?),* + )) } $($output)* ) @@ -433,10 +440,12 @@ macro_rules! EnumTypeFoldableImpl { input($($input)*) output( $variant { $($variant_arg),* } => { - $variant { + // FIXME(#58274): investigate parser bug + Ok({$variant { $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with( $variant_arg, $folder - )),* } + )?),* + }}) } $($output)* ) @@ -450,7 +459,7 @@ macro_rules! EnumTypeFoldableImpl { @FoldVariants($this, $folder) input($($input)*) output( - $variant => { $variant } + $variant => { Ok($variant) } $($output)* ) ) @@ -470,9 +479,10 @@ macro_rules! EnumTypeFoldableImpl { input($($input)*) output( $variant ( $($variant_arg),* ) => { - false $(|| $crate::ty::fold::TypeFoldable::visit_with( + $($crate::ty::fold::TypeFoldable::visit_with( $variant_arg, $visitor - ))* + )?;)*; + Ok(()) } $($output)* ) @@ -487,9 +497,10 @@ macro_rules! EnumTypeFoldableImpl { input($($input)*) output( $variant { $($variant_arg),* } => { - false $(|| $crate::ty::fold::TypeFoldable::visit_with( + $($crate::ty::fold::TypeFoldable::visit_with( $variant_arg, $visitor - ))* + )?;)* + Ok(()) } $($output)* ) @@ -503,10 +514,9 @@ macro_rules! EnumTypeFoldableImpl { @VisitVariants($this, $visitor) input($($input)*) output( - $variant => { false } + $variant => { Ok(()) } $($output)* ) ) }; } - diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index b6f5ff25c8fb8..5788bbdee8266 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1916,12 +1916,18 @@ pub enum PlaceBase<'tcx> { /// The `DefId` of a static, along with its normalized type (which is /// stored to avoid requiring normalization when reading MIR). -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct Static<'tcx> { pub def_id: DefId, pub ty: Ty<'tcx>, } +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for Static<'tcx> { + def_id, ty + } +} + impl_stable_hash_for!(struct Static<'tcx> { def_id, ty @@ -2046,24 +2052,32 @@ impl<'tcx> Place<'tcx> { } } -impl<'tcx> Debug for Place<'tcx> { +impl<'tcx> Debug for PlaceBase<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { - use self::Place::*; - match *self { - Base(PlaceBase::Local(id)) => write!(fmt, "{:?}", id), - Base(PlaceBase::Static(box self::Static { def_id, ty })) => write!( + PlaceBase::Local(id) => write!(fmt, "{:?}", id), + PlaceBase::Static(box self::Static { def_id, ty }) => write!( fmt, "({}: {:?})", ty::tls::with(|tcx| tcx.item_path_str(def_id)), ty ), - Base(PlaceBase::Promoted(ref promoted)) => write!( + PlaceBase::Promoted(ref promoted) => write!( fmt, "({:?}: {:?})", promoted.0, promoted.1 ), + } + } +} + +impl<'tcx> Debug for Place<'tcx> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + use self::Place::*; + + match *self { + Base(ref base) => Debug::fmt(base, fmt), Projection(ref data) => match data.elem { ProjectionElem::Downcast(ref adt_def, index) => { write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident) @@ -2641,10 +2655,12 @@ impl<'tcx> UserTypeProjection<'tcx> { CloneTypeFoldableAndLiftImpls! { ProjectionKind<'tcx>, } impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { use crate::mir::ProjectionElem::*; - let base = self.base.fold_with(folder); + let base = self.base.fold_with(folder)?; let projs: Vec<_> = self.projs .iter() .map(|elem| { @@ -2656,10 +2672,10 @@ impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection<'tcx> { }}) .collect(); - UserTypeProjection { base, projs } + Ok(UserTypeProjection { base, projs }) } - fn super_visit_with>(&self, visitor: &mut Vs) -> bool { + fn super_visit_with>(&self, visitor: &mut Vs) -> Result<(), Vs::Error> { self.base.visit_with(visitor) // Note: there's nothing in `self.proj` to visit. } @@ -3132,7 +3148,9 @@ EnumTypeFoldableImpl! { } impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { use crate::mir::TerminatorKind::*; let kind = match self.kind { @@ -3143,8 +3161,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { ref values, ref targets, } => SwitchInt { - discr: discr.fold_with(folder), - switch_ty: switch_ty.fold_with(folder), + discr: discr.fold_with(folder)?, + switch_ty: switch_ty.fold_with(folder)?, values: values.clone(), targets: targets.clone(), }, @@ -3153,7 +3171,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { target, unwind, } => Drop { - location: location.fold_with(folder), + location: location.fold_with(folder)?, target, unwind, }, @@ -3163,8 +3181,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { target, unwind, } => DropAndReplace { - location: location.fold_with(folder), - value: value.fold_with(folder), + location: location.fold_with(folder)?, + value: value.fold_with(folder)?, target, unwind, }, @@ -3173,7 +3191,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { resume, drop, } => Yield { - value: value.fold_with(folder), + value: value.fold_with(folder)?, resume: resume, drop: drop, }, @@ -3186,11 +3204,12 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { } => { let dest = destination .as_ref() - .map(|&(ref loc, dest)| (loc.fold_with(folder), dest)); + .map(|&(ref loc, dest)| Ok((loc.fold_with(folder)?, dest))) + .transpose()?; Call { - func: func.fold_with(folder), - args: args.fold_with(folder), + func: func.fold_with(folder)?, + args: args.fold_with(folder)?, destination: dest, cleanup, from_hir_call, @@ -3205,14 +3224,14 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { } => { let msg = if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg { EvalErrorKind::BoundsCheck { - len: len.fold_with(folder), - index: index.fold_with(folder), + len: len.fold_with(folder)?, + index: index.fold_with(folder)?, } } else { msg.clone() }; Assert { - cond: cond.fold_with(folder), + cond: cond.fold_with(folder)?, expected, msg, target, @@ -3239,13 +3258,13 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { unwind, }, }; - Terminator { + Ok(Terminator { source_info: self.source_info, kind, - } + }) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { use crate::mir::TerminatorKind::*; match self.kind { @@ -3253,39 +3272,37 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { ref discr, switch_ty, .. - } => discr.visit_with(visitor) || switch_ty.visit_with(visitor), + } => { discr.visit_with(visitor)?; switch_ty.visit_with(visitor) } Drop { ref location, .. } => location.visit_with(visitor), DropAndReplace { ref location, ref value, .. - } => location.visit_with(visitor) || value.visit_with(visitor), + } => { location.visit_with(visitor)?; value.visit_with(visitor) }, Yield { ref value, .. } => value.visit_with(visitor), Call { ref func, ref args, ref destination, - .. + cleanup: _, + from_hir_call: _ } => { - let dest = if let Some((ref loc, _)) = *destination { - loc.visit_with(visitor) - } else { - false + if let Some((ref loc, _bb)) = *destination { + loc.visit_with(visitor)? }; - dest || func.visit_with(visitor) || args.visit_with(visitor) + func.visit_with(visitor)?; + args.visit_with(visitor) } Assert { ref cond, ref msg, .. } => { - if cond.visit_with(visitor) { - if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg { - len.visit_with(visitor) || index.visit_with(visitor) - } else { - false - } - } else { - false + cond.visit_with(visitor)?; + if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg { + len.visit_with(visitor)?; + index.visit_with(visitor)?; } + + Ok(()) } Goto { .. } | Resume @@ -3294,114 +3311,109 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { | GeneratorDrop | Unreachable | FalseEdges { .. } - | FalseUnwind { .. } => false, + | FalseUnwind { .. } => Ok(()), } } } -impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - match self { - &Place::Projection(ref p) => Place::Projection(p.fold_with(folder)), - _ => self.clone(), - } +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { + (Place::Base)(base), + (Place::Projection)(projection), } +} - fn super_visit_with>(&self, visitor: &mut V) -> bool { - if let &Place::Projection(ref p) = self { - p.visit_with(visitor) - } else { - false - } +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for PlaceBase<'tcx> { + (PlaceBase::Local)(local), + (PlaceBase::Static)(statik), + (PlaceBase::Promoted)(promoted), } } impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { use crate::mir::Rvalue::*; - match *self { - Use(ref op) => Use(op.fold_with(folder)), - Repeat(ref op, len) => Repeat(op.fold_with(folder), len), + Ok(match *self { + Use(ref op) => Use(op.fold_with(folder)?), + Repeat(ref op, len) => Repeat(op.fold_with(folder)?, len), Ref(region, bk, ref place) => { - Ref(region.fold_with(folder), bk, place.fold_with(folder)) + Ref(region.fold_with(folder)?, bk, place.fold_with(folder)?) } - Len(ref place) => Len(place.fold_with(folder)), - Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)), + Len(ref place) => Len(place.fold_with(folder)?), + Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder)?, ty.fold_with(folder)?), BinaryOp(op, ref rhs, ref lhs) => { - BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)) + BinaryOp(op, rhs.fold_with(folder)?, lhs.fold_with(folder)?) } CheckedBinaryOp(op, ref rhs, ref lhs) => { - CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)) + CheckedBinaryOp(op, rhs.fold_with(folder)?, lhs.fold_with(folder)?) } - UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)), - Discriminant(ref place) => Discriminant(place.fold_with(folder)), - NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)), + UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)?), + Discriminant(ref place) => Discriminant(place.fold_with(folder)?), + NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)?), Aggregate(ref kind, ref fields) => { let kind = box match **kind { - AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)), + AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)?), AggregateKind::Tuple => AggregateKind::Tuple, AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt( def, v, - substs.fold_with(folder), - user_ty.fold_with(folder), + substs.fold_with(folder)?, + user_ty.fold_with(folder)?, n, ), AggregateKind::Closure(id, substs) => { - AggregateKind::Closure(id, substs.fold_with(folder)) + AggregateKind::Closure(id, substs.fold_with(folder)?) } AggregateKind::Generator(id, substs, movablity) => { - AggregateKind::Generator(id, substs.fold_with(folder), movablity) + AggregateKind::Generator(id, substs.fold_with(folder)?, movablity) } }; - Aggregate(kind, fields.fold_with(folder)) + Aggregate(kind, fields.fold_with(folder)?) } - } + }) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { use crate::mir::Rvalue::*; match *self { Use(ref op) => op.visit_with(visitor), Repeat(ref op, _) => op.visit_with(visitor), - Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor), + Ref(region, _, ref place) => { region.visit_with(visitor)?; place.visit_with(visitor) }, Len(ref place) => place.visit_with(visitor), - Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor), + Cast(_, ref op, ty) => { op.visit_with(visitor)?; ty.visit_with(visitor) }, BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => { - rhs.visit_with(visitor) || lhs.visit_with(visitor) + rhs.visit_with(visitor)?; + lhs.visit_with(visitor) } UnaryOp(_, ref val) => val.visit_with(visitor), Discriminant(ref place) => place.visit_with(visitor), NullaryOp(_, ty) => ty.visit_with(visitor), Aggregate(ref kind, ref fields) => { - (match **kind { - AggregateKind::Array(ty) => ty.visit_with(visitor), - AggregateKind::Tuple => false, + match **kind { + AggregateKind::Array(ty) => ty.visit_with(visitor)?, + AggregateKind::Tuple => {}, AggregateKind::Adt(_, _, substs, user_ty, _) => { - substs.visit_with(visitor) || user_ty.visit_with(visitor) + substs.visit_with(visitor)?; + user_ty.visit_with(visitor)?; } - AggregateKind::Closure(_, substs) => substs.visit_with(visitor), - AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor), - }) || fields.visit_with(visitor) + AggregateKind::Closure(_, substs) => substs.visit_with(visitor)?, + AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor)?, + } + fields.visit_with(visitor) } } } } -impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - match *self { - Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)), - Operand::Move(ref place) => Operand::Move(place.fold_with(folder)), - Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)), - } - } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - match *self { - Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor), - Operand::Constant(ref c) => c.visit_with(visitor), - } +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { + (Operand::Copy)(place), + (Operand::Move)(place), + (Operand::Constant)(c), } } @@ -3411,50 +3423,37 @@ where V: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>, { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { use crate::mir::ProjectionElem::*; - let base = self.base.fold_with(folder); + let base = self.base.fold_with(folder)?; let elem = match self.elem { Deref => Deref, - Field(f, ref ty) => Field(f, ty.fold_with(folder)), - Index(ref v) => Index(v.fold_with(folder)), + Field(f, ref ty) => Field(f, ty.fold_with(folder)?), + Index(ref v) => Index(v.fold_with(folder)?), ref elem => elem.clone(), }; - Projection { base, elem } + Ok(Projection { base, elem }) } - fn super_visit_with>(&self, visitor: &mut Vs) -> bool { + fn super_visit_with>(&self, visitor: &mut Vs) -> Result<(), Vs::Error> { use crate::mir::ProjectionElem::*; - self.base.visit_with(visitor) || match self.elem { + self.base.visit_with(visitor)?; + + match self.elem { Field(_, ref ty) => ty.visit_with(visitor), Index(ref v) => v.visit_with(visitor), - _ => false, + _ => Ok(()), } } } -impl<'tcx> TypeFoldable<'tcx> for Field { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _: &mut F) -> Self { - *self - } - fn super_visit_with>(&self, _: &mut V) -> bool { - false - } -} - -impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - Constant { - span: self.span.clone(), - ty: self.ty.fold_with(folder), - user_ty: self.user_ty.fold_with(folder), - literal: self.literal.fold_with(folder), - } - } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.ty.visit_with(visitor) || self.literal.visit_with(visitor) +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { + span, ty, user_ty, literal } } diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index e93351197fe47..6a3f51953be30 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -823,14 +823,16 @@ pub struct RegionReplacer<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - (match r { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { + Ok((match r { &ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(), _ => None, - }).unwrap_or_else(|| r.super_fold_with(self)) + }).unwrap_or_else(|| { let Ok(r) = r.super_fold_with(self); r })) } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 3eb49092fed1d..1a37d0b0493b0 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1393,14 +1393,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ParamToVarFolder<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result, !> { if let ty::Param(ty::ParamTy {name, ..}) = ty.sty { let infcx = self.infcx; - self.var_map.entry(ty).or_insert_with(|| + Ok(self.var_map.entry(ty).or_insert_with(|| infcx.next_ty_var( - TypeVariableOrigin::TypeParameterDefinition(DUMMY_SP, name))) + TypeVariableOrigin::TypeParameterDefinition(DUMMY_SP, name)))) } else { ty.super_fold_with(self) } @@ -1410,7 +1412,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.probe(|_| { let mut selcx = SelectionContext::new(self); - let cleaned_pred = pred.fold_with(&mut ParamToVarFolder { + let Ok(cleaned_pred) = pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() }); diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index ee7893a27de7d..62eff360b7ee2 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -1185,12 +1185,12 @@ where fn fold_ex_clause_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>( ex_clause: &chalk_engine::ExClause, folder: &mut F, - ) -> chalk_engine::ExClause; + ) -> Result, F::Error>; fn visit_ex_clause_with<'gcx: 'tcx, V: TypeVisitor<'tcx>>( ex_clause: &chalk_engine::ExClause, visitor: &mut V, - ) -> bool; + ) -> Result<(), V::Error>; } pub trait ChalkContextLift<'tcx> diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 72df12bc535a6..835c5cf497e81 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -315,17 +315,19 @@ impl<'a, 'b, 'gcx, 'tcx> AssociatedTypeNormalizer<'a, 'b, 'gcx, 'tcx> { if !value.has_projections() { value } else { - value.fold_with(self) + value.fold_with(self).unwrap_or_else(|e: !| e) } } } impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, 'b, 'gcx, 'tcx> { + type Error = !; + fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'tcx> { self.selcx.tcx() } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result, !> { // We don't want to normalize associated types that occur inside of region // binders, because they may contain bound regions, and we can't cope with that. // @@ -337,8 +339,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, // normalize it when we instantiate those bound regions (which // should occur eventually). - let ty = ty.super_fold_with(self); - match ty.sty { + let ty = ty.super_fold_with(self)?; + Ok(match ty.sty { ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*) // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal { @@ -359,7 +361,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, let generic_ty = self.tcx().type_of(def_id); let concrete_ty = generic_ty.subst(self.tcx(), substs); self.depth += 1; - let folded_ty = self.fold_ty(concrete_ty); + let folded_ty = self.fold_ty(concrete_ty)?; self.depth -= 1; folded_ty } @@ -393,10 +395,12 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, } _ => ty - } + }) } - fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> { + fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) + -> Result<&'tcx ty::LazyConst<'tcx>, !> + { if let ty::LazyConst::Unevaluated(def_id, substs) = *constant { let tcx = self.selcx.tcx().global_tcx(); if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) { @@ -411,7 +415,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { let substs = tcx.lift_to_global(&substs).unwrap(); let evaluated = evaluated.subst(tcx, substs); - return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated)); + return Ok(tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated))); } } } else { @@ -423,14 +427,14 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, promoted: None }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated)); + return Ok(tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated))); } } } } } } - constant + Ok(constant) } } diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 8a30c18d6e5f7..127997ff55389 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -54,7 +54,7 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { anon_depth: 0, }; - let value1 = value.fold_with(&mut normalizer); + let Ok(value1) = value.fold_with(&mut normalizer); if normalizer.error { Err(NoSolution) } else { @@ -78,23 +78,26 @@ struct QueryNormalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> { cause: &'cx ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, obligations: Vec>, + // FIXME: consider using a type folder error instead. error: bool, anon_depth: usize, } impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx> { + type Error = !; + fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'tcx> { self.infcx.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - let ty = ty.super_fold_with(self); + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result, !> { + let ty = ty.super_fold_with(self)?; match ty.sty { ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*) // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal { - Reveal::UserFacing => ty, + Reveal::UserFacing => Ok(ty), Reveal::All => { let recursion_limit = *self.tcx().sess.recursion_limit.get(); @@ -154,7 +157,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx // We don't expect ambiguity. if result.is_ambiguous() { self.error = true; - return ty; + return Ok(ty); } match self.infcx.instantiate_query_response_and_region_obligations( @@ -167,28 +170,30 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx debug!("QueryNormalizer: result = {:#?}", result); debug!("QueryNormalizer: obligations = {:#?}", obligations); self.obligations.extend(obligations); - return result.normalized_ty; + return Ok(result.normalized_ty); } Err(_) => { self.error = true; - return ty; + return Ok(ty); } } } Err(NoSolution) => { self.error = true; - ty + Ok(ty) } } } - _ => ty, + _ => Ok(ty), } } - fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> { + fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) + -> Result<&'tcx ty::LazyConst<'tcx>, !> + { if let ty::LazyConst::Unevaluated(def_id, substs) = *constant { let tcx = self.infcx.tcx.global_tcx(); if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) { @@ -203,7 +208,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { let substs = tcx.lift_to_global(&substs).unwrap(); let evaluated = evaluated.subst(tcx, substs); - return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated)); + return Ok(tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated))); } } } else { @@ -215,14 +220,14 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx promoted: None, }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated)); + return Ok(tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated))); } } } } } } - constant + Ok(constant) } } diff --git a/src/librustc/traits/query/normalize_erasing_regions.rs b/src/librustc/traits/query/normalize_erasing_regions.rs index 0c1252680c1db..72c9db926b778 100644 --- a/src/librustc/traits/query/normalize_erasing_regions.rs +++ b/src/librustc/traits/query/normalize_erasing_regions.rs @@ -33,10 +33,11 @@ impl<'cx, 'tcx> TyCtxt<'cx, 'tcx, 'tcx> { if !value.has_projections() { value } else { - value.fold_with(&mut NormalizeAfterErasingRegionsFolder { + let Ok(t) = value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env: param_env, - }) + }); + t } } @@ -68,11 +69,13 @@ struct NormalizeAfterErasingRegionsFolder<'cx, 'tcx: 'cx> { } impl<'cx, 'tcx> TypeFolder<'tcx, 'tcx> for NormalizeAfterErasingRegionsFolder<'cx, 'tcx> { + type Error = !; + fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.tcx.normalize_ty_after_erasing_regions(self.param_env.and(ty)) + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result, !> { + Ok(self.tcx.normalize_ty_after_erasing_regions(self.param_env.and(ty))) } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index e7cc9618080c2..9b2a56cf0e8a0 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3684,7 +3684,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { previous_stack: TraitObligationStackList<'s, 'tcx>, obligation: &'o TraitObligation<'tcx>, ) -> TraitObligationStack<'o, 'tcx> { - let fresh_trait_ref = obligation + let Ok(fresh_trait_ref) = obligation .predicate .to_poly_trait_ref() .fold_with(&mut self.freshener); diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index b5be1777fa0d8..07ddcde12244f 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -303,14 +303,16 @@ impl BoundNamesCollector { } impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector { - fn visit_binder>(&mut self, t: &ty::Binder) -> bool { + type Error = !; + + fn visit_binder>(&mut self, t: &ty::Binder) -> Result<(), !> { 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::Ty<'tcx>) -> bool { + fn visit_ty(&mut self, t: ty::Ty<'tcx>) -> Result<(), !> { use syntax::symbol::Symbol; match t.sty { @@ -332,7 +334,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector { t.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Result<(), !> { use syntax::symbol::Symbol; match r { @@ -379,7 +381,7 @@ impl<'tcx> fmt::Display for traits::Goal<'tcx> { DomainGoal(goal) => write!(fmt, "{}", goal), Quantified(qkind, goal) => { let mut collector = BoundNamesCollector::new(); - goal.skip_binder().visit_with(&mut collector); + let Ok(_) = goal.skip_binder().visit_with(&mut collector); if !collector.is_empty() { write!(fmt, "{}<", qkind)?; @@ -426,7 +428,7 @@ impl<'tcx> fmt::Display for traits::Clause<'tcx> { Implies(clause) => write!(fmt, "{}", clause), ForAll(clause) => { let mut collector = BoundNamesCollector::new(); - clause.skip_binder().visit_with(&mut collector); + let Ok(_) = clause.skip_binder().visit_with(&mut collector); if !collector.is_empty() { write!(fmt, "forall<")?; @@ -757,17 +759,32 @@ where // TypeFoldable implementations. impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - traits::Obligation { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + Ok(traits::Obligation { cause: self.cause.clone(), recursion_depth: self.recursion_depth, - predicate: self.predicate.fold_with(folder), - param_env: self.param_env.fold_with(folder), - } + predicate: self.predicate.fold_with(folder)?, + param_env: self.param_env.fold_with(folder)?, + }) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.predicate.visit_with(visitor) + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + let traits::Obligation { + cause: _, + recursion_depth: _, + predicate, + /* HACK: visiting the param-env is a serious performance footgun because + * it can be very large and cause scalability problems. So just don't + * visit it. The code had never visited it, so I suppose it still hadn't + * bit anyone in a serious enough way, but it probably will one day. + * + * Maybe the permafix will be to have `Obligation` not be `TypeFoldable`? + */ + param_env: _, + } = self; + predicate.visit_with(visitor) } } @@ -890,25 +907,32 @@ EnumTypeFoldableImpl! { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { let v = self.iter() .map(|t| t.fold_with(folder)) - .collect::>(); - folder.tcx().intern_goals(&v) + .collect::, _>>()?; + Ok(folder.tcx().intern_goals(&v)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + for t in self.iter() { + t.visit_with(visitor)?; + } + Ok(()) } } impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { let v = (**self).fold_with(folder); - folder.tcx().mk_goal(v) + Ok(folder.tcx().mk_goal(v?)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { (**self).visit_with(visitor) } } @@ -944,15 +968,20 @@ BraceStructTypeFoldableImpl! { } impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { let v = self.iter() .map(|t| t.fold_with(folder)) - .collect::>(); - folder.tcx().intern_clauses(&v) + .collect::, _>>(); + Ok(folder.tcx().intern_clauses(&(v?))) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + for t in self.iter() { + t.visit_with(visitor)?; + } + Ok(()) } } @@ -962,14 +991,16 @@ where C::Substitution: Clone, C::RegionConstraint: Clone, { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { ::fold_ex_clause_with( self, folder, ) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { ::visit_ex_clause_with( self, visitor, diff --git a/src/librustc/ty/erase_regions.rs b/src/librustc/ty/erase_regions.rs index 0431afcc76c9e..ba18d7f4d90ea 100644 --- a/src/librustc/ty/erase_regions.rs +++ b/src/librustc/ty/erase_regions.rs @@ -11,7 +11,7 @@ pub(super) fn provide(providers: &mut ty::query::Providers<'_>) { fn erase_regions_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { // N.B., use `super_fold_with` here. If we used `fold_with`, it // could invoke the `erase_regions_ty` query recursively. - ty.super_fold_with(&mut RegionEraserVisitor { tcx }) + ty.super_fold_with(&mut RegionEraserVisitor { tcx }).unwrap_or_else(|e: !| e) } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { @@ -26,7 +26,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { return value.clone(); } - let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self }); + let Ok(value1) = value.fold_with(&mut RegionEraserVisitor { tcx: self }); debug!("erase_regions({:?}) = {:?}", value, value1); value1 } @@ -37,26 +37,28 @@ struct RegionEraserVisitor<'a, 'gcx: 'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraserVisitor<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result, !> { if let Some(ty_lifted) = self.tcx.lift_to_global(&ty) { - self.tcx.erase_regions_ty(ty_lifted) + Ok(self.tcx.erase_regions_ty(ty_lifted)) } else { ty.super_fold_with(self) } } - fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder + fn fold_binder(&mut self, t: &ty::Binder) -> Result, !> where T : TypeFoldable<'tcx> { let u = self.tcx.anonymize_late_bound_regions(t); u.super_fold_with(self) } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { // because late-bound regions affect subtyping, we can't // erase the bound/free distinction, but we can replace // all free regions with 'erased. @@ -65,9 +67,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionEraserVisitor<'a, 'gcx, 't // type system never "sees" those, they get substituted // away. In codegen, they will always be erased to 'erased // whenever a substitution occurs. - match *r { + Ok(match *r { ty::ReLateBound(..) => r, _ => self.tcx.types.re_erased - } + }) } } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index aa4d1e5ea90cb..ed25030e09295 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -33,6 +33,7 @@ use crate::hir::def_id::DefId; use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags}; +use crate::ty::subst::SubstsRef; use std::collections::BTreeMap; use std::fmt; @@ -44,13 +45,16 @@ use crate::util::nodemap::FxHashSet; /// To implement this conveniently, use the /// `BraceStructTypeFoldableImpl` etc macros found in `macros.rs`. pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self; - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>> + (&self, folder: &mut F) -> Result; + fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>> + (&self, folder: &mut F) -> Result + { self.super_fold_with(folder) } - fn super_visit_with>(&self, visitor: &mut V) -> bool; - fn visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error>; + fn visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { self.super_visit_with(visitor) } @@ -59,7 +63,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { /// If `binder` is `ty::INNERMOST`, this indicates whether /// there are any late-bound regions that appear free. fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { - self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }) + self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_err() } /// Returns `true` if this `self` has any regions that escape `binder` (and @@ -73,7 +77,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { } fn has_type_flags(&self, flags: TypeFlags) -> bool { - self.visit_with(&mut HasTypeFlagsVisitor { flags }) + self.visit_with(&mut HasTypeFlagsVisitor { flags }).is_err() } fn has_projections(&self) -> bool { self.has_type_flags(TypeFlags::HAS_PROJECTION) @@ -134,12 +138,17 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { pub struct Visitor(F); impl<'tcx, F: FnMut(Ty<'tcx>) -> bool> TypeVisitor<'tcx> for Visitor { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - self.0(ty) + type Error = (); + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Result<(), ()> { + match self.0(ty) { + true => Err(()), + false => Ok(()) + } } } - self.visit_with(&mut Visitor(visit)) + self.visit_with(&mut Visitor(visit)).is_err() } } @@ -149,41 +158,77 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { /// identity fold, it should invoke `foo.fold_with(self)` to fold each /// sub-item. pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { + type Error; + fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>; - fn fold_binder(&mut self, t: &Binder) -> Binder + fn fold_binder(&mut self, t: &Binder) -> Result, Self::Error> where T : TypeFoldable<'tcx> { t.super_fold_with(self) } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + #[inline] + /// If `false` - the default - then `ty::Invariant` might be used instead of the + /// correct variance when folding an item with a variance. + /// + /// Otherwise, the correct variance is looked up from the tcx, which can + /// be a performance and cycle hazard. + fn use_variances(&self) -> bool { + false + } + + #[inline] + fn fold_item_substs(&mut self, item_def_id: DefId, substs: SubstsRef<'tcx>) + -> Result, Self::Error> + { + if self.use_variances() { + let variances = self.tcx().variances_of(item_def_id); + ty::subst::fold_with_variances(self, &variances, substs) + } else { + substs.fold_with(self) + } + } + + #[inline] + fn fold_with_variance(&mut self, _variance: ty::Variance, t: &T) + -> Result + where T : TypeFoldable<'tcx> + { + t.fold_with(self) + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { t.super_fold_with(self) } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { r.super_fold_with(self) } - fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> { + fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) + -> Result<&'tcx ty::LazyConst<'tcx>, Self::Error> + { c.super_fold_with(self) } } pub trait TypeVisitor<'tcx> : Sized { - fn visit_binder>(&mut self, t: &Binder) -> bool { + type Error; + + fn visit_binder>(&mut self, t: &Binder) -> Result<(), Self::Error> { t.super_visit_with(self) } - fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Result<(), Self::Error> { t.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Result<(), Self::Error> { r.super_visit_with(self) } - fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool { + fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> Result<(), Self::Error> { c.super_visit_with(self) } } @@ -204,16 +249,18 @@ impl<'a, 'gcx, 'tcx, F, G> TypeFolder<'gcx, 'tcx> for BottomUpFolder<'a, 'gcx, ' where F: FnMut(Ty<'tcx>) -> Ty<'tcx>, G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>, { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - let t1 = ty.super_fold_with(self); - (self.fldop)(t1) + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result, !> { + let t1 = ty.super_fold_with(self)?; + Ok((self.fldop)(t1)) } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - let r = r.super_fold_with(self); - (self.reg_op)(r) + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { + let r = r.super_fold_with(self)?; + Ok((self.reg_op)(r)) } } @@ -249,7 +296,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { where T : TypeFoldable<'tcx>, { - value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f)) + let Ok(r) = value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f)); + r } /// Invoke `callback` on every region appearing free in `value`. @@ -282,7 +330,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { return value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback - }); + }).is_err(); struct RegionVisitor { /// The index of a binder *just outside* the things we have @@ -309,28 +357,33 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor where F: FnMut(ty::Region<'tcx>) -> bool { - fn visit_binder>(&mut self, t: &Binder) -> bool { + type Error = (); + + fn visit_binder>(&mut self, t: &Binder) -> Result<(), ()> { self.outer_index.shift_in(1); let result = t.skip_binder().visit_with(self); self.outer_index.shift_out(1); result } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Result<(), ()> { match *r { ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => { - false // ignore bound regions, keep visiting + Ok(()) // ignore bound regions, keep visiting + } + _ => match (self.callback)(r) { + true => Err(()), + false => Ok(()) } - _ => (self.callback)(r), } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Result<(), ()> { // We're only interested in types involving regions if ty.flags.intersects(TypeFlags::HAS_FREE_REGIONS) { ty.super_visit_with(self) } else { - false // keep visiting + Ok(()) // keep visiting } } } @@ -381,27 +434,31 @@ impl<'a, 'gcx, 'tcx> RegionFolder<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFolder<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: &ty::Binder) -> ty::Binder { + fn fold_binder>(&mut self, t: &ty::Binder) + -> Result, !> + { self.current_index.shift_in(1); let t = t.super_fold_with(self); self.current_index.shift_out(1); t } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { match *r { ty::ReLateBound(debruijn, _) if debruijn < self.current_index => { debug!("RegionFolder.fold_region({:?}) skipped bound region (current index={:?})", r, self.current_index); *self.skipped_regions = true; - r + Ok(r) } _ => { debug!("RegionFolder.fold_region({:?}) folding free region (current_index={:?})", r, self.current_index); - (self.fold_region_fn)(r, self.current_index) + Ok((self.fold_region_fn)(r, self.current_index)) } } } @@ -441,17 +498,21 @@ impl<'a, 'gcx, 'tcx> BoundVarReplacer<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: &ty::Binder) -> ty::Binder { + fn fold_binder>(&mut self, t: &ty::Binder) + -> Result, !> + { self.current_index.shift_in(1); let t = t.super_fold_with(self); self.current_index.shift_out(1); t } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.sty { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result, !> { + Ok(match t.sty { ty::Bound(debruijn, bound_ty) => { if debruijn == self.current_index { let fld_t = &mut self.fld_t; @@ -470,14 +531,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx> // Nothing more to substitute. t } else { - t.super_fold_with(self) + t.super_fold_with(self)? } } - } + }) } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { + Ok(match *r { ty::ReLateBound(debruijn, br) if debruijn == self.current_index => { let fld_r = &mut self.fld_r; let region = fld_r(br); @@ -493,7 +554,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx> } } _ => r - } + }) } } @@ -551,7 +612,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }; let mut replacer = BoundVarReplacer::new(self, &mut real_fld_r, &mut real_fld_t); - let result = value.fold_with(&mut replacer); + let Ok(result) = value.fold_with(&mut replacer); (result, region_map) } } @@ -612,8 +673,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { where T : TypeFoldable<'tcx> { let mut collector = LateBoundRegionsCollector::new(just_constraint); - let result = value.skip_binder().visit_with(&mut collector); - assert!(!result); // should never have stopped early + let Ok(_) = value.skip_binder().visit_with(&mut collector); collector.regions } @@ -678,17 +738,21 @@ impl Shifter<'a, 'gcx, 'tcx> { } impl TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: &ty::Binder) -> ty::Binder { + fn fold_binder>(&mut self, t: &ty::Binder) + -> Result, !> + { self.current_index.shift_in(1); let t = t.super_fold_with(self); self.current_index.shift_out(1); t } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { + Ok(match *r { ty::ReLateBound(debruijn, br) => { if self.amount == 0 || debruijn < self.current_index { r @@ -705,11 +769,11 @@ impl TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> { } } _ => r - } + }) } - fn fold_ty(&mut self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> { - match ty.sty { + fn fold_ty(&mut self, ty: ty::Ty<'tcx>) -> Result, !> { + Ok(match ty.sty { ty::Bound(debruijn, bound_ty) => { if self.amount == 0 || debruijn < self.current_index { ty @@ -727,8 +791,8 @@ impl TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> { } } - _ => ty.super_fold_with(self), - } + _ => ty.super_fold_with(self)?, + }) } } @@ -755,7 +819,7 @@ pub fn shift_vars<'a, 'gcx, 'tcx, T>( debug!("shift_vars(value={:?}, amount={})", value, amount); - value.fold_with(&mut Shifter::new(tcx, amount, Direction::In)) + value.fold_with(&mut Shifter::new(tcx, amount, Direction::In)).unwrap_or_else(|e: !| e) } pub fn shift_out_vars<'a, 'gcx, 'tcx, T>( @@ -766,7 +830,7 @@ pub fn shift_out_vars<'a, 'gcx, 'tcx, T>( debug!("shift_out_vars(value={:?}, amount={})", value, amount); - value.fold_with(&mut Shifter::new(tcx, amount, Direction::Out)) + value.fold_with(&mut Shifter::new(tcx, amount, Direction::Out)).unwrap_or_else(|e: !| e) } /// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a @@ -800,27 +864,35 @@ struct HasEscapingVarsVisitor { } impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { - fn visit_binder>(&mut self, t: &Binder) -> bool { + type Error = (); + + fn visit_binder>(&mut self, t: &Binder) -> Result<(), ()> { 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>) -> bool { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Result<(), ()> { // 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. - t.outer_exclusive_binder > self.outer_index + match t.outer_exclusive_binder > self.outer_index { + true => Err(()), + false => Ok(()) + } } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Result<(), ()> { // If the region is bound by `outer_index` or anything outside // of outer index, then it escapes the binders we have // visited. - r.bound_at_or_above_binder(self.outer_index) + match r.bound_at_or_above_binder(self.outer_index) { + true => Err(()), + false => Ok(()) + } } } @@ -829,23 +901,31 @@ struct HasTypeFlagsVisitor { } impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { - fn visit_ty(&mut self, t: Ty<'_>) -> bool { + type Error = (); + + fn visit_ty(&mut self, t: Ty<'_>) -> Result<(), ()> { debug!("HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}", t, t.flags, self.flags); - t.flags.intersects(self.flags) + match t.flags.intersects(self.flags) { + true => Err(()), + false => Ok(()) + } } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Result<(), ()> { let flags = r.type_flags(); debug!("HasTypeFlagsVisitor: r={:?} r.flags={:?} self.flags={:?}", r, flags, self.flags); - flags.intersects(self.flags) + match flags.intersects(self.flags) { + true => Err(()), + false => Ok(()) + } } - fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool { + fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> Result<(), ()> { if let ty::LazyConst::Unevaluated(..) = c { let projection_flags = TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION; if projection_flags.intersects(self.flags) { - return true; + return Err(()); } } c.super_visit_with(self) @@ -879,20 +959,22 @@ impl LateBoundRegionsCollector { } impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { - fn visit_binder>(&mut self, t: &Binder) -> bool { + type Error = !; + + fn visit_binder>(&mut self, t: &Binder) -> Result<(), !> { 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>) -> bool { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Result<(), !> { // 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 if self.just_constrained { match t.sty { - ty::Projection(..) | ty::Opaque(..) => { return false; } + ty::Projection(..) | ty::Opaque(..) => { return Ok(()); } _ => { } } } @@ -900,12 +982,12 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { t.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Result<(), !> { if let ty::ReLateBound(debruijn, br) = *r { if debruijn == self.current_index { self.regions.insert(br); } } - false + Ok(()) } } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 2940757fa905b..92a054ad98f63 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -8,9 +8,7 @@ use crate::hir::def_id::DefId; use crate::ty::subst::{Kind, UnpackedKind, SubstsRef}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use crate::ty::error::{ExpectedFound, TypeError}; -use crate::mir::interpret::GlobalId; use crate::util::common::ErrorReported; -use syntax_pos::DUMMY_SP; use std::rc::Rc; use std::iter; use rustc_target::spec::abi; @@ -468,42 +466,8 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => { let t = relation.relate(&a_t, &b_t)?; - let to_u64 = |x: ty::LazyConst<'tcx>| -> Result { - match x { - ty::LazyConst::Unevaluated(def_id, substs) => { - // FIXME(eddyb) get the right param_env. - let param_env = ty::ParamEnv::empty(); - if let Some(substs) = tcx.lift_to_global(&substs) { - let instance = ty::Instance::resolve( - tcx.global_tcx(), - param_env, - def_id, - substs, - ); - if let Some(instance) = instance { - let cid = GlobalId { - instance, - promoted: None - }; - if let Some(s) = tcx.const_eval(param_env.and(cid)) - .ok() - .map(|c| c.unwrap_usize(tcx)) { - return Ok(s) - } - } - } - tcx.sess.delay_span_bug(tcx.def_span(def_id), - "array length could not be evaluated"); - Err(ErrorReported) - } - ty::LazyConst::Evaluated(c) => c.assert_usize(tcx).ok_or_else(|| { - tcx.sess.delay_span_bug(DUMMY_SP, - "array length could not be evaluated"); - ErrorReported - }) - } - }; - match (to_u64(*sz_a), to_u64(*sz_b)) { + match (tcx.force_eval_array_length(*sz_a), + tcx.force_eval_array_length(*sz_b)) { (Ok(sz_a_u64), Ok(sz_b_u64)) => { if sz_a_u64 == sz_b_u64 { Ok(tcx.mk_ty(ty::Array(t, sz_a))) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index f1a465e1f1724..d87ad4e1a91fd 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -3,6 +3,7 @@ //! hand, though we've recently added some macros (e.g., //! `BraceStructLiftImpl!`) to help with the tedium. +use crate::hir; use crate::mir::ProjectionKind; use crate::mir::interpret::ConstValue; use crate::ty::{self, Lift, Ty, TyCtxt}; @@ -12,6 +13,7 @@ use smallvec::SmallVec; use crate::mir::interpret; use std::rc::Rc; +use std::iter; /////////////////////////////////////////////////////////////////////////// // Atomic structs @@ -39,6 +41,7 @@ CloneTypeFoldableAndLiftImpls! { ::rustc_target::spec::abi::Abi, crate::mir::Local, crate::mir::Promoted, + crate::mir::Field, crate::traits::Reveal, crate::ty::adjustment::AutoBorrowMutability, crate::ty::AdtKind, @@ -525,22 +528,27 @@ impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> { /// AdtDefs are basically the same as a DefId. impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self { - *self + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) + -> Result + { + Ok(*self) } - fn super_visit_with>(&self, _visitor: &mut V) -> bool { - false + fn super_visit_with>(&self, _visitor: &mut V) -> Result<(), V::Error> { + Ok(()) } } impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> (T, U) { - (self.0.fold_with(folder), self.1.fold_with(folder)) + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + Ok((self.0.fold_with(folder)?, self.1.fold_with(folder)?)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.0.visit_with(visitor) || self.1.visit_with(visitor) + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + self.0.visit_with(visitor)?; + self.1.visit_with(visitor) } } @@ -552,60 +560,81 @@ EnumTypeFoldableImpl! { } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - Rc::new((**self).fold_with(folder)) + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + Ok(Rc::new((**self).fold_with(folder)?)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { (**self).visit_with(visitor) } } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let content: T = (**self).fold_with(folder); - box content + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + let content: T = (**self).fold_with(folder)?; + Ok(box content) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { (**self).visit_with(visitor) } } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { self.iter().map(|t| t.fold_with(folder)).collect() } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + for t in self.iter() { + t.visit_with(visitor)?; + } + Ok(()) } } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - self.iter().map(|t| t.fold_with(folder)).collect::>().into_boxed_slice() - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + Ok(self.iter() + .map(|t| t.fold_with(folder)) + .collect::, _>>()? + .into_boxed_slice()) + } + + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + for t in self.iter() { + t.visit_with(visitor)?; + } + Ok(()) } } impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - self.map_bound_ref(|ty| ty.fold_with(folder)) + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + Ok(ty::Binder::bind(self.skip_binder().fold_with(folder)?)) } - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { folder.fold_binder(self) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { self.skip_binder().visit_with(visitor) } - fn visit_with>(&self, visitor: &mut V) -> bool { + fn visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { visitor.visit_binder(self) } } @@ -615,13 +644,18 @@ BraceStructTypeFoldableImpl! { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let v = self.iter().map(|p| p.fold_with(folder)).collect::>(); - folder.tcx().intern_existential_predicates(&v) + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + let v = self.iter().map(|p| p.fold_with(folder)).collect::, _>>()?; + Ok(folder.tcx().intern_existential_predicates(&v)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|p| p.visit_with(visitor)) + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + for t in self.iter() { + t.visit_with(visitor)?; + } + Ok(()) } } @@ -634,71 +668,85 @@ EnumTypeFoldableImpl! { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let v = self.iter().map(|t| t.fold_with(folder)).collect::>(); - folder.tcx().intern_type_list(&v) + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + let v = self.iter().map(|t| t.fold_with(folder)).collect::, _>>()?; + Ok(folder.tcx().intern_type_list(&v)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + for t in self.iter() { + t.visit_with(visitor)?; + } + Ok(()) } } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let v = self.iter().map(|t| t.fold_with(folder)).collect::>(); - folder.tcx().intern_projs(&v) + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + let v = self.iter().map(|t| t.fold_with(folder)).collect::, _>>()?; + Ok(folder.tcx().intern_projs(&v)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + for t in self.iter() { + t.visit_with(visitor)?; + } + Ok(()) } } impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { use crate::ty::InstanceDef::*; - Self { - substs: self.substs.fold_with(folder), + Ok(Self { + substs: self.substs.fold_with(folder)?, def: match self.def { - Item(did) => Item(did.fold_with(folder)), - VtableShim(did) => VtableShim(did.fold_with(folder)), - Intrinsic(did) => Intrinsic(did.fold_with(folder)), + Item(did) => Item(did.fold_with(folder)?), + VtableShim(did) => VtableShim(did.fold_with(folder)?), + Intrinsic(did) => Intrinsic(did.fold_with(folder)?), FnPtrShim(did, ty) => FnPtrShim( - did.fold_with(folder), - ty.fold_with(folder), + did.fold_with(folder)?, + ty.fold_with(folder)?, ), Virtual(did, i) => Virtual( - did.fold_with(folder), + did.fold_with(folder)?, i, ), ClosureOnceShim { call_once } => ClosureOnceShim { - call_once: call_once.fold_with(folder), + call_once: call_once.fold_with(folder)?, }, DropGlue(did, ty) => DropGlue( - did.fold_with(folder), - ty.fold_with(folder), + did.fold_with(folder)?, + ty.fold_with(folder)?, ), CloneShim(did, ty) => CloneShim( - did.fold_with(folder), - ty.fold_with(folder), + did.fold_with(folder)?, + ty.fold_with(folder)?, ), }, - } + }) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { use crate::ty::InstanceDef::*; - self.substs.visit_with(visitor) || + self.substs.visit_with(visitor)?; match self.def { Item(did) | VtableShim(did) | Intrinsic(did) | Virtual(did, _) => { did.visit_with(visitor) }, FnPtrShim(did, ty) | CloneShim(did, ty) => { - did.visit_with(visitor) || ty.visit_with(visitor) + did.visit_with(visitor)?; + ty.visit_with(visitor) }, DropGlue(did, ty) => { - did.visit_with(visitor) || ty.visit_with(visitor) + did.visit_with(visitor)?; + ty.visit_with(visitor) }, ClosureOnceShim { call_once } => call_once.visit_with(visitor), } @@ -706,48 +754,60 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - Self { - instance: self.instance.fold_with(folder), + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + Ok(Self { + instance: self.instance.fold_with(folder)?, promoted: self.promoted - } + }) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { self.instance.visit_with(visitor) } } impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { let sty = match self.sty { - ty::RawPtr(tm) => ty::RawPtr(tm.fold_with(folder)), - ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)), - ty::Slice(typ) => ty::Slice(typ.fold_with(folder)), - ty::Adt(tid, substs) => ty::Adt(tid, substs.fold_with(folder)), - ty::Dynamic(ref trait_ty, ref region) => - ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder)), - ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)), + ty::RawPtr(tm) => ty::RawPtr(tm.fold_with(folder)?), + ty::Array(typ, sz) => ty::Array(typ.fold_with(folder)?, sz.fold_with(folder)?), + ty::Slice(typ) => ty::Slice(typ.fold_with(folder)?), + ty::Adt(tid, substs) => { + ty::Adt(tid, folder.fold_item_substs(tid.did, substs)?) + } + ty::Dynamic(ref trait_ty, ref region) => { + let principal = trait_ty.fold_with(folder)?; + let region_bound = folder.fold_with_variance(ty::Contravariant, region)?; + ty::Dynamic(principal, region_bound) + } + ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)?), ty::FnDef(def_id, substs) => { - ty::FnDef(def_id, substs.fold_with(folder)) + ty::FnDef(def_id, folder.fold_item_substs(def_id, substs)?) } - ty::FnPtr(f) => ty::FnPtr(f.fold_with(folder)), + ty::FnPtr(f) => ty::FnPtr(f.fold_with(folder)?), ty::Ref(ref r, ty, mutbl) => { - ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl) + let r = folder.fold_with_variance(ty::Contravariant, r)?; + // Fold the type as a TypeAndMut to get the correct variance. + let mt = ty::TypeAndMut { ty, mutbl }.fold_with(folder)?; + ty::Ref(r, mt.ty, mt.mutbl) } ty::Generator(did, substs, movability) => { ty::Generator( did, - substs.fold_with(folder), + substs.fold_with(folder)?, movability) } - ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)), - ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)), - ty::Projection(ref data) => ty::Projection(data.fold_with(folder)), + ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)?), + ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)?), + ty::Projection(ref data) => ty::Projection(data.fold_with(folder)?), ty::UnnormalizedProjection(ref data) => { - ty::UnnormalizedProjection(data.fold_with(folder)) + ty::UnnormalizedProjection(data.fold_with(folder)?) } - ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)), + ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)?), ty::Bool | ty::Char | @@ -761,32 +821,34 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::Bound(..) | ty::Placeholder(..) | ty::Never | - ty::Foreign(..) => return self + ty::Foreign(..) => return Ok(self) }; if self.sty == sty { - self + Ok(self) } else { - folder.tcx().mk_ty(sty) + Ok(folder.tcx().mk_ty(sty)) } } - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { folder.fold_ty(*self) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { match self.sty { ty::RawPtr(ref tm) => tm.visit_with(visitor), - ty::Array(typ, sz) => typ.visit_with(visitor) || sz.visit_with(visitor), + ty::Array(typ, sz) => { typ.visit_with(visitor)?; sz.visit_with(visitor) } ty::Slice(typ) => typ.visit_with(visitor), ty::Adt(_, substs) => substs.visit_with(visitor), ty::Dynamic(ref trait_ty, ref reg) => - trait_ty.visit_with(visitor) || reg.visit_with(visitor), + { trait_ty.visit_with(visitor)?; reg.visit_with(visitor) } ty::Tuple(ts) => ts.visit_with(visitor), ty::FnDef(_, substs) => substs.visit_with(visitor), ty::FnPtr(ref f) => f.visit_with(visitor), - ty::Ref(r, ty, _) => r.visit_with(visitor) || ty.visit_with(visitor), + ty::Ref(r, ty, _) => { r.visit_with(visitor)?; ty.visit_with(visitor) }, ty::Generator(_did, ref substs, _) => { substs.visit_with(visitor) } @@ -809,18 +871,40 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::Placeholder(..) | ty::Param(..) | ty::Never | - ty::Foreign(..) => false, + ty::Foreign(..) => Ok(()), } } - fn visit_with>(&self, visitor: &mut V) -> bool { + fn visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { visitor.visit_ty(self) } } -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::TypeAndMut<'tcx> { - ty, mutbl + + +impl<'tcx> TypeFoldable<'tcx> for ty::TypeAndMut<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + let ty::TypeAndMut { ty, mutbl } = self; + let variance = match mutbl { + hir::Mutability::MutImmutable => ty::Covariant, + hir::Mutability::MutMutable => ty::Invariant, + }; + + Ok(ty::TypeAndMut { + ty: folder.fold_with_variance(variance, ty)?, + mutbl: mutbl.fold_with(folder)?, + }) + } + + fn super_visit_with>(&self, visitor: &mut V) + -> Result<(), V::Error> + { + let ty::TypeAndMut { ty, mutbl } = self; + + ty.visit_with(visitor)?; + mutbl.visit_with(visitor) } } @@ -830,9 +914,45 @@ BraceStructTypeFoldableImpl! { } } -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> { - inputs_and_output, c_variadic, unsafety, abi +impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + let ty::FnSig { inputs_and_output, c_variadic, unsafety, abi } = self; + + let inputs_and_output = if folder.use_variances() { + let inputs_and_output = self.inputs().iter().cloned() + .map(|x| (x, false)) + .chain(iter::once((self.output(), true))) + .map(|(a, is_output)| { + if is_output { + a.fold_with(folder) + } else { + folder.fold_with_variance(ty::Contravariant, &a) + } + }).collect::, _>>()?; + folder.tcx().intern_type_list(&inputs_and_output) + } else { + folder.fold_with_variance(ty::Invariant, inputs_and_output)? + }; + + Ok(ty::FnSig { + inputs_and_output, + c_variadic: *c_variadic, + unsafety: *unsafety, + abi: *abi, + }) + } + + fn super_visit_with>(&self, visitor: &mut V) + -> Result<(), V::Error> + { + let ty::FnSig { inputs_and_output, c_variadic, unsafety, abi } = self; + + inputs_and_output.visit_with(visitor)?; + c_variadic.visit_with(visitor)?; + unsafety.visit_with(visitor)?; + abi.visit_with(visitor) } } @@ -854,19 +974,23 @@ BraceStructTypeFoldableImpl! { } impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self { - *self + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) + -> Result + { + Ok(*self) } - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { folder.fold_region(*self) } - fn super_visit_with>(&self, _visitor: &mut V) -> bool { - false + fn super_visit_with>(&self, _visitor: &mut V) -> Result<(), V::Error> { + Ok(()) } - fn visit_with>(&self, visitor: &mut V) -> bool { + fn visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { visitor.visit_region(*self) } } @@ -923,13 +1047,18 @@ BraceStructTypeFoldableImpl! { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let v = self.iter().map(|p| p.fold_with(folder)).collect::>(); - folder.tcx().intern_predicates(&v) + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + let v = self.iter().map(|p| p.fold_with(folder)).collect::, _>>()?; + Ok(folder.tcx().intern_predicates(&v)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|p| p.visit_with(visitor)) + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + for t in self.iter() { + t.visit_with(visitor)?; + } + Ok(()) } } @@ -1008,12 +1137,17 @@ BraceStructTypeFoldableImpl! { } impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { self.iter().map(|x| x.fold_with(folder)).collect() } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + for t in self.iter() { + t.visit_with(visitor)?; + } + Ok(()) } } @@ -1043,53 +1177,62 @@ EnumTypeFoldableImpl! { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { let new = match self { - ty::LazyConst::Evaluated(v) => ty::LazyConst::Evaluated(v.fold_with(folder)), + ty::LazyConst::Evaluated(v) => ty::LazyConst::Evaluated(v.fold_with(folder)?), ty::LazyConst::Unevaluated(def_id, substs) => { - ty::LazyConst::Unevaluated(*def_id, substs.fold_with(folder)) + ty::LazyConst::Unevaluated(*def_id, substs.fold_with(folder)?) } }; - folder.tcx().mk_lazy_const(new) + Ok(folder.tcx().mk_lazy_const(new)) } - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { folder.fold_const(*self) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { match *self { ty::LazyConst::Evaluated(c) => c.visit_with(visitor), ty::LazyConst::Unevaluated(_, substs) => substs.visit_with(visitor), } } - fn visit_with>(&self, visitor: &mut V) -> bool { + fn visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { visitor.visit_const(self) } } impl<'tcx> TypeFoldable<'tcx> for ty::Const<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let ty = self.ty.fold_with(folder); - let val = self.val.fold_with(folder); - ty::Const { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + let ty = self.ty.fold_with(folder)?; + let val = self.val.fold_with(folder)?; + Ok(ty::Const { ty, val - } + }) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.ty.visit_with(visitor) || self.val.visit_with(visitor) + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + self.ty.visit_with(visitor)?; + self.val.visit_with(visitor) } } impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self { - *self + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) + -> Result + { + Ok(*self) } - fn super_visit_with>(&self, _visitor: &mut V) -> bool { - false + fn super_visit_with>(&self, _visitor: &mut V) -> Result<(), V::Error> { + Ok(()) } } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 450fab81661fc..2dbc84deea265 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -129,14 +129,16 @@ impl<'a, 'tcx> Lift<'tcx> for Kind<'a> { } impl<'tcx> TypeFoldable<'tcx> for Kind<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { match self.unpack() { - UnpackedKind::Lifetime(lt) => lt.fold_with(folder).into(), - UnpackedKind::Type(ty) => ty.fold_with(folder).into(), + UnpackedKind::Lifetime(lt) => lt.fold_with(folder).map(|a| a.into()), + UnpackedKind::Type(ty) => ty.fold_with(folder).map(|a| a.into()), } } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { match self.unpack() { UnpackedKind::Lifetime(lt) => lt.visit_with(visitor), UnpackedKind::Type(ty) => ty.visit_with(visitor), @@ -326,20 +328,48 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let params: SmallVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect(); + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { + let params = self.iter().map(|k| { + folder.fold_with_variance(ty::Invariant, k) + }).collect::, _>>()?; // If folding doesn't change the substs, it's faster to avoid // calling `mk_substs` and instead reuse the existing substs. if params[..] == self[..] { - self + Ok(self) } else { - folder.tcx().intern_substs(¶ms) + Ok(folder.tcx().intern_substs(¶ms)) + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + for t in self.iter() { + t.visit_with(visitor)?; } + Ok(()) } +} - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) +pub fn fold_with_variances<'gcx, 'tcx, F: TypeFolder<'gcx, 'tcx>>( + folder: &mut F, + variances: &[ty::Variance], + substs: SubstsRef<'tcx>) + -> Result, F::Error> +{ + assert_eq!(substs.len(), variances.len()); + + let params = substs.iter().zip(variances.iter()).map(|(k, v)| { + folder.fold_with_variance(*v, k) + }).collect::, _>>()?; + + // If folding doesn't change the substs, it's faster to avoid + // calling `mk_substs` and instead reuse the existing substs. + if params[..] == substs[..] { + Ok(substs) + } else { + Ok(folder.tcx().intern_substs(¶ms)) } } @@ -376,7 +406,8 @@ impl<'tcx, T:TypeFoldable<'tcx>> Subst<'tcx> for T { root_ty: None, ty_stack_depth: 0, binders_passed: 0 }; - (*self).fold_with(&mut folder) + let Ok(res) = (*self).fold_with(&mut folder); + res } } @@ -401,22 +432,26 @@ struct SubstFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: &ty::Binder) -> ty::Binder { + fn fold_binder>(&mut self, t: &ty::Binder) + -> Result, !> + { self.binders_passed += 1; let t = t.super_fold_with(self); self.binders_passed -= 1; t } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { // Note: This routine only handles regions that are bound on // type declarations and other outer declarations, not those // bound in *fn types*. Region substitution of the bound // regions that appear in a function signature is done using // the specialized routine `ty::replace_late_regions()`. - match *r { + Ok(match *r { ty::ReEarlyBound(data) => { let r = self.substs.get(data.index as usize).map(|k| k.unpack()); match r { @@ -437,12 +472,12 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { } } _ => r - } + }) } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result, !> { if !t.needs_subst() { - return t; + return Ok(t); } // track the root type we were asked to substitute @@ -454,7 +489,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { let t1 = match t.sty { ty::Param(p) => { - self.ty_for_param(p, t) + Ok(self.ty_for_param(p, t)) } _ => { t.super_fold_with(self) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 4ad3ffaa93da4..e9e31b436fbcb 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -14,6 +14,7 @@ use crate::ty::TyKind::*; use crate::ty::layout::{Integer, IntegerExt}; use crate::util::common::ErrorReported; use crate::middle::lang_items; +use crate::mir::interpret::GlobalId; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -660,7 +661,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } else if self.seen_opaque_tys.insert(def_id) { let generic_ty = self.tcx.type_of(def_id); let concrete_ty = generic_ty.subst(self.tcx, substs); - let expanded_ty = self.fold_ty(concrete_ty); + let Ok(expanded_ty) = self.fold_ty(concrete_ty); self.seen_opaque_tys.remove(&def_id); Some(expanded_ty) } else { @@ -673,13 +674,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpaqueTypeExpander<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> { self.tcx } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result, !> { if let ty::Opaque(def_id, substs) = t.sty { - self.expand_opaque_ty(def_id, substs).unwrap_or(t) + Ok(self.expand_opaque_ty(def_id, substs).unwrap_or(t)) } else { t.super_fold_with(self) } @@ -699,6 +702,42 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { Ok(expanded_type) } } + + pub fn force_eval_array_length(self, x: ty::LazyConst<'tcx>) -> Result { + match x { + ty::LazyConst::Unevaluated(def_id, substs) => { + // FIXME(eddyb) get the right param_env. + let param_env = ty::ParamEnv::empty(); + if let Some(substs) = self.lift_to_global(&substs) { + let instance = ty::Instance::resolve( + self.global_tcx(), + param_env, + def_id, + substs, + ); + if let Some(instance) = instance { + let cid = GlobalId { + instance, + promoted: None + }; + if let Some(s) = self.const_eval(param_env.and(cid)) + .ok() + .map(|c| c.unwrap_usize(self)) { + return Ok(s) + } + } + } + self.sess.delay_span_bug(self.def_span(def_id), + "array length could not be evaluated"); + Err(ErrorReported) + } + ty::LazyConst::Evaluated(c) => c.assert_usize(self).ok_or_else(|| { + self.sess.delay_span_bug(DUMMY_SP, + "array length could not be evaluated"); + ErrorReported + }) + } + } } impl<'a, 'tcx> ty::TyS<'tcx> { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index aecef3c5ec71e..f35bb3cd9a7f5 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -277,7 +277,9 @@ macro_rules! print { struct LateBoundRegionNameCollector(FxHashSet); impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { - fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { + type Error = !; + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Result<(), !> { match *r { ty::ReLateBound(_, ty::BrNamed(_, name)) => { self.0.insert(name); @@ -317,7 +319,7 @@ impl PrintContext { where T: TypeFoldable<'tcx> { let mut collector = LateBoundRegionNameCollector(Default::default()); - value.visit_with(&mut collector); + let Ok(()) = value.visit_with(&mut collector); self.used_region_names = Some(collector.0); self.region_index = 0; } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 550b333700b04..56327f45583ef 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -61,7 +61,7 @@ trait DefIdVisitor<'a, 'tcx: 'a> { } } fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> bool { - ty_fragment.visit_with(&mut self.skeleton()) + ty_fragment.visit_with(&mut self.skeleton()).is_err() } fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { self.skeleton().visit_trait(trait_ref) @@ -85,7 +85,7 @@ impl<'a, 'tcx, V> DefIdVisitorSkeleton<'_, 'a, 'tcx, V> fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { let TraitRef { def_id, substs } = trait_ref; self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) || - (!self.def_id_visitor.shallow() && substs.visit_with(self)) + (!self.def_id_visitor.shallow() && substs.visit_with(self).is_err()) } fn visit_predicates(&mut self, predicates: Lrc>) -> bool { @@ -101,7 +101,7 @@ impl<'a, 'tcx, V> DefIdVisitorSkeleton<'_, 'a, 'tcx, V> ty::Predicate::Projection(poly_predicate) => { let ty::ProjectionPredicate { projection_ty, ty } = *poly_predicate.skip_binder(); - if ty.visit_with(self) { + if ty.visit_with(self).is_err() { return true; } if self.visit_trait(projection_ty.trait_ref(self.def_id_visitor.tcx())) { @@ -110,7 +110,7 @@ impl<'a, 'tcx, V> DefIdVisitorSkeleton<'_, 'a, 'tcx, V> } ty::Predicate::TypeOutlives(poly_predicate) => { let ty::OutlivesPredicate(ty, _region) = *poly_predicate.skip_binder(); - if ty.visit_with(self) { + if ty.visit_with(self).is_err() { return true; } } @@ -125,7 +125,9 @@ impl<'a, 'tcx, V> DefIdVisitorSkeleton<'_, 'a, 'tcx, V> impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> where V: DefIdVisitor<'a, 'tcx> + ?Sized { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + type Error = (); + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Result<(), ()> { let tcx = self.def_id_visitor.tcx(); // InternalSubsts are not visited here because they are visited below in `super_visit_with`. match ty.sty { @@ -135,18 +137,16 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> ty::Closure(def_id, ..) | ty::Generator(def_id, ..) => { if self.def_id_visitor.visit_def_id(def_id, "type", ty) { - return true; + return Err(()); } if self.def_id_visitor.shallow() { - return false; + return Ok(()); } // Default type visitor doesn't visit signatures of fn types. // Something like `fn() -> Priv {my_func}` is considered a private type even if // `my_func` is public, so we need to visit signatures. if let ty::FnDef(..) = ty.sty { - if tcx.fn_sig(def_id).visit_with(self) { - return true; - } + tcx.fn_sig(def_id).visit_with(self)?; } // Inherent static methods don't have self type in substs. // Something like `fn() {my_method}` type of the method @@ -154,9 +154,7 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> // so we need to visit the self type additionally. if let Some(assoc_item) = tcx.opt_associated_item(def_id) { if let ty::ImplContainer(impl_def_id) = assoc_item.container { - if tcx.type_of(impl_def_id).visit_with(self) { - return true; - } + tcx.type_of(impl_def_id).visit_with(self)?; } } } @@ -167,10 +165,13 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> // as visible/reachable even if both `Type` and `Trait` are private. // Ideally, associated types should be substituted in the same way as // free type aliases, but this isn't done yet. - return false; + return Ok(()); } + // This will also visit substs if necessary, so we don't need to recurse. - return self.visit_trait(proj.trait_ref(tcx)); + if self.visit_trait(proj.trait_ref(tcx)) { + return Err(()); + } } ty::Dynamic(predicates, ..) => { // All traits in the list are considered the "primary" part of the type @@ -184,7 +185,7 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> }; let ty::ExistentialTraitRef { def_id, substs: _ } = trait_ref; if self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) { - return true; + return Err(()); } } } @@ -199,7 +200,7 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> // All traits in the list are considered the "primary" part of the type // and are visited by shallow visitors. if self.visit_predicates(tcx.predicates_of(def_id)) { - return true; + return Err(()); } } } @@ -214,7 +215,11 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> bug!("unexpected type: {:?}", ty), } - !self.def_id_visitor.shallow() && ty.super_visit_with(self) + if self.def_id_visitor.shallow() { + Ok(()) + } else { + ty.super_visit_with(self) + } } } diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs index a326d84725ab4..b38d3345e99f9 100644 --- a/src/librustc_traits/chalk_context/mod.rs +++ b/src/librustc_traits/chalk_context/mod.rs @@ -559,29 +559,30 @@ impl ExClauseFold<'tcx> for ChalkArenas<'tcx> { fn fold_ex_clause_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>( ex_clause: &ChalkExClause<'tcx>, folder: &mut F, - ) -> ChalkExClause<'tcx> { - ExClause { - subst: ex_clause.subst.fold_with(folder), - delayed_literals: ex_clause.delayed_literals.fold_with(folder), - constraints: ex_clause.constraints.fold_with(folder), - subgoals: ex_clause.subgoals.fold_with(folder), - } + ) -> Result, F::Error> { + Ok(ExClause { + subst: ex_clause.subst.fold_with(folder)?, + delayed_literals: ex_clause.delayed_literals.fold_with(folder)?, + constraints: ex_clause.constraints.fold_with(folder)?, + subgoals: ex_clause.subgoals.fold_with(folder)?, + }) } fn visit_ex_clause_with<'gcx: 'tcx, V: TypeVisitor<'tcx>>( ex_clause: &ExClause, visitor: &mut V, - ) -> bool { + ) -> Result<(), V::Error> { let ExClause { subst, delayed_literals, constraints, subgoals, } = ex_clause; - subst.visit_with(visitor) - || delayed_literals.visit_with(visitor) - || constraints.visit_with(visitor) - || subgoals.visit_with(visitor) + subst.visit_with(visitor)?; + delayed_literals.visit_with(visitor)?; + constraints.visit_with(visitor)?; + subgoals.visit_with(visitor)?; + Ok(()) } } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 860fa526a1b91..23d5671632b4d 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -481,10 +481,13 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>( }); // Now we build the substituted predicates. let default_obligations = predicates.predicates.iter().flat_map(|&(pred, _)| { + struct HasRegion; #[derive(Default)] struct CountParams { params: FxHashSet } impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { - fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { + type Error = HasRegion; + + fn visit_ty(&mut self, t: Ty<'tcx>) -> Result<(), HasRegion> { match t.sty { ty::Param(p) => { self.params.insert(p.idx); @@ -494,12 +497,12 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>( } } - fn visit_region(&mut self, _: ty::Region<'tcx>) -> bool { - true + fn visit_region(&mut self, _: ty::Region<'tcx>) -> Result<(), HasRegion> { + Err(HasRegion) } } let mut param_count = CountParams::default(); - let has_region = pred.visit_with(&mut param_count); + let has_region = pred.visit_with(&mut param_count).is_err(); let substituted_pred = pred.subst(fcx.tcx, substs); // Don't check non-defaulted params, dependent defaults (including lifetimes) // or preds with multiple params. @@ -602,7 +605,7 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>( ) -> Vec> { trace!("check_existential_types: {:?}, {:?}", ty, ty.sty); let mut substituted_predicates = Vec::new(); - ty.fold_with(&mut ty::fold::BottomUpFolder { + let Ok(_) = ty.fold_with(&mut ty::fold::BottomUpFolder { tcx: fcx.tcx, fldop: |ty| { if let ty::Opaque(def_id, substs) = ty.sty { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 5981d9bb66bfc..025dba5891231 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -553,7 +553,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } }, - }) + }).unwrap_or_else(|e: !| e) }; if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.sty { @@ -714,7 +714,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { where T: TypeFoldable<'tcx> + ty::Lift<'gcx>, { - let x = x.fold_with(&mut Resolver::new(self.fcx, span, self.body)); + let Ok(x) = x.fold_with(&mut Resolver::new(self.fcx, span, self.body)); if let Some(lifted) = self.tcx().lift_to_global(&x) { lifted } else { @@ -791,28 +791,30 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> { } impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Resolver<'cx, 'gcx, 'tcx> { + type Error = !; + fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result, !> { match self.infcx.fully_resolve(&t) { - Ok(t) => t, + Ok(t) => Ok(t), Err(_) => { debug!( "Resolver::fold_ty: input type `{:?}` not fully resolvable", t ); self.report_error(t); - self.tcx().types.err + Ok(self.tcx().types.err) } } } // FIXME This should be carefully checked // We could use `self.report_error` but it doesn't accept a ty::Region, right now. - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - self.infcx.fully_resolve(&r).unwrap_or(self.tcx.types.re_static) + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { + Ok(self.infcx.fully_resolve(&r).unwrap_or(self.tcx.types.re_static)) } } diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs index 6a530f454d2b3..d7c0311fe9a98 100644 --- a/src/librustc_typeck/constrained_type_params.rs +++ b/src/librustc_typeck/constrained_type_params.rs @@ -41,7 +41,7 @@ pub fn parameters_for<'tcx, T>(t: &T, parameters: vec![], include_nonconstraining, }; - t.visit_with(&mut collector); + let Ok(()) = t.visit_with(&mut collector); collector.parameters } @@ -51,11 +51,13 @@ struct ParameterCollector { } impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { - fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { + type Error = !; + + fn visit_ty(&mut self, t: Ty<'tcx>) -> Result<(), !> { match t.sty { ty::Projection(..) | ty::Opaque(..) if !self.include_nonconstraining => { // projections are not injective - return false; + return Ok(()); } ty::Param(data) => { self.parameters.push(Parameter::from(data)); @@ -66,11 +68,11 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { t.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Result<(), !> { if let ty::ReEarlyBound(data) = *r { self.parameters.push(Parameter::from(data)); } - false + Ok(()) } } diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index d07a4579ad5c3..c262c1ac35219 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -558,7 +558,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { } }) .map(|p| { - let replaced = p.fold_with(&mut replacer); + let Ok(replaced) = p.fold_with(&mut replacer); (replaced.clone(), replaced.clean(self.cx)) }); @@ -863,14 +863,16 @@ struct RegionReplacer<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> { + type Error = !; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - (match r { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { + Ok(match r { &ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(), _ => None, - }).unwrap_or_else(|| r.super_fold_with(self)) + }).transpose().unwrap_or_else(|| r.super_fold_with(self)) } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b3807d750b6ea..3d9d02bd7140f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -16,6 +16,8 @@ #![feature(const_fn)] #![feature(drain_filter)] #![feature(inner_deref)] +#![feature(never_type)] +#![feature(exhaustive_patterns)] #![recursion_limit="256"]