From e8601fe325417d365bc400588bbce8f5fd584291 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 7 Feb 2019 23:28:58 +0100 Subject: [PATCH 1/5] lift TypeFoldable over Result --- src/librustc/infer/canonical/canonicalizer.rs | 36 +- src/librustc/infer/freshen.rs | 20 +- src/librustc/infer/fudge.rs | 16 +- src/librustc/infer/mod.rs | 6 +- src/librustc/infer/nll_relate/mod.rs | 14 +- src/librustc/infer/opaque_types/mod.rs | 22 +- src/librustc/infer/resolve.rs | 51 +-- src/librustc/macros.rs | 62 ++-- src/librustc/mir/mod.rs | 206 ++++++------ src/librustc/traits/auto_trait.rs | 8 +- src/librustc/traits/error_reporting.rs | 10 +- src/librustc/traits/mod.rs | 4 +- src/librustc/traits/project.rs | 22 +- src/librustc/traits/query/normalize.rs | 29 +- .../traits/query/normalize_erasing_regions.rs | 11 +- src/librustc/traits/select.rs | 2 +- src/librustc/traits/structural_impls.rs | 61 ++-- src/librustc/ty/erase_regions.rs | 18 +- src/librustc/ty/fold.rs | 184 ++++++---- src/librustc/ty/structural_impls.rs | 313 +++++++++++------- src/librustc/ty/subst.rs | 45 ++- src/librustc/ty/util.rs | 8 +- src/librustc/util/ppaux.rs | 6 +- src/librustc_privacy/lib.rs | 41 ++- src/librustc_traits/chalk_context/mod.rs | 25 +- src/librustc_typeck/check/wfcheck.rs | 13 +- src/librustc_typeck/check/writeback.rs | 16 +- .../constrained_type_params.rs | 12 +- src/librustdoc/clean/auto_trait.rs | 10 +- src/librustdoc/lib.rs | 2 + 30 files changed, 721 insertions(+), 552 deletions(-) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index d06334c3ba643..e3d0ac37d4640 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -275,11 +275,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); @@ -288,8 +290,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") @@ -324,10 +326,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); @@ -345,29 +347,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(_)) @@ -375,18 +377,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) } } @@ -418,7 +420,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) } } } @@ -476,7 +478,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 @@ -618,7 +620,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/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 a61771b2a4eea..59a6827a9d686 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 { @@ -1277,7 +1277,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 @@ -1290,7 +1290,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..56d30575ebad4 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -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, @@ -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(()) } } diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 1f81321d22d6e..d3444521918bf 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 ccae9d3ad5a82..549d4d9c73c16 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 3513d652b5346..4c8ac8247cdc8 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2624,10 +2624,10 @@ 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| { @@ -2639,10 +2639,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. } @@ -3115,7 +3115,7 @@ 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 { @@ -3126,8 +3126,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(), }, @@ -3136,7 +3136,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { target, unwind, } => Drop { - location: location.fold_with(folder), + location: location.fold_with(folder)?, target, unwind, }, @@ -3146,8 +3146,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, }, @@ -3156,7 +3156,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, }, @@ -3169,11 +3169,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, @@ -3188,14 +3189,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, @@ -3222,13 +3223,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 { @@ -3236,39 +3237,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 @@ -3277,114 +3276,110 @@ 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 { + // TODO: this doesn't look correct! + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Result { match self { - &Place::Projection(ref p) => Place::Projection(p.fold_with(folder)), - _ => self.clone(), + &Place::Projection(ref p) => Ok(Place::Projection(p.fold_with(folder)?)), + _ => Ok(self.clone()), } } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { if let &Place::Projection(ref p) = self { p.visit_with(visitor) } else { - false + Ok(()) } } } 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), } } @@ -3394,50 +3389,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 - } -} +CloneTypeFoldableImpls! { Field, } -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 8957bbaa4ad7d..6f25ff3501d71 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -817,14 +817,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 eb284645d36c8..86cfcce3eed20 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1388,14 +1388,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) } @@ -1405,7 +1407,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 99d1e32d52398..f95e42b71fb52 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 5a44d886e3c0a..eb2a3bf5feb7e 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -312,17 +312,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. // @@ -334,8 +336,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 { @@ -356,7 +358,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 } @@ -390,10 +392,10 @@ 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) { @@ -408,7 +410,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 { @@ -420,14 +422,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 224076ce17e72..d6adc9cbcd7a3 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,28 @@ 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 +206,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 +218,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 c2c05ce7af50b..95966283a98b8 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3644,7 +3644,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..f6897cd145a36 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,16 +759,17 @@ 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 { + fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { + // TODO: re-add param-env self.predicate.visit_with(visitor) } } @@ -890,25 +893,28 @@ 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 +950,18 @@ 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 +971,14 @@ 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..27d6e3d38ff59 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -44,13 +44,13 @@ 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 +59,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 +73,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 +134,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 +154,45 @@ 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> { + 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 +213,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 +260,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 +294,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 +321,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 +398,29 @@ 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 +460,19 @@ 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 +491,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 +514,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx> } } _ => r - } + }) } } @@ -551,7 +572,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 +633,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 +698,19 @@ 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 +727,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 +749,8 @@ impl TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> { } } - _ => ty.super_fold_with(self), - } + _ => ty.super_fold_with(self)?, + }) } } @@ -755,7 +777,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 +788,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 +822,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 +859,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 +917,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 +940,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/structural_impls.rs b/src/librustc/ty/structural_impls.rs index d09cfa84a1690..8121c4ba72de4 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -519,22 +519,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) } } @@ -546,60 +551,78 @@ 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_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) -> 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 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) } } @@ -609,13 +632,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(()) } } @@ -628,71 +656,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), } @@ -700,48 +742,52 @@ 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::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::Dynamic(trait_ty.fold_with(folder)?, region.fold_with(folder)?), + 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, substs.fold_with(folder)?) } - 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) + ty::Ref(r.fold_with(folder)?, ty.fold_with(folder)?, 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 | @@ -755,32 +801,32 @@ 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) } @@ -803,11 +849,11 @@ 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) } } @@ -848,19 +894,21 @@ 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) } } @@ -917,13 +965,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(()) } } @@ -1002,12 +1055,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(()) } } @@ -1035,53 +1093,60 @@ 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 7559ea90b1782..4a25a7a3ffe62 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -129,14 +129,14 @@ 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), @@ -324,20 +324,26 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'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| k.fold_with(folder)) + .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) -> 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(()) } } @@ -374,7 +380,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 } } @@ -399,22 +406,24 @@ 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 { @@ -435,12 +444,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 @@ -452,7 +461,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 1ba7c3bba797c..ae1bf9e81d930 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -659,7 +659,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 { @@ -672,13 +672,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) } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 1cb9f47bb31f1..4ddf7f7bd3f8d 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 91651ad29dfa4..c327b74291ccc 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(); // Substs 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 86b2e0bfe8aef..286fa48766dcd 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -482,10 +482,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); @@ -495,12 +498,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. @@ -603,7 +606,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 e68c50d752bd5..2bb3f6398a254 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 { @@ -707,7 +707,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 { @@ -784,28 +784,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 b99181c0d4f9e..9544ef1026b85 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -556,7 +556,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)) }); @@ -860,14 +860,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 ddb730672d294..f20e99d5aaf67 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -15,6 +15,8 @@ #![feature(const_fn)] #![feature(drain_filter)] #![feature(inner_deref)] +#![feature(never_type)] +#![feature(exhaustive_patterns)] #![recursion_limit="256"] From 60dd5f705c91076e6ef0637dab0ff1c5945827c3 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 9 Feb 2019 22:36:11 +0100 Subject: [PATCH 2/5] add variance support to TypeFoldable --- src/librustc/ty/fold.rs | 30 ++++++++++ src/librustc/ty/structural_impls.rs | 90 +++++++++++++++++++++++++---- src/librustc/ty/subst.rs | 26 ++++++++- src/llvm-project | 2 +- 4 files changed, 134 insertions(+), 14 deletions(-) diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 27d6e3d38ff59..34985b3a9fe6c 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::Substs; use std::collections::BTreeMap; use std::fmt; @@ -164,6 +165,35 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { t.super_fold_with(self) } + #[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: &'tcx Substs<'tcx>) + -> Result<&'tcx Substs<'tcx>, 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) } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 8121c4ba72de4..b43555be8612f 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 @@ -764,16 +766,24 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { 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::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::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( @@ -858,9 +868,31 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { } } -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) } } @@ -870,9 +902,45 @@ BraceStructTypeFoldableImpl! { } } -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> { - inputs_and_output, 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, 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, + variadic: *variadic, + unsafety: *unsafety, + abi: *abi, + }) + } + + fn super_visit_with>(&self, visitor: &mut V) + -> Result<(), V::Error> + { + let ty::FnSig { inputs_and_output, variadic, unsafety, abi } = self; + + inputs_and_output.visit_with(visitor)?; + variadic.visit_with(visitor)?; + unsafety.visit_with(visitor)?; + abi.visit_with(visitor) } } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 4a25a7a3ffe62..8792ddc3e2997 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -327,8 +327,9 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Result { - let params = self.iter().map(|k| k.fold_with(folder)) - .collect::, _>>()?; + 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. @@ -347,6 +348,27 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> { } } +pub fn fold_with_variances<'gcx, 'tcx, F: TypeFolder<'gcx, 'tcx>>( + folder: &mut F, + variances: &[ty::Variance], + substs: &'tcx Substs<'tcx>) + -> Result<&'tcx Substs<'tcx>, 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)) + } +} + impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Substs<'tcx> {} /////////////////////////////////////////////////////////////////////////// diff --git a/src/llvm-project b/src/llvm-project index 73a75d35b9776..683d3522690b7 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 73a75d35b9776d56160fa3200aca4a970ae49b60 +Subproject commit 683d3522690b7a9d0163e7e7e6586f2b1364ed02 From cd23553e1ed116714fe2694dab89706d6a240dee Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 9 Feb 2019 22:36:21 +0100 Subject: [PATCH 3/5] use TypeFolder in generalization instead of Relate This kills the annoying `relate(a, a)` hack --- src/librustc/infer/combine.rs | 88 +++++++++++++--------------- src/librustc/infer/nll_relate/mod.rs | 68 ++++++++++----------- src/librustc/ty/relate.rs | 40 +------------ src/librustc/ty/util.rs | 37 ++++++++++++ 4 files changed, 114 insertions(+), 119 deletions(-) diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 361fbfea09798..f8e892aa493e8 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::Substs; +use crate::ty::relate::{RelateResult, TypeRelation}; use crate::traits::{Obligation, PredicateObligations}; +use crate::util::common::ErrorReported; use syntax::ast; use syntax_pos::Span; @@ -264,7 +264,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); @@ -332,60 +332,40 @@ 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: &'tcx Substs<'tcx>, - b_subst: &'tcx Substs<'tcx>) - -> RelateResult<'tcx, &'tcx Substs<'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); // Check to see whether the type we are genealizing references // any other type variable related to `vid` via // subtyping. This is basically our "occurs check", preventing @@ -403,7 +383,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' match variables.probe(vid) { TypeVariableValue::Known { value: u } => { drop(variables); - self.relate(&u, &u) + u.fold_with(self) } TypeVariableValue::Unknown { universe } => { match self.ambient_variance { @@ -423,7 +403,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(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); @@ -433,21 +413,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); match *r { // Never make variables for regions bound within the type itself, // nor for erased regions. diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index 56d30575ebad4..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; @@ -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) } } @@ -680,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(_)) @@ -746,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 { @@ -789,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 @@ -801,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 { @@ -840,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/ty/relate.rs b/src/librustc/ty/relate.rs index db248072d9b50..6a20e8737955e 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, Substs}; 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/util.rs b/src/librustc/ty/util.rs index ae1bf9e81d930..dd67cca0f9c56 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -13,6 +13,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}; @@ -700,6 +701,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> { From 4d14c6631dc3897cf44bbc9d2f3391c455340633 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 10 Feb 2019 20:03:09 +0200 Subject: [PATCH 4/5] shorten long lines --- src/librustc/infer/combine.rs | 3 ++- src/librustc/mir/mod.rs | 20 ++++++++++++++----- src/librustc/traits/project.rs | 4 +++- src/librustc/traits/query/normalize.rs | 4 +++- src/librustc/traits/structural_impls.rs | 20 ++++++++++++++----- src/librustc/ty/fold.rs | 26 ++++++++++++++++++------- src/librustc/ty/structural_impls.rs | 17 ++++++++++++---- src/librustc/ty/subst.rs | 8 ++++++-- 8 files changed, 76 insertions(+), 26 deletions(-) diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index f8e892aa493e8..762d72c4c665d 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -356,7 +356,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx, 'tcx> { -> RelateResult<'tcx, T> { let old_ambient_variance = self.ambient_variance; - debug!("Generalize: fold_with_variance({:?}, {:?}, old_variance={:?})", variance, a, old_ambient_variance); + debug!("Generalize: fold_with_variance({:?}, {:?}, old_variance={:?})", + variance, a, old_ambient_variance); self.ambient_variance = self.ambient_variance.xform(variance); let result = a.fold_with(self); diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 4c8ac8247cdc8..f2729f1759e23 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2624,7 +2624,9 @@ 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) -> Result { + 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)?; @@ -3115,7 +3117,9 @@ EnumTypeFoldableImpl! { } impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Result { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { use crate::mir::TerminatorKind::*; let kind = match self.kind { @@ -3283,7 +3287,9 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { // TODO: this doesn't look correct! - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Result { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { match self { &Place::Projection(ref p) => Ok(Place::Projection(p.fold_with(folder)?)), _ => Ok(self.clone()), @@ -3300,7 +3306,9 @@ impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Result { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { use crate::mir::Rvalue::*; Ok(match *self { Use(ref op) => Use(op.fold_with(folder)?), @@ -3389,7 +3397,9 @@ where V: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>, { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Result { + 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)?; diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index eb2a3bf5feb7e..cc658615d0a0f 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -395,7 +395,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, }) } - fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> Result<&'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) { diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index d6adc9cbcd7a3..c0bae9def9ebe 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -191,7 +191,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx } } - fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> Result<&'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) { diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index f6897cd145a36..2c07f3426f028 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -759,7 +759,9 @@ 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) -> Result { + 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, @@ -893,7 +895,9 @@ EnumTypeFoldableImpl! { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Result { + 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::, _>>()?; @@ -909,7 +913,9 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { } impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Result { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { let v = (**self).fold_with(folder); Ok(folder.tcx().mk_goal(v?)) } @@ -950,7 +956,9 @@ BraceStructTypeFoldableImpl! { } impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Result { + 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::, _>>(); @@ -971,7 +979,9 @@ where C::Substitution: Clone, C::RegionConstraint: Clone, { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Result { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) + -> Result + { ::fold_ex_clause_with( self, folder, diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 34985b3a9fe6c..d9972c3344af6 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -45,8 +45,11 @@ 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) -> Result; - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Result { + 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) } @@ -188,7 +191,8 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { } #[inline] - fn fold_with_variance(&mut self, _variance: ty::Variance, t: &T) -> Result + fn fold_with_variance(&mut self, _variance: ty::Variance, t: &T) + -> Result where T : TypeFoldable<'tcx> { t.fold_with(self) @@ -202,7 +206,9 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { r.super_fold_with(self) } - fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> Result<&'tcx ty::LazyConst<'tcx>, Self::Error> { + fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) + -> Result<&'tcx ty::LazyConst<'tcx>, Self::Error> + { c.super_fold_with(self) } } @@ -432,7 +438,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFolder<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: &ty::Binder) -> Result, !> { + 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); @@ -494,7 +502,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx> fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: &ty::Binder) -> Result, !> { + 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); @@ -732,7 +742,9 @@ impl TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: &ty::Binder) -> Result, !> { + 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); diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index b43555be8612f..95507428cf1b0 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -596,7 +596,10 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> { 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()) + Ok(self.iter() + .map(|t| t.fold_with(folder)) + .collect::, _>>()? + .into_boxed_slice()) } fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { @@ -821,7 +824,9 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { } } - fn 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 + { folder.fold_ty(*self) } @@ -968,7 +973,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> { Ok(*self) } - fn 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 + { folder.fold_region(*self) } @@ -1173,7 +1180,9 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> { Ok(folder.tcx().mk_lazy_const(new)) } - fn 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 + { folder.fold_const(*self) } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 8792ddc3e2997..eae664e713c72 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -129,7 +129,9 @@ 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) -> Result { + 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).map(|a| a.into()), UnpackedKind::Type(ty) => ty.fold_with(folder).map(|a| a.into()), @@ -432,7 +434,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - fn fold_binder>(&mut self, t: &ty::Binder) -> Result, !> { + fn fold_binder>(&mut self, t: &ty::Binder) + -> Result, !> + { self.binders_passed += 1; let t = t.super_fold_with(self); self.binders_passed -= 1; From 090f21e76559b4476133e40cdfa9262e266e2855 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 10 Feb 2019 20:36:18 +0200 Subject: [PATCH 5/5] fix some suspicious TypeFolder patterns --- src/librustc/mir/mod.rs | 33 ++++++++++--------------- src/librustc/traits/structural_impls.rs | 4 +-- src/librustc/ty/structural_impls.rs | 1 + 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index f2729f1759e23..45d3175b42676 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1906,12 +1906,18 @@ pub enum Place<'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 @@ -3285,23 +3291,12 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { - // TODO: this doesn't look correct! - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) - -> Result - { - match self { - &Place::Projection(ref p) => Ok(Place::Projection(p.fold_with(folder)?)), - _ => Ok(self.clone()), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { - if let &Place::Projection(ref p) = self { - p.visit_with(visitor) - } else { - Ok(()) - } +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { + (Place::Local)(local), + (Place::Static)(statik), + (Place::Promoted)(promoted), + (Place::Projection)(projection), } } @@ -3426,8 +3421,6 @@ where } } -CloneTypeFoldableImpls! { Field, } - BraceStructTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { span, ty, user_ty, literal diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 2c07f3426f028..b377c5bd325ba 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -771,8 +771,8 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx } fn super_visit_with>(&self, visitor: &mut V) -> Result<(), V::Error> { - // TODO: re-add param-env - self.predicate.visit_with(visitor) + self.predicate.visit_with(visitor)?; + self.param_env.visit_with(visitor) } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 95507428cf1b0..4149c4b929a2c 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -41,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,