From c5f0d0ebb4eca79491d30bfb6f32a4541faeaa25 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut <leseulartichaut@gmail.com> Date: Wed, 19 May 2021 13:20:39 +0200 Subject: [PATCH 1/9] Make `TypeFolder::fold_*` return `Result` --- compiler/rustc_middle/src/ty/fold.rs | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index e16491dcc90b2..a306656984f31 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -46,8 +46,8 @@ use std::ops::ControlFlow; /// /// To implement this conveniently, use the derive macro located in `rustc_macros`. pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self; - fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error>; + fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { self.super_fold_with(folder) } @@ -193,32 +193,43 @@ impl TypeFoldable<'tcx> for hir::Constness { /// identity fold, it should invoke `foo.fold_with(self)` to fold each /// sub-item. pub trait TypeFolder<'tcx>: Sized { + type Error = !; + fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; - fn fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> + fn fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, 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<Ty<'tcx>, 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<ty::Region<'tcx>, Self::Error> { r.super_fold_with(self) } - fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const( + &mut self, + c: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { c.super_fold_with(self) } - fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + fn fold_predicate( + &mut self, + p: ty::Predicate<'tcx>, + ) -> Result<ty::Predicate<'tcx>, Self::Error> { p.super_fold_with(self) } - fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + fn fold_mir_const( + &mut self, + c: mir::ConstantKind<'tcx>, + ) -> Result<mir::ConstantKind<'tcx>, Self::Error> { bug!("most type folders should not be folding MIR datastructures: {:?}", c) } } From 6e3fa20b00d5b3713848aa162969d7a460bd194a Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut <leseulartichaut@gmail.com> Date: Wed, 19 May 2021 13:34:54 +0200 Subject: [PATCH 2/9] Make `TypeFoldable` implementors short-circuit on error Co-authored-by: Alan Egerton <eggyal@gmail.com> --- compiler/rustc_data_structures/src/functor.rs | 70 ++++++- .../src/traits/structural_impls.rs | 10 +- compiler/rustc_macros/src/type_foldable.rs | 6 +- compiler/rustc_middle/src/macros.rs | 14 +- compiler/rustc_middle/src/mir/mod.rs | 10 +- .../rustc_middle/src/mir/type_foldable.rs | 175 +++++++++--------- compiler/rustc_middle/src/ty/fold.rs | 4 +- compiler/rustc_middle/src/ty/mod.rs | 7 +- .../rustc_middle/src/ty/structural_impls.rs | 162 ++++++++-------- compiler/rustc_middle/src/ty/sty.rs | 12 ++ compiler/rustc_middle/src/ty/subst.rs | 33 ++-- 11 files changed, 299 insertions(+), 204 deletions(-) diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs index 5b83ae3124766..1307c68ba0b18 100644 --- a/compiler/rustc_data_structures/src/functor.rs +++ b/compiler/rustc_data_structures/src/functor.rs @@ -2,12 +2,16 @@ use rustc_index::vec::{Idx, IndexVec}; use std::mem; use std::ptr; -pub trait IdFunctor { +pub trait IdFunctor: Sized { type Inner; fn map_id<F>(self, f: F) -> Self where F: FnMut(Self::Inner) -> Self::Inner; + + fn try_map_id<F, E>(self, f: F) -> Result<Self, E> + where + F: FnMut(Self::Inner) -> Result<Self::Inner, E>; } impl<T> IdFunctor for Box<T> { @@ -31,6 +35,25 @@ impl<T> IdFunctor for Box<T> { raw.assume_init() } } + + #[inline] + fn try_map_id<F, E>(self, mut f: F) -> Result<Self, E> + where + F: FnMut(Self::Inner) -> Result<Self::Inner, E>, + { + let raw = Box::into_raw(self); + Ok(unsafe { + // SAFETY: The raw pointer points to a valid value of type `T`. + let value = ptr::read(raw); + // SAFETY: Converts `Box<T>` to `Box<MaybeUninit<T>>` which is the + // inverse of `Box::assume_init()` and should be safe. + let mut raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast()); + // SAFETY: Write the mapped value back into the `Box`. + ptr::write(raw.as_mut_ptr(), f(value)?); + // SAFETY: We just initialized `raw`. + raw.assume_init() + }) + } } impl<T> IdFunctor for Vec<T> { @@ -55,6 +78,35 @@ impl<T> IdFunctor for Vec<T> { } self } + + #[inline] + fn try_map_id<F, E>(mut self, mut f: F) -> Result<Self, E> + where + F: FnMut(Self::Inner) -> Result<Self::Inner, E>, + { + // FIXME: We don't really care about panics here and leak + // far more than we should, but that should be fine for now. + let len = self.len(); + let mut error = Ok(()); + unsafe { + self.set_len(0); + let start = self.as_mut_ptr(); + for i in 0..len { + let p = start.add(i); + match f(ptr::read(p)) { + Ok(value) => ptr::write(p, value), + Err(err) => { + error = Err(err); + break; + } + } + } + // Even if we encountered an error, set the len back + // so we don't leak memory. + self.set_len(len); + } + error.map(|()| self) + } } impl<T> IdFunctor for Box<[T]> { @@ -67,6 +119,14 @@ impl<T> IdFunctor for Box<[T]> { { Vec::from(self).map_id(f).into() } + + #[inline] + fn try_map_id<F, E>(self, f: F) -> Result<Self, E> + where + F: FnMut(Self::Inner) -> Result<Self::Inner, E>, + { + Vec::from(self).try_map_id(f).map(Into::into) + } } impl<I: Idx, T> IdFunctor for IndexVec<I, T> { @@ -79,4 +139,12 @@ impl<I: Idx, T> IdFunctor for IndexVec<I, T> { { IndexVec::from_raw(self.raw.map_id(f)) } + + #[inline] + fn try_map_id<F, E>(self, f: F) -> Result<Self, E> + where + F: FnMut(Self::Inner) -> Result<Self::Inner, E>, + { + self.raw.try_map_id(f).map(IndexVec::from_raw) + } } diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index c4a2ecee096eb..1ce5f35691000 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -60,13 +60,13 @@ impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> { // TypeFoldable implementations. impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - traits::Obligation { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + Ok(traits::Obligation { cause: self.cause, 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<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs index 082af087bf49f..769f009b49206 100644 --- a/compiler/rustc_macros/src/type_foldable.rs +++ b/compiler/rustc_macros/src/type_foldable.rs @@ -17,7 +17,7 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:: vi.construct(|_, index| { let bind = &bindings[index]; quote! { - ::rustc_middle::ty::fold::TypeFoldable::fold_with(#bind, __folder) + ::rustc_middle::ty::fold::TypeFoldable::fold_with(#bind, __folder)? } }) }); @@ -28,8 +28,8 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:: fn super_fold_with<__F: ::rustc_middle::ty::fold::TypeFolder<'tcx>>( self, __folder: &mut __F - ) -> Self { - match self { #body_fold } + ) -> Result<Self, __F::Error> { + Ok(match self { #body_fold }) } fn super_visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>( diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index c0f2a76c19d6e..c0cf265b22879 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -55,8 +55,8 @@ macro_rules! TrivialTypeFoldableImpls { fn super_fold_with<F: $crate::ty::fold::TypeFolder<$tcx>>( self, _: &mut F - ) -> $ty { - self + ) -> ::std::result::Result<$ty, F::Error> { + Ok(self) } fn super_visit_with<F: $crate::ty::fold::TypeVisitor<$tcx>>( @@ -98,7 +98,7 @@ macro_rules! EnumTypeFoldableImpl { fn super_fold_with<V: $crate::ty::fold::TypeFolder<$tcx>>( self, folder: &mut V, - ) -> Self { + ) -> ::std::result::Result<Self, V::Error> { EnumTypeFoldableImpl!(@FoldVariants(self, folder) input($($variants)*) output()) } @@ -112,9 +112,9 @@ macro_rules! EnumTypeFoldableImpl { }; (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => { - match $this { + Ok(match $this { $($output)* - } + }) }; (@FoldVariants($this:expr, $folder:expr) @@ -126,7 +126,7 @@ macro_rules! EnumTypeFoldableImpl { output( $variant ( $($variant_arg),* ) => { $variant ( - $($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)),* + $($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)?),* ) } $($output)* @@ -145,7 +145,7 @@ macro_rules! EnumTypeFoldableImpl { $variant { $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with( $variant_arg, $folder - )),* } + )?),* } } $($output)* ) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 4210e07d2780b..a05b8a1da8d7f 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2760,11 +2760,11 @@ impl UserTypeProjection { TrivialTypeFoldableAndLiftImpls! { ProjectionKind, } impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - UserTypeProjection { - base: self.base.fold_with(folder), - projs: self.projs.fold_with(folder), - } + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + Ok(UserTypeProjection { + base: self.base.fold_with(folder)?, + projs: self.projs.fold_with(folder)?, + }) } fn super_visit_with<Vs: TypeVisitor<'tcx>>( diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index b7201f7acf392..df7c6d9cf6650 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -16,37 +16,39 @@ TrivialTypeFoldableAndLiftImpls! { } impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { use crate::mir::TerminatorKind::*; let kind = match self.kind { Goto { target } => Goto { target }, SwitchInt { discr, switch_ty, 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)?, targets, }, Drop { place, target, unwind } => { - Drop { place: place.fold_with(folder), target, unwind } + Drop { place: place.fold_with(folder)?, target, unwind } } DropAndReplace { place, value, target, unwind } => DropAndReplace { - place: place.fold_with(folder), - value: value.fold_with(folder), + place: place.fold_with(folder)?, + value: value.fold_with(folder)?, target, unwind, }, Yield { value, resume, resume_arg, drop } => Yield { - value: value.fold_with(folder), + value: value.fold_with(folder)?, resume, - resume_arg: resume_arg.fold_with(folder), + resume_arg: resume_arg.fold_with(folder)?, drop, }, Call { func, args, destination, cleanup, from_hir_call, fn_span } => { - let dest = destination.map(|(loc, dest)| (loc.fold_with(folder), dest)); + let dest = destination + .map(|(loc, dest)| (loc.fold_with(folder).map(|loc| (loc, 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, @@ -57,15 +59,15 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { use AssertKind::*; let msg = match msg { BoundsCheck { len, index } => { - BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) } + BoundsCheck { len: len.fold_with(folder)?, index: index.fold_with(folder)? } } - Overflow(op, l, r) => Overflow(op, l.fold_with(folder), r.fold_with(folder)), - OverflowNeg(op) => OverflowNeg(op.fold_with(folder)), - DivisionByZero(op) => DivisionByZero(op.fold_with(folder)), - RemainderByZero(op) => RemainderByZero(op.fold_with(folder)), + Overflow(op, l, r) => Overflow(op, l.fold_with(folder)?, r.fold_with(folder)?), + OverflowNeg(op) => OverflowNeg(op.fold_with(folder)?), + DivisionByZero(op) => DivisionByZero(op.fold_with(folder)?), + RemainderByZero(op) => RemainderByZero(op.fold_with(folder)?), ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg, }; - Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup } + Assert { cond: cond.fold_with(folder)?, expected, msg, target, cleanup } } GeneratorDrop => GeneratorDrop, Resume => Resume, @@ -78,13 +80,13 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind }, InlineAsm { template, operands, options, line_spans, destination } => InlineAsm { template, - operands: operands.fold_with(folder), + operands: operands.fold_with(folder)?, options, line_spans, destination, }, }; - Terminator { source_info: self.source_info, kind } + Ok(Terminator { source_info: self.source_info, kind }) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -140,8 +142,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for GeneratorKind { - fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self { - self + fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> { + Ok(self) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { @@ -150,8 +152,11 @@ impl<'tcx> TypeFoldable<'tcx> for GeneratorKind { } impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) } + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + Ok(Place { + local: self.local.fold_with(folder)?, + projection: self.projection.fold_with(folder)?, + }) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -161,7 +166,7 @@ impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v)) } @@ -171,47 +176,49 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> { } impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { use crate::mir::Rvalue::*; - match self { - Use(op) => Use(op.fold_with(folder)), - Repeat(op, len) => Repeat(op.fold_with(folder), len.fold_with(folder)), - ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)), - Ref(region, bk, place) => Ref(region.fold_with(folder), bk, place.fold_with(folder)), - AddressOf(mutability, place) => AddressOf(mutability, place.fold_with(folder)), - Len(place) => Len(place.fold_with(folder)), - Cast(kind, op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)), + Ok(match self { + Use(op) => Use(op.fold_with(folder)?), + Repeat(op, len) => Repeat(op.fold_with(folder)?, len.fold_with(folder)?), + ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)?), + Ref(region, bk, place) => Ref(region.fold_with(folder)?, bk, place.fold_with(folder)?), + AddressOf(mutability, place) => AddressOf(mutability, place.fold_with(folder)?), + Len(place) => Len(place.fold_with(folder)?), + Cast(kind, op, ty) => Cast(kind, op.fold_with(folder)?, ty.fold_with(folder)?), BinaryOp(op, box (rhs, lhs)) => { - BinaryOp(op, Box::new((rhs.fold_with(folder), lhs.fold_with(folder)))) + BinaryOp(op, Box::new((rhs.fold_with(folder)?, lhs.fold_with(folder)?))) } CheckedBinaryOp(op, box (rhs, lhs)) => { - CheckedBinaryOp(op, Box::new((rhs.fold_with(folder), lhs.fold_with(folder)))) + CheckedBinaryOp(op, Box::new((rhs.fold_with(folder)?, lhs.fold_with(folder)?))) } - UnaryOp(op, val) => UnaryOp(op, val.fold_with(folder)), - Discriminant(place) => Discriminant(place.fold_with(folder)), - NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)), + UnaryOp(op, val) => UnaryOp(op, val.fold_with(folder)?), + Discriminant(place) => Discriminant(place.fold_with(folder)?), + NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)?), Aggregate(kind, fields) => { - let kind = kind.map_id(|kind| match kind { - 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), - n, - ), - AggregateKind::Closure(id, substs) => { - AggregateKind::Closure(id, substs.fold_with(folder)) - } - AggregateKind::Generator(id, substs, movablity) => { - AggregateKind::Generator(id, substs.fold_with(folder), movablity) - } - }); - Aggregate(kind, fields.fold_with(folder)) + let kind = kind.try_map_id(|kind| { + Ok(match kind { + 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)?, + n, + ), + AggregateKind::Closure(id, substs) => { + AggregateKind::Closure(id, substs.fold_with(folder)?) + } + AggregateKind::Generator(id, substs, movablity) => { + AggregateKind::Generator(id, substs.fold_with(folder)?, movablity) + } + }) + })?; + Aggregate(kind, fields.fold_with(folder)?) } - ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder), ty.fold_with(folder)), - } + ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder)?, ty.fold_with(folder)?), + }) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -265,12 +272,12 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - match self { - Operand::Copy(place) => Operand::Copy(place.fold_with(folder)), - Operand::Move(place) => Operand::Move(place.fold_with(folder)), - Operand::Constant(c) => Operand::Constant(c.fold_with(folder)), - } + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + Ok(match self { + Operand::Copy(place) => Operand::Copy(place.fold_with(folder)?), + Operand::Move(place) => Operand::Move(place.fold_with(folder)?), + Operand::Constant(c) => Operand::Constant(c.fold_with(folder)?), + }) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -282,19 +289,19 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { use crate::mir::ProjectionElem::*; - match self { + Ok(match self { Deref => Deref, - Field(f, ty) => Field(f, ty.fold_with(folder)), - Index(v) => Index(v.fold_with(folder)), + Field(f, ty) => Field(f, ty.fold_with(folder)?), + Index(v) => Index(v.fold_with(folder)?), Downcast(symbol, variantidx) => Downcast(symbol, variantidx), ConstantIndex { offset, min_length, from_end } => { ConstantIndex { offset, min_length, from_end } } Subslice { from, to, from_end } => Subslice { from, to, from_end }, - } + }) } fn super_visit_with<Vs: TypeVisitor<'tcx>>( @@ -312,8 +319,8 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for Field { - fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self { - self + fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> { + Ok(self) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { ControlFlow::CONTINUE @@ -321,8 +328,8 @@ impl<'tcx> TypeFoldable<'tcx> for Field { } impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal { - fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self { - self + fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> { + Ok(self) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { ControlFlow::CONTINUE @@ -330,8 +337,8 @@ impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal { } impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self { - self + fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> { + Ok(self) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { ControlFlow::CONTINUE @@ -339,12 +346,12 @@ impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> { } impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - Constant { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + Ok(Constant { span: self.span, - user_ty: self.user_ty.fold_with(folder), - literal: self.literal.fold_with(folder), - } + user_ty: self.user_ty.fold_with(folder)?, + literal: self.literal.fold_with(folder)?, + }) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.literal.visit_with(visitor)?; @@ -354,14 +361,14 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> { #[inline(always)] - fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { folder.fold_mir_const(self) } - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { match self { - ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)), - ConstantKind::Val(v, t) => ConstantKind::Val(v, t.fold_with(folder)), + ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.fold_with(folder)?)), + ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.fold_with(folder)?)), } } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index a306656984f31..3b77b5a9d46d5 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -179,8 +179,8 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { } impl TypeFoldable<'tcx> for hir::Constness { - fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self { - self + fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> { + Ok(self) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { ControlFlow::CONTINUE diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 673733faa766f..2d6926703726c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1260,8 +1260,11 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> { - fn super_fold_with<F: ty::fold::TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - ParamEnv::new(self.caller_bounds().fold_with(folder), self.reveal().fold_with(folder)) + fn super_fold_with<F: ty::fold::TypeFolder<'tcx>>( + self, + folder: &mut F, + ) -> Result<Self, F::Error> { + Ok(ParamEnv::new(self.caller_bounds().fold_with(folder)?, self.reveal().fold_with(folder)?)) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 0f8e80806e31e..a2612df5a442f 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -669,8 +669,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> { /// AdtDefs are basically the same as a DefId. impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef { - fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Self { - self + fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> { + Ok(self) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -679,8 +679,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef { } impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> (T, U) { - (self.0.fold_with(folder), self.1.fold_with(folder)) + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<(T, U), F::Error> { + Ok((self.0.fold_with(folder)?, self.1.fold_with(folder)?)) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -692,8 +692,8 @@ impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>> TypeFoldable<'tcx> for (A, B, C) { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> (A, B, C) { - (self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder)) + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<(A, B, C), F::Error> { + Ok((self.0.fold_with(folder)?, self.1.fold_with(folder)?, self.2.fold_with(folder)?)) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -718,9 +718,9 @@ EnumTypeFoldableImpl! { } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { // FIXME: Reuse the `Rc` here. - Rc::new((*self).clone().fold_with(folder)) + Ok(Rc::new((*self).clone().fold_with(folder)?)) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -729,9 +729,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> { } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { // FIXME: Reuse the `Arc` here. - Arc::new((*self).clone().fold_with(folder)) + Ok(Arc::new((*self).clone().fold_with(folder)?)) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -740,8 +740,8 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> { } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - self.map_id(|value| value.fold_with(folder)) + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + self.try_map_id(|value| value.fold_with(folder)) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -750,8 +750,8 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> { } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - self.map_id(|t| t.fold_with(folder)) + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + self.try_map_id(|t| t.fold_with(folder)) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -760,8 +760,8 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> { } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - self.map_id(|t| t.fold_with(folder)) + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + self.try_map_id(|t| t.fold_with(folder)) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -770,11 +770,11 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> { } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - self.map_bound(|ty| ty.fold_with(folder)) + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + self.try_map_bound(|ty| ty.fold_with(folder)) } - fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { folder.fold_binder(self) } @@ -788,7 +788,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v)) } @@ -798,7 +798,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::Existentia } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)) } @@ -808,7 +808,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v)) } @@ -818,24 +818,24 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> { } impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { use crate::ty::InstanceDef::*; - Self { - substs: self.substs.fold_with(folder), + Ok(Self { + substs: self.substs.fold_with(folder)?, def: match self.def { - Item(def) => Item(def.fold_with(folder)), - VtableShim(did) => VtableShim(did.fold_with(folder)), - ReifyShim(did) => ReifyShim(did.fold_with(folder)), - Intrinsic(did) => Intrinsic(did.fold_with(folder)), - FnPtrShim(did, ty) => FnPtrShim(did.fold_with(folder), ty.fold_with(folder)), - Virtual(did, i) => Virtual(did.fold_with(folder), i), + Item(def) => Item(def.fold_with(folder)?), + VtableShim(did) => VtableShim(did.fold_with(folder)?), + ReifyShim(did) => ReifyShim(did.fold_with(folder)?), + Intrinsic(did) => Intrinsic(did.fold_with(folder)?), + FnPtrShim(did, ty) => FnPtrShim(did.fold_with(folder)?, ty.fold_with(folder)?), + Virtual(did, i) => Virtual(did.fold_with(folder)?, i), ClosureOnceShim { call_once, track_caller } => { - ClosureOnceShim { call_once: call_once.fold_with(folder), track_caller } + ClosureOnceShim { call_once: call_once.fold_with(folder)?, track_caller } } - DropGlue(did, ty) => DropGlue(did.fold_with(folder), ty.fold_with(folder)), - CloneShim(did, ty) => CloneShim(did.fold_with(folder), ty.fold_with(folder)), + DropGlue(did, ty) => DropGlue(did.fold_with(folder)?, ty.fold_with(folder)?), + CloneShim(did, ty) => CloneShim(did.fold_with(folder)?, ty.fold_with(folder)?), }, - } + }) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -860,8 +860,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - Self { instance: self.instance.fold_with(folder), promoted: self.promoted } + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + Ok(Self { instance: self.instance.fold_with(folder)?, promoted: self.promoted }) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -870,26 +870,26 @@ impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { let kind = match *self.kind() { - 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(trait_ty, region) => { - ty::Dynamic(trait_ty.fold_with(folder), region.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::FnPtr(f) => ty::FnPtr(f.fold_with(folder)), - ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl), + ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)?), + ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.fold_with(folder)?), + ty::FnPtr(f) => ty::FnPtr(f.fold_with(folder)?), + ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder)?, ty.fold_with(folder)?, mutbl), ty::Generator(did, substs, movability) => { - ty::Generator(did, substs.fold_with(folder), movability) + ty::Generator(did, 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(data) => ty::Projection(data.fold_with(folder)), - ty::Opaque(did, substs) => ty::Opaque(did, substs.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(data) => ty::Projection(data.fold_with(folder)?), + ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)?), ty::Bool | ty::Char @@ -903,13 +903,13 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { | ty::Bound(..) | ty::Placeholder(..) | ty::Never - | ty::Foreign(..) => return self, + | ty::Foreign(..) => return Ok(self), }; - if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) } + Ok(if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) }) } - fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { folder.fold_ty(self) } @@ -961,11 +961,11 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Self { - self + fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> { + Ok(self) } - fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { folder.fold_region(self) } @@ -979,13 +979,13 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { - fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { folder.fold_predicate(self) } - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - let new = self.inner.kind.fold_with(folder); - folder.tcx().reuse_or_mk_predicate(self, new) + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + let new = self.inner.kind.fold_with(folder)?; + Ok(folder.tcx().reuse_or_mk_predicate(self, new)) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -1006,7 +1006,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_predicates(v)) } @@ -1016,8 +1016,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> { } impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - self.map_id(|x| x.fold_with(folder)) + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + self.try_map_id(|x| x.fold_with(folder)) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -1026,17 +1026,17 @@ impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T> } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - let ty = self.ty.fold_with(folder); - let val = self.val.fold_with(folder); + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + let ty = self.ty.fold_with(folder)?; + let val = self.val.fold_with(folder)?; if ty != self.ty || val != self.val { - folder.tcx().mk_const(ty::Const { ty, val }) + Ok(folder.tcx().mk_const(ty::Const { ty, val })) } else { - self + Ok(self) } } - fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { folder.fold_const(self) } @@ -1051,16 +1051,16 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - match self { - ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)), - ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)), - ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)), + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + Ok(match self { + ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)?), + ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)?), + ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)?), ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) | ty::ConstKind::Error(_) => self, - } + }) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -1077,8 +1077,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Self { - self + fn super_fold_with<F: TypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> { + Ok(self) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -1090,7 +1090,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { ty::Unevaluated { def: self.def, - substs_: Some(self.substs(folder.tcx()).fold_with(folder)), + substs_: Some(self.substs(folder.tcx()).fold_with(folder)?), promoted: self.promoted, } } @@ -1115,7 +1115,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> { fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { ty::Unevaluated { def: self.def, - substs_: Some(self.substs(folder.tcx()).fold_with(folder)), + substs_: Some(self.substs(folder.tcx()).fold_with(folder)?), promoted: self.promoted, } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index c2b32cd06ea0a..fcbf15b3bca47 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1101,6 +1101,18 @@ impl<'tcx, T> Binder<'tcx, T> { Binder(value, self.1) } + pub fn try_map_bound<F, U: TypeFoldable<'tcx>, E>(self, f: F) -> Result<Binder<'tcx, U>, E> + where + F: FnOnce(T) -> Result<U, E>, + { + let value = f(self.0)?; + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(self.1); + value.visit_with(&mut validator); + } + Ok(Binder(value, self.1)) + } + /// Wraps a `value` in a binder, using the same bound variables as the /// current `Binder`. This should not be used if the new value *changes* /// the bound variables. Note: the (old or new) value itself does not diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 73a8e18949de0..67cf21a9556fa 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -153,11 +153,11 @@ impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> { } impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { match self.unpack() { - GenericArgKind::Lifetime(lt) => lt.fold_with(folder).into(), - GenericArgKind::Type(ty) => ty.fold_with(folder).into(), - GenericArgKind::Const(ct) => ct.fold_with(folder).into(), + GenericArgKind::Lifetime(lt) => lt.fold_with(folder).map(Into::into), + GenericArgKind::Type(ty) => ty.fold_with(folder).map(Into::into), + GenericArgKind::Const(ct) => ct.fold_with(folder).map(Into::into), } } @@ -372,7 +372,7 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { // This code is hot enough that it's worth specializing for the most // common length lists, to avoid the overhead of `SmallVec` creation. // The match arms are in order of frequency. The 1, 2, and 0 cases are @@ -381,22 +381,27 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { // calling `intern_substs`. match self.len() { 1 => { - let param0 = self[0].fold_with(folder); - if param0 == self[0] { self } else { folder.tcx().intern_substs(&[param0]) } + let param0 = self[0].fold_with(folder)?; + if param0 == self[0] { Ok(self) } else { Ok(folder.tcx().intern_substs(&[param0])) } } 2 => { - let param0 = self[0].fold_with(folder); - let param1 = self[1].fold_with(folder); + let param0 = self[0].fold_with(folder)?; + let param1 = self[1].fold_with(folder)?; if param0 == self[0] && param1 == self[1] { - self + Ok(self) } else { - folder.tcx().intern_substs(&[param0, param1]) + Ok(folder.tcx().intern_substs(&[param0, param1])) } } - 0 => self, + 0 => Ok(self), _ => { - let params: SmallVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect(); - if params[..] == self[..] { self } else { folder.tcx().intern_substs(¶ms) } + let params: SmallVec<[_; 8]> = + self.iter().map(|k| k.fold_with(folder)).collect::<Result<_, _>>()?; + if params[..] == self[..] { + Ok(self) + } else { + Ok(folder.tcx().intern_substs(¶ms)) + } } } } From 6dc3dae46f600efe75627a7ad386e7462066e34d Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut <leseulartichaut@gmail.com> Date: Wed, 19 May 2021 15:01:30 +0200 Subject: [PATCH 3/9] Adapt `TypeFolder` implementors to return a `Result` Co-authored-by: Alan Egerton <eggyal@gmail.com> --- .../src/infer/canonical/canonicalizer.rs | 49 +++++---- compiler/rustc_infer/src/infer/freshen.rs | 37 ++++--- compiler/rustc_infer/src/infer/fudge.rs | 33 +++--- compiler/rustc_infer/src/infer/mod.rs | 13 ++- compiler/rustc_infer/src/infer/resolve.rs | 57 ++++++---- compiler/rustc_middle/src/ty/erase_regions.rs | 17 +-- compiler/rustc_middle/src/ty/fold.rs | 92 +++++++++------- compiler/rustc_middle/src/ty/instance.rs | 10 +- .../src/ty/normalize_erasing_regions.rs | 18 ++- compiler/rustc_middle/src/ty/print/pretty.rs | 14 +-- .../rustc_middle/src/ty/structural_impls.rs | 12 +- compiler/rustc_middle/src/ty/subst.rs | 34 ++++-- compiler/rustc_middle/src/ty/util.rs | 36 +++--- .../rustc_trait_selection/src/opaque_types.rs | 33 +++--- .../src/traits/auto_trait.rs | 6 +- .../src/traits/error_reporting/mod.rs | 6 +- .../src/traits/project.rs | 104 ++++++++++-------- .../src/traits/query/normalize.rs | 38 ++++--- compiler/rustc_traits/src/chalk/lowering.rs | 34 +++--- compiler/rustc_typeck/src/check/op.rs | 6 +- compiler/rustc_typeck/src/check/writeback.rs | 25 +++-- compiler/rustc_typeck/src/collect/type_of.rs | 8 +- compiler/rustc_typeck/src/hir_wf_check.rs | 4 +- src/librustdoc/clean/auto_trait.rs | 6 +- 24 files changed, 387 insertions(+), 305 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 934ada9932e71..dd1f0d63aff05 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -278,7 +278,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { self.tcx } - fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> + fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> Result<ty::Binder<'tcx, T>, Self::Error> where T: TypeFoldable<'tcx>, { @@ -288,13 +288,13 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { t } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { match *r { ty::ReLateBound(index, ..) => { if index >= self.binder_index { bug!("escaping late-bound region during canonicalization"); } else { - r + Ok(r) } } @@ -311,7 +311,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { vid, r ); let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid)); - self.canonicalize_region_mode.canonicalize_free_region(self, r) + Ok(self.canonicalize_region_mode.canonicalize_free_region(self, r)) } ty::ReStatic @@ -319,11 +319,11 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { | ty::ReFree(_) | ty::ReEmpty(_) | ty::RePlaceholder(..) - | ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r), + | ty::ReErased => Ok(self.canonicalize_region_mode.canonicalize_free_region(self, r)), } } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { match *t.kind() { ty::Infer(ty::TyVar(vid)) => { debug!("canonical: type var found with vid {:?}", vid); @@ -339,40 +339,40 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { Err(mut ui) => { // 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::FreshIntTy(_) | ty::FreshFloatTy(_)) => { 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) } } @@ -403,13 +403,16 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { if t.flags().intersects(self.needs_canonical_flags) { t.super_fold_with(self) } else { - t + Ok(t) } } } } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const( + &mut self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { match ct.val { ty::ConstKind::Infer(InferConst::Var(vid)) => { debug!("canonical: const var found with vid {:?}", vid); @@ -424,10 +427,10 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { Err(mut ui) => { // FIXME: perf problem described in #55921. ui = ty::UniverseIndex::ROOT; - return self.canonicalize_const_var( + return Ok(self.canonicalize_const_var( CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) }, ct, - ); + )); } } } @@ -438,20 +441,20 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { if debruijn >= self.binder_index { bug!("escaping bound type during canonicalization") } else { - return ct; + return Ok(ct); } } ty::ConstKind::Placeholder(placeholder) => { - return self.canonicalize_const_var( + return Ok(self.canonicalize_const_var( CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderConst(placeholder) }, ct, - ); + )); } _ => {} } let flags = FlagComputation::for_const(ct); - if flags.intersects(self.needs_canonical_flags) { ct.super_fold_with(self) } else { ct } + if flags.intersects(self.needs_canonical_flags) { ct.super_fold_with(self) } else { Ok(ct) } } } diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index c40e409891bc2..fce6403575b79 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -119,11 +119,11 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { self.infcx.tcx } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { match *r { ty::ReLateBound(..) => { // leave bound regions alone - r + Ok(r) } ty::ReEarlyBound(..) @@ -133,21 +133,21 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { | ty::ReEmpty(_) | ty::ReErased => { // replace all free regions with 'erased - self.tcx().lifetimes.re_erased + Ok(self.tcx().lifetimes.re_erased) } ty::ReStatic => { if self.keep_static { - r + Ok(r) } else { - self.tcx().lifetimes.re_erased + Ok(self.tcx().lifetimes.re_erased) } } } } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { if !t.needs_infer() && !t.has_erasable_regions(self.tcx()) { - return t; + return Ok(t); } let tcx = self.infcx.tcx; @@ -155,10 +155,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { match *t.kind() { ty::Infer(ty::TyVar(v)) => { let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); - self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy) + Ok(self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy)) } - ty::Infer(ty::IntVar(v)) => self.freshen_ty( + ty::Infer(ty::IntVar(v)) => Ok(self.freshen_ty( self.infcx .inner .borrow_mut() @@ -167,9 +167,9 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { .map(|v| v.to_type(tcx)), ty::IntVar(v), ty::FreshIntTy, - ), + )), - ty::Infer(ty::FloatVar(v)) => self.freshen_ty( + ty::Infer(ty::FloatVar(v)) => Ok(self.freshen_ty( self.infcx .inner .borrow_mut() @@ -178,7 +178,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { .map(|v| v.to_type(tcx)), ty::FloatVar(v), ty::FreshFloatTy, - ), + )), ty::Infer(ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct)) => { if ct >= self.ty_freshen_count { @@ -189,7 +189,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { self.ty_freshen_count ); } - t + Ok(t) } ty::Generator(..) @@ -221,7 +221,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { } } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const( + &mut self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { match ct.val { ty::ConstKind::Infer(ty::InferConst::Var(v)) => { let opt_ct = self @@ -232,12 +235,12 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { .probe_value(v) .val .known(); - return self.freshen_const( + return Ok(self.freshen_const( opt_ct, ty::InferConst::Var(v), ty::InferConst::Fresh, ct.ty, - ); + )); } ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => { if i >= self.const_freshen_count { @@ -248,7 +251,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { self.const_freshen_count, ); } - return ct; + return Ok(ct); } ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs index 773753a036326..c889abf3d3c88 100644 --- a/compiler/rustc_infer/src/infer/fudge.rs +++ b/compiler/rustc_infer/src/infer/fudge.rs @@ -180,7 +180,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> { self.infcx.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { match *ty.kind() { ty::Infer(ty::InferTy::TyVar(vid)) => { if self.type_vars.0.contains(&vid) { @@ -188,7 +188,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> { // Recreate it with a fresh variable here. let idx = (vid.as_usize() - self.type_vars.0.start.as_usize()) as usize; let origin = self.type_vars.1[idx]; - self.infcx.next_ty_var(origin) + Ok(self.infcx.next_ty_var(origin)) } else { // This variable was created before the // "fudging". Since we refresh all type @@ -198,48 +198,43 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> { debug_assert!( self.infcx.inner.borrow_mut().type_variables().probe(vid).is_unknown() ); - ty + Ok(ty) } } ty::Infer(ty::InferTy::IntVar(vid)) => { - if self.int_vars.contains(&vid) { - self.infcx.next_int_var() - } else { - ty - } + Ok(if self.int_vars.contains(&vid) { self.infcx.next_int_var() } else { ty }) } ty::Infer(ty::InferTy::FloatVar(vid)) => { - if self.float_vars.contains(&vid) { - self.infcx.next_float_var() - } else { - ty - } + Ok(if self.float_vars.contains(&vid) { self.infcx.next_float_var() } else { ty }) } _ => ty.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<ty::Region<'tcx>, Self::Error> { if let ty::ReVar(vid) = *r { if self.region_vars.0.contains(&vid) { let idx = vid.index() - self.region_vars.0.start.index(); let origin = self.region_vars.1[idx]; - return self.infcx.next_region_var(origin); + return Ok(self.infcx.next_region_var(origin)); } } - r + Ok(r) } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const( + &mut self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { if let ty::Const { val: ty::ConstKind::Infer(ty::InferConst::Var(vid)), ty } = ct { if self.const_vars.0.contains(&vid) { // This variable was created during the fudging. // Recreate it with a fresh variable here. let idx = (vid.index - self.const_vars.0.start.index) as usize; let origin = self.const_vars.1[idx]; - self.infcx.next_const_var(ty, origin) + Ok(self.infcx.next_const_var(ty, origin)) } else { - ct + Ok(ct) } } else { ct.super_fold_with(self) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2fd01c2d595fa..afac40b0ebd0d 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1745,12 +1745,15 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> { self.infcx.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.infcx.shallow_resolve_ty(ty) + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { + Ok(self.infcx.shallow_resolve_ty(ty)) } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = ct { + fn fold_const( + &mut self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + Ok(if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = ct { self.infcx .inner .borrow_mut() @@ -1761,7 +1764,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> { .unwrap_or(ct) } else { ct - } + }) } } diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 4b08c2eb9c19e..d09c585a02598 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -30,25 +30,28 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> { self.infcx.tcx } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { if !t.has_infer_types_or_consts() { - 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 t = self.infcx.shallow_resolve(t); t.super_fold_with(self) } } - fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> { + fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> Result<&'tcx Const<'tcx>, Self::Error> { if !ct.has_infer_types_or_consts() { - ct // micro-optimize -- if there is nothing in this const that this fold affects... + Ok(ct) // micro-optimize -- if there is nothing in this const that this fold affects... } else { let ct = self.infcx.shallow_resolve(ct); ct.super_fold_with(self) } } - fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + fn fold_mir_const( + &mut self, + constant: mir::ConstantKind<'tcx>, + ) -> Result<mir::ConstantKind<'tcx>, Self::Error> { constant.super_fold_with(self) } } @@ -75,16 +78,16 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> { self.infcx.tcx } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { if !t.has_infer_regions() { - 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 { 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<ty::Region<'tcx>, Self::Error> { + Ok(match *r { ty::ReVar(rid) => { let resolved = self .infcx @@ -95,12 +98,15 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> { self.tcx().reuse_or_mk_region(r, ty::ReVar(resolved)) } _ => r, - } + }) } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const( + &mut self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { if !ct.has_infer_regions() { - ct // micro-optimize -- if there is nothing in this const that this fold affects... + Ok(ct) // micro-optimize -- if there is nothing in this const that this fold affects... } else { ct.super_fold_with(self) } @@ -195,23 +201,23 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { self.infcx.tcx } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { 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 t = self.infcx.shallow_resolve(t); match *t.kind() { ty::Infer(ty::TyVar(vid)) => { self.err = Some(FixupError::UnresolvedTy(vid)); - self.tcx().ty_error() + Ok(self.tcx().ty_error()) } ty::Infer(ty::IntVar(vid)) => { self.err = Some(FixupError::UnresolvedIntTy(vid)); - self.tcx().ty_error() + Ok(self.tcx().ty_error()) } ty::Infer(ty::FloatVar(vid)) => { self.err = Some(FixupError::UnresolvedFloatTy(vid)); - self.tcx().ty_error() + Ok(self.tcx().ty_error()) } ty::Infer(_) => { bug!("Unexpected type in full type resolver: {:?}", t); @@ -221,28 +227,31 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { } } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { match *r { - ty::ReVar(rid) => self + ty::ReVar(rid) => Ok(self .infcx .lexical_region_resolutions .borrow() .as_ref() .expect("region resolution not performed") - .resolve_var(rid), - _ => r, + .resolve_var(rid)), + _ => Ok(r), } } - fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const( + &mut self, + c: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { if !c.needs_infer() { - c // micro-optimize -- if there is nothing in this const that this fold affects... + Ok(c) // micro-optimize -- if there is nothing in this const that this fold affects... } else { let c = self.infcx.shallow_resolve(c); match c.val { ty::ConstKind::Infer(InferConst::Var(vid)) => { self.err = Some(FixupError::UnresolvedConst(vid)); - return self.tcx().const_error(c.ty); + return Ok(self.tcx().const_error(c.ty)); } ty::ConstKind::Infer(InferConst::Fresh(_)) => { bug!("Unexpected const in full const resolver: {:?}", c); diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 63eb55ed1a620..559534a7aa4e3 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -42,11 +42,11 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> { self.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if ty.needs_infer() { ty.super_fold_with(self) } else { self.tcx.erase_regions_ty(ty) } + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { + if ty.needs_infer() { ty.super_fold_with(self) } else { Ok(self.tcx.erase_regions_ty(ty)) } } - fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> + fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> Result<ty::Binder<'tcx, T>, Self::Error> where T: TypeFoldable<'tcx>, { @@ -54,7 +54,7 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> { 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<ty::Region<'tcx>, Self::Error> { // because late-bound regions affect subtyping, we can't // erase the bound/free distinction, but we can replace // all free regions with 'erased. @@ -64,12 +64,15 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> { // away. In codegen, they will always be erased to 'erased // whenever a substitution occurs. match *r { - ty::ReLateBound(..) => r, - _ => self.tcx.lifetimes.re_erased, + ty::ReLateBound(..) => Ok(r), + _ => Ok(self.tcx.lifetimes.re_erased), } } - fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + fn fold_mir_const( + &mut self, + c: mir::ConstantKind<'tcx>, + ) -> Result<mir::ConstantKind<'tcx>, Self::Error> { c.super_fold_with(self) } } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 3b77b5a9d46d5..639606f6b891e 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -301,19 +301,22 @@ where self.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - let t = ty.super_fold_with(self); - (self.ty_op)(t) + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { + let t = ty.super_fold_with(self)?; + Ok((self.ty_op)(t)) } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - let r = r.super_fold_with(self); - (self.lt_op)(r) + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { + let r = r.super_fold_with(self)?; + Ok((self.lt_op)(r)) } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - let ct = ct.super_fold_with(self); - (self.ct_op)(ct) + fn fold_const( + &mut self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + let ct = ct.super_fold_with(self)?; + Ok((self.ct_op)(ct)) } } @@ -481,7 +484,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { fn fold_binder<T: TypeFoldable<'tcx>>( &mut self, t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { + ) -> Result<ty::Binder<'tcx, T>, Self::Error> { self.current_index.shift_in(1); let t = t.super_fold_with(self); self.current_index.shift_out(1); @@ -489,16 +492,16 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { } #[instrument(skip(self), level = "debug")] - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { match *r { ty::ReLateBound(debruijn, _) if debruijn < self.current_index => { debug!(?self.current_index, "skipped bound region"); *self.skipped_regions = true; - r + Ok(r) } _ => { debug!(?self.current_index, "folding free region"); - (self.fold_region_fn)(r, self.current_index) + Ok((self.fold_region_fn)(r, self.current_index)) } } } @@ -539,19 +542,19 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> { fn fold_binder<T: TypeFoldable<'tcx>>( &mut self, t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { + ) -> Result<ty::Binder<'tcx, T>, Self::Error> { 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> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { match *t.kind() { ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => { if let Some(fld_t) = self.fld_t.as_mut() { let ty = fld_t(bound_ty); - return ty::fold::shift_vars(self.tcx, &ty, self.current_index.as_u32()); + return Ok(ty::fold::shift_vars(self.tcx, &ty, self.current_index.as_u32())); } } _ if t.has_vars_bound_at_or_above(self.current_index) => { @@ -559,10 +562,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> { } _ => {} } - t + Ok(t) } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { match *r { ty::ReLateBound(debruijn, br) if debruijn == self.current_index => { if let Some(fld_r) = self.fld_r.as_mut() { @@ -573,25 +576,28 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> { // debruijn index. Then we adjust it to the // correct depth. assert_eq!(debruijn1, ty::INNERMOST); - self.tcx.mk_region(ty::ReLateBound(debruijn, br)) + Ok(self.tcx.mk_region(ty::ReLateBound(debruijn, br))) } else { - region + Ok(region) }; } } _ => {} } - r + Ok(r) } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const( + &mut self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { match *ct { ty::Const { val: ty::ConstKind::Bound(debruijn, bound_const), ty } if debruijn == self.current_index => { if let Some(fld_c) = self.fld_c.as_mut() { let ct = fld_c(bound_const, ty); - return ty::fold::shift_vars(self.tcx, &ct, self.current_index.as_u32()); + return Ok(ty::fold::shift_vars(self.tcx, &ct, self.current_index.as_u32())); } } _ if ct.has_vars_bound_at_or_above(self.current_index) => { @@ -599,7 +605,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> { } _ => {} } - ct + Ok(ct) } } @@ -949,36 +955,36 @@ impl TypeFolder<'tcx> for Shifter<'tcx> { fn fold_binder<T: TypeFoldable<'tcx>>( &mut self, t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { + ) -> Result<ty::Binder<'tcx, T>, Self::Error> { 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<ty::Region<'tcx>, Self::Error> { match *r { ty::ReLateBound(debruijn, br) => { if self.amount == 0 || debruijn < self.current_index { - r + Ok(r) } else { let debruijn = debruijn.shifted_in(self.amount); let shifted = ty::ReLateBound(debruijn, br); - self.tcx.mk_region(shifted) + Ok(self.tcx.mk_region(shifted)) } } - _ => r, + _ => Ok(r), } } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { match *ty.kind() { ty::Bound(debruijn, bound_ty) => { if self.amount == 0 || debruijn < self.current_index { - ty + Ok(ty) } else { let debruijn = debruijn.shifted_in(self.amount); - self.tcx.mk_ty(ty::Bound(debruijn, bound_ty)) + Ok(self.tcx.mk_ty(ty::Bound(debruijn, bound_ty))) } } @@ -986,13 +992,18 @@ impl TypeFolder<'tcx> for Shifter<'tcx> { } } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const( + &mut self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty } = *ct { if self.amount == 0 || debruijn < self.current_index { - ct + Ok(ct) } else { let debruijn = debruijn.shifted_in(self.amount); - self.tcx.mk_const(ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty }) + Ok(self + .tcx + .mk_const(ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty })) } } else { ct.super_fold_with(self) @@ -1295,19 +1306,22 @@ impl<'tcx> TypeFolder<'tcx> for ExposeDefaultConstSubstsFolder<'tcx> { self.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { if ty.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) { ty.super_fold_with(self) } else { - ty + Ok(ty) } } - fn fold_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + fn fold_predicate( + &mut self, + pred: ty::Predicate<'tcx>, + ) -> Result<ty::Predicate<'tcx>, Self::Error> { if pred.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) { pred.super_fold_with(self) } else { - pred + Ok(pred) } } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 4b38105e44717..23863bf389e5a 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -622,7 +622,7 @@ fn polymorphize<'tcx>( self.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { debug!("fold_ty: ty={:?}", ty); match ty.kind { ty::Closure(def_id, substs) => { @@ -631,11 +631,11 @@ fn polymorphize<'tcx>( ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), substs, ); - if substs == polymorphized_substs { + Ok(if substs == polymorphized_substs { ty } else { self.tcx.mk_closure(def_id, polymorphized_substs) - } + }) } ty::Generator(def_id, substs, movability) => { let polymorphized_substs = polymorphize( @@ -643,11 +643,11 @@ fn polymorphize<'tcx>( ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), substs, ); - if substs == polymorphized_substs { + Ok(if substs == polymorphized_substs { ty } else { self.tcx.mk_generator(def_id, polymorphized_substs, movability) - } + }) } _ => ty.super_fold_with(self), } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 11399506b96e4..c5d845f97559d 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -103,18 +103,24 @@ impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> { self.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.normalize_generic_arg_after_erasing_regions(ty.into()).expect_ty() + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { + Ok(self.normalize_generic_arg_after_erasing_regions(ty.into()).expect_ty()) } - fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - self.normalize_generic_arg_after_erasing_regions(c.into()).expect_const() + fn fold_const( + &mut self, + c: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + Ok(self.normalize_generic_arg_after_erasing_regions(c.into()).expect_const()) } #[inline] - fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + fn fold_mir_const( + &mut self, + c: mir::ConstantKind<'tcx>, + ) -> Result<mir::ConstantKind<'tcx>, Self::Error> { // FIXME: This *probably* needs canonicalization too! let arg = self.param_env.and(c); - self.tcx.normalize_mir_const_after_erasing_regions(arg) + Ok(self.tcx.normalize_mir_const_after_erasing_regions(arg)) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 175295b3199e8..13c6b4d6b01ba 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2016,24 +2016,24 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { fn fold_binder<T: TypeFoldable<'tcx>>( &mut self, t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { + ) -> Result<ty::Binder<'tcx, T>, Self::Error> { 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> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { match *t.kind() { _ if t.has_vars_bound_at_or_above(self.current_index) || t.has_placeholders() => { return t.super_fold_with(self); } _ => {} } - t + Ok(t) } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { let name = &mut self.name; let region = match *r { ty::ReLateBound(_, br) => self.region_map.entry(br).or_insert_with(|| name(br)), @@ -2049,13 +2049,13 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { } } } - _ => return r, + _ => return Ok(r), }; if let ty::ReLateBound(debruijn1, br) = *region { assert_eq!(debruijn1, ty::INNERMOST); - self.tcx.mk_region(ty::ReLateBound(self.current_index, br)) + Ok(self.tcx.mk_region(ty::ReLateBound(self.current_index, br))) } else { - region + Ok(region) } } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index a2612df5a442f..ee6eed0f39b2d 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -1087,12 +1087,12 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - ty::Unevaluated { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + Ok(ty::Unevaluated { def: self.def, substs_: Some(self.substs(folder.tcx()).fold_with(folder)?), promoted: self.promoted, - } + }) } fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -1112,12 +1112,12 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> { - fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self { - ty::Unevaluated { + fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + Ok(ty::Unevaluated { def: self.def, substs_: Some(self.substs(folder.tcx()).fold_with(folder)?), promoted: self.promoted, - } + }) } fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 67cf21a9556fa..419cf164db3b6 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -465,14 +465,14 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { fn fold_binder<T: TypeFoldable<'tcx>>( &mut self, t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { + ) -> Result<ty::Binder<'tcx, T>, Self::Error> { self.binders_passed += 1; - let t = t.super_fold_with(self); + let t = t.super_fold_with(self)?; self.binders_passed -= 1; - t + Ok(t) } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { // 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 @@ -482,7 +482,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { ty::ReEarlyBound(data) => { let rk = self.substs.get(data.index as usize).map(|k| k.unpack()); match rk { - Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt), + Some(GenericArgKind::Lifetime(lt)) => Ok(self.shift_region_through_binders(lt)), _ => { let span = self.span.unwrap_or(DUMMY_SP); let msg = format!( @@ -494,31 +494,41 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { } } } - _ => r, + _ => Ok(r), } } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { if !t.potentially_needs_subst() { - return t; + return Ok(t); } match *t.kind() { - ty::Param(p) => self.ty_for_param(p, t), + ty::Param(p) => Ok(self.ty_for_param(p, t)), _ => t.super_fold_with(self), } } - fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const( + &mut self, + c: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + if !c.potentially_needs_subst() { + return Ok(c); + } + if let ty::ConstKind::Param(p) = c.val { - self.const_for_param(p, c) + Ok(self.const_for_param(p, c)) } else { c.super_fold_with(self) } } #[inline] - fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + fn fold_mir_const( + &mut self, + c: mir::ConstantKind<'tcx>, + ) -> Result<mir::ConstantKind<'tcx>, Self::Error> { c.super_fold_with(self) } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 6e7acb244d159..b90123b4cee82 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -605,13 +605,13 @@ impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> { self.tcx } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { if let ty::Opaque(def_id, substs) = t.kind { - self.expand_opaque_ty(def_id, substs).unwrap_or(t) + Ok(self.expand_opaque_ty(def_id, substs).unwrap_or(t)) } else if t.has_opaque_types() { t.super_fold_with(self) } else { - t + Ok(t) } } } @@ -1046,25 +1046,31 @@ pub fn fold_list<'tcx, F, T>( list: &'tcx ty::List<T>, folder: &mut F, intern: impl FnOnce(TyCtxt<'tcx>, &[T]) -> &'tcx ty::List<T>, -) -> &'tcx ty::List<T> +) -> Result<&'tcx ty::List<T>, F::Error> where F: TypeFolder<'tcx>, T: TypeFoldable<'tcx> + PartialEq + Copy, { let mut iter = list.iter(); // Look for the first element that changed - if let Some((i, new_t)) = iter.by_ref().enumerate().find_map(|(i, t)| { - let new_t = t.fold_with(folder); - if new_t == t { None } else { Some((i, new_t)) } + match iter.by_ref().enumerate().find_map(|(i, t)| match t.fold_with(folder) { + Ok(new_t) if new_t == t => None, + new_t => Some((i, new_t)), }) { - // An element changed, prepare to intern the resulting list - let mut new_list = SmallVec::<[_; 8]>::with_capacity(list.len()); - new_list.extend_from_slice(&list[..i]); - new_list.push(new_t); - new_list.extend(iter.map(|t| t.fold_with(folder))); - intern(folder.tcx(), &new_list) - } else { - list + Some((i, Ok(new_t))) => { + // An element changed, prepare to intern the resulting list + let mut new_list = SmallVec::<[_; 8]>::with_capacity(list.len()); + new_list.extend_from_slice(&list[..i]); + new_list.push(new_t); + for t in iter { + new_list.push(t.fold_with(folder)?) + } + Ok(intern(folder.tcx(), &new_list)) + } + Some((_, Err(err))) => { + return Err(err); + } + None => Ok(list), } } diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 75d57d78e3b02..eb7293ae86e69 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -140,17 +140,17 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { } #[instrument(skip(self), level = "debug")] - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { match r { // Ignore bound regions and `'static` regions that appear in the // type, we only need to remap regions that reference lifetimes // from the function declaraion. // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`. - ty::ReLateBound(..) | ty::ReStatic => return r, + ty::ReLateBound(..) | ty::ReStatic => return Ok(r), // If regions have been erased (by writeback), don't try to unerase // them. - ty::ReErased => return r, + ty::ReErased => return Ok(r), // The regions that we expect from borrow checking. ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {} @@ -165,10 +165,10 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { let generics = self.tcx().generics_of(self.opaque_type_def_id); match self.map.get(&r.into()).map(|k| k.unpack()) { - Some(GenericArgKind::Lifetime(r1)) => r1, + Some(GenericArgKind::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 => { - self.tcx.lifetimes.re_root_empty + Ok(self.tcx.lifetimes.re_root_empty) } None if generics.parent.is_some() => { if let Some(hidden_ty) = self.hidden_ty.take() { @@ -180,7 +180,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { ) .emit(); } - self.tcx.lifetimes.re_root_empty + Ok(self.tcx.lifetimes.re_root_empty) } None => { self.tcx @@ -196,12 +196,12 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { ) .emit(); - self.tcx().lifetimes.re_static + Ok(self.tcx().lifetimes.re_static) } } } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { match *ty.kind() { ty::Closure(def_id, substs) => { // I am a horrible monster and I pray for death. When @@ -239,7 +239,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { } })); - self.tcx.mk_closure(def_id, substs) + Ok(self.tcx.mk_closure(def_id, substs)) } ty::Generator(def_id, substs, movability) => { @@ -254,7 +254,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { } })); - self.tcx.mk_generator(def_id, substs, movability) + Ok(self.tcx.mk_generator(def_id, substs, movability)) } ty::Param(param) => { @@ -262,7 +262,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { match self.map.get(&ty.into()).map(|k| k.unpack()) { // Found it in the substitution list; replace with the parameter from the // opaque type. - Some(GenericArgKind::Type(t1)) => t1, + Some(GenericArgKind::Type(t1)) => Ok(t1), Some(u) => panic!("type mapped to unexpected kind: {:?}", u), None => { debug!(?param, ?self.map); @@ -278,7 +278,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { ) .emit(); - self.tcx().ty_error() + Ok(self.tcx().ty_error()) } } } @@ -287,10 +287,13 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { } } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const( + &mut self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { trace!("checking const {:?}", ct); // Find a const parameter - match ct.val { + Ok(match ct.val { ty::ConstKind::Param(..) => { // Look it up in the substitution list. match self.map.get(&ct.into()).map(|k| k.unpack()) { @@ -317,7 +320,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { } _ => ct, - } + }) } } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 54f7b91080dd9..7af32b2f3b174 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -860,11 +860,11 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, '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<ty::Region<'tcx>, Self::Error> { + 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(|| r.super_fold_with(self).into_ok())) } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index f8df0e2595973..1876b0ce80eed 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1898,15 +1898,15 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { self.infcx.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { if let ty::Param(ty::ParamTy { name, .. }) = *ty.kind() { 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 { kind: TypeVariableOriginKind::TypeParameterDefinition(name, None), span: DUMMY_SP, }) - }) + })) } else { ty.super_fold_with(self) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index b8c66931cbe52..2baa21a43d61d 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -352,16 +352,16 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { fn fold_binder<T: TypeFoldable<'tcx>>( &mut self, t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { + ) -> Result<ty::Binder<'tcx, T>, Self::Error> { self.universes.push(None); let t = t.super_fold_with(self); self.universes.pop(); t } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { if !needs_normalization(&ty, self.param_env.reveal()) { - return ty; + return Ok(ty); } // We try to be a little clever here as a performance optimization in @@ -387,14 +387,14 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { // replace bound vars if the current type is a `Projection` and we need // to make sure we don't forget to fold the substs regardless. - match *ty.kind() { + Ok(match *ty.kind() { // This is really important. While we *can* handle this, this has // severe performance implications for large opaque types with // late-bound regions. See `issue-88862` benchmark. 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.super_fold_with(self), + Reveal::UserFacing => ty.super_fold_with(self)?, Reveal::All => { let recursion_limit = self.tcx().recursion_limit(); @@ -408,11 +408,11 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { self.selcx.infcx().report_overflow_error(&obligation, true); } - let substs = substs.super_fold_with(self); + let substs = substs.super_fold_with(self)?; 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 } @@ -426,7 +426,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { // register an obligation to *later* project, since we know // there won't be bound vars there. - let data = data.super_fold_with(self); + let data = data.super_fold_with(self)?; let normalized_ty = normalize_projection_type( self.selcx, self.param_env, @@ -461,7 +461,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { let infcx = self.selcx.infcx(); let (data, mapped_regions, mapped_types, mapped_consts) = BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); - let data = data.super_fold_with(self); + let data = data.super_fold_with(self)?; let normalized_ty = opt_normalize_projection_type( self.selcx, self.param_env, @@ -473,16 +473,18 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { .ok() .flatten() .map(|normalized_ty| { - PlaceholderReplacer::replace_placeholders( - infcx, - mapped_regions, - mapped_types, - mapped_consts, - &self.universes, - normalized_ty, - ) + Ok({ + PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + normalized_ty, + ) + }) }) - .unwrap_or_else(|| ty.super_fold_with(self)); + .unwrap_or_else(|| ty.super_fold_with(self))?; debug!( ?self.depth, @@ -494,16 +496,19 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { normalized_ty } - _ => ty.super_fold_with(self), - } + _ => ty.super_fold_with(self)?, + }) } - fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const( + &mut self, + constant: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { if self.selcx.tcx().lazy_normalization() { - constant + Ok(constant) } else { - let constant = constant.super_fold_with(self); - constant.eval(self.selcx.tcx(), self.param_env) + let constant = constant.super_fold_with(self)?; + Ok(constant.eval(self.selcx.tcx(), self.param_env)) } } } @@ -577,14 +582,14 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { fn fold_binder<T: TypeFoldable<'tcx>>( &mut self, t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { + ) -> Result<ty::Binder<'tcx, T>, Self::Error> { 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<ty::Region<'tcx>, Self::Error> { match *r { ty::ReLateBound(debruijn, _) if debruijn.as_usize() + 1 @@ -596,13 +601,13 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { let universe = self.universe_for(debruijn); let p = ty::PlaceholderRegion { universe, name: br.kind }; self.mapped_regions.insert(p, br); - self.infcx.tcx.mk_region(ty::RePlaceholder(p)) + Ok(self.infcx.tcx.mk_region(ty::RePlaceholder(p))) } - _ => r, + _ => Ok(r), } } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { match *t.kind() { ty::Bound(debruijn, _) if debruijn.as_usize() + 1 @@ -614,14 +619,17 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { let universe = self.universe_for(debruijn); let p = ty::PlaceholderType { universe, name: bound_ty.var }; self.mapped_types.insert(p, bound_ty); - self.infcx.tcx.mk_ty(ty::Placeholder(p)) + Ok(self.infcx.tcx.mk_ty(ty::Placeholder(p))) } _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self), - _ => t, + _ => Ok(t), } } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const( + &mut self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { match *ct { ty::Const { val: ty::ConstKind::Bound(debruijn, _), ty: _ } if debruijn.as_usize() + 1 @@ -638,10 +646,10 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { name: ty::BoundConst { var: bound_const, ty }, }; self.mapped_consts.insert(p, bound_const); - self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty }) + Ok(self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty })) } _ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self), - _ => ct, + _ => Ok(ct), } } } @@ -685,9 +693,9 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> { fn fold_binder<T: TypeFoldable<'tcx>>( &mut self, t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { + ) -> Result<ty::Binder<'tcx, T>, Self::Error> { if !t.has_placeholders() && !t.has_infer_regions() { - return t; + return Ok(t); } self.current_index.shift_in(1); let t = t.super_fold_with(self); @@ -695,7 +703,7 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> { t } - fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r0: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { let r1 = match r0 { ty::ReVar(_) => self .infcx @@ -729,10 +737,10 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> { debug!(?r0, ?r1, ?r2, "fold_region"); - r2 + Ok(r2) } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { match *ty.kind() { ty::Placeholder(p) => { let replace_var = self.mapped_types.get(&p); @@ -746,18 +754,21 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> { let db = ty::DebruijnIndex::from_usize( self.universe_indices.len() - index + self.current_index.as_usize() - 1, ); - self.tcx().mk_ty(ty::Bound(db, *replace_var)) + Ok(self.tcx().mk_ty(ty::Bound(db, *replace_var))) } - None => ty, + None => Ok(ty), } } _ if ty.has_placeholders() || ty.has_infer_regions() => ty.super_fold_with(self), - _ => ty, + _ => Ok(ty), } } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const( + &mut self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { if let ty::Const { val: ty::ConstKind::Placeholder(p), ty } = *ct { let replace_var = self.mapped_consts.get(&p); match replace_var { @@ -770,10 +781,11 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> { let db = ty::DebruijnIndex::from_usize( self.universe_indices.len() - index + self.current_index.as_usize() - 1, ); - self.tcx() - .mk_const(ty::Const { val: ty::ConstKind::Bound(db, *replace_var), ty }) + Ok(self + .tcx() + .mk_const(ty::Const { val: ty::ConstKind::Bound(db, *replace_var), ty })) } - None => ct, + None => Ok(ct), } } else { ct.super_fold_with(self) diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 1364cf1c99535..f3a90935a9fdf 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -184,7 +184,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { fn fold_binder<T: TypeFoldable<'tcx>>( &mut self, t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { + ) -> Result<ty::Binder<'tcx, T>, Self::Error> { self.universes.push(None); let t = t.super_fold_with(self); self.universes.pop(); @@ -192,13 +192,13 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { if !needs_normalization(&ty, self.param_env.reveal()) { - return ty; + return Ok(ty); } if let Some(ty) = self.cache.get(&ty) { - return ty; + return Ok(ty); } // See note in `rustc_trait_selection::traits::project` about why we @@ -215,7 +215,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { Reveal::UserFacing => ty.super_fold_with(self), Reveal::All => { - let substs = substs.super_fold_with(self); + let substs = substs.super_fold_with(self)?; let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.anon_depth) { let obligation = Obligation::with_depth( @@ -252,7 +252,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { // we don't need to replace them with placeholders (see branch below). let tcx = self.infcx.tcx; - let data = data.super_fold_with(self); + let data = data.super_fold_with(self)?; let mut orig_values = OriginalQueryValues::default(); // HACK(matthewjasper) `'static` is special-cased in selection, @@ -280,7 +280,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { debug!("QueryNormalizer: result = {:#?}", result); debug!("QueryNormalizer: obligations = {:#?}", obligations); self.obligations.extend(obligations); - result.normalized_ty + Ok(result.normalized_ty) } Err(_) => { @@ -308,7 +308,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { &mut self.universes, data, ); - let data = data.super_fold_with(self); + let data = data.super_fold_with(self)?; let mut orig_values = OriginalQueryValues::default(); // HACK(matthewjasper) `'static` is special-cased in selection, @@ -335,14 +335,14 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { debug!("QueryNormalizer: result = {:#?}", result); debug!("QueryNormalizer: obligations = {:#?}", obligations); self.obligations.extend(obligations); - crate::traits::project::PlaceholderReplacer::replace_placeholders( + Ok(crate::traits::project::PlaceholderReplacer::replace_placeholders( infcx, mapped_regions, mapped_types, mapped_consts, &self.universes, result.normalized_ty, - ) + )) } Err(_) => { self.error = true; @@ -358,17 +358,23 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { } _ => ty.super_fold_with(self), - })(); + })()?; self.cache.insert(ty, res); - res + Ok(res) } - fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - let constant = constant.super_fold_with(self); - constant.eval(self.infcx.tcx, self.param_env) + fn fold_const( + &mut self, + constant: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + let constant = constant.super_fold_with(self)?; + Ok(constant.eval(self.infcx.tcx, self.param_env)) } - fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + fn fold_mir_const( + &mut self, + constant: mir::ConstantKind<'tcx>, + ) -> Result<mir::ConstantKind<'tcx>, Self::Error> { constant.super_fold_with(self) } } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index e24f699adf6b3..033a94658425b 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -943,20 +943,23 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> { self.tcx } - fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> { + fn fold_binder<T: TypeFoldable<'tcx>>( + &mut self, + t: Binder<'tcx, T>, + ) -> Result<Binder<'tcx, T>, Self::Error> { self.binder_index.shift_in(1); let result = t.super_fold_with(self); self.binder_index.shift_out(1); result } - fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { + fn fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, Self::Error> { match r { ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind { ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) { Some(idx) => { let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx) }; - return self.tcx.mk_region(RegionKind::ReLateBound(*index, new_br)); + return Ok(self.tcx.mk_region(RegionKind::ReLateBound(*index, new_br))); } None => panic!("Missing `BrNamed`."), }, @@ -999,32 +1002,35 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> { self.tcx } - fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> { + fn fold_binder<T: TypeFoldable<'tcx>>( + &mut self, + t: Binder<'tcx, T>, + ) -> Result<Binder<'tcx, T>, Self::Error> { self.binder_index.shift_in(1); let result = t.super_fold_with(self); self.binder_index.shift_out(1); result } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { match *t.kind() { // FIXME(chalk): currently we convert params to placeholders starting at // index `0`. To support placeholders, we'll actually need to do a // first pass to collect placeholders. Then we can insert params after. ty::Placeholder(_) => unimplemented!(), ty::Param(param) => match self.list.iter().position(|r| r == ¶m) { - Some(idx) => self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType { + Some(idx) => Ok(self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::from_usize(0), name: ty::BoundVar::from_usize(idx), - })), + }))), None => { self.list.push(param); let idx = self.list.len() - 1 + self.next_ty_placeholder; self.params.insert(idx, param); - self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType { + Ok(self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::from_usize(0), name: ty::BoundVar::from_usize(idx), - })) + }))) } }, @@ -1032,7 +1038,7 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> { } } - fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { + fn fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, Self::Error> { match r { // FIXME(chalk) - jackh726 - this currently isn't hit in any tests. // This covers any region variables in a goal, right? @@ -1042,14 +1048,14 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> { var: ty::BoundVar::from_u32(*idx), kind: ty::BrAnon(*idx), }; - self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)) + Ok(self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br))) } None => { let idx = self.named_regions.len() as u32; let br = ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) }; self.named_regions.insert(_re.def_id, idx); - self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br)) + Ok(self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br))) } }, @@ -1125,11 +1131,11 @@ impl<'tcx> TypeFolder<'tcx> for RegionsSubstitutor<'tcx> { self.tcx } - fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { + fn fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, Self::Error> { match r { ty::ReEmpty(ui) => { assert_eq!(ui.as_usize(), 0); - self.reempty_placeholder + Ok(self.reempty_placeholder) } _ => r.super_fold_with(self), diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index f83209f57a897..8f852c0b51c98 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -1015,12 +1015,12 @@ impl TypeFolder<'tcx> for TypeParamEraser<'_, 'tcx> { self.0.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { match ty.kind() { - ty::Param(_) => self.0.next_ty_var(TypeVariableOrigin { + ty::Param(_) => Ok(self.0.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span: self.1, - }), + })), _ => ty.super_fold_with(self), } } diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index fdc8b6b5e6451..ecf0332db7b8b 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -749,15 +749,15 @@ impl<'tcx> TypeFolder<'tcx> for EraseEarlyRegions<'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { if ty.has_type_flags(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) { ty.super_fold_with(self) } else { - ty + Ok(ty) } } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if let ty::ReLateBound(..) = r { r } else { self.tcx.lifetimes.re_erased } + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { + Ok(if let ty::ReLateBound(..) = r { r } else { self.tcx.lifetimes.re_erased }) } } @@ -766,7 +766,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { self.tcx } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { match self.infcx.fully_resolve(t) { Ok(t) => { // Do not anonymize late-bound regions @@ -779,18 +779,21 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t); self.report_type_error(t); self.replaced_with_error = true; - self.tcx().ty_error() + Ok(self.tcx().ty_error()) } } } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> { debug_assert!(!r.is_late_bound(), "Should not be resolving bound region."); - self.tcx.lifetimes.re_erased + Ok(self.tcx.lifetimes.re_erased) } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - match self.infcx.fully_resolve(ct) { + fn fold_const( + &mut self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + Ok(match self.infcx.fully_resolve(ct) { Ok(ct) => self.infcx.tcx.erase_regions(ct), Err(_) => { debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct); @@ -798,7 +801,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { self.replaced_with_error = true; self.tcx().const_error(ct.ty) } - } + }) } } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 04a68250ced0c..1dce63416dc96 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -729,17 +729,17 @@ fn infer_placeholder_type<'a>( self.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> { if !self.success { - return ty; + return Ok(ty); } match ty.kind() { - ty::FnDef(def_id, _) => self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id)), + ty::FnDef(def_id, _) => Ok(self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id))), // FIXME: non-capturing closures should also suggest a function pointer ty::Closure(..) | ty::Generator(..) => { self.success = false; - ty + Ok(ty) } _ => ty.super_fold_with(self), } diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_typeck/src/hir_wf_check.rs index a49eda6572de2..5c229c86ddc1a 100644 --- a/compiler/rustc_typeck/src/hir_wf_check.rs +++ b/compiler/rustc_typeck/src/hir_wf_check.rs @@ -183,7 +183,7 @@ impl<'tcx> TypeFolder<'tcx> for EraseAllBoundRegions<'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx } - fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { - if let ty::ReLateBound(..) = r { &ty::ReErased } else { r } + fn fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, Self::Error> { + if let ty::ReLateBound(..) = r { Ok(&ty::ReErased) } else { Ok(r) } } } diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 2ccf17387d1c7..3a6f611660ece 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -714,11 +714,11 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, '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<ty::Region<'tcx>, Self::Error> { + 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(|| r.super_fold_with(self).into_ok())) } } From 30bf20a692df794c9c639ef7153115b7db5aade5 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut <leseulartichaut@gmail.com> Date: Wed, 19 May 2021 15:03:43 +0200 Subject: [PATCH 4/9] Unwrap the results of type folders Co-authored-by: Alan Egerton <eggyal@gmail.com> --- compiler/rustc_const_eval/src/lib.rs | 1 + .../src/transform/validate.rs | 3 +- .../src/infer/canonical/canonicalizer.rs | 8 +- compiler/rustc_infer/src/infer/freshen.rs | 4 +- compiler/rustc_infer/src/infer/fudge.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 6 +- .../rustc_infer/src/infer/opaque_types.rs | 196 +++++++++--------- compiler/rustc_infer/src/infer/resolve.rs | 2 +- compiler/rustc_infer/src/lib.rs | 1 + compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_middle/src/ty/erase_regions.rs | 4 +- compiler/rustc_middle/src/ty/fold.rs | 10 +- compiler/rustc_middle/src/ty/instance.rs | 2 +- .../src/ty/normalize_erasing_regions.rs | 4 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/ty/subst.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 6 +- compiler/rustc_trait_selection/src/lib.rs | 1 + .../rustc_trait_selection/src/opaque_types.rs | 22 +- .../src/traits/error_reporting/mod.rs | 5 +- .../src/traits/project.rs | 9 +- .../src/traits/query/normalize.rs | 2 +- .../src/traits/select/mod.rs | 1 + compiler/rustc_traits/src/chalk/db.rs | 38 ++-- compiler/rustc_traits/src/chalk/lowering.rs | 2 +- compiler/rustc_traits/src/chalk/mod.rs | 4 +- compiler/rustc_traits/src/lib.rs | 1 + compiler/rustc_typeck/src/check/op.rs | 4 +- compiler/rustc_typeck/src/check/writeback.rs | 2 +- compiler/rustc_typeck/src/collect/type_of.rs | 4 +- compiler/rustc_typeck/src/hir_wf_check.rs | 7 +- compiler/rustc_typeck/src/lib.rs | 1 + src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/lib.rs | 1 + 34 files changed, 192 insertions(+), 168 deletions(-) diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index f308e764e861d..0d36466f6e3e7 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -23,6 +23,7 @@ Rust MIR: a lowered representation of Rust. #![feature(trusted_len)] #![feature(trusted_step)] #![feature(try_blocks)] +#![feature(unwrap_infallible)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index b09b2227f3e88..0ab077cf2bf40 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -95,7 +95,8 @@ pub fn equal_up_to_regions( // Leave consts and types unchanged. ct_op: |ct| ct, ty_op: |ty| ty, - }), + }) + .into_ok(), ) }; tcx.infer_ctxt().enter(|infcx| infcx.can_eq(param_env, normalize(src), normalize(dest)).is_ok()) diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index dd1f0d63aff05..27e73738b7f35 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -503,7 +503,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { indices: FxHashMap::default(), binder_index: ty::INNERMOST, }; - let out_value = value.fold_with(&mut canonicalizer); + let out_value = value.fold_with(&mut canonicalizer).into_ok(); // Once we have canonicalized `out_value`, it should not // contain anything that ties it to this inference context @@ -621,7 +621,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { let infcx = self.infcx; let bound_to = infcx.shallow_resolve(ty_var); if bound_to != ty_var { - self.fold_ty(bound_to) + self.fold_ty(bound_to).into_ok() } else { let var = self.canonical_var(info, ty_var.into()); self.tcx().mk_ty(ty::Bound(self.binder_index, var.into())) @@ -640,12 +640,12 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { let infcx = self.infcx; let bound_to = infcx.shallow_resolve(const_var); if bound_to != const_var { - self.fold_const(bound_to) + self.fold_const(bound_to).into_ok() } else { let var = self.canonical_var(info, const_var.into()); self.tcx().mk_const(ty::Const { val: ty::ConstKind::Bound(self.binder_index, var), - ty: self.fold_ty(const_var.ty), + ty: self.fold_ty(const_var.ty).into_ok(), }) } } diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index fce6403575b79..7599e98167fb5 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -72,7 +72,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { F: FnOnce(u32) -> ty::InferTy, { if let Some(ty) = opt_ty { - return ty.fold_with(self); + return ty.fold_with(self).into_ok(); } match self.ty_freshen_map.entry(key) { @@ -98,7 +98,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { F: FnOnce(u32) -> ty::InferConst<'tcx>, { if let Some(ct) = opt_ct { - return ct.fold_with(self); + return ct.fold_with(self).into_ok(); } match self.const_freshen_map.entry(key) { diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs index c889abf3d3c88..4e6f1315d1024 100644 --- a/compiler/rustc_infer/src/infer/fudge.rs +++ b/compiler/rustc_infer/src/infer/fudge.rs @@ -161,7 +161,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { { Ok(value) } else { - Ok(value.fold_with(&mut fudger)) + Ok(value.fold_with(&mut fudger).into_ok()) } } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index afac40b0ebd0d..4a9a63e1c7602 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -681,7 +681,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T { - t.fold_with(&mut self.freshener()) + t.fold_with(&mut self.freshener()).into_ok() } /// Returns the origin of the type variable identified by `vid`, or `None` @@ -1381,7 +1381,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { where T: TypeFoldable<'tcx>, { - value.fold_with(&mut ShallowResolver { infcx: self }) + value.fold_with(&mut ShallowResolver { infcx: self }).into_ok() } pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid { @@ -1402,7 +1402,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { return value; // Avoid duplicated subst-folding. } let mut r = resolve::OpportunisticVarResolver::new(self); - value.fold_with(&mut r) + value.fold_with(&mut r).into_ok() } /// Returns the first unresolved variable contained in `T`. In the diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index e2e07f2072e49..932f26d555010 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -418,92 +418,94 @@ struct Instantiator<'a, 'tcx> { impl<'a, 'tcx> Instantiator<'a, 'tcx> { fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T { let tcx = self.infcx.tcx; - value.fold_with(&mut BottomUpFolder { - tcx, - ty_op: |ty| { - if ty.references_error() { - return tcx.ty_error(); - } else if let ty::Opaque(def_id, substs) = ty.kind() { - // Check that this is `impl Trait` type is - // declared by `parent_def_id` -- i.e., one whose - // value we are inferring. At present, this is - // always true during the first phase of - // type-check, but not always true later on during - // NLL. Once we support named opaque types more fully, - // this same scenario will be able to arise during all phases. - // - // Here is an example using type alias `impl Trait` - // that indicates the distinction we are checking for: - // - // ```rust - // mod a { - // pub type Foo = impl Iterator; - // pub fn make_foo() -> Foo { .. } - // } - // - // mod b { - // fn foo() -> a::Foo { a::make_foo() } - // } - // ``` - // - // Here, the return type of `foo` references an - // `Opaque` indeed, but not one whose value is - // presently being inferred. You can get into a - // similar situation with closure return types - // today: - // - // ```rust - // fn foo() -> impl Iterator { .. } - // fn bar() { - // let x = || foo(); // returns the Opaque assoc with `foo` - // } - // ``` - if let Some(def_id) = def_id.as_local() { - let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let parent_def_id = self.infcx.defining_use_anchor; - let def_scope_default = || { - let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id); - parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id) - }; - let (in_definition_scope, origin) = - match tcx.hir().expect_item(opaque_hir_id).kind { - // Anonymous `impl Trait` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: Some(parent), - origin, - .. - }) => (parent == parent_def_id.to_def_id(), origin), - // Named `type Foo = impl Bar;` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: None, - origin, - .. - }) => ( - may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), - origin, - ), - _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias), + value + .fold_with(&mut BottomUpFolder { + tcx, + ty_op: |ty| { + if ty.references_error() { + return tcx.ty_error(); + } else if let ty::Opaque(def_id, substs) = ty.kind() { + // Check that this is `impl Trait` type is + // declared by `parent_def_id` -- i.e., one whose + // value we are inferring. At present, this is + // always true during the first phase of + // type-check, but not always true later on during + // NLL. Once we support named opaque types more fully, + // this same scenario will be able to arise during all phases. + // + // Here is an example using type alias `impl Trait` + // that indicates the distinction we are checking for: + // + // ```rust + // mod a { + // pub type Foo = impl Iterator; + // pub fn make_foo() -> Foo { .. } + // } + // + // mod b { + // fn foo() -> a::Foo { a::make_foo() } + // } + // ``` + // + // Here, the return type of `foo` references an + // `Opaque` indeed, but not one whose value is + // presently being inferred. You can get into a + // similar situation with closure return types + // today: + // + // ```rust + // fn foo() -> impl Iterator { .. } + // fn bar() { + // let x = || foo(); // returns the Opaque assoc with `foo` + // } + // ``` + if let Some(def_id) = def_id.as_local() { + let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let parent_def_id = self.infcx.defining_use_anchor; + let def_scope_default = || { + let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id); + parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id) }; - if in_definition_scope { - let opaque_type_key = - OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; - return self.fold_opaque_ty(ty, opaque_type_key, origin); - } - - debug!( - "instantiate_opaque_types_in_map: \ + let (in_definition_scope, origin) = + match tcx.hir().expect_item(opaque_hir_id).kind { + // Anonymous `impl Trait` + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + impl_trait_fn: Some(parent), + origin, + .. + }) => (parent == parent_def_id.to_def_id(), origin), + // Named `type Foo = impl Bar;` + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + impl_trait_fn: None, + origin, + .. + }) => ( + may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), + origin, + ), + _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias), + }; + if in_definition_scope { + let opaque_type_key = + OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; + return self.fold_opaque_ty(ty, opaque_type_key, origin); + } + + debug!( + "instantiate_opaque_types_in_map: \ encountered opaque outside its definition scope \ def_id={:?}", - def_id, - ); + def_id, + ); + } } - } - ty - }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }) + ty + }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }) + .into_ok() } #[instrument(skip(self), level = "debug")] @@ -556,21 +558,23 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { debug!(?predicate); // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them. - let predicate = predicate.fold_with(&mut BottomUpFolder { - tcx, - ty_op: |ty| match ty.kind() { - ty::Projection(projection_ty) => infcx.infer_projection( - self.param_env, - *projection_ty, - traits::ObligationCause::misc(self.value_span, self.body_id), - 0, - &mut self.obligations, - ), - _ => ty, - }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }); + let predicate = predicate + .fold_with(&mut BottomUpFolder { + tcx, + ty_op: |ty| match ty.kind() { + ty::Projection(projection_ty) => infcx.infer_projection( + self.param_env, + *projection_ty, + traits::ObligationCause::misc(self.value_span, self.body_id), + 0, + &mut self.obligations, + ), + _ => ty, + }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }) + .into_ok(); debug!(?predicate); if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() { diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index d09c585a02598..554c5b162f755 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -182,7 +182,7 @@ where T: TypeFoldable<'tcx>, { let mut full_resolver = FullTypeResolver { infcx, err: None }; - let result = value.fold_with(&mut full_resolver); + let result = value.fold_with(&mut full_resolver).into_ok(); match full_resolver.err { None => Ok(result), Some(e) => Err(e), diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index e4b407e7c112d..5153427954ccc 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -24,6 +24,7 @@ #![feature(control_flow_enum)] #![feature(min_specialization)] #![feature(label_break_value)] +#![feature(unwrap_infallible)] #![recursion_limit = "512"] // For rustdoc #[macro_use] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 9ce9f65a49066..b67ad8b770ea1 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -56,6 +56,7 @@ #![feature(try_blocks)] #![feature(try_reserve_kind)] #![feature(nonzero_ops)] +#![feature(unwrap_infallible)] #![recursion_limit = "512"] #[macro_use] diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 559534a7aa4e3..25b460cf16d3c 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -9,7 +9,7 @@ pub(super) fn provide(providers: &mut ty::query::Providers) { fn erase_regions_ty<'tcx>(tcx: TyCtxt<'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 }).into_ok() } impl<'tcx> TyCtxt<'tcx> { @@ -27,7 +27,7 @@ impl<'tcx> TyCtxt<'tcx> { return value; } debug!("erase_regions({:?})", value); - let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self }); + let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self }).into_ok(); debug!("erase_regions = {:?}", value1); value1 } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 639606f6b891e..31055c03a5d36 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -336,7 +336,7 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable<'tcx>, { - value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f)) + value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f)).into_ok() } /// Invoke `callback` on every region appearing free in `value`. @@ -638,7 +638,7 @@ impl<'tcx> TyCtxt<'tcx> { value } else { let mut replacer = BoundVarReplacer::new(self, Some(&mut real_fld_r), None, None); - value.fold_with(&mut replacer) + value.fold_with(&mut replacer).into_ok() }; (value, region_map) } @@ -664,7 +664,7 @@ impl<'tcx> TyCtxt<'tcx> { } else { let mut replacer = BoundVarReplacer::new(self, Some(&mut fld_r), Some(&mut fld_t), Some(&mut fld_c)); - value.fold_with(&mut replacer) + value.fold_with(&mut replacer).into_ok() } } @@ -1030,7 +1030,7 @@ where { debug!("shift_vars(value={:?}, amount={})", value, amount); - value.fold_with(&mut Shifter::new(tcx, amount)) + value.fold_with(&mut Shifter::new(tcx, amount)).into_ok() } #[derive(Debug, PartialEq, Eq, Copy, Clone)] @@ -1293,7 +1293,7 @@ impl<'tcx> TyCtxt<'tcx> { /// /// FIXME(@lcnr): explain this function a bit more pub fn expose_default_const_substs<T: TypeFoldable<'tcx>>(self, v: T) -> T { - v.fold_with(&mut ExposeDefaultConstSubstsFolder { tcx: self }) + v.fold_with(&mut ExposeDefaultConstSubstsFolder { tcx: self }).into_ok() } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 23863bf389e5a..15931b8d2c86a 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -669,7 +669,7 @@ fn polymorphize<'tcx>( // ..and polymorphize any closures/generators captured as upvars. let upvars_ty = upvars_ty.unwrap(); let polymorphized_upvars_ty = upvars_ty.fold_with( - &mut PolymorphizationFolder { tcx }); + &mut PolymorphizationFolder { tcx }).into_ok(); debug!("polymorphize: polymorphized_upvars_ty={:?}", polymorphized_upvars_ty); ty::GenericArg::from(polymorphized_upvars_ty) }, diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index c5d845f97559d..e6f67adae93da 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -35,7 +35,9 @@ impl<'tcx> TyCtxt<'tcx> { if !value.has_projections() { value } else { - value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env }) + value + .fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env }) + .into_ok() } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 13c6b4d6b01ba..f454b95862bab 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2193,7 +2193,7 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> { name: &mut name, region_map: BTreeMap::new(), }; - let new_value = value.clone().skip_binder().fold_with(&mut folder); + let new_value = value.clone().skip_binder().fold_with(&mut folder).into_ok(); let region_map = folder.region_map; start_or_continue(&mut self, "", "> "); (new_value, region_map) diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 419cf164db3b6..0767224ad9288 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -439,7 +439,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> Subst<'tcx> for T { span: Option<Span>, ) -> T { let mut folder = SubstFolder { tcx, substs, span, binders_passed: 0 }; - self.fold_with(&mut folder) + self.fold_with(&mut folder).into_ok() } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index b90123b4cee82..5137f9650633a 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -574,14 +574,14 @@ impl<'tcx> OpaqueTypeExpander<'tcx> { if self.found_any_recursion { return None; } - let substs = substs.fold_with(self); + let substs = substs.fold_with(self).into_ok(); if !self.check_recursion || self.seen_opaque_tys.insert(def_id) { let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) { Some(expanded_ty) => expanded_ty, None => { 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 expanded_ty = self.fold_ty(concrete_ty).into_ok(); self.expanded_cache.insert((def_id, substs), expanded_ty); expanded_ty } @@ -1092,7 +1092,7 @@ pub fn normalize_opaque_types( check_recursion: false, tcx, }; - val.fold_with(&mut visitor) + val.fold_with(&mut visitor).into_ok() } pub fn provide(providers: &mut ty::query::Providers) { diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 1820e33b19bf4..ecc352c1a49b5 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -22,6 +22,7 @@ #![feature(never_type)] #![feature(crate_visibility_modifier)] #![feature(control_flow_enum)] +#![feature(unwrap_infallible)] #![recursion_limit = "512"] // For rustdoc #[macro_use] diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index eb7293ae86e69..9052dff0aaa83 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -65,14 +65,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, '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 = instantiated_ty.fold_with(&mut ReverseMapper::new( - self.tcx, - self.is_tainted_by_errors(), - def_id, - map, - instantiated_ty, - span, - )); + let definition_ty = instantiated_ty + .fold_with(&mut ReverseMapper::new( + self.tcx, + self.is_tainted_by_errors(), + def_id, + map, + instantiated_ty, + span, + )) + .into_ok(); debug!(?definition_ty); definition_ty @@ -123,14 +125,14 @@ impl ReverseMapper<'tcx> { ) -> GenericArg<'tcx> { assert!(!self.map_missing_regions_to_empty); self.map_missing_regions_to_empty = true; - let kind = kind.fold_with(self); + let kind = kind.fold_with(self).into_ok(); self.map_missing_regions_to_empty = false; kind } fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> { assert!(!self.map_missing_regions_to_empty); - kind.fold_with(self) + kind.fold_with(self).into_ok() } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 1876b0ce80eed..866bcde1bfd4f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1916,8 +1916,9 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { self.probe(|_| { let mut selcx = SelectionContext::new(self); - let cleaned_pred = - pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() }); + let cleaned_pred = pred + .fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() }) + .into_ok(); let cleaned_pred = super::project::normalize( &mut selcx, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 2baa21a43d61d..0911b2c529ab2 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -339,7 +339,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { if !needs_normalization(&value, self.param_env.reveal()) { value } else { - value.fold_with(self) + value.fold_with(self).into_ok() } } } @@ -555,7 +555,7 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> { universe_indices, }; - let value = value.super_fold_with(&mut replacer); + let value = value.super_fold_with(&mut replacer).into_ok(); (value, replacer.mapped_regions, replacer.mapped_types, replacer.mapped_consts) } @@ -681,7 +681,7 @@ impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> { universe_indices, current_index: ty::INNERMOST, }; - value.super_fold_with(&mut replacer) + value.super_fold_with(&mut replacer).into_ok() } } @@ -1546,7 +1546,8 @@ fn confirm_candidate<'cx, 'tcx>( // when possible for this to work. See `auto-trait-projection-recursion.rs` // for a case where this matters. if progress.ty.has_infer_regions() { - progress.ty = OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty); + progress.ty = + OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty).into_ok(); } progress } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index f3a90935a9fdf..dd9cd51936ec3 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -88,7 +88,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { normalizer.universes.extend((0..max_visitor.escaping).map(|_| None)); } } - let result = value.fold_with(&mut normalizer); + let result = value.fold_with(&mut normalizer).into_ok(); info!( "normalize::<{}>: result={:?} with {} obligations", std::any::type_name::<T>(), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2aa214694cb14..767cb1618bb67 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2222,6 +2222,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .predicate .to_poly_trait_ref() .fold_with(&mut self.freshener) + .into_ok() .with_constness(obligation.predicate.skip_binder().constness); let dfn = previous_stack.cache.next_dfn(); diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 1d457d6761fd0..fdff07302c240 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -45,7 +45,7 @@ impl<'tcx> RustIrDatabase<'tcx> { predicates .iter() .map(|(wc, _)| wc.subst(self.interner.tcx, bound_vars)) - .map(|wc| wc.fold_with(&mut regions_substitutor)) + .map(|wc| wc.fold_with(&mut regions_substitutor).into_ok()) .filter_map(|wc| LowerInto::<Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>>>::lower_into(wc, &self.interner)).collect() } @@ -287,7 +287,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t let trait_ref = trait_ref.subst(self.interner.tcx, bound_vars); let mut regions_substitutor = lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder); - let trait_ref = trait_ref.fold_with(&mut regions_substitutor); + let trait_ref = trait_ref.fold_with(&mut regions_substitutor).into_ok(); let where_clauses = self.where_clauses_for(def_id, bound_vars); @@ -335,7 +335,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t let self_ty = self_ty.subst(self.interner.tcx, bound_vars); let mut regions_substitutor = lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder); - let self_ty = self_ty.fold_with(&mut regions_substitutor); + let self_ty = self_ty.fold_with(&mut regions_substitutor).into_ok(); let lowered_ty = self_ty.lower_into(&self.interner); parameters[0].assert_ty_ref(&self.interner).could_match( @@ -501,22 +501,24 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t .iter() .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars)) .map(|bound| { - bound.fold_with(&mut ty::fold::BottomUpFolder { - tcx: self.interner.tcx, - ty_op: |ty| { - if let ty::Opaque(def_id, substs) = *ty.kind() { - if def_id == opaque_ty_id.0 && substs == identity_substs { - return self.interner.tcx.mk_ty(ty::Bound( - ty::INNERMOST, - ty::BoundTy::from(ty::BoundVar::from_u32(0)), - )); + bound + .fold_with(&mut ty::fold::BottomUpFolder { + tcx: self.interner.tcx, + ty_op: |ty| { + if let ty::Opaque(def_id, substs) = *ty.kind() { + if def_id == opaque_ty_id.0 && substs == identity_substs { + return self.interner.tcx.mk_ty(ty::Bound( + ty::INNERMOST, + ty::BoundTy::from(ty::BoundVar::from_u32(0)), + )); + } } - } - ty - }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }) + ty + }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }) + .into_ok() }) .filter_map(|bound| { LowerInto::< diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 033a94658425b..66073facf4b0c 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -817,7 +817,7 @@ crate fn collect_bound_vars<'tcx, T: TypeFoldable<'tcx>>( .collect(); let mut bound_var_substitutor = NamedBoundVarSubstitutor::new(tcx, &named_parameters); - let new_ty = ty.skip_binder().fold_with(&mut bound_var_substitutor); + let new_ty = ty.skip_binder().fold_with(&mut bound_var_substitutor).into_ok(); for var in named_parameters.values() { parameters.insert(*var, chalk_ir::VariableKind::Lifetime); diff --git a/compiler/rustc_traits/src/chalk/mod.rs b/compiler/rustc_traits/src/chalk/mod.rs index b7275bac19048..a6f7c4d7988f6 100644 --- a/compiler/rustc_traits/src/chalk/mod.rs +++ b/compiler/rustc_traits/src/chalk/mod.rs @@ -49,12 +49,12 @@ crate fn evaluate_goal<'tcx>( let mut params_substitutor = ParamsSubstitutor::new(tcx, placeholders_collector.next_ty_placeholder); - let obligation = obligation.fold_with(&mut params_substitutor); + let obligation = obligation.fold_with(&mut params_substitutor).into_ok(); // FIXME(chalk): we really should be substituting these back in the solution let _params: FxHashMap<usize, ParamTy> = params_substitutor.params; let mut regions_substitutor = RegionsSubstitutor::new(tcx, reempty_placeholder); - let obligation = obligation.fold_with(&mut regions_substitutor); + let obligation = obligation.fold_with(&mut regions_substitutor).into_ok(); let max_universe = obligation.max_universe.index(); diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index 8612499623be6..ea70a8d9e3a0d 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -4,6 +4,7 @@ #![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] #![feature(nll)] +#![feature(unwrap_infallible)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 8f852c0b51c98..1c4e0522bef8f 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -442,8 +442,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut eraser = TypeParamEraser(self, expr.span); let needs_bound = self .lookup_op_method( - eraser.fold_ty(lhs_ty), - &[eraser.fold_ty(rhs_ty)], + eraser.fold_ty(lhs_ty).into_ok(), + &[eraser.fold_ty(rhs_ty).into_ok()], Op::Binary(op, is_assign), ) .is_ok(); diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index ecf0332db7b8b..a5965411020a4 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -658,7 +658,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { T: TypeFoldable<'tcx>, { let mut resolver = Resolver::new(self.fcx, span, self.body); - let x = x.fold_with(&mut resolver); + let x = x.fold_with(&mut resolver).into_ok(); if cfg!(debug_assertions) && x.needs_infer() { span_bug!(span.to_span(self.fcx.tcx), "writeback: `{:?}` has inference variables", x); } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 1dce63416dc96..1ea379c57389a 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -761,7 +761,7 @@ fn infer_placeholder_type<'a>( // Suggesting unnameable types won't help. let mut mk_nameable = MakeNameable::new(tcx); - let ty = mk_nameable.fold_ty(ty); + let ty = mk_nameable.fold_ty(ty).into_ok(); let sugg_ty = if mk_nameable.success { Some(ty) } else { None }; if let Some(sugg_ty) = sugg_ty { err.span_suggestion( @@ -785,7 +785,7 @@ fn infer_placeholder_type<'a>( if !ty.references_error() { let mut mk_nameable = MakeNameable::new(tcx); - let ty = mk_nameable.fold_ty(ty); + let ty = mk_nameable.fold_ty(ty).into_ok(); let sugg_ty = if mk_nameable.success { Some(ty) } else { None }; if let Some(sugg_ty) = sugg_ty { diag.span_suggestion( diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_typeck/src/hir_wf_check.rs index 5c229c86ddc1a..f9de6376b0ff5 100644 --- a/compiler/rustc_typeck/src/hir_wf_check.rs +++ b/compiler/rustc_typeck/src/hir_wf_check.rs @@ -71,8 +71,11 @@ fn diagnostic_hir_wf_check<'tcx>( fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { self.tcx.infer_ctxt().enter(|infcx| { let mut fulfill = traits::FulfillmentContext::new(); - let tcx_ty = - self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx }); + let tcx_ty = self + .icx + .to_ty(ty) + .fold_with(&mut EraseAllBoundRegions { tcx: self.tcx }) + .into_ok(); let cause = traits::ObligationCause::new( ty.span, self.hir_id, diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 0881cf07586b3..c0f0b3fe7046e 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -71,6 +71,7 @@ This API is completely unstable and subject to change. #![feature(slice_partition_dedup)] #![feature(control_flow_enum)] #![feature(hash_drain_filter)] +#![feature(unwrap_infallible)] #![recursion_limit = "256"] #[macro_use] diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 3a6f611660ece..04fe1dccce44b 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -449,7 +449,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { _ => false, } }) - .map(|p| p.fold_with(&mut replacer)); + .map(|p| p.fold_with(&mut replacer).into_ok()); let mut generic_params = (tcx.generics_of(item_def_id), tcx.explicit_predicates_of(item_def_id)) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b6311abb5c3e8..6ba56fe01a935 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -18,6 +18,7 @@ #![feature(type_ascription)] #![feature(iter_intersperse)] #![recursion_limit = "256"] +#![feature(unwrap_infallible)] #![warn(rustc::internal)] #[macro_use] From 6db9605d85dafd6759b82a934ac833baf0cd9214 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut <leseulartichaut@gmail.com> Date: Wed, 19 May 2021 23:08:32 +0200 Subject: [PATCH 5/9] Use `TypeFolder::Error` for `FullTypeResolver` and `QueryNormalizer` Co-authored-by: Alan Egerton <eggyal@gmail.com> --- compiler/rustc_infer/src/infer/resolve.rs | 28 ++--- .../src/traits/query/normalize.rs | 117 ++++++------------ 2 files changed, 48 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 554c5b162f755..cccdfb7452a77 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -181,22 +181,18 @@ pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, value: T) -> Fixu where T: TypeFoldable<'tcx>, { - let mut full_resolver = FullTypeResolver { infcx, err: None }; - let result = value.fold_with(&mut full_resolver).into_ok(); - match full_resolver.err { - None => Ok(result), - Some(e) => Err(e), - } + value.fold_with(&mut FullTypeResolver { infcx }) } // N.B. This type is not public because the protocol around checking the // `err` field is not enforceable otherwise. struct FullTypeResolver<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, - err: Option<FixupError<'tcx>>, } impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { + type Error = FixupError<'tcx>; + fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -207,18 +203,9 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { } else { let t = self.infcx.shallow_resolve(t); match *t.kind() { - ty::Infer(ty::TyVar(vid)) => { - self.err = Some(FixupError::UnresolvedTy(vid)); - Ok(self.tcx().ty_error()) - } - ty::Infer(ty::IntVar(vid)) => { - self.err = Some(FixupError::UnresolvedIntTy(vid)); - Ok(self.tcx().ty_error()) - } - ty::Infer(ty::FloatVar(vid)) => { - self.err = Some(FixupError::UnresolvedFloatTy(vid)); - Ok(self.tcx().ty_error()) - } + ty::Infer(ty::TyVar(vid)) => Err(FixupError::UnresolvedTy(vid)), + ty::Infer(ty::IntVar(vid)) => Err(FixupError::UnresolvedIntTy(vid)), + ty::Infer(ty::FloatVar(vid)) => Err(FixupError::UnresolvedFloatTy(vid)), ty::Infer(_) => { bug!("Unexpected type in full type resolver: {:?}", t); } @@ -250,8 +237,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { let c = self.infcx.shallow_resolve(c); match c.val { ty::ConstKind::Infer(InferConst::Var(vid)) => { - self.err = Some(FixupError::UnresolvedConst(vid)); - return Ok(self.tcx().const_error(c.ty)); + return Err(FixupError::UnresolvedConst(vid)); } ty::ConstKind::Infer(InferConst::Fresh(_)) => { bug!("Unexpected const in full const resolver: {:?}", c); diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index dd9cd51936ec3..af507feffba5b 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -61,7 +61,6 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { cause: self.cause, param_env: self.param_env, obligations: vec![], - error: false, cache: SsoHashMap::new(), anon_depth: 0, universes: vec![], @@ -88,7 +87,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { normalizer.universes.extend((0..max_visitor.escaping).map(|_| None)); } } - let result = value.fold_with(&mut normalizer).into_ok(); + let result = value.fold_with(&mut normalizer); info!( "normalize::<{}>: result={:?} with {} obligations", std::any::type_name::<T>(), @@ -100,11 +99,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { std::any::type_name::<T>(), normalizer.obligations, ); - if normalizer.error { - Err(NoSolution) - } else { - Ok(Normalized { value: result, obligations: normalizer.obligations }) - } + result.map(|value| Normalized { value, obligations: normalizer.obligations }) } } @@ -171,12 +166,13 @@ struct QueryNormalizer<'cx, 'tcx> { param_env: ty::ParamEnv<'tcx>, obligations: Vec<PredicateObligation<'tcx>>, cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>, - error: bool, anon_depth: usize, universes: Vec<Option<ty::UniverseIndex>>, } impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { + type Error = NoSolution; + fn tcx<'c>(&'c self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -262,39 +258,22 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values); debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: orig_values = {:#?}", orig_values); - match tcx.normalize_projection_ty(c_data) { - Ok(result) => { - // We don't expect ambiguity. - if result.is_ambiguous() { - self.error = true; - return ty.super_fold_with(self); - } - - match self.infcx.instantiate_query_response_and_region_obligations( - self.cause, - self.param_env, - &orig_values, - result, - ) { - Ok(InferOk { value: result, obligations }) => { - debug!("QueryNormalizer: result = {:#?}", result); - debug!("QueryNormalizer: obligations = {:#?}", obligations); - self.obligations.extend(obligations); - Ok(result.normalized_ty) - } - - Err(_) => { - self.error = true; - ty.super_fold_with(self) - } - } - } - - Err(NoSolution) => { - self.error = true; - ty.super_fold_with(self) - } + let result = tcx.normalize_projection_ty(c_data)?; + // We don't expect ambiguity. + if result.is_ambiguous() { + return Err(NoSolution); } + let InferOk { value: result, obligations } = + self.infcx.instantiate_query_response_and_region_obligations( + self.cause, + self.param_env, + &orig_values, + result, + )?; + debug!("QueryNormalizer: result = {:#?}", result); + debug!("QueryNormalizer: obligations = {:#?}", obligations); + self.obligations.extend(obligations); + Ok(result.normalized_ty) } ty::Projection(data) => { @@ -318,43 +297,29 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values); debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: orig_values = {:#?}", orig_values); - match tcx.normalize_projection_ty(c_data) { - Ok(result) => { - // We don't expect ambiguity. - if result.is_ambiguous() { - self.error = true; - return ty.super_fold_with(self); - } - match self.infcx.instantiate_query_response_and_region_obligations( - self.cause, - self.param_env, - &orig_values, - result, - ) { - Ok(InferOk { value: result, obligations }) => { - debug!("QueryNormalizer: result = {:#?}", result); - debug!("QueryNormalizer: obligations = {:#?}", obligations); - self.obligations.extend(obligations); - Ok(crate::traits::project::PlaceholderReplacer::replace_placeholders( - infcx, - mapped_regions, - mapped_types, - mapped_consts, - &self.universes, - result.normalized_ty, - )) - } - Err(_) => { - self.error = true; - ty.super_fold_with(self) - } - } - } - Err(NoSolution) => { - self.error = true; - ty.super_fold_with(self) - } + let result = tcx.normalize_projection_ty(c_data)?; + // We don't expect ambiguity. + if result.is_ambiguous() { + return Err(NoSolution); } + let InferOk { value: result, obligations } = + self.infcx.instantiate_query_response_and_region_obligations( + self.cause, + self.param_env, + &orig_values, + result, + )?; + debug!("QueryNormalizer: result = {:#?}", result); + debug!("QueryNormalizer: obligations = {:#?}", obligations); + self.obligations.extend(obligations); + Ok(crate::traits::project::PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + result.normalized_ty, + )) } _ => ty.super_fold_with(self), From 51e15ac7099c00efb425219cf17c8e412d1e14d7 Mon Sep 17 00:00:00 2001 From: Alan Egerton <eggyal@gmail.com> Date: Sat, 27 Nov 2021 11:53:00 +0000 Subject: [PATCH 6/9] Remove erroneous merge conflict --- compiler/rustc_middle/src/ty/subst.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 0767224ad9288..ffa495ce4803f 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -513,10 +513,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { &mut self, c: &'tcx ty::Const<'tcx>, ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { - if !c.potentially_needs_subst() { - return Ok(c); - } - if let ty::ConstKind::Param(p) = c.val { Ok(self.const_for_param(p, c)) } else { From 04f1c09f90abebd0c6a7658105dec57099a63caa Mon Sep 17 00:00:00 2001 From: Alan Egerton <eggyal@gmail.com> Date: Sat, 27 Nov 2021 14:19:24 +0000 Subject: [PATCH 7/9] Avoid UB when short-circuiting try_map_id for Vec --- compiler/rustc_data_structures/src/functor.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs index 1307c68ba0b18..d3715a998cec9 100644 --- a/compiler/rustc_data_structures/src/functor.rs +++ b/compiler/rustc_data_structures/src/functor.rs @@ -87,7 +87,6 @@ impl<T> IdFunctor for Vec<T> { // FIXME: We don't really care about panics here and leak // far more than we should, but that should be fine for now. let len = self.len(); - let mut error = Ok(()); unsafe { self.set_len(0); let start = self.as_mut_ptr(); @@ -96,8 +95,16 @@ impl<T> IdFunctor for Vec<T> { match f(ptr::read(p)) { Ok(value) => ptr::write(p, value), Err(err) => { - error = Err(err); - break; + // drop all other elements in self + // (current element was "moved" into the call to f) + for j in (0..i).chain(i + 1..len) { + let p = start.add(j); + ptr::drop_in_place(p); + } + + // returning will drop self, releasing the allocation + // (len is 0 so elements will not be re-dropped) + return Err(err); } } } @@ -105,7 +112,7 @@ impl<T> IdFunctor for Vec<T> { // so we don't leak memory. self.set_len(len); } - error.map(|()| self) + Ok(self) } } From 9f714ef03567d588fbb63c662670fd9326d7348e Mon Sep 17 00:00:00 2001 From: Alan Egerton <eggyal@gmail.com> Date: Sat, 27 Nov 2021 16:40:47 +0000 Subject: [PATCH 8/9] Delegate from `map_id` to `try_map_id` --- compiler/rustc_data_structures/src/functor.rs | 63 ++----------------- compiler/rustc_data_structures/src/lib.rs | 1 + 2 files changed, 7 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs index d3715a998cec9..8f441a1841e91 100644 --- a/compiler/rustc_data_structures/src/functor.rs +++ b/compiler/rustc_data_structures/src/functor.rs @@ -5,9 +5,13 @@ use std::ptr; pub trait IdFunctor: Sized { type Inner; - fn map_id<F>(self, f: F) -> Self + #[inline] + fn map_id<F>(self, mut f: F) -> Self where - F: FnMut(Self::Inner) -> Self::Inner; + F: FnMut(Self::Inner) -> Self::Inner, + { + self.try_map_id::<_, !>(|value| Ok(f(value))).into_ok() + } fn try_map_id<F, E>(self, f: F) -> Result<Self, E> where @@ -17,25 +21,6 @@ pub trait IdFunctor: Sized { impl<T> IdFunctor for Box<T> { type Inner = T; - #[inline] - fn map_id<F>(self, mut f: F) -> Self - where - F: FnMut(Self::Inner) -> Self::Inner, - { - let raw = Box::into_raw(self); - unsafe { - // SAFETY: The raw pointer points to a valid value of type `T`. - let value = ptr::read(raw); - // SAFETY: Converts `Box<T>` to `Box<MaybeUninit<T>>` which is the - // inverse of `Box::assume_init()` and should be safe. - let mut raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast()); - // SAFETY: Write the mapped value back into the `Box`. - raw.write(f(value)); - // SAFETY: We just initialized `raw`. - raw.assume_init() - } - } - #[inline] fn try_map_id<F, E>(self, mut f: F) -> Result<Self, E> where @@ -59,26 +44,6 @@ impl<T> IdFunctor for Box<T> { impl<T> IdFunctor for Vec<T> { type Inner = T; - #[inline] - fn map_id<F>(mut self, mut f: F) -> Self - where - F: FnMut(Self::Inner) -> Self::Inner, - { - // FIXME: We don't really care about panics here and leak - // far more than we should, but that should be fine for now. - let len = self.len(); - unsafe { - self.set_len(0); - let start = self.as_mut_ptr(); - for i in 0..len { - let p = start.add(i); - ptr::write(p, f(ptr::read(p))); - } - self.set_len(len); - } - self - } - #[inline] fn try_map_id<F, E>(mut self, mut f: F) -> Result<Self, E> where @@ -119,14 +84,6 @@ impl<T> IdFunctor for Vec<T> { impl<T> IdFunctor for Box<[T]> { type Inner = T; - #[inline] - fn map_id<F>(self, f: F) -> Self - where - F: FnMut(Self::Inner) -> Self::Inner, - { - Vec::from(self).map_id(f).into() - } - #[inline] fn try_map_id<F, E>(self, f: F) -> Result<Self, E> where @@ -139,14 +96,6 @@ impl<T> IdFunctor for Box<[T]> { impl<I: Idx, T> IdFunctor for IndexVec<I, T> { type Inner = T; - #[inline] - fn map_id<F>(self, f: F) -> Self - where - F: FnMut(Self::Inner) -> Self::Inner, - { - IndexVec::from_raw(self.raw.map_id(f)) - } - #[inline] fn try_map_id<F, E>(self, f: F) -> Result<Self, E> where diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 77784bf170523..d4eb622e780ce 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -25,6 +25,7 @@ #![feature(once_cell)] #![feature(test)] #![feature(thread_id_value)] +#![feature(unwrap_infallible)] #![allow(rustc::default_hash_types)] #![deny(unaligned_references)] From afa6f92c466a554e71a6ce434680196958a8cb59 Mon Sep 17 00:00:00 2001 From: Alan Egerton <eggyal@gmail.com> Date: Sat, 27 Nov 2021 16:59:18 +0000 Subject: [PATCH 9/9] Use intrinsic pointer methods --- compiler/rustc_data_structures/src/functor.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs index 8f441a1841e91..920f7b1ed0a54 100644 --- a/compiler/rustc_data_structures/src/functor.rs +++ b/compiler/rustc_data_structures/src/functor.rs @@ -1,6 +1,5 @@ use rustc_index::vec::{Idx, IndexVec}; use std::mem; -use std::ptr; pub trait IdFunctor: Sized { type Inner; @@ -29,12 +28,12 @@ impl<T> IdFunctor for Box<T> { let raw = Box::into_raw(self); Ok(unsafe { // SAFETY: The raw pointer points to a valid value of type `T`. - let value = ptr::read(raw); + let value = raw.read(); // SAFETY: Converts `Box<T>` to `Box<MaybeUninit<T>>` which is the // inverse of `Box::assume_init()` and should be safe. let mut raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast()); // SAFETY: Write the mapped value back into the `Box`. - ptr::write(raw.as_mut_ptr(), f(value)?); + raw.write(f(value)?); // SAFETY: We just initialized `raw`. raw.assume_init() }) @@ -57,14 +56,13 @@ impl<T> IdFunctor for Vec<T> { let start = self.as_mut_ptr(); for i in 0..len { let p = start.add(i); - match f(ptr::read(p)) { - Ok(value) => ptr::write(p, value), + match f(p.read()) { + Ok(val) => p.write(val), Err(err) => { // drop all other elements in self // (current element was "moved" into the call to f) for j in (0..i).chain(i + 1..len) { - let p = start.add(j); - ptr::drop_in_place(p); + start.add(j).drop_in_place(); } // returning will drop self, releasing the allocation