1
Fork 0

Make TypeFoldable implementors short-circuit on error

Co-authored-by: Alan Egerton <eggyal@gmail.com>
This commit is contained in:
LeSeulArtichaut 2021-05-19 13:34:54 +02:00 committed by Alan Egerton
parent c5f0d0ebb4
commit 6e3fa20b00
No known key found for this signature in database
GPG key ID: 07CAC3CCA7E0643F
11 changed files with 299 additions and 204 deletions

View file

@ -2,12 +2,16 @@ use rustc_index::vec::{Idx, IndexVec};
use std::mem; use std::mem;
use std::ptr; use std::ptr;
pub trait IdFunctor { pub trait IdFunctor: Sized {
type Inner; type Inner;
fn map_id<F>(self, f: F) -> Self fn map_id<F>(self, f: F) -> Self
where where
F: FnMut(Self::Inner) -> Self::Inner; 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> { impl<T> IdFunctor for Box<T> {
@ -31,6 +35,25 @@ impl<T> IdFunctor for Box<T> {
raw.assume_init() 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> { impl<T> IdFunctor for Vec<T> {
@ -55,6 +78,35 @@ impl<T> IdFunctor for Vec<T> {
} }
self 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]> { impl<T> IdFunctor for Box<[T]> {
@ -67,6 +119,14 @@ impl<T> IdFunctor for Box<[T]> {
{ {
Vec::from(self).map_id(f).into() 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> { 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)) 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)
}
} }

View file

@ -60,13 +60,13 @@ impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> {
// TypeFoldable implementations. // TypeFoldable implementations.
impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O> { impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O> {
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> {
traits::Obligation { Ok(traits::Obligation {
cause: self.cause, cause: self.cause,
recursion_depth: self.recursion_depth, recursion_depth: self.recursion_depth,
predicate: self.predicate.fold_with(folder), predicate: self.predicate.fold_with(folder)?,
param_env: self.param_env.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> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {

View file

@ -17,7 +17,7 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
vi.construct(|_, index| { vi.construct(|_, index| {
let bind = &bindings[index]; let bind = &bindings[index];
quote! { 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>>( fn super_fold_with<__F: ::rustc_middle::ty::fold::TypeFolder<'tcx>>(
self, self,
__folder: &mut __F __folder: &mut __F
) -> Self { ) -> Result<Self, __F::Error> {
match self { #body_fold } Ok(match self { #body_fold })
} }
fn super_visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>( fn super_visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>(

View file

@ -55,8 +55,8 @@ macro_rules! TrivialTypeFoldableImpls {
fn super_fold_with<F: $crate::ty::fold::TypeFolder<$tcx>>( fn super_fold_with<F: $crate::ty::fold::TypeFolder<$tcx>>(
self, self,
_: &mut F _: &mut F
) -> $ty { ) -> ::std::result::Result<$ty, F::Error> {
self Ok(self)
} }
fn super_visit_with<F: $crate::ty::fold::TypeVisitor<$tcx>>( 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>>( fn super_fold_with<V: $crate::ty::fold::TypeFolder<$tcx>>(
self, self,
folder: &mut V, folder: &mut V,
) -> Self { ) -> ::std::result::Result<Self, V::Error> {
EnumTypeFoldableImpl!(@FoldVariants(self, folder) input($($variants)*) output()) EnumTypeFoldableImpl!(@FoldVariants(self, folder) input($($variants)*) output())
} }
@ -112,9 +112,9 @@ macro_rules! EnumTypeFoldableImpl {
}; };
(@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => { (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
match $this { Ok(match $this {
$($output)* $($output)*
} })
}; };
(@FoldVariants($this:expr, $folder:expr) (@FoldVariants($this:expr, $folder:expr)
@ -126,7 +126,7 @@ macro_rules! EnumTypeFoldableImpl {
output( output(
$variant ( $($variant_arg),* ) => { $variant ( $($variant_arg),* ) => {
$variant ( $variant (
$($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)),* $($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)?),*
) )
} }
$($output)* $($output)*
@ -145,7 +145,7 @@ macro_rules! EnumTypeFoldableImpl {
$variant { $variant {
$($variant_arg: $crate::ty::fold::TypeFoldable::fold_with( $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with(
$variant_arg, $folder $variant_arg, $folder
)),* } )?),* }
} }
$($output)* $($output)*
) )

View file

@ -2760,11 +2760,11 @@ impl UserTypeProjection {
TrivialTypeFoldableAndLiftImpls! { ProjectionKind, } TrivialTypeFoldableAndLiftImpls! { ProjectionKind, }
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection { impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
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> {
UserTypeProjection { Ok(UserTypeProjection {
base: self.base.fold_with(folder), base: self.base.fold_with(folder)?,
projs: self.projs.fold_with(folder), projs: self.projs.fold_with(folder)?,
} })
} }
fn super_visit_with<Vs: TypeVisitor<'tcx>>( fn super_visit_with<Vs: TypeVisitor<'tcx>>(

View file

@ -16,37 +16,39 @@ TrivialTypeFoldableAndLiftImpls! {
} }
impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { 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::*; use crate::mir::TerminatorKind::*;
let kind = match self.kind { let kind = match self.kind {
Goto { target } => Goto { target }, Goto { target } => Goto { target },
SwitchInt { discr, switch_ty, targets } => SwitchInt { SwitchInt { discr, switch_ty, targets } => SwitchInt {
discr: discr.fold_with(folder), discr: discr.fold_with(folder)?,
switch_ty: switch_ty.fold_with(folder), switch_ty: switch_ty.fold_with(folder)?,
targets, targets,
}, },
Drop { place, target, unwind } => { 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 { DropAndReplace { place, value, target, unwind } => DropAndReplace {
place: place.fold_with(folder), place: place.fold_with(folder)?,
value: value.fold_with(folder), value: value.fold_with(folder)?,
target, target,
unwind, unwind,
}, },
Yield { value, resume, resume_arg, drop } => Yield { Yield { value, resume, resume_arg, drop } => Yield {
value: value.fold_with(folder), value: value.fold_with(folder)?,
resume, resume,
resume_arg: resume_arg.fold_with(folder), resume_arg: resume_arg.fold_with(folder)?,
drop, drop,
}, },
Call { func, args, destination, cleanup, from_hir_call, fn_span } => { 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 { Call {
func: func.fold_with(folder), func: func.fold_with(folder)?,
args: args.fold_with(folder), args: args.fold_with(folder)?,
destination: dest, destination: dest,
cleanup, cleanup,
from_hir_call, from_hir_call,
@ -57,15 +59,15 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
use AssertKind::*; use AssertKind::*;
let msg = match msg { let msg = match msg {
BoundsCheck { len, index } => { 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)), Overflow(op, l, r) => Overflow(op, l.fold_with(folder)?, r.fold_with(folder)?),
OverflowNeg(op) => OverflowNeg(op.fold_with(folder)), OverflowNeg(op) => OverflowNeg(op.fold_with(folder)?),
DivisionByZero(op) => DivisionByZero(op.fold_with(folder)), DivisionByZero(op) => DivisionByZero(op.fold_with(folder)?),
RemainderByZero(op) => RemainderByZero(op.fold_with(folder)), RemainderByZero(op) => RemainderByZero(op.fold_with(folder)?),
ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg, 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, GeneratorDrop => GeneratorDrop,
Resume => Resume, Resume => Resume,
@ -78,13 +80,13 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind }, FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
InlineAsm { template, operands, options, line_spans, destination } => InlineAsm { InlineAsm { template, operands, options, line_spans, destination } => InlineAsm {
template, template,
operands: operands.fold_with(folder), operands: operands.fold_with(folder)?,
options, options,
line_spans, line_spans,
destination, 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> { 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 { impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self { fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
self Ok(self)
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { 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> { impl<'tcx> TypeFoldable<'tcx> for Place<'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> {
Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) } 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> { 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>> { 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)) 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> { 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::*; use crate::mir::Rvalue::*;
match self { Ok(match self {
Use(op) => Use(op.fold_with(folder)), Use(op) => Use(op.fold_with(folder)?),
Repeat(op, len) => Repeat(op.fold_with(folder), len.fold_with(folder)), Repeat(op, len) => Repeat(op.fold_with(folder)?, len.fold_with(folder)?),
ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)), ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)?),
Ref(region, bk, place) => Ref(region.fold_with(folder), bk, place.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)), AddressOf(mutability, place) => AddressOf(mutability, place.fold_with(folder)?),
Len(place) => Len(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)), Cast(kind, op, ty) => Cast(kind, op.fold_with(folder)?, ty.fold_with(folder)?),
BinaryOp(op, box (rhs, lhs)) => { 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 (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)), UnaryOp(op, val) => UnaryOp(op, val.fold_with(folder)?),
Discriminant(place) => Discriminant(place.fold_with(folder)), Discriminant(place) => Discriminant(place.fold_with(folder)?),
NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)), NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)?),
Aggregate(kind, fields) => { Aggregate(kind, fields) => {
let kind = kind.map_id(|kind| match kind { let kind = kind.try_map_id(|kind| {
AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)), Ok(match kind {
AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)?),
AggregateKind::Tuple => AggregateKind::Tuple, AggregateKind::Tuple => AggregateKind::Tuple,
AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt( AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
def, def,
v, v,
substs.fold_with(folder), substs.fold_with(folder)?,
user_ty.fold_with(folder), user_ty.fold_with(folder)?,
n, n,
), ),
AggregateKind::Closure(id, substs) => { AggregateKind::Closure(id, substs) => {
AggregateKind::Closure(id, substs.fold_with(folder)) AggregateKind::Closure(id, substs.fold_with(folder)?)
} }
AggregateKind::Generator(id, substs, movablity) => { AggregateKind::Generator(id, substs, movablity) => {
AggregateKind::Generator(id, substs.fold_with(folder), movablity) AggregateKind::Generator(id, substs.fold_with(folder)?, movablity)
} }
}); })
Aggregate(kind, fields.fold_with(folder)) })?;
} Aggregate(kind, fields.fold_with(folder)?)
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> { 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> { impl<'tcx> TypeFoldable<'tcx> for Operand<'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 { Ok(match self {
Operand::Copy(place) => Operand::Copy(place.fold_with(folder)), Operand::Copy(place) => Operand::Copy(place.fold_with(folder)?),
Operand::Move(place) => Operand::Move(place.fold_with(folder)), Operand::Move(place) => Operand::Move(place.fold_with(folder)?),
Operand::Constant(c) => Operand::Constant(c.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> { 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> { 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::*; use crate::mir::ProjectionElem::*;
match self { Ok(match self {
Deref => Deref, Deref => Deref,
Field(f, ty) => Field(f, ty.fold_with(folder)), Field(f, ty) => Field(f, ty.fold_with(folder)?),
Index(v) => Index(v.fold_with(folder)), Index(v) => Index(v.fold_with(folder)?),
Downcast(symbol, variantidx) => Downcast(symbol, variantidx), Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
ConstantIndex { offset, min_length, from_end } => { ConstantIndex { offset, min_length, from_end } => {
ConstantIndex { offset, min_length, from_end } ConstantIndex { offset, min_length, from_end }
} }
Subslice { from, to, from_end } => Subslice { from, to, from_end }, Subslice { from, to, from_end } => Subslice { from, to, from_end },
} })
} }
fn super_visit_with<Vs: TypeVisitor<'tcx>>( fn super_visit_with<Vs: TypeVisitor<'tcx>>(
@ -312,8 +319,8 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
} }
impl<'tcx> TypeFoldable<'tcx> for Field { impl<'tcx> TypeFoldable<'tcx> for Field {
fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self { fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
self Ok(self)
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE ControlFlow::CONTINUE
@ -321,8 +328,8 @@ impl<'tcx> TypeFoldable<'tcx> for Field {
} }
impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal { impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self { fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
self Ok(self)
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE ControlFlow::CONTINUE
@ -330,8 +337,8 @@ impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
} }
impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> { impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self { fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
self Ok(self)
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE 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> { impl<'tcx> TypeFoldable<'tcx> for Constant<'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> {
Constant { Ok(Constant {
span: self.span, span: self.span,
user_ty: self.user_ty.fold_with(folder), user_ty: self.user_ty.fold_with(folder)?,
literal: self.literal.fold_with(folder), literal: self.literal.fold_with(folder)?,
} })
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.literal.visit_with(visitor)?; self.literal.visit_with(visitor)?;
@ -354,14 +361,14 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
#[inline(always)] #[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) 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 { match self {
ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)), ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.fold_with(folder)?)),
ConstantKind::Val(v, t) => ConstantKind::Val(v, t.fold_with(folder)), ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.fold_with(folder)?)),
} }
} }

View file

@ -179,8 +179,8 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
} }
impl TypeFoldable<'tcx> for hir::Constness { impl TypeFoldable<'tcx> for hir::Constness {
fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Self { fn super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
self Ok(self)
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE ControlFlow::CONTINUE

View file

@ -1260,8 +1260,11 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> {
} }
impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
fn super_fold_with<F: ty::fold::TypeFolder<'tcx>>(self, folder: &mut F) -> Self { fn super_fold_with<F: ty::fold::TypeFolder<'tcx>>(
ParamEnv::new(self.caller_bounds().fold_with(folder), self.reveal().fold_with(folder)) 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> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {

View file

@ -669,8 +669,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> {
/// AdtDefs are basically the same as a DefId. /// AdtDefs are basically the same as a DefId.
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef { impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef {
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> {
self Ok(self)
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> { 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) { 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) { fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<(T, U), F::Error> {
(self.0.fold_with(folder), self.1.fold_with(folder)) 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> { 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> impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>> TypeFoldable<'tcx>
for (A, B, C) for (A, B, C)
{ {
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> (A, B, C) { fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<(A, B, C), F::Error> {
(self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder)) 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> { 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> { 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. // 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> { 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> { 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. // 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> { 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> { impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<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> {
self.map_id(|value| value.fold_with(folder)) self.try_map_id(|value| value.fold_with(folder))
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { 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> { impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<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> {
self.map_id(|t| t.fold_with(folder)) self.try_map_id(|t| t.fold_with(folder))
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { 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]> { impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[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> {
self.map_id(|t| t.fold_with(folder)) self.try_map_id(|t| t.fold_with(folder))
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { 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> { impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, 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> {
self.map_bound(|ty| ty.fold_with(folder)) 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) 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>>> { 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)) 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>> { 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)) 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> { 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)) 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> { 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::*; use crate::ty::InstanceDef::*;
Self { Ok(Self {
substs: self.substs.fold_with(folder), substs: self.substs.fold_with(folder)?,
def: match self.def { def: match self.def {
Item(def) => Item(def.fold_with(folder)), Item(def) => Item(def.fold_with(folder)?),
VtableShim(did) => VtableShim(did.fold_with(folder)), VtableShim(did) => VtableShim(did.fold_with(folder)?),
ReifyShim(did) => ReifyShim(did.fold_with(folder)), ReifyShim(did) => ReifyShim(did.fold_with(folder)?),
Intrinsic(did) => Intrinsic(did.fold_with(folder)), Intrinsic(did) => Intrinsic(did.fold_with(folder)?),
FnPtrShim(did, ty) => FnPtrShim(did.fold_with(folder), ty.fold_with(folder)), FnPtrShim(did, ty) => FnPtrShim(did.fold_with(folder)?, ty.fold_with(folder)?),
Virtual(did, i) => Virtual(did.fold_with(folder), i), Virtual(did, i) => Virtual(did.fold_with(folder)?, i),
ClosureOnceShim { call_once, track_caller } => { 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)), DropGlue(did, ty) => DropGlue(did.fold_with(folder)?, ty.fold_with(folder)?),
CloneShim(did, ty) => CloneShim(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> { 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> { impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'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> {
Self { instance: self.instance.fold_with(folder), promoted: self.promoted } 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> { 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> { 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() { let kind = match *self.kind() {
ty::RawPtr(tm) => ty::RawPtr(tm.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::Array(typ, sz) => ty::Array(typ.fold_with(folder)?, sz.fold_with(folder)?),
ty::Slice(typ) => ty::Slice(typ.fold_with(folder)), ty::Slice(typ) => ty::Slice(typ.fold_with(folder)?),
ty::Adt(tid, substs) => ty::Adt(tid, substs.fold_with(folder)), ty::Adt(tid, substs) => ty::Adt(tid, substs.fold_with(folder)?),
ty::Dynamic(trait_ty, region) => { 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::Tuple(ts) => ty::Tuple(ts.fold_with(folder)?),
ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.fold_with(folder)), ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.fold_with(folder)?),
ty::FnPtr(f) => ty::FnPtr(f.fold_with(folder)), ty::FnPtr(f) => ty::FnPtr(f.fold_with(folder)?),
ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl), 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, 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::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)?),
ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)), ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)?),
ty::Projection(data) => ty::Projection(data.fold_with(folder)), ty::Projection(data) => ty::Projection(data.fold_with(folder)?),
ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)), ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)?),
ty::Bool ty::Bool
| ty::Char | ty::Char
@ -903,13 +903,13 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
| ty::Bound(..) | ty::Bound(..)
| ty::Placeholder(..) | ty::Placeholder(..)
| ty::Never | 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) folder.fold_ty(self)
} }
@ -961,11 +961,11 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
} }
impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ty::Region<'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> {
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_region(self) folder.fold_region(self)
} }
@ -979,13 +979,13 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
} }
impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'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) folder.fold_predicate(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> {
let new = self.inner.kind.fold_with(folder); let new = self.inner.kind.fold_with(folder)?;
folder.tcx().reuse_or_mk_predicate(self, new) Ok(folder.tcx().reuse_or_mk_predicate(self, new))
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { 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>> { 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)) 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> { 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 { fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
self.map_id(|x| x.fold_with(folder)) self.try_map_id(|x| x.fold_with(folder))
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { 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> { impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'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 ty = self.ty.fold_with(folder); let ty = self.ty.fold_with(folder)?;
let val = self.val.fold_with(folder); let val = self.val.fold_with(folder)?;
if ty != self.ty || val != self.val { 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 { } 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) 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> { impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'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 { Ok(match self {
ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)), ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)?),
ty::ConstKind::Param(p) => ty::ConstKind::Param(p.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::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)?),
ty::ConstKind::Value(_) ty::ConstKind::Value(_)
| ty::ConstKind::Bound(..) | ty::ConstKind::Bound(..)
| ty::ConstKind::Placeholder(..) | ty::ConstKind::Placeholder(..)
| ty::ConstKind::Error(_) => self, | ty::ConstKind::Error(_) => self,
} })
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { 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> { impl<'tcx> TypeFoldable<'tcx> for InferConst<'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> {
self Ok(self)
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> { 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 { fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
ty::Unevaluated { ty::Unevaluated {
def: self.def, def: self.def,
substs_: Some(self.substs(folder.tcx()).fold_with(folder)), substs_: Some(self.substs(folder.tcx()).fold_with(folder)?),
promoted: self.promoted, 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 { fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
ty::Unevaluated { ty::Unevaluated {
def: self.def, def: self.def,
substs_: Some(self.substs(folder.tcx()).fold_with(folder)), substs_: Some(self.substs(folder.tcx()).fold_with(folder)?),
promoted: self.promoted, promoted: self.promoted,
} }
} }

View file

@ -1101,6 +1101,18 @@ impl<'tcx, T> Binder<'tcx, T> {
Binder(value, self.1) 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 /// 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* /// current `Binder`. This should not be used if the new value *changes*
/// the bound variables. Note: the (old or new) value itself does not /// the bound variables. Note: the (old or new) value itself does not

View file

@ -153,11 +153,11 @@ impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> {
} }
impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> { 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() { match self.unpack() {
GenericArgKind::Lifetime(lt) => lt.fold_with(folder).into(), GenericArgKind::Lifetime(lt) => lt.fold_with(folder).map(Into::into),
GenericArgKind::Type(ty) => ty.fold_with(folder).into(), GenericArgKind::Type(ty) => ty.fold_with(folder).map(Into::into),
GenericArgKind::Const(ct) => ct.fold_with(folder).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> { 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 // This code is hot enough that it's worth specializing for the most
// common length lists, to avoid the overhead of `SmallVec` creation. // 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 // 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`. // calling `intern_substs`.
match self.len() { match self.len() {
1 => { 1 => {
let param0 = self[0].fold_with(folder); let param0 = self[0].fold_with(folder)?;
if param0 == self[0] { self } else { folder.tcx().intern_substs(&[param0]) } if param0 == self[0] { Ok(self) } else { Ok(folder.tcx().intern_substs(&[param0])) }
} }
2 => { 2 => {
let param0 = self[0].fold_with(folder); let param0 = self[0].fold_with(folder)?;
let param1 = self[1].fold_with(folder); let param1 = self[1].fold_with(folder)?;
if param0 == self[0] && param1 == self[1] { if param0 == self[0] && param1 == self[1] {
self Ok(self)
} else { } 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(); let params: SmallVec<[_; 8]> =
if params[..] == self[..] { self } else { folder.tcx().intern_substs(&params) } self.iter().map(|k| k.fold_with(folder)).collect::<Result<_, _>>()?;
if params[..] == self[..] {
Ok(self)
} else {
Ok(folder.tcx().intern_substs(&params))
}
} }
} }
} }