1
Fork 0

Adapt TypeFolder implementors to return a Result

Co-authored-by: Alan Egerton <eggyal@gmail.com>
This commit is contained in:
LeSeulArtichaut 2021-05-19 15:01:30 +02:00 committed by Alan Egerton
parent 6e3fa20b00
commit 6dc3dae46f
No known key found for this signature in database
GPG key ID: 07CAC3CCA7E0643F
24 changed files with 387 additions and 305 deletions

View file

@ -278,7 +278,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
self.tcx
}
fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> Result<ty::Binder<'tcx, T>, Self::Error>
where
T: TypeFoldable<'tcx>,
{
@ -288,13 +288,13 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
t
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
match *r {
ty::ReLateBound(index, ..) => {
if index >= self.binder_index {
bug!("escaping late-bound region during canonicalization");
} else {
r
Ok(r)
}
}
@ -311,7 +311,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
vid, r
);
let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid));
self.canonicalize_region_mode.canonicalize_free_region(self, r)
Ok(self.canonicalize_region_mode.canonicalize_free_region(self, r))
}
ty::ReStatic
@ -319,11 +319,11 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
| ty::ReFree(_)
| ty::ReEmpty(_)
| ty::RePlaceholder(..)
| ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r),
| ty::ReErased => Ok(self.canonicalize_region_mode.canonicalize_free_region(self, r)),
}
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
match *t.kind() {
ty::Infer(ty::TyVar(vid)) => {
debug!("canonical: type var found with vid {:?}", vid);
@ -339,40 +339,40 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
Err(mut ui) => {
// FIXME: perf problem described in #55921.
ui = ty::UniverseIndex::ROOT;
self.canonicalize_ty_var(
Ok(self.canonicalize_ty_var(
CanonicalVarInfo {
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
},
t,
)
))
}
}
}
ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(
ty::Infer(ty::IntVar(_)) => Ok(self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
t,
),
)),
ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(
ty::Infer(ty::FloatVar(_)) => Ok(self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
t,
),
)),
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
bug!("encountered a fresh type during canonicalization")
}
ty::Placeholder(placeholder) => self.canonicalize_ty_var(
ty::Placeholder(placeholder) => Ok(self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderTy(placeholder) },
t,
),
)),
ty::Bound(debruijn, _) => {
if debruijn >= self.binder_index {
bug!("escaping bound type during canonicalization")
} else {
t
Ok(t)
}
}
@ -403,13 +403,16 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
if t.flags().intersects(self.needs_canonical_flags) {
t.super_fold_with(self)
} else {
t
Ok(t)
}
}
}
}
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
fn fold_const(
&mut self,
ct: &'tcx ty::Const<'tcx>,
) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
match ct.val {
ty::ConstKind::Infer(InferConst::Var(vid)) => {
debug!("canonical: const var found with vid {:?}", vid);
@ -424,10 +427,10 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
Err(mut ui) => {
// FIXME: perf problem described in #55921.
ui = ty::UniverseIndex::ROOT;
return self.canonicalize_const_var(
return Ok(self.canonicalize_const_var(
CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) },
ct,
);
));
}
}
}
@ -438,20 +441,20 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
if debruijn >= self.binder_index {
bug!("escaping bound type during canonicalization")
} else {
return ct;
return Ok(ct);
}
}
ty::ConstKind::Placeholder(placeholder) => {
return self.canonicalize_const_var(
return Ok(self.canonicalize_const_var(
CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderConst(placeholder) },
ct,
);
));
}
_ => {}
}
let flags = FlagComputation::for_const(ct);
if flags.intersects(self.needs_canonical_flags) { ct.super_fold_with(self) } else { ct }
if flags.intersects(self.needs_canonical_flags) { ct.super_fold_with(self) } else { Ok(ct) }
}
}

View file

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

View file

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

View file

@ -1745,12 +1745,15 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
self.infcx.tcx
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
self.infcx.shallow_resolve_ty(ty)
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
Ok(self.infcx.shallow_resolve_ty(ty))
}
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = ct {
fn fold_const(
&mut self,
ct: &'tcx ty::Const<'tcx>,
) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
Ok(if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = ct {
self.infcx
.inner
.borrow_mut()
@ -1761,7 +1764,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
.unwrap_or(ct)
} else {
ct
}
})
}
}

View file

@ -30,25 +30,28 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
self.infcx.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
if !t.has_infer_types_or_consts() {
t // micro-optimize -- if there is nothing in this type that this fold affects...
Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects...
} else {
let t = self.infcx.shallow_resolve(t);
t.super_fold_with(self)
}
}
fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> {
fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> Result<&'tcx Const<'tcx>, Self::Error> {
if !ct.has_infer_types_or_consts() {
ct // micro-optimize -- if there is nothing in this const that this fold affects...
Ok(ct) // micro-optimize -- if there is nothing in this const that this fold affects...
} else {
let ct = self.infcx.shallow_resolve(ct);
ct.super_fold_with(self)
}
}
fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
fn fold_mir_const(
&mut self,
constant: mir::ConstantKind<'tcx>,
) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
constant.super_fold_with(self)
}
}
@ -75,16 +78,16 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
self.infcx.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
if !t.has_infer_regions() {
t // micro-optimize -- if there is nothing in this type that this fold affects...
Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects...
} else {
t.super_fold_with(self)
}
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
Ok(match *r {
ty::ReVar(rid) => {
let resolved = self
.infcx
@ -95,12 +98,15 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
self.tcx().reuse_or_mk_region(r, ty::ReVar(resolved))
}
_ => r,
}
})
}
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
fn fold_const(
&mut self,
ct: &'tcx ty::Const<'tcx>,
) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
if !ct.has_infer_regions() {
ct // micro-optimize -- if there is nothing in this const that this fold affects...
Ok(ct) // micro-optimize -- if there is nothing in this const that this fold affects...
} else {
ct.super_fold_with(self)
}
@ -195,23 +201,23 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
self.infcx.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
if !t.needs_infer() {
t // micro-optimize -- if there is nothing in this type that this fold affects...
Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects...
} else {
let t = self.infcx.shallow_resolve(t);
match *t.kind() {
ty::Infer(ty::TyVar(vid)) => {
self.err = Some(FixupError::UnresolvedTy(vid));
self.tcx().ty_error()
Ok(self.tcx().ty_error())
}
ty::Infer(ty::IntVar(vid)) => {
self.err = Some(FixupError::UnresolvedIntTy(vid));
self.tcx().ty_error()
Ok(self.tcx().ty_error())
}
ty::Infer(ty::FloatVar(vid)) => {
self.err = Some(FixupError::UnresolvedFloatTy(vid));
self.tcx().ty_error()
Ok(self.tcx().ty_error())
}
ty::Infer(_) => {
bug!("Unexpected type in full type resolver: {:?}", t);
@ -221,28 +227,31 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
}
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
match *r {
ty::ReVar(rid) => self
ty::ReVar(rid) => Ok(self
.infcx
.lexical_region_resolutions
.borrow()
.as_ref()
.expect("region resolution not performed")
.resolve_var(rid),
_ => r,
.resolve_var(rid)),
_ => Ok(r),
}
}
fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
fn fold_const(
&mut self,
c: &'tcx ty::Const<'tcx>,
) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
if !c.needs_infer() {
c // micro-optimize -- if there is nothing in this const that this fold affects...
Ok(c) // micro-optimize -- if there is nothing in this const that this fold affects...
} else {
let c = self.infcx.shallow_resolve(c);
match c.val {
ty::ConstKind::Infer(InferConst::Var(vid)) => {
self.err = Some(FixupError::UnresolvedConst(vid));
return self.tcx().const_error(c.ty);
return Ok(self.tcx().const_error(c.ty));
}
ty::ConstKind::Infer(InferConst::Fresh(_)) => {
bug!("Unexpected const in full const resolver: {:?}", c);