1
Fork 0

Auto merge of #91230 - eggyal:fallible-type-fold, r=jackh726

Make `TypeFolder::fold_*` return `Result`

Implements rust-lang/compiler-team#432.

Initially this is just a rebase of `@LeSeulArtichaut's` work in #85469 (abandoned; see https://github.com/rust-lang/rust/pull/85485#issuecomment-908781112).  At that time, it caused a regression in performance that required some further exploration... with this rebased PR bors can hopefully report some perf analysis from which we can investigate further (if the regression is indeed still present).

r? `@jackh726` cc `@nikomatsakis`
This commit is contained in:
bors 2021-11-28 13:04:27 +00:00
commit e6d2de9483
45 changed files with 908 additions and 794 deletions

View file

@ -23,6 +23,7 @@ Rust MIR: a lowered representation of Rust.
#![feature(trusted_len)] #![feature(trusted_len)]
#![feature(trusted_step)] #![feature(trusted_step)]
#![feature(try_blocks)] #![feature(try_blocks)]
#![feature(unwrap_infallible)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#[macro_use] #[macro_use]

View file

@ -95,7 +95,8 @@ pub fn equal_up_to_regions(
// Leave consts and types unchanged. // Leave consts and types unchanged.
ct_op: |ct| ct, ct_op: |ct| ct,
ty_op: |ty| ty, ty_op: |ty| ty,
}), })
.into_ok(),
) )
}; };
tcx.infer_ctxt().enter(|infcx| infcx.can_eq(param_env, normalize(src), normalize(dest)).is_ok()) tcx.infer_ctxt().enter(|infcx| infcx.can_eq(param_env, normalize(src), normalize(dest)).is_ok())

View file

@ -1,35 +1,42 @@
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use std::mem; use std::mem;
use std::ptr;
pub trait IdFunctor { pub trait IdFunctor: Sized {
type Inner; type Inner;
fn map_id<F>(self, f: F) -> Self
where
F: FnMut(Self::Inner) -> Self::Inner;
}
impl<T> IdFunctor for Box<T> {
type Inner = T;
#[inline] #[inline]
fn map_id<F>(self, mut f: F) -> Self fn map_id<F>(self, mut f: F) -> Self
where 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
F: FnMut(Self::Inner) -> Result<Self::Inner, E>;
}
impl<T> IdFunctor for Box<T> {
type Inner = T;
#[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); let raw = Box::into_raw(self);
unsafe { Ok(unsafe {
// SAFETY: The raw pointer points to a valid value of type `T`. // 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 // SAFETY: Converts `Box<T>` to `Box<MaybeUninit<T>>` which is the
// inverse of `Box::assume_init()` and should be safe. // inverse of `Box::assume_init()` and should be safe.
let mut raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast()); let mut raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast());
// SAFETY: Write the mapped value back into the `Box`. // SAFETY: Write the mapped value back into the `Box`.
raw.write(f(value)); raw.write(f(value)?);
// SAFETY: We just initialized `raw`. // SAFETY: We just initialized `raw`.
raw.assume_init() raw.assume_init()
} })
} }
} }
@ -37,9 +44,9 @@ impl<T> IdFunctor for Vec<T> {
type Inner = T; type Inner = T;
#[inline] #[inline]
fn map_id<F>(mut self, mut f: F) -> Self fn try_map_id<F, E>(mut self, mut f: F) -> Result<Self, E>
where where
F: FnMut(Self::Inner) -> Self::Inner, F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
{ {
// FIXME: We don't really care about panics here and leak // FIXME: We don't really care about panics here and leak
// far more than we should, but that should be fine for now. // far more than we should, but that should be fine for now.
@ -49,11 +56,26 @@ impl<T> IdFunctor for Vec<T> {
let start = self.as_mut_ptr(); let start = self.as_mut_ptr();
for i in 0..len { for i in 0..len {
let p = start.add(i); let p = start.add(i);
ptr::write(p, f(ptr::read(p))); 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) {
start.add(j).drop_in_place();
}
// returning will drop self, releasing the allocation
// (len is 0 so elements will not be re-dropped)
return Err(err);
}
}
} }
// Even if we encountered an error, set the len back
// so we don't leak memory.
self.set_len(len); self.set_len(len);
} }
self Ok(self)
} }
} }
@ -61,11 +83,11 @@ impl<T> IdFunctor for Box<[T]> {
type Inner = T; type Inner = T;
#[inline] #[inline]
fn map_id<F>(self, f: F) -> Self fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
where where
F: FnMut(Self::Inner) -> Self::Inner, F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
{ {
Vec::from(self).map_id(f).into() Vec::from(self).try_map_id(f).map(Into::into)
} }
} }
@ -73,10 +95,10 @@ impl<I: Idx, T> IdFunctor for IndexVec<I, T> {
type Inner = T; type Inner = T;
#[inline] #[inline]
fn map_id<F>(self, f: F) -> Self fn try_map_id<F, E>(self, f: F) -> Result<Self, E>
where where
F: FnMut(Self::Inner) -> Self::Inner, F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
{ {
IndexVec::from_raw(self.raw.map_id(f)) self.raw.try_map_id(f).map(IndexVec::from_raw)
} }
} }

View file

@ -25,6 +25,7 @@
#![feature(once_cell)] #![feature(once_cell)]
#![feature(test)] #![feature(test)]
#![feature(thread_id_value)] #![feature(thread_id_value)]
#![feature(unwrap_infallible)]
#![allow(rustc::default_hash_types)] #![allow(rustc::default_hash_types)]
#![deny(unaligned_references)] #![deny(unaligned_references)]

View file

@ -278,7 +278,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
self.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 where
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,
{ {
@ -288,13 +288,13 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
t 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 { match *r {
ty::ReLateBound(index, ..) => { ty::ReLateBound(index, ..) => {
if index >= self.binder_index { if index >= self.binder_index {
bug!("escaping late-bound region during canonicalization"); bug!("escaping late-bound region during canonicalization");
} else { } else {
r Ok(r)
} }
} }
@ -311,7 +311,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
vid, r vid, r
); );
let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid)); 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 ty::ReStatic
@ -319,11 +319,11 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
| ty::ReFree(_) | ty::ReFree(_)
| ty::ReEmpty(_) | ty::ReEmpty(_)
| ty::RePlaceholder(..) | 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() { match *t.kind() {
ty::Infer(ty::TyVar(vid)) => { ty::Infer(ty::TyVar(vid)) => {
debug!("canonical: type var found with vid {:?}", 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) => { Err(mut ui) => {
// FIXME: perf problem described in #55921. // FIXME: perf problem described in #55921.
ui = ty::UniverseIndex::ROOT; ui = ty::UniverseIndex::ROOT;
self.canonicalize_ty_var( Ok(self.canonicalize_ty_var(
CanonicalVarInfo { CanonicalVarInfo {
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)), kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
}, },
t, t,
) ))
} }
} }
} }
ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var( ty::Infer(ty::IntVar(_)) => Ok(self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) }, CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
t, t,
), )),
ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var( ty::Infer(ty::FloatVar(_)) => Ok(self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) }, CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
t, t,
), )),
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
bug!("encountered a fresh type during canonicalization") 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) }, CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderTy(placeholder) },
t, t,
), )),
ty::Bound(debruijn, _) => { ty::Bound(debruijn, _) => {
if debruijn >= self.binder_index { if debruijn >= self.binder_index {
bug!("escaping bound type during canonicalization") bug!("escaping bound type during canonicalization")
} else { } 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) { if t.flags().intersects(self.needs_canonical_flags) {
t.super_fold_with(self) t.super_fold_with(self)
} else { } 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 { match ct.val {
ty::ConstKind::Infer(InferConst::Var(vid)) => { ty::ConstKind::Infer(InferConst::Var(vid)) => {
debug!("canonical: const var found with vid {:?}", 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) => { Err(mut ui) => {
// FIXME: perf problem described in #55921. // FIXME: perf problem described in #55921.
ui = ty::UniverseIndex::ROOT; ui = ty::UniverseIndex::ROOT;
return self.canonicalize_const_var( return Ok(self.canonicalize_const_var(
CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) }, CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) },
ct, ct,
); ));
} }
} }
} }
@ -438,20 +441,20 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
if debruijn >= self.binder_index { if debruijn >= self.binder_index {
bug!("escaping bound type during canonicalization") bug!("escaping bound type during canonicalization")
} else { } else {
return ct; return Ok(ct);
} }
} }
ty::ConstKind::Placeholder(placeholder) => { ty::ConstKind::Placeholder(placeholder) => {
return self.canonicalize_const_var( return Ok(self.canonicalize_const_var(
CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderConst(placeholder) }, CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderConst(placeholder) },
ct, ct,
); ));
} }
_ => {} _ => {}
} }
let flags = FlagComputation::for_const(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) }
} }
} }
@ -500,7 +503,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
indices: FxHashMap::default(), indices: FxHashMap::default(),
binder_index: ty::INNERMOST, 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 // Once we have canonicalized `out_value`, it should not
// contain anything that ties it to this inference context // contain anything that ties it to this inference context
@ -618,7 +621,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
let infcx = self.infcx; let infcx = self.infcx;
let bound_to = infcx.shallow_resolve(ty_var); let bound_to = infcx.shallow_resolve(ty_var);
if bound_to != ty_var { if bound_to != ty_var {
self.fold_ty(bound_to) self.fold_ty(bound_to).into_ok()
} else { } else {
let var = self.canonical_var(info, ty_var.into()); let var = self.canonical_var(info, ty_var.into());
self.tcx().mk_ty(ty::Bound(self.binder_index, var.into())) self.tcx().mk_ty(ty::Bound(self.binder_index, var.into()))
@ -637,12 +640,12 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
let infcx = self.infcx; let infcx = self.infcx;
let bound_to = infcx.shallow_resolve(const_var); let bound_to = infcx.shallow_resolve(const_var);
if bound_to != const_var { if bound_to != const_var {
self.fold_const(bound_to) self.fold_const(bound_to).into_ok()
} else { } else {
let var = self.canonical_var(info, const_var.into()); let var = self.canonical_var(info, const_var.into());
self.tcx().mk_const(ty::Const { self.tcx().mk_const(ty::Const {
val: ty::ConstKind::Bound(self.binder_index, var), val: ty::ConstKind::Bound(self.binder_index, var),
ty: self.fold_ty(const_var.ty), ty: self.fold_ty(const_var.ty).into_ok(),
}) })
} }
} }

View file

@ -72,7 +72,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
F: FnOnce(u32) -> ty::InferTy, F: FnOnce(u32) -> ty::InferTy,
{ {
if let Some(ty) = opt_ty { 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) { match self.ty_freshen_map.entry(key) {
@ -98,7 +98,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
F: FnOnce(u32) -> ty::InferConst<'tcx>, F: FnOnce(u32) -> ty::InferConst<'tcx>,
{ {
if let Some(ct) = opt_ct { 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) { match self.const_freshen_map.entry(key) {
@ -119,11 +119,11 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
self.infcx.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 { match *r {
ty::ReLateBound(..) => { ty::ReLateBound(..) => {
// leave bound regions alone // leave bound regions alone
r Ok(r)
} }
ty::ReEarlyBound(..) ty::ReEarlyBound(..)
@ -133,21 +133,21 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
| ty::ReEmpty(_) | ty::ReEmpty(_)
| ty::ReErased => { | ty::ReErased => {
// replace all free regions with 'erased // replace all free regions with 'erased
self.tcx().lifetimes.re_erased Ok(self.tcx().lifetimes.re_erased)
} }
ty::ReStatic => { ty::ReStatic => {
if self.keep_static { if self.keep_static {
r Ok(r)
} else { } 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()) { if !t.needs_infer() && !t.has_erasable_regions(self.tcx()) {
return t; return Ok(t);
} }
let tcx = self.infcx.tcx; let tcx = self.infcx.tcx;
@ -155,10 +155,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
match *t.kind() { match *t.kind() {
ty::Infer(ty::TyVar(v)) => { ty::Infer(ty::TyVar(v)) => {
let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); 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 self.infcx
.inner .inner
.borrow_mut() .borrow_mut()
@ -167,9 +167,9 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
.map(|v| v.to_type(tcx)), .map(|v| v.to_type(tcx)),
ty::IntVar(v), ty::IntVar(v),
ty::FreshIntTy, ty::FreshIntTy,
), )),
ty::Infer(ty::FloatVar(v)) => self.freshen_ty( ty::Infer(ty::FloatVar(v)) => Ok(self.freshen_ty(
self.infcx self.infcx
.inner .inner
.borrow_mut() .borrow_mut()
@ -178,7 +178,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
.map(|v| v.to_type(tcx)), .map(|v| v.to_type(tcx)),
ty::FloatVar(v), ty::FloatVar(v),
ty::FreshFloatTy, ty::FreshFloatTy,
), )),
ty::Infer(ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct)) => { ty::Infer(ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct)) => {
if ct >= self.ty_freshen_count { if ct >= self.ty_freshen_count {
@ -189,7 +189,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
self.ty_freshen_count self.ty_freshen_count
); );
} }
t Ok(t)
} }
ty::Generator(..) 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 { match ct.val {
ty::ConstKind::Infer(ty::InferConst::Var(v)) => { ty::ConstKind::Infer(ty::InferConst::Var(v)) => {
let opt_ct = self let opt_ct = self
@ -232,12 +235,12 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
.probe_value(v) .probe_value(v)
.val .val
.known(); .known();
return self.freshen_const( return Ok(self.freshen_const(
opt_ct, opt_ct,
ty::InferConst::Var(v), ty::InferConst::Var(v),
ty::InferConst::Fresh, ty::InferConst::Fresh,
ct.ty, ct.ty,
); ));
} }
ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => { ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => {
if i >= self.const_freshen_count { if i >= self.const_freshen_count {
@ -248,7 +251,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
self.const_freshen_count, self.const_freshen_count,
); );
} }
return ct; return Ok(ct);
} }
ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {

View file

@ -161,7 +161,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
{ {
Ok(value) Ok(value)
} else { } else {
Ok(value.fold_with(&mut fudger)) Ok(value.fold_with(&mut fudger).into_ok())
} }
} }
} }
@ -180,7 +180,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> {
self.infcx.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() { match *ty.kind() {
ty::Infer(ty::InferTy::TyVar(vid)) => { ty::Infer(ty::InferTy::TyVar(vid)) => {
if self.type_vars.0.contains(&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. // Recreate it with a fresh variable here.
let idx = (vid.as_usize() - self.type_vars.0.start.as_usize()) as usize; let idx = (vid.as_usize() - self.type_vars.0.start.as_usize()) as usize;
let origin = self.type_vars.1[idx]; let origin = self.type_vars.1[idx];
self.infcx.next_ty_var(origin) Ok(self.infcx.next_ty_var(origin))
} else { } else {
// This variable was created before the // This variable was created before the
// "fudging". Since we refresh all type // "fudging". Since we refresh all type
@ -198,48 +198,43 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> {
debug_assert!( debug_assert!(
self.infcx.inner.borrow_mut().type_variables().probe(vid).is_unknown() self.infcx.inner.borrow_mut().type_variables().probe(vid).is_unknown()
); );
ty Ok(ty)
} }
} }
ty::Infer(ty::InferTy::IntVar(vid)) => { ty::Infer(ty::InferTy::IntVar(vid)) => {
if self.int_vars.contains(&vid) { Ok(if self.int_vars.contains(&vid) { self.infcx.next_int_var() } else { ty })
self.infcx.next_int_var()
} else {
ty
}
} }
ty::Infer(ty::InferTy::FloatVar(vid)) => { ty::Infer(ty::InferTy::FloatVar(vid)) => {
if self.float_vars.contains(&vid) { Ok(if self.float_vars.contains(&vid) { self.infcx.next_float_var() } else { ty })
self.infcx.next_float_var()
} else {
ty
}
} }
_ => ty.super_fold_with(self), _ => 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 let ty::ReVar(vid) = *r {
if self.region_vars.0.contains(&vid) { if self.region_vars.0.contains(&vid) {
let idx = vid.index() - self.region_vars.0.start.index(); let idx = vid.index() - self.region_vars.0.start.index();
let origin = self.region_vars.1[idx]; 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 let ty::Const { val: ty::ConstKind::Infer(ty::InferConst::Var(vid)), ty } = ct {
if self.const_vars.0.contains(&vid) { if self.const_vars.0.contains(&vid) {
// This variable was created during the fudging. // This variable was created during the fudging.
// Recreate it with a fresh variable here. // Recreate it with a fresh variable here.
let idx = (vid.index - self.const_vars.0.start.index) as usize; let idx = (vid.index - self.const_vars.0.start.index) as usize;
let origin = self.const_vars.1[idx]; let origin = self.const_vars.1[idx];
self.infcx.next_const_var(ty, origin) Ok(self.infcx.next_const_var(ty, origin))
} else { } else {
ct Ok(ct)
} }
} else { } else {
ct.super_fold_with(self) ct.super_fold_with(self)

View file

@ -681,7 +681,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} }
pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T { 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` /// Returns the origin of the type variable identified by `vid`, or `None`
@ -1381,7 +1381,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
where where
T: TypeFoldable<'tcx>, 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 { 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. return value; // Avoid duplicated subst-folding.
} }
let mut r = resolve::OpportunisticVarResolver::new(self); 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 /// Returns the first unresolved variable contained in `T`. In the
@ -1745,12 +1745,15 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
self.infcx.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> {
self.infcx.shallow_resolve_ty(ty) Ok(self.infcx.shallow_resolve_ty(ty))
} }
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { fn fold_const(
if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = ct { &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 self.infcx
.inner .inner
.borrow_mut() .borrow_mut()
@ -1761,7 +1764,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
.unwrap_or(ct) .unwrap_or(ct)
} else { } else {
ct ct
} })
} }
} }

View file

@ -418,92 +418,94 @@ struct Instantiator<'a, 'tcx> {
impl<'a, 'tcx> Instantiator<'a, 'tcx> { impl<'a, 'tcx> Instantiator<'a, 'tcx> {
fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T { fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
let tcx = self.infcx.tcx; let tcx = self.infcx.tcx;
value.fold_with(&mut BottomUpFolder { value
tcx, .fold_with(&mut BottomUpFolder {
ty_op: |ty| { tcx,
if ty.references_error() { ty_op: |ty| {
return tcx.ty_error(); if ty.references_error() {
} else if let ty::Opaque(def_id, substs) = ty.kind() { return tcx.ty_error();
// Check that this is `impl Trait` type is } else if let ty::Opaque(def_id, substs) = ty.kind() {
// declared by `parent_def_id` -- i.e., one whose // Check that this is `impl Trait` type is
// value we are inferring. At present, this is // declared by `parent_def_id` -- i.e., one whose
// always true during the first phase of // value we are inferring. At present, this is
// type-check, but not always true later on during // always true during the first phase of
// NLL. Once we support named opaque types more fully, // type-check, but not always true later on during
// this same scenario will be able to arise during all phases. // 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: // Here is an example using type alias `impl Trait`
// // that indicates the distinction we are checking for:
// ```rust //
// mod a { // ```rust
// pub type Foo = impl Iterator; // mod a {
// pub fn make_foo() -> Foo { .. } // pub type Foo = impl Iterator;
// } // pub fn make_foo() -> Foo { .. }
// // }
// mod b { //
// fn foo() -> a::Foo { a::make_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 // Here, the return type of `foo` references an
// presently being inferred. You can get into a // `Opaque` indeed, but not one whose value is
// similar situation with closure return types // presently being inferred. You can get into a
// today: // similar situation with closure return types
// // today:
// ```rust //
// fn foo() -> impl Iterator { .. } // ```rust
// fn bar() { // fn foo() -> impl Iterator { .. }
// let x = || foo(); // returns the Opaque assoc with `foo` // 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); if let Some(def_id) = def_id.as_local() {
let parent_def_id = self.infcx.defining_use_anchor; let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let def_scope_default = || { let parent_def_id = self.infcx.defining_use_anchor;
let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id); let def_scope_default = || {
parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id) 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),
}; };
if in_definition_scope { let (in_definition_scope, origin) =
let opaque_type_key = match tcx.hir().expect_item(opaque_hir_id).kind {
OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; // Anonymous `impl Trait`
return self.fold_opaque_ty(ty, opaque_type_key, origin); 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!( debug!(
"instantiate_opaque_types_in_map: \ "instantiate_opaque_types_in_map: \
encountered opaque outside its definition scope \ encountered opaque outside its definition scope \
def_id={:?}", def_id={:?}",
def_id, def_id,
); );
}
} }
}
ty ty
}, },
lt_op: |lt| lt, lt_op: |lt| lt,
ct_op: |ct| ct, ct_op: |ct| ct,
}) })
.into_ok()
} }
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
@ -556,21 +558,23 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
debug!(?predicate); debug!(?predicate);
// We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them. // 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 { let predicate = predicate
tcx, .fold_with(&mut BottomUpFolder {
ty_op: |ty| match ty.kind() { tcx,
ty::Projection(projection_ty) => infcx.infer_projection( ty_op: |ty| match ty.kind() {
self.param_env, ty::Projection(projection_ty) => infcx.infer_projection(
*projection_ty, self.param_env,
traits::ObligationCause::misc(self.value_span, self.body_id), *projection_ty,
0, traits::ObligationCause::misc(self.value_span, self.body_id),
&mut self.obligations, 0,
), &mut self.obligations,
_ => ty, ),
}, _ => ty,
lt_op: |lt| lt, },
ct_op: |ct| ct, lt_op: |lt| lt,
}); ct_op: |ct| ct,
})
.into_ok();
debug!(?predicate); debug!(?predicate);
if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() { if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {

View file

@ -30,25 +30,28 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
self.infcx.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() { 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 { } else {
let t = self.infcx.shallow_resolve(t); let t = self.infcx.shallow_resolve(t);
t.super_fold_with(self) 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() { 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 { } else {
let ct = self.infcx.shallow_resolve(ct); let ct = self.infcx.shallow_resolve(ct);
ct.super_fold_with(self) 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) constant.super_fold_with(self)
} }
} }
@ -75,16 +78,16 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
self.infcx.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() { 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 { } else {
t.super_fold_with(self) 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> {
match *r { Ok(match *r {
ty::ReVar(rid) => { ty::ReVar(rid) => {
let resolved = self let resolved = self
.infcx .infcx
@ -95,12 +98,15 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
self.tcx().reuse_or_mk_region(r, ty::ReVar(resolved)) self.tcx().reuse_or_mk_region(r, ty::ReVar(resolved))
} }
_ => r, _ => 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() { 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 { } else {
ct.super_fold_with(self) ct.super_fold_with(self)
} }
@ -175,44 +181,31 @@ pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, value: T) -> Fixu
where where
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,
{ {
let mut full_resolver = FullTypeResolver { infcx, err: None }; value.fold_with(&mut FullTypeResolver { infcx })
let result = value.fold_with(&mut full_resolver);
match full_resolver.err {
None => Ok(result),
Some(e) => Err(e),
}
} }
// N.B. This type is not public because the protocol around checking the // N.B. This type is not public because the protocol around checking the
// `err` field is not enforceable otherwise. // `err` field is not enforceable otherwise.
struct FullTypeResolver<'a, 'tcx> { struct FullTypeResolver<'a, 'tcx> {
infcx: &'a InferCtxt<'a, 'tcx>, infcx: &'a InferCtxt<'a, 'tcx>,
err: Option<FixupError<'tcx>>,
} }
impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
type Error = FixupError<'tcx>;
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
self.infcx.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() { 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 { } else {
let t = self.infcx.shallow_resolve(t); let t = self.infcx.shallow_resolve(t);
match *t.kind() { match *t.kind() {
ty::Infer(ty::TyVar(vid)) => { ty::Infer(ty::TyVar(vid)) => Err(FixupError::UnresolvedTy(vid)),
self.err = Some(FixupError::UnresolvedTy(vid)); ty::Infer(ty::IntVar(vid)) => Err(FixupError::UnresolvedIntTy(vid)),
self.tcx().ty_error() ty::Infer(ty::FloatVar(vid)) => Err(FixupError::UnresolvedFloatTy(vid)),
}
ty::Infer(ty::IntVar(vid)) => {
self.err = Some(FixupError::UnresolvedIntTy(vid));
self.tcx().ty_error()
}
ty::Infer(ty::FloatVar(vid)) => {
self.err = Some(FixupError::UnresolvedFloatTy(vid));
self.tcx().ty_error()
}
ty::Infer(_) => { ty::Infer(_) => {
bug!("Unexpected type in full type resolver: {:?}", t); bug!("Unexpected type in full type resolver: {:?}", t);
} }
@ -221,28 +214,30 @@ 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 { match *r {
ty::ReVar(rid) => self ty::ReVar(rid) => Ok(self
.infcx .infcx
.lexical_region_resolutions .lexical_region_resolutions
.borrow() .borrow()
.as_ref() .as_ref()
.expect("region resolution not performed") .expect("region resolution not performed")
.resolve_var(rid), .resolve_var(rid)),
_ => r, _ => 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() { 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 { } else {
let c = self.infcx.shallow_resolve(c); let c = self.infcx.shallow_resolve(c);
match c.val { match c.val {
ty::ConstKind::Infer(InferConst::Var(vid)) => { ty::ConstKind::Infer(InferConst::Var(vid)) => {
self.err = Some(FixupError::UnresolvedConst(vid)); return Err(FixupError::UnresolvedConst(vid));
return self.tcx().const_error(c.ty);
} }
ty::ConstKind::Infer(InferConst::Fresh(_)) => { ty::ConstKind::Infer(InferConst::Fresh(_)) => {
bug!("Unexpected const in full const resolver: {:?}", c); bug!("Unexpected const in full const resolver: {:?}", c);

View file

@ -24,6 +24,7 @@
#![feature(control_flow_enum)] #![feature(control_flow_enum)]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(label_break_value)] #![feature(label_break_value)]
#![feature(unwrap_infallible)]
#![recursion_limit = "512"] // For rustdoc #![recursion_limit = "512"] // For rustdoc
#[macro_use] #[macro_use]

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

@ -56,6 +56,7 @@
#![feature(try_blocks)] #![feature(try_blocks)]
#![feature(try_reserve_kind)] #![feature(try_reserve_kind)]
#![feature(nonzero_ops)] #![feature(nonzero_ops)]
#![feature(unwrap_infallible)]
#![recursion_limit = "512"] #![recursion_limit = "512"]
#[macro_use] #[macro_use]

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::Tuple => AggregateKind::Tuple, AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)?),
AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt( AggregateKind::Tuple => AggregateKind::Tuple,
def, AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
v, def,
substs.fold_with(folder), v,
user_ty.fold_with(folder), substs.fold_with(folder)?,
n, user_ty.fold_with(folder)?,
), n,
AggregateKind::Closure(id, substs) => { ),
AggregateKind::Closure(id, substs.fold_with(folder)) AggregateKind::Closure(id, substs) => {
} AggregateKind::Closure(id, substs.fold_with(folder)?)
AggregateKind::Generator(id, substs, movablity) => { }
AggregateKind::Generator(id, substs.fold_with(folder), movablity) AggregateKind::Generator(id, substs, 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

@ -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> { 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 // N.B., use `super_fold_with` here. If we used `fold_with`, it
// could invoke the `erase_regions_ty` query recursively. // 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> { impl<'tcx> TyCtxt<'tcx> {
@ -27,7 +27,7 @@ impl<'tcx> TyCtxt<'tcx> {
return value; return value;
} }
debug!("erase_regions({:?})", 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); debug!("erase_regions = {:?}", value1);
value1 value1
} }
@ -42,11 +42,11 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> {
self.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.needs_infer() { ty.super_fold_with(self) } else { self.tcx.erase_regions_ty(ty) } 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 where
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,
{ {
@ -54,7 +54,7 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> {
u.super_fold_with(self) 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 // because late-bound regions affect subtyping, we can't
// erase the bound/free distinction, but we can replace // erase the bound/free distinction, but we can replace
// all free regions with 'erased. // 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 // away. In codegen, they will always be erased to 'erased
// whenever a substitution occurs. // whenever a substitution occurs.
match *r { match *r {
ty::ReLateBound(..) => r, ty::ReLateBound(..) => Ok(r),
_ => self.tcx.lifetimes.re_erased, _ => 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) c.super_fold_with(self)
} }
} }

View file

@ -46,8 +46,8 @@ use std::ops::ControlFlow;
/// ///
/// To implement this conveniently, use the derive macro located in `rustc_macros`. /// To implement this conveniently, use the derive macro located in `rustc_macros`.
pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
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>;
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> {
self.super_fold_with(folder) self.super_fold_with(folder)
} }
@ -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
@ -193,32 +193,43 @@ impl TypeFoldable<'tcx> for hir::Constness {
/// identity fold, it should invoke `foo.fold_with(self)` to fold each /// identity fold, it should invoke `foo.fold_with(self)` to fold each
/// sub-item. /// sub-item.
pub trait TypeFolder<'tcx>: Sized { pub trait TypeFolder<'tcx>: Sized {
type Error = !;
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; 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 where
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,
{ {
t.super_fold_with(self) 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) 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) 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) 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) 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) bug!("most type folders should not be folding MIR datastructures: {:?}", c)
} }
} }
@ -290,19 +301,22 @@ where
self.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> {
let t = ty.super_fold_with(self); let t = ty.super_fold_with(self)?;
(self.ty_op)(t) Ok((self.ty_op)(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 r = r.super_fold_with(self); let r = r.super_fold_with(self)?;
(self.lt_op)(r) Ok((self.lt_op)(r))
} }
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { fn fold_const(
let ct = ct.super_fold_with(self); &mut self,
(self.ct_op)(ct) ct: &'tcx ty::Const<'tcx>,
) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
let ct = ct.super_fold_with(self)?;
Ok((self.ct_op)(ct))
} }
} }
@ -322,7 +336,7 @@ impl<'tcx> TyCtxt<'tcx> {
where where
T: TypeFoldable<'tcx>, 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`. /// Invoke `callback` on every region appearing free in `value`.
@ -470,7 +484,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
fn fold_binder<T: TypeFoldable<'tcx>>( fn fold_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: ty::Binder<'tcx, T>, t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> { ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
self.current_index.shift_in(1); self.current_index.shift_in(1);
let t = t.super_fold_with(self); let t = t.super_fold_with(self);
self.current_index.shift_out(1); self.current_index.shift_out(1);
@ -478,16 +492,16 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
} }
#[instrument(skip(self), level = "debug")] #[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 { match *r {
ty::ReLateBound(debruijn, _) if debruijn < self.current_index => { ty::ReLateBound(debruijn, _) if debruijn < self.current_index => {
debug!(?self.current_index, "skipped bound region"); debug!(?self.current_index, "skipped bound region");
*self.skipped_regions = true; *self.skipped_regions = true;
r Ok(r)
} }
_ => { _ => {
debug!(?self.current_index, "folding free region"); debug!(?self.current_index, "folding free region");
(self.fold_region_fn)(r, self.current_index) Ok((self.fold_region_fn)(r, self.current_index))
} }
} }
} }
@ -528,19 +542,19 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> {
fn fold_binder<T: TypeFoldable<'tcx>>( fn fold_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: ty::Binder<'tcx, T>, t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> { ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
self.current_index.shift_in(1); self.current_index.shift_in(1);
let t = t.super_fold_with(self); let t = t.super_fold_with(self);
self.current_index.shift_out(1); self.current_index.shift_out(1);
t 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() { match *t.kind() {
ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => { ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => {
if let Some(fld_t) = self.fld_t.as_mut() { if let Some(fld_t) = self.fld_t.as_mut() {
let ty = fld_t(bound_ty); 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) => { _ if t.has_vars_bound_at_or_above(self.current_index) => {
@ -548,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 { match *r {
ty::ReLateBound(debruijn, br) if debruijn == self.current_index => { ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
if let Some(fld_r) = self.fld_r.as_mut() { if let Some(fld_r) = self.fld_r.as_mut() {
@ -562,25 +576,28 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> {
// debruijn index. Then we adjust it to the // debruijn index. Then we adjust it to the
// correct depth. // correct depth.
assert_eq!(debruijn1, ty::INNERMOST); assert_eq!(debruijn1, ty::INNERMOST);
self.tcx.mk_region(ty::ReLateBound(debruijn, br)) Ok(self.tcx.mk_region(ty::ReLateBound(debruijn, br)))
} else { } 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 { match *ct {
ty::Const { val: ty::ConstKind::Bound(debruijn, bound_const), ty } ty::Const { val: ty::ConstKind::Bound(debruijn, bound_const), ty }
if debruijn == self.current_index => if debruijn == self.current_index =>
{ {
if let Some(fld_c) = self.fld_c.as_mut() { if let Some(fld_c) = self.fld_c.as_mut() {
let ct = fld_c(bound_const, ty); 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) => { _ if ct.has_vars_bound_at_or_above(self.current_index) => {
@ -588,7 +605,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> {
} }
_ => {} _ => {}
} }
ct Ok(ct)
} }
} }
@ -621,7 +638,7 @@ impl<'tcx> TyCtxt<'tcx> {
value value
} else { } else {
let mut replacer = BoundVarReplacer::new(self, Some(&mut real_fld_r), None, None); 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) (value, region_map)
} }
@ -647,7 +664,7 @@ impl<'tcx> TyCtxt<'tcx> {
} else { } else {
let mut replacer = let mut replacer =
BoundVarReplacer::new(self, Some(&mut fld_r), Some(&mut fld_t), Some(&mut fld_c)); 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()
} }
} }
@ -938,36 +955,36 @@ impl TypeFolder<'tcx> for Shifter<'tcx> {
fn fold_binder<T: TypeFoldable<'tcx>>( fn fold_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: ty::Binder<'tcx, T>, t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> { ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
self.current_index.shift_in(1); self.current_index.shift_in(1);
let t = t.super_fold_with(self); let t = t.super_fold_with(self);
self.current_index.shift_out(1); self.current_index.shift_out(1);
t 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 { match *r {
ty::ReLateBound(debruijn, br) => { ty::ReLateBound(debruijn, br) => {
if self.amount == 0 || debruijn < self.current_index { if self.amount == 0 || debruijn < self.current_index {
r Ok(r)
} else { } else {
let debruijn = debruijn.shifted_in(self.amount); let debruijn = debruijn.shifted_in(self.amount);
let shifted = ty::ReLateBound(debruijn, br); 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() { match *ty.kind() {
ty::Bound(debruijn, bound_ty) => { ty::Bound(debruijn, bound_ty) => {
if self.amount == 0 || debruijn < self.current_index { if self.amount == 0 || debruijn < self.current_index {
ty Ok(ty)
} else { } else {
let debruijn = debruijn.shifted_in(self.amount); 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)))
} }
} }
@ -975,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 let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty } = *ct {
if self.amount == 0 || debruijn < self.current_index { if self.amount == 0 || debruijn < self.current_index {
ct Ok(ct)
} else { } else {
let debruijn = debruijn.shifted_in(self.amount); 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 { } else {
ct.super_fold_with(self) ct.super_fold_with(self)
@ -1008,7 +1030,7 @@ where
{ {
debug!("shift_vars(value={:?}, amount={})", value, amount); 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)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
@ -1271,7 +1293,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// ///
/// FIXME(@lcnr): explain this function a bit more /// FIXME(@lcnr): explain this function a bit more
pub fn expose_default_const_substs<T: TypeFoldable<'tcx>>(self, v: T) -> T { 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()
} }
} }
@ -1284,19 +1306,22 @@ impl<'tcx> TypeFolder<'tcx> for ExposeDefaultConstSubstsFolder<'tcx> {
self.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) { if ty.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
ty.super_fold_with(self) ty.super_fold_with(self)
} else { } 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) { if pred.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
pred.super_fold_with(self) pred.super_fold_with(self)
} else { } else {
pred Ok(pred)
} }
} }
} }

View file

@ -622,7 +622,7 @@ fn polymorphize<'tcx>(
self.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); debug!("fold_ty: ty={:?}", ty);
match ty.kind { match ty.kind {
ty::Closure(def_id, substs) => { ty::Closure(def_id, substs) => {
@ -631,11 +631,11 @@ fn polymorphize<'tcx>(
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
substs, substs,
); );
if substs == polymorphized_substs { Ok(if substs == polymorphized_substs {
ty ty
} else { } else {
self.tcx.mk_closure(def_id, polymorphized_substs) self.tcx.mk_closure(def_id, polymorphized_substs)
} })
} }
ty::Generator(def_id, substs, movability) => { ty::Generator(def_id, substs, movability) => {
let polymorphized_substs = polymorphize( let polymorphized_substs = polymorphize(
@ -643,11 +643,11 @@ fn polymorphize<'tcx>(
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
substs, substs,
); );
if substs == polymorphized_substs { Ok(if substs == polymorphized_substs {
ty ty
} else { } else {
self.tcx.mk_generator(def_id, polymorphized_substs, movability) self.tcx.mk_generator(def_id, polymorphized_substs, movability)
} })
} }
_ => ty.super_fold_with(self), _ => ty.super_fold_with(self),
} }
@ -669,7 +669,7 @@ fn polymorphize<'tcx>(
// ..and polymorphize any closures/generators captured as upvars. // ..and polymorphize any closures/generators captured as upvars.
let upvars_ty = upvars_ty.unwrap(); let upvars_ty = upvars_ty.unwrap();
let polymorphized_upvars_ty = upvars_ty.fold_with( let polymorphized_upvars_ty = upvars_ty.fold_with(
&mut PolymorphizationFolder { tcx }); &mut PolymorphizationFolder { tcx }).into_ok();
debug!("polymorphize: polymorphized_upvars_ty={:?}", polymorphized_upvars_ty); debug!("polymorphize: polymorphized_upvars_ty={:?}", polymorphized_upvars_ty);
ty::GenericArg::from(polymorphized_upvars_ty) ty::GenericArg::from(polymorphized_upvars_ty)
}, },

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

@ -35,7 +35,9 @@ impl<'tcx> TyCtxt<'tcx> {
if !value.has_projections() { if !value.has_projections() {
value value
} else { } else {
value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env }) value
.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env })
.into_ok()
} }
} }
@ -103,18 +105,24 @@ impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> {
self.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> {
self.normalize_generic_arg_after_erasing_regions(ty.into()).expect_ty() 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> { fn fold_const(
self.normalize_generic_arg_after_erasing_regions(c.into()).expect_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] #[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! // FIXME: This *probably* needs canonicalization too!
let arg = self.param_env.and(c); 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))
} }
} }

View file

@ -2016,24 +2016,24 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
fn fold_binder<T: TypeFoldable<'tcx>>( fn fold_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: ty::Binder<'tcx, T>, t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> { ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
self.current_index.shift_in(1); self.current_index.shift_in(1);
let t = t.super_fold_with(self); let t = t.super_fold_with(self);
self.current_index.shift_out(1); self.current_index.shift_out(1);
t 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() { match *t.kind() {
_ if t.has_vars_bound_at_or_above(self.current_index) || t.has_placeholders() => { _ if t.has_vars_bound_at_or_above(self.current_index) || t.has_placeholders() => {
return t.super_fold_with(self); 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 name = &mut self.name;
let region = match *r { let region = match *r {
ty::ReLateBound(_, br) => self.region_map.entry(br).or_insert_with(|| name(br)), 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 { if let ty::ReLateBound(debruijn1, br) = *region {
assert_eq!(debruijn1, ty::INNERMOST); 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 { } else {
region Ok(region)
} }
} }
} }
@ -2193,7 +2193,7 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
name: &mut name, name: &mut name,
region_map: BTreeMap::new(), 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; let region_map = folder.region_map;
start_or_continue(&mut self, "", "> "); start_or_continue(&mut self, "", "> ");
(new_value, region_map) (new_value, region_map)

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> {
@ -1087,12 +1087,12 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
} }
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 { fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
ty::Unevaluated { Ok(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,
} })
} }
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { 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, ()> { 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) -> Result<Self, F::Error> {
ty::Unevaluated { Ok(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,
} })
} }
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {

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))
}
} }
} }
} }
@ -434,7 +439,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> Subst<'tcx> for T {
span: Option<Span>, span: Option<Span>,
) -> T { ) -> T {
let mut folder = SubstFolder { tcx, substs, span, binders_passed: 0 }; let mut folder = SubstFolder { tcx, substs, span, binders_passed: 0 };
self.fold_with(&mut folder) self.fold_with(&mut folder).into_ok()
} }
} }
@ -460,14 +465,14 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
fn fold_binder<T: TypeFoldable<'tcx>>( fn fold_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: ty::Binder<'tcx, T>, t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> { ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
self.binders_passed += 1; self.binders_passed += 1;
let t = t.super_fold_with(self); let t = t.super_fold_with(self)?;
self.binders_passed -= 1; 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 // Note: This routine only handles regions that are bound on
// type declarations and other outer declarations, not those // type declarations and other outer declarations, not those
// bound in *fn types*. Region substitution of the bound // bound in *fn types*. Region substitution of the bound
@ -477,7 +482,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
ty::ReEarlyBound(data) => { ty::ReEarlyBound(data) => {
let rk = self.substs.get(data.index as usize).map(|k| k.unpack()); let rk = self.substs.get(data.index as usize).map(|k| k.unpack());
match rk { 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 span = self.span.unwrap_or(DUMMY_SP);
let msg = format!( let msg = format!(
@ -489,31 +494,37 @@ 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() { if !t.potentially_needs_subst() {
return t; return Ok(t);
} }
match *t.kind() { 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), _ => 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 let ty::ConstKind::Param(p) = c.val { if let ty::ConstKind::Param(p) = c.val {
self.const_for_param(p, c) Ok(self.const_for_param(p, c))
} else { } else {
c.super_fold_with(self) c.super_fold_with(self)
} }
} }
#[inline] #[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) c.super_fold_with(self)
} }
} }

View file

@ -574,14 +574,14 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
if self.found_any_recursion { if self.found_any_recursion {
return None; 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) { if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) { let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
Some(expanded_ty) => expanded_ty, Some(expanded_ty) => expanded_ty,
None => { None => {
let generic_ty = self.tcx.type_of(def_id); let generic_ty = self.tcx.type_of(def_id);
let concrete_ty = generic_ty.subst(self.tcx, substs); 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); self.expanded_cache.insert((def_id, substs), expanded_ty);
expanded_ty expanded_ty
} }
@ -605,13 +605,13 @@ impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
self.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 { 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() { } else if t.has_opaque_types() {
t.super_fold_with(self) t.super_fold_with(self)
} else { } else {
t Ok(t)
} }
} }
} }
@ -1046,25 +1046,31 @@ pub fn fold_list<'tcx, F, T>(
list: &'tcx ty::List<T>, list: &'tcx ty::List<T>,
folder: &mut F, folder: &mut F,
intern: impl FnOnce(TyCtxt<'tcx>, &[T]) -> &'tcx ty::List<T>, intern: impl FnOnce(TyCtxt<'tcx>, &[T]) -> &'tcx ty::List<T>,
) -> &'tcx ty::List<T> ) -> Result<&'tcx ty::List<T>, F::Error>
where where
F: TypeFolder<'tcx>, F: TypeFolder<'tcx>,
T: TypeFoldable<'tcx> + PartialEq + Copy, T: TypeFoldable<'tcx> + PartialEq + Copy,
{ {
let mut iter = list.iter(); let mut iter = list.iter();
// Look for the first element that changed // Look for the first element that changed
if let Some((i, new_t)) = iter.by_ref().enumerate().find_map(|(i, t)| { match iter.by_ref().enumerate().find_map(|(i, t)| match t.fold_with(folder) {
let new_t = t.fold_with(folder); Ok(new_t) if new_t == t => None,
if new_t == t { None } else { Some((i, new_t)) } new_t => Some((i, new_t)),
}) { }) {
// An element changed, prepare to intern the resulting list Some((i, Ok(new_t))) => {
let mut new_list = SmallVec::<[_; 8]>::with_capacity(list.len()); // An element changed, prepare to intern the resulting list
new_list.extend_from_slice(&list[..i]); let mut new_list = SmallVec::<[_; 8]>::with_capacity(list.len());
new_list.push(new_t); new_list.extend_from_slice(&list[..i]);
new_list.extend(iter.map(|t| t.fold_with(folder))); new_list.push(new_t);
intern(folder.tcx(), &new_list) for t in iter {
} else { new_list.push(t.fold_with(folder)?)
list }
Ok(intern(folder.tcx(), &new_list))
}
Some((_, Err(err))) => {
return Err(err);
}
None => Ok(list),
} }
} }
@ -1086,7 +1092,7 @@ pub fn normalize_opaque_types(
check_recursion: false, check_recursion: false,
tcx, tcx,
}; };
val.fold_with(&mut visitor) val.fold_with(&mut visitor).into_ok()
} }
pub fn provide(providers: &mut ty::query::Providers) { pub fn provide(providers: &mut ty::query::Providers) {

View file

@ -22,6 +22,7 @@
#![feature(never_type)] #![feature(never_type)]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(control_flow_enum)] #![feature(control_flow_enum)]
#![feature(unwrap_infallible)]
#![recursion_limit = "512"] // For rustdoc #![recursion_limit = "512"] // For rustdoc
#[macro_use] #[macro_use]

View file

@ -65,14 +65,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// Convert the type from the function into a type valid outside // Convert the type from the function into a type valid outside
// the function, by replacing invalid regions with 'static, // the function, by replacing invalid regions with 'static,
// after producing an error for each of them. // after producing an error for each of them.
let definition_ty = instantiated_ty.fold_with(&mut ReverseMapper::new( let definition_ty = instantiated_ty
self.tcx, .fold_with(&mut ReverseMapper::new(
self.is_tainted_by_errors(), self.tcx,
def_id, self.is_tainted_by_errors(),
map, def_id,
instantiated_ty, map,
span, instantiated_ty,
)); span,
))
.into_ok();
debug!(?definition_ty); debug!(?definition_ty);
definition_ty definition_ty
@ -123,14 +125,14 @@ impl ReverseMapper<'tcx> {
) -> GenericArg<'tcx> { ) -> GenericArg<'tcx> {
assert!(!self.map_missing_regions_to_empty); assert!(!self.map_missing_regions_to_empty);
self.map_missing_regions_to_empty = true; 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; self.map_missing_regions_to_empty = false;
kind kind
} }
fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> { fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
assert!(!self.map_missing_regions_to_empty); assert!(!self.map_missing_regions_to_empty);
kind.fold_with(self) kind.fold_with(self).into_ok()
} }
} }
@ -140,17 +142,17 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
} }
#[instrument(skip(self), level = "debug")] #[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 { match r {
// Ignore bound regions and `'static` regions that appear in the // Ignore bound regions and `'static` regions that appear in the
// type, we only need to remap regions that reference lifetimes // type, we only need to remap regions that reference lifetimes
// from the function declaraion. // from the function declaraion.
// This would ignore `'r` in a type like `for<'r> fn(&'r u32)`. // 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 // If regions have been erased (by writeback), don't try to unerase
// them. // them.
ty::ReErased => return r, ty::ReErased => return Ok(r),
// The regions that we expect from borrow checking. // The regions that we expect from borrow checking.
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {} ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
@ -165,10 +167,10 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
let generics = self.tcx().generics_of(self.opaque_type_def_id); let generics = self.tcx().generics_of(self.opaque_type_def_id);
match self.map.get(&r.into()).map(|k| k.unpack()) { 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), Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
None if self.map_missing_regions_to_empty || self.tainted_by_errors => { 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() => { None if generics.parent.is_some() => {
if let Some(hidden_ty) = self.hidden_ty.take() { if let Some(hidden_ty) = self.hidden_ty.take() {
@ -180,7 +182,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
) )
.emit(); .emit();
} }
self.tcx.lifetimes.re_root_empty Ok(self.tcx.lifetimes.re_root_empty)
} }
None => { None => {
self.tcx self.tcx
@ -196,12 +198,12 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
) )
.emit(); .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() { match *ty.kind() {
ty::Closure(def_id, substs) => { ty::Closure(def_id, substs) => {
// I am a horrible monster and I pray for death. When // I am a horrible monster and I pray for death. When
@ -239,7 +241,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) => { ty::Generator(def_id, substs, movability) => {
@ -254,7 +256,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) => { ty::Param(param) => {
@ -262,7 +264,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
match self.map.get(&ty.into()).map(|k| k.unpack()) { match self.map.get(&ty.into()).map(|k| k.unpack()) {
// Found it in the substitution list; replace with the parameter from the // Found it in the substitution list; replace with the parameter from the
// opaque type. // opaque type.
Some(GenericArgKind::Type(t1)) => t1, Some(GenericArgKind::Type(t1)) => Ok(t1),
Some(u) => panic!("type mapped to unexpected kind: {:?}", u), Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
None => { None => {
debug!(?param, ?self.map); debug!(?param, ?self.map);
@ -278,7 +280,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
) )
.emit(); .emit();
self.tcx().ty_error() Ok(self.tcx().ty_error())
} }
} }
} }
@ -287,10 +289,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); trace!("checking const {:?}", ct);
// Find a const parameter // Find a const parameter
match ct.val { Ok(match ct.val {
ty::ConstKind::Param(..) => { ty::ConstKind::Param(..) => {
// Look it up in the substitution list. // Look it up in the substitution list.
match self.map.get(&ct.into()).map(|k| k.unpack()) { match self.map.get(&ct.into()).map(|k| k.unpack()) {
@ -317,7 +322,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
} }
_ => ct, _ => ct,
} })
} }
} }

View file

@ -860,11 +860,11 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx> {
self.tcx self.tcx
} }
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
(match r { Ok((match r {
ty::ReVar(vid) => self.vid_to_region.get(vid).cloned(), ty::ReVar(vid) => self.vid_to_region.get(vid).cloned(),
_ => None, _ => None,
}) })
.unwrap_or_else(|| r.super_fold_with(self)) .unwrap_or_else(|| r.super_fold_with(self).into_ok()))
} }
} }

View file

@ -1898,15 +1898,15 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
self.infcx.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() { if let ty::Param(ty::ParamTy { name, .. }) = *ty.kind() {
let infcx = self.infcx; 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 { infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeParameterDefinition(name, None), kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
span: DUMMY_SP, span: DUMMY_SP,
}) })
}) }))
} else { } else {
ty.super_fold_with(self) ty.super_fold_with(self)
} }
@ -1916,8 +1916,9 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
self.probe(|_| { self.probe(|_| {
let mut selcx = SelectionContext::new(self); let mut selcx = SelectionContext::new(self);
let cleaned_pred = let cleaned_pred = pred
pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() }); .fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() })
.into_ok();
let cleaned_pred = super::project::normalize( let cleaned_pred = super::project::normalize(
&mut selcx, &mut selcx,

View file

@ -339,7 +339,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
if !needs_normalization(&value, self.param_env.reveal()) { if !needs_normalization(&value, self.param_env.reveal()) {
value value
} else { } else {
value.fold_with(self) value.fold_with(self).into_ok()
} }
} }
} }
@ -352,16 +352,16 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
fn fold_binder<T: TypeFoldable<'tcx>>( fn fold_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: ty::Binder<'tcx, T>, t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> { ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
self.universes.push(None); self.universes.push(None);
let t = t.super_fold_with(self); let t = t.super_fold_with(self);
self.universes.pop(); self.universes.pop();
t 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()) { 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 // 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 // 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. // 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 // This is really important. While we *can* handle this, this has
// severe performance implications for large opaque types with // severe performance implications for large opaque types with
// late-bound regions. See `issue-88862` benchmark. // late-bound regions. See `issue-88862` benchmark.
ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
// Only normalize `impl Trait` after type-checking, usually in codegen. // Only normalize `impl Trait` after type-checking, usually in codegen.
match self.param_env.reveal() { match self.param_env.reveal() {
Reveal::UserFacing => ty.super_fold_with(self), Reveal::UserFacing => ty.super_fold_with(self)?,
Reveal::All => { Reveal::All => {
let recursion_limit = self.tcx().recursion_limit(); 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); 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 generic_ty = self.tcx().type_of(def_id);
let concrete_ty = generic_ty.subst(self.tcx(), substs); let concrete_ty = generic_ty.subst(self.tcx(), substs);
self.depth += 1; self.depth += 1;
let folded_ty = self.fold_ty(concrete_ty); let folded_ty = self.fold_ty(concrete_ty)?;
self.depth -= 1; self.depth -= 1;
folded_ty 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 // register an obligation to *later* project, since we know
// there won't be bound vars there. // 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( let normalized_ty = normalize_projection_type(
self.selcx, self.selcx,
self.param_env, self.param_env,
@ -461,7 +461,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
let infcx = self.selcx.infcx(); let infcx = self.selcx.infcx();
let (data, mapped_regions, mapped_types, mapped_consts) = let (data, mapped_regions, mapped_types, mapped_consts) =
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data); 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( let normalized_ty = opt_normalize_projection_type(
self.selcx, self.selcx,
self.param_env, self.param_env,
@ -473,16 +473,18 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
.ok() .ok()
.flatten() .flatten()
.map(|normalized_ty| { .map(|normalized_ty| {
PlaceholderReplacer::replace_placeholders( Ok({
infcx, PlaceholderReplacer::replace_placeholders(
mapped_regions, infcx,
mapped_types, mapped_regions,
mapped_consts, mapped_types,
&self.universes, mapped_consts,
normalized_ty, &self.universes,
) normalized_ty,
)
})
}) })
.unwrap_or_else(|| ty.super_fold_with(self)); .unwrap_or_else(|| ty.super_fold_with(self))?;
debug!( debug!(
?self.depth, ?self.depth,
@ -494,16 +496,19 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
normalized_ty 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() { if self.selcx.tcx().lazy_normalization() {
constant Ok(constant)
} else { } else {
let constant = constant.super_fold_with(self); let constant = constant.super_fold_with(self)?;
constant.eval(self.selcx.tcx(), self.param_env) Ok(constant.eval(self.selcx.tcx(), self.param_env))
} }
} }
} }
@ -550,7 +555,7 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
universe_indices, 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) (value, replacer.mapped_regions, replacer.mapped_types, replacer.mapped_consts)
} }
@ -577,14 +582,14 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
fn fold_binder<T: TypeFoldable<'tcx>>( fn fold_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: ty::Binder<'tcx, T>, t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> { ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
self.current_index.shift_in(1); self.current_index.shift_in(1);
let t = t.super_fold_with(self); let t = t.super_fold_with(self);
self.current_index.shift_out(1); self.current_index.shift_out(1);
t 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 { match *r {
ty::ReLateBound(debruijn, _) ty::ReLateBound(debruijn, _)
if debruijn.as_usize() + 1 if debruijn.as_usize() + 1
@ -596,13 +601,13 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
let universe = self.universe_for(debruijn); let universe = self.universe_for(debruijn);
let p = ty::PlaceholderRegion { universe, name: br.kind }; let p = ty::PlaceholderRegion { universe, name: br.kind };
self.mapped_regions.insert(p, br); 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() { match *t.kind() {
ty::Bound(debruijn, _) ty::Bound(debruijn, _)
if debruijn.as_usize() + 1 if debruijn.as_usize() + 1
@ -614,14 +619,17 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
let universe = self.universe_for(debruijn); let universe = self.universe_for(debruijn);
let p = ty::PlaceholderType { universe, name: bound_ty.var }; let p = ty::PlaceholderType { universe, name: bound_ty.var };
self.mapped_types.insert(p, bound_ty); 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), _ 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 { match *ct {
ty::Const { val: ty::ConstKind::Bound(debruijn, _), ty: _ } ty::Const { val: ty::ConstKind::Bound(debruijn, _), ty: _ }
if debruijn.as_usize() + 1 if debruijn.as_usize() + 1
@ -638,10 +646,10 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
name: ty::BoundConst { var: bound_const, ty }, name: ty::BoundConst { var: bound_const, ty },
}; };
self.mapped_consts.insert(p, bound_const); 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), _ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self),
_ => ct, _ => Ok(ct),
} }
} }
} }
@ -673,7 +681,7 @@ impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> {
universe_indices, universe_indices,
current_index: ty::INNERMOST, current_index: ty::INNERMOST,
}; };
value.super_fold_with(&mut replacer) value.super_fold_with(&mut replacer).into_ok()
} }
} }
@ -685,9 +693,9 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
fn fold_binder<T: TypeFoldable<'tcx>>( fn fold_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: ty::Binder<'tcx, T>, t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> { ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
if !t.has_placeholders() && !t.has_infer_regions() { if !t.has_placeholders() && !t.has_infer_regions() {
return t; return Ok(t);
} }
self.current_index.shift_in(1); self.current_index.shift_in(1);
let t = t.super_fold_with(self); let t = t.super_fold_with(self);
@ -695,7 +703,7 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
t 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 { let r1 = match r0 {
ty::ReVar(_) => self ty::ReVar(_) => self
.infcx .infcx
@ -729,10 +737,10 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
debug!(?r0, ?r1, ?r2, "fold_region"); 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() { match *ty.kind() {
ty::Placeholder(p) => { ty::Placeholder(p) => {
let replace_var = self.mapped_types.get(&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( let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1, 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), _ 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 { if let ty::Const { val: ty::ConstKind::Placeholder(p), ty } = *ct {
let replace_var = self.mapped_consts.get(&p); let replace_var = self.mapped_consts.get(&p);
match replace_var { match replace_var {
@ -770,10 +781,11 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
let db = ty::DebruijnIndex::from_usize( let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1, self.universe_indices.len() - index + self.current_index.as_usize() - 1,
); );
self.tcx() Ok(self
.mk_const(ty::Const { val: ty::ConstKind::Bound(db, *replace_var), ty }) .tcx()
.mk_const(ty::Const { val: ty::ConstKind::Bound(db, *replace_var), ty }))
} }
None => ct, None => Ok(ct),
} }
} else { } else {
ct.super_fold_with(self) ct.super_fold_with(self)
@ -1534,7 +1546,8 @@ fn confirm_candidate<'cx, 'tcx>(
// when possible for this to work. See `auto-trait-projection-recursion.rs` // when possible for this to work. See `auto-trait-projection-recursion.rs`
// for a case where this matters. // for a case where this matters.
if progress.ty.has_infer_regions() { 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 progress
} }

View file

@ -61,7 +61,6 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
cause: self.cause, cause: self.cause,
param_env: self.param_env, param_env: self.param_env,
obligations: vec![], obligations: vec![],
error: false,
cache: SsoHashMap::new(), cache: SsoHashMap::new(),
anon_depth: 0, anon_depth: 0,
universes: vec![], universes: vec![],
@ -100,11 +99,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
std::any::type_name::<T>(), std::any::type_name::<T>(),
normalizer.obligations, normalizer.obligations,
); );
if normalizer.error { result.map(|value| Normalized { value, obligations: normalizer.obligations })
Err(NoSolution)
} else {
Ok(Normalized { value: result, obligations: normalizer.obligations })
}
} }
} }
@ -171,12 +166,13 @@ struct QueryNormalizer<'cx, 'tcx> {
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
obligations: Vec<PredicateObligation<'tcx>>, obligations: Vec<PredicateObligation<'tcx>>,
cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>, cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
error: bool,
anon_depth: usize, anon_depth: usize,
universes: Vec<Option<ty::UniverseIndex>>, universes: Vec<Option<ty::UniverseIndex>>,
} }
impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
type Error = NoSolution;
fn tcx<'c>(&'c self) -> TyCtxt<'tcx> { fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
self.infcx.tcx self.infcx.tcx
} }
@ -184,7 +180,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
fn fold_binder<T: TypeFoldable<'tcx>>( fn fold_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
t: ty::Binder<'tcx, T>, t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> { ) -> Result<ty::Binder<'tcx, T>, Self::Error> {
self.universes.push(None); self.universes.push(None);
let t = t.super_fold_with(self); let t = t.super_fold_with(self);
self.universes.pop(); self.universes.pop();
@ -192,13 +188,13 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
} }
#[instrument(level = "debug", skip(self))] #[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()) { if !needs_normalization(&ty, self.param_env.reveal()) {
return ty; return Ok(ty);
} }
if let Some(ty) = self.cache.get(&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 // See note in `rustc_trait_selection::traits::project` about why we
@ -215,7 +211,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
Reveal::UserFacing => ty.super_fold_with(self), Reveal::UserFacing => ty.super_fold_with(self),
Reveal::All => { Reveal::All => {
let substs = substs.super_fold_with(self); let substs = substs.super_fold_with(self)?;
let recursion_limit = self.tcx().recursion_limit(); let recursion_limit = self.tcx().recursion_limit();
if !recursion_limit.value_within_limit(self.anon_depth) { if !recursion_limit.value_within_limit(self.anon_depth) {
let obligation = Obligation::with_depth( let obligation = Obligation::with_depth(
@ -252,7 +248,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
// we don't need to replace them with placeholders (see branch below). // we don't need to replace them with placeholders (see branch below).
let tcx = self.infcx.tcx; 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(); let mut orig_values = OriginalQueryValues::default();
// HACK(matthewjasper) `'static` is special-cased in selection, // HACK(matthewjasper) `'static` is special-cased in selection,
@ -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); .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: c_data = {:#?}", c_data);
debug!("QueryNormalizer: orig_values = {:#?}", orig_values); debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
match tcx.normalize_projection_ty(c_data) { let result = tcx.normalize_projection_ty(c_data)?;
Ok(result) => { // We don't expect ambiguity.
// We don't expect ambiguity. if result.is_ambiguous() {
if result.is_ambiguous() { return Err(NoSolution);
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);
result.normalized_ty
}
Err(_) => {
self.error = true;
ty.super_fold_with(self)
}
}
}
Err(NoSolution) => {
self.error = true;
ty.super_fold_with(self)
}
} }
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) => { ty::Projection(data) => {
@ -308,7 +287,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
&mut self.universes, &mut self.universes,
data, data,
); );
let data = data.super_fold_with(self); let data = data.super_fold_with(self)?;
let mut orig_values = OriginalQueryValues::default(); let mut orig_values = OriginalQueryValues::default();
// HACK(matthewjasper) `'static` is special-cased in selection, // HACK(matthewjasper) `'static` is special-cased in selection,
@ -318,57 +297,49 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
.canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values); .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: c_data = {:#?}", c_data);
debug!("QueryNormalizer: orig_values = {:#?}", orig_values); debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
match tcx.normalize_projection_ty(c_data) { let result = tcx.normalize_projection_ty(c_data)?;
Ok(result) => { // We don't expect ambiguity.
// We don't expect ambiguity. if result.is_ambiguous() {
if result.is_ambiguous() { return Err(NoSolution);
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);
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 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), _ => ty.super_fold_with(self),
})(); })()?;
self.cache.insert(ty, res); self.cache.insert(ty, res);
res Ok(res)
} }
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { fn fold_const(
let constant = constant.super_fold_with(self); &mut self,
constant.eval(self.infcx.tcx, self.param_env) 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) constant.super_fold_with(self)
} }
} }

View file

@ -2222,6 +2222,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.predicate .predicate
.to_poly_trait_ref() .to_poly_trait_ref()
.fold_with(&mut self.freshener) .fold_with(&mut self.freshener)
.into_ok()
.with_constness(obligation.predicate.skip_binder().constness); .with_constness(obligation.predicate.skip_binder().constness);
let dfn = previous_stack.cache.next_dfn(); let dfn = previous_stack.cache.next_dfn();

View file

@ -45,7 +45,7 @@ impl<'tcx> RustIrDatabase<'tcx> {
predicates predicates
.iter() .iter()
.map(|(wc, _)| wc.subst(self.interner.tcx, bound_vars)) .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() .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 trait_ref = trait_ref.subst(self.interner.tcx, bound_vars);
let mut regions_substitutor = let mut regions_substitutor =
lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder); 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); 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 self_ty = self_ty.subst(self.interner.tcx, bound_vars);
let mut regions_substitutor = let mut regions_substitutor =
lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder); 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); let lowered_ty = self_ty.lower_into(&self.interner);
parameters[0].assert_ty_ref(&self.interner).could_match( parameters[0].assert_ty_ref(&self.interner).could_match(
@ -501,22 +501,24 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
.iter() .iter()
.map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars)) .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars))
.map(|bound| { .map(|bound| {
bound.fold_with(&mut ty::fold::BottomUpFolder { bound
tcx: self.interner.tcx, .fold_with(&mut ty::fold::BottomUpFolder {
ty_op: |ty| { tcx: self.interner.tcx,
if let ty::Opaque(def_id, substs) = *ty.kind() { ty_op: |ty| {
if def_id == opaque_ty_id.0 && substs == identity_substs { if let ty::Opaque(def_id, substs) = *ty.kind() {
return self.interner.tcx.mk_ty(ty::Bound( if def_id == opaque_ty_id.0 && substs == identity_substs {
ty::INNERMOST, return self.interner.tcx.mk_ty(ty::Bound(
ty::BoundTy::from(ty::BoundVar::from_u32(0)), ty::INNERMOST,
)); ty::BoundTy::from(ty::BoundVar::from_u32(0)),
));
}
} }
} ty
ty },
}, lt_op: |lt| lt,
lt_op: |lt| lt, ct_op: |ct| ct,
ct_op: |ct| ct, })
}) .into_ok()
}) })
.filter_map(|bound| { .filter_map(|bound| {
LowerInto::< LowerInto::<

View file

@ -817,7 +817,7 @@ crate fn collect_bound_vars<'tcx, T: TypeFoldable<'tcx>>(
.collect(); .collect();
let mut bound_var_substitutor = NamedBoundVarSubstitutor::new(tcx, &named_parameters); 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() { for var in named_parameters.values() {
parameters.insert(*var, chalk_ir::VariableKind::Lifetime); parameters.insert(*var, chalk_ir::VariableKind::Lifetime);
@ -943,20 +943,23 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> {
self.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); self.binder_index.shift_in(1);
let result = t.super_fold_with(self); let result = t.super_fold_with(self);
self.binder_index.shift_out(1); self.binder_index.shift_out(1);
result 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 { match r {
ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind { ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind {
ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) { ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
Some(idx) => { Some(idx) => {
let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*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`."), None => panic!("Missing `BrNamed`."),
}, },
@ -999,32 +1002,35 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
self.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); self.binder_index.shift_in(1);
let result = t.super_fold_with(self); let result = t.super_fold_with(self);
self.binder_index.shift_out(1); self.binder_index.shift_out(1);
result 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() { match *t.kind() {
// FIXME(chalk): currently we convert params to placeholders starting at // FIXME(chalk): currently we convert params to placeholders starting at
// index `0`. To support placeholders, we'll actually need to do a // index `0`. To support placeholders, we'll actually need to do a
// first pass to collect placeholders. Then we can insert params after. // first pass to collect placeholders. Then we can insert params after.
ty::Placeholder(_) => unimplemented!(), ty::Placeholder(_) => unimplemented!(),
ty::Param(param) => match self.list.iter().position(|r| r == &param) { ty::Param(param) => match self.list.iter().position(|r| r == &param) {
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), universe: ty::UniverseIndex::from_usize(0),
name: ty::BoundVar::from_usize(idx), name: ty::BoundVar::from_usize(idx),
})), }))),
None => { None => {
self.list.push(param); self.list.push(param);
let idx = self.list.len() - 1 + self.next_ty_placeholder; let idx = self.list.len() - 1 + self.next_ty_placeholder;
self.params.insert(idx, param); 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), universe: ty::UniverseIndex::from_usize(0),
name: ty::BoundVar::from_usize(idx), 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 { match r {
// FIXME(chalk) - jackh726 - this currently isn't hit in any tests. // FIXME(chalk) - jackh726 - this currently isn't hit in any tests.
// This covers any region variables in a goal, right? // 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), var: ty::BoundVar::from_u32(*idx),
kind: ty::BrAnon(*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 => { None => {
let idx = self.named_regions.len() as u32; let idx = self.named_regions.len() as u32;
let br = let br =
ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) }; ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) };
self.named_regions.insert(_re.def_id, 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 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 { match r {
ty::ReEmpty(ui) => { ty::ReEmpty(ui) => {
assert_eq!(ui.as_usize(), 0); assert_eq!(ui.as_usize(), 0);
self.reempty_placeholder Ok(self.reempty_placeholder)
} }
_ => r.super_fold_with(self), _ => r.super_fold_with(self),

View file

@ -49,12 +49,12 @@ crate fn evaluate_goal<'tcx>(
let mut params_substitutor = let mut params_substitutor =
ParamsSubstitutor::new(tcx, placeholders_collector.next_ty_placeholder); 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 // FIXME(chalk): we really should be substituting these back in the solution
let _params: FxHashMap<usize, ParamTy> = params_substitutor.params; let _params: FxHashMap<usize, ParamTy> = params_substitutor.params;
let mut regions_substitutor = RegionsSubstitutor::new(tcx, reempty_placeholder); 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(); let max_universe = obligation.max_universe.index();

View file

@ -4,6 +4,7 @@
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(in_band_lifetimes)] #![feature(in_band_lifetimes)]
#![feature(nll)] #![feature(nll)]
#![feature(unwrap_infallible)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#[macro_use] #[macro_use]

View file

@ -442,8 +442,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut eraser = TypeParamEraser(self, expr.span); let mut eraser = TypeParamEraser(self, expr.span);
let needs_bound = self let needs_bound = self
.lookup_op_method( .lookup_op_method(
eraser.fold_ty(lhs_ty), eraser.fold_ty(lhs_ty).into_ok(),
&[eraser.fold_ty(rhs_ty)], &[eraser.fold_ty(rhs_ty).into_ok()],
Op::Binary(op, is_assign), Op::Binary(op, is_assign),
) )
.is_ok(); .is_ok();
@ -1015,12 +1015,12 @@ impl TypeFolder<'tcx> for TypeParamEraser<'_, 'tcx> {
self.0.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() { match ty.kind() {
ty::Param(_) => self.0.next_ty_var(TypeVariableOrigin { ty::Param(_) => Ok(self.0.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable, kind: TypeVariableOriginKind::MiscVariable,
span: self.1, span: self.1,
}), })),
_ => ty.super_fold_with(self), _ => ty.super_fold_with(self),
} }
} }

View file

@ -658,7 +658,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,
{ {
let mut resolver = Resolver::new(self.fcx, span, self.body); 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() { if cfg!(debug_assertions) && x.needs_infer() {
span_bug!(span.to_span(self.fcx.tcx), "writeback: `{:?}` has inference variables", x); span_bug!(span.to_span(self.fcx.tcx), "writeback: `{:?}` has inference variables", x);
} }
@ -749,15 +749,15 @@ impl<'tcx> TypeFolder<'tcx> for EraseEarlyRegions<'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
self.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) { if ty.has_type_flags(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
ty.super_fold_with(self) ty.super_fold_with(self)
} else { } else {
ty Ok(ty)
} }
} }
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::ReLateBound(..) = r { r } else { self.tcx.lifetimes.re_erased } 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 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) { match self.infcx.fully_resolve(t) {
Ok(t) => { Ok(t) => {
// Do not anonymize late-bound regions // 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); debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
self.report_type_error(t); self.report_type_error(t);
self.replaced_with_error = true; 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."); 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> { fn fold_const(
match self.infcx.fully_resolve(ct) { &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), Ok(ct) => self.infcx.tcx.erase_regions(ct),
Err(_) => { Err(_) => {
debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct); 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.replaced_with_error = true;
self.tcx().const_error(ct.ty) self.tcx().const_error(ct.ty)
} }
} })
} }
} }

View file

@ -729,17 +729,17 @@ fn infer_placeholder_type<'a>(
self.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 !self.success { if !self.success {
return ty; return Ok(ty);
} }
match ty.kind() { 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 // FIXME: non-capturing closures should also suggest a function pointer
ty::Closure(..) | ty::Generator(..) => { ty::Closure(..) | ty::Generator(..) => {
self.success = false; self.success = false;
ty Ok(ty)
} }
_ => ty.super_fold_with(self), _ => ty.super_fold_with(self),
} }
@ -761,7 +761,7 @@ fn infer_placeholder_type<'a>(
// Suggesting unnameable types won't help. // Suggesting unnameable types won't help.
let mut mk_nameable = MakeNameable::new(tcx); 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 }; let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
if let Some(sugg_ty) = sugg_ty { if let Some(sugg_ty) = sugg_ty {
err.span_suggestion( err.span_suggestion(
@ -785,7 +785,7 @@ fn infer_placeholder_type<'a>(
if !ty.references_error() { if !ty.references_error() {
let mut mk_nameable = MakeNameable::new(tcx); 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 }; let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
if let Some(sugg_ty) = sugg_ty { if let Some(sugg_ty) = sugg_ty {
diag.span_suggestion( diag.span_suggestion(

View file

@ -71,8 +71,11 @@ fn diagnostic_hir_wf_check<'tcx>(
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
self.tcx.infer_ctxt().enter(|infcx| { self.tcx.infer_ctxt().enter(|infcx| {
let mut fulfill = traits::FulfillmentContext::new(); let mut fulfill = traits::FulfillmentContext::new();
let tcx_ty = let tcx_ty = self
self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx }); .icx
.to_ty(ty)
.fold_with(&mut EraseAllBoundRegions { tcx: self.tcx })
.into_ok();
let cause = traits::ObligationCause::new( let cause = traits::ObligationCause::new(
ty.span, ty.span,
self.hir_id, self.hir_id,
@ -183,7 +186,7 @@ impl<'tcx> TypeFolder<'tcx> for EraseAllBoundRegions<'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
self.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> {
if let ty::ReLateBound(..) = r { &ty::ReErased } else { r } if let ty::ReLateBound(..) = r { Ok(&ty::ReErased) } else { Ok(r) }
} }
} }

View file

@ -71,6 +71,7 @@ This API is completely unstable and subject to change.
#![feature(slice_partition_dedup)] #![feature(slice_partition_dedup)]
#![feature(control_flow_enum)] #![feature(control_flow_enum)]
#![feature(hash_drain_filter)] #![feature(hash_drain_filter)]
#![feature(unwrap_infallible)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#[macro_use] #[macro_use]

View file

@ -449,7 +449,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
_ => false, _ => false,
} }
}) })
.map(|p| p.fold_with(&mut replacer)); .map(|p| p.fold_with(&mut replacer).into_ok());
let mut generic_params = let mut generic_params =
(tcx.generics_of(item_def_id), tcx.explicit_predicates_of(item_def_id)) (tcx.generics_of(item_def_id), tcx.explicit_predicates_of(item_def_id))
@ -714,11 +714,11 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx> {
self.tcx self.tcx
} }
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
(match *r { Ok((match *r {
ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(), ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
_ => None, _ => None,
}) })
.unwrap_or_else(|| r.super_fold_with(self)) .unwrap_or_else(|| r.super_fold_with(self).into_ok()))
} }
} }

View file

@ -18,6 +18,7 @@
#![feature(type_ascription)] #![feature(type_ascription)]
#![feature(iter_intersperse)] #![feature(iter_intersperse)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#![feature(unwrap_infallible)]
#![warn(rustc::internal)] #![warn(rustc::internal)]
#[macro_use] #[macro_use]