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

@ -140,17 +140,17 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
}
#[instrument(skip(self), level = "debug")]
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
match r {
// Ignore bound regions and `'static` regions that appear in the
// type, we only need to remap regions that reference lifetimes
// from the function declaraion.
// This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
ty::ReLateBound(..) | ty::ReStatic => return r,
ty::ReLateBound(..) | ty::ReStatic => return Ok(r),
// If regions have been erased (by writeback), don't try to unerase
// them.
ty::ReErased => return r,
ty::ReErased => return Ok(r),
// The regions that we expect from borrow checking.
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
@ -165,10 +165,10 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
let generics = self.tcx().generics_of(self.opaque_type_def_id);
match self.map.get(&r.into()).map(|k| k.unpack()) {
Some(GenericArgKind::Lifetime(r1)) => r1,
Some(GenericArgKind::Lifetime(r1)) => Ok(r1),
Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
None if self.map_missing_regions_to_empty || self.tainted_by_errors => {
self.tcx.lifetimes.re_root_empty
Ok(self.tcx.lifetimes.re_root_empty)
}
None if generics.parent.is_some() => {
if let Some(hidden_ty) = self.hidden_ty.take() {
@ -180,7 +180,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
)
.emit();
}
self.tcx.lifetimes.re_root_empty
Ok(self.tcx.lifetimes.re_root_empty)
}
None => {
self.tcx
@ -196,12 +196,12 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
)
.emit();
self.tcx().lifetimes.re_static
Ok(self.tcx().lifetimes.re_static)
}
}
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
match *ty.kind() {
ty::Closure(def_id, substs) => {
// I am a horrible monster and I pray for death. When
@ -239,7 +239,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
}
}));
self.tcx.mk_closure(def_id, substs)
Ok(self.tcx.mk_closure(def_id, substs))
}
ty::Generator(def_id, substs, movability) => {
@ -254,7 +254,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
}
}));
self.tcx.mk_generator(def_id, substs, movability)
Ok(self.tcx.mk_generator(def_id, substs, movability))
}
ty::Param(param) => {
@ -262,7 +262,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
match self.map.get(&ty.into()).map(|k| k.unpack()) {
// Found it in the substitution list; replace with the parameter from the
// opaque type.
Some(GenericArgKind::Type(t1)) => t1,
Some(GenericArgKind::Type(t1)) => Ok(t1),
Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
None => {
debug!(?param, ?self.map);
@ -278,7 +278,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
)
.emit();
self.tcx().ty_error()
Ok(self.tcx().ty_error())
}
}
}
@ -287,10 +287,13 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
}
}
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
fn fold_const(
&mut self,
ct: &'tcx ty::Const<'tcx>,
) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
trace!("checking const {:?}", ct);
// Find a const parameter
match ct.val {
Ok(match ct.val {
ty::ConstKind::Param(..) => {
// Look it up in the substitution list.
match self.map.get(&ct.into()).map(|k| k.unpack()) {
@ -317,7 +320,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
}
_ => ct,
}
})
}
}

View file

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

View file

@ -1898,15 +1898,15 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
self.infcx.tcx
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
if let ty::Param(ty::ParamTy { name, .. }) = *ty.kind() {
let infcx = self.infcx;
self.var_map.entry(ty).or_insert_with(|| {
Ok(self.var_map.entry(ty).or_insert_with(|| {
infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
span: DUMMY_SP,
})
})
}))
} else {
ty.super_fold_with(self)
}

View file

@ -352,16 +352,16 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
fn fold_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
) -> Result<ty::Binder<'tcx, T>, Self::Error> {
self.universes.push(None);
let t = t.super_fold_with(self);
self.universes.pop();
t
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
if !needs_normalization(&ty, self.param_env.reveal()) {
return ty;
return Ok(ty);
}
// We try to be a little clever here as a performance optimization in
@ -387,14 +387,14 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
// replace bound vars if the current type is a `Projection` and we need
// to make sure we don't forget to fold the substs regardless.
match *ty.kind() {
Ok(match *ty.kind() {
// This is really important. While we *can* handle this, this has
// severe performance implications for large opaque types with
// late-bound regions. See `issue-88862` benchmark.
ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
// Only normalize `impl Trait` after type-checking, usually in codegen.
match self.param_env.reveal() {
Reveal::UserFacing => ty.super_fold_with(self),
Reveal::UserFacing => ty.super_fold_with(self)?,
Reveal::All => {
let recursion_limit = self.tcx().recursion_limit();
@ -408,11 +408,11 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
self.selcx.infcx().report_overflow_error(&obligation, true);
}
let substs = substs.super_fold_with(self);
let substs = substs.super_fold_with(self)?;
let generic_ty = self.tcx().type_of(def_id);
let concrete_ty = generic_ty.subst(self.tcx(), substs);
self.depth += 1;
let folded_ty = self.fold_ty(concrete_ty);
let folded_ty = self.fold_ty(concrete_ty)?;
self.depth -= 1;
folded_ty
}
@ -426,7 +426,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
// register an obligation to *later* project, since we know
// there won't be bound vars there.
let data = data.super_fold_with(self);
let data = data.super_fold_with(self)?;
let normalized_ty = normalize_projection_type(
self.selcx,
self.param_env,
@ -461,7 +461,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
let infcx = self.selcx.infcx();
let (data, mapped_regions, mapped_types, mapped_consts) =
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
let data = data.super_fold_with(self);
let data = data.super_fold_with(self)?;
let normalized_ty = opt_normalize_projection_type(
self.selcx,
self.param_env,
@ -473,16 +473,18 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
.ok()
.flatten()
.map(|normalized_ty| {
PlaceholderReplacer::replace_placeholders(
infcx,
mapped_regions,
mapped_types,
mapped_consts,
&self.universes,
normalized_ty,
)
Ok({
PlaceholderReplacer::replace_placeholders(
infcx,
mapped_regions,
mapped_types,
mapped_consts,
&self.universes,
normalized_ty,
)
})
})
.unwrap_or_else(|| ty.super_fold_with(self));
.unwrap_or_else(|| ty.super_fold_with(self))?;
debug!(
?self.depth,
@ -494,16 +496,19 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
normalized_ty
}
_ => ty.super_fold_with(self),
}
_ => ty.super_fold_with(self)?,
})
}
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
fn fold_const(
&mut self,
constant: &'tcx ty::Const<'tcx>,
) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
if self.selcx.tcx().lazy_normalization() {
constant
Ok(constant)
} else {
let constant = constant.super_fold_with(self);
constant.eval(self.selcx.tcx(), self.param_env)
let constant = constant.super_fold_with(self)?;
Ok(constant.eval(self.selcx.tcx(), self.param_env))
}
}
}
@ -577,14 +582,14 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
fn fold_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
) -> Result<ty::Binder<'tcx, T>, Self::Error> {
self.current_index.shift_in(1);
let t = t.super_fold_with(self);
self.current_index.shift_out(1);
t
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
match *r {
ty::ReLateBound(debruijn, _)
if debruijn.as_usize() + 1
@ -596,13 +601,13 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
let universe = self.universe_for(debruijn);
let p = ty::PlaceholderRegion { universe, name: br.kind };
self.mapped_regions.insert(p, br);
self.infcx.tcx.mk_region(ty::RePlaceholder(p))
Ok(self.infcx.tcx.mk_region(ty::RePlaceholder(p)))
}
_ => r,
_ => Ok(r),
}
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
fn fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
match *t.kind() {
ty::Bound(debruijn, _)
if debruijn.as_usize() + 1
@ -614,14 +619,17 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
let universe = self.universe_for(debruijn);
let p = ty::PlaceholderType { universe, name: bound_ty.var };
self.mapped_types.insert(p, bound_ty);
self.infcx.tcx.mk_ty(ty::Placeholder(p))
Ok(self.infcx.tcx.mk_ty(ty::Placeholder(p)))
}
_ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
_ => t,
_ => Ok(t),
}
}
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
fn fold_const(
&mut self,
ct: &'tcx ty::Const<'tcx>,
) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
match *ct {
ty::Const { val: ty::ConstKind::Bound(debruijn, _), ty: _ }
if debruijn.as_usize() + 1
@ -638,10 +646,10 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
name: ty::BoundConst { var: bound_const, ty },
};
self.mapped_consts.insert(p, bound_const);
self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty })
Ok(self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty }))
}
_ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self),
_ => ct,
_ => Ok(ct),
}
}
}
@ -685,9 +693,9 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
fn fold_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
) -> Result<ty::Binder<'tcx, T>, Self::Error> {
if !t.has_placeholders() && !t.has_infer_regions() {
return t;
return Ok(t);
}
self.current_index.shift_in(1);
let t = t.super_fold_with(self);
@ -695,7 +703,7 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
t
}
fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> {
fn fold_region(&mut self, r0: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
let r1 = match r0 {
ty::ReVar(_) => self
.infcx
@ -729,10 +737,10 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
debug!(?r0, ?r1, ?r2, "fold_region");
r2
Ok(r2)
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
match *ty.kind() {
ty::Placeholder(p) => {
let replace_var = self.mapped_types.get(&p);
@ -746,18 +754,21 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
self.tcx().mk_ty(ty::Bound(db, *replace_var))
Ok(self.tcx().mk_ty(ty::Bound(db, *replace_var)))
}
None => ty,
None => Ok(ty),
}
}
_ if ty.has_placeholders() || ty.has_infer_regions() => ty.super_fold_with(self),
_ => ty,
_ => Ok(ty),
}
}
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
fn fold_const(
&mut self,
ct: &'tcx ty::Const<'tcx>,
) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
if let ty::Const { val: ty::ConstKind::Placeholder(p), ty } = *ct {
let replace_var = self.mapped_consts.get(&p);
match replace_var {
@ -770,10 +781,11 @@ impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
self.tcx()
.mk_const(ty::Const { val: ty::ConstKind::Bound(db, *replace_var), ty })
Ok(self
.tcx()
.mk_const(ty::Const { val: ty::ConstKind::Bound(db, *replace_var), ty }))
}
None => ct,
None => Ok(ct),
}
} else {
ct.super_fold_with(self)

View file

@ -184,7 +184,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
fn fold_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
) -> Result<ty::Binder<'tcx, T>, Self::Error> {
self.universes.push(None);
let t = t.super_fold_with(self);
self.universes.pop();
@ -192,13 +192,13 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
}
#[instrument(level = "debug", skip(self))]
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
if !needs_normalization(&ty, self.param_env.reveal()) {
return ty;
return Ok(ty);
}
if let Some(ty) = self.cache.get(&ty) {
return ty;
return Ok(ty);
}
// See note in `rustc_trait_selection::traits::project` about why we
@ -215,7 +215,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
Reveal::UserFacing => ty.super_fold_with(self),
Reveal::All => {
let substs = substs.super_fold_with(self);
let substs = substs.super_fold_with(self)?;
let recursion_limit = self.tcx().recursion_limit();
if !recursion_limit.value_within_limit(self.anon_depth) {
let obligation = Obligation::with_depth(
@ -252,7 +252,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
// we don't need to replace them with placeholders (see branch below).
let tcx = self.infcx.tcx;
let data = data.super_fold_with(self);
let data = data.super_fold_with(self)?;
let mut orig_values = OriginalQueryValues::default();
// HACK(matthewjasper) `'static` is special-cased in selection,
@ -280,7 +280,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
debug!("QueryNormalizer: result = {:#?}", result);
debug!("QueryNormalizer: obligations = {:#?}", obligations);
self.obligations.extend(obligations);
result.normalized_ty
Ok(result.normalized_ty)
}
Err(_) => {
@ -308,7 +308,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
&mut self.universes,
data,
);
let data = data.super_fold_with(self);
let data = data.super_fold_with(self)?;
let mut orig_values = OriginalQueryValues::default();
// HACK(matthewjasper) `'static` is special-cased in selection,
@ -335,14 +335,14 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
debug!("QueryNormalizer: result = {:#?}", result);
debug!("QueryNormalizer: obligations = {:#?}", obligations);
self.obligations.extend(obligations);
crate::traits::project::PlaceholderReplacer::replace_placeholders(
Ok(crate::traits::project::PlaceholderReplacer::replace_placeholders(
infcx,
mapped_regions,
mapped_types,
mapped_consts,
&self.universes,
result.normalized_ty,
)
))
}
Err(_) => {
self.error = true;
@ -358,17 +358,23 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
}
_ => ty.super_fold_with(self),
})();
})()?;
self.cache.insert(ty, res);
res
Ok(res)
}
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
let constant = constant.super_fold_with(self);
constant.eval(self.infcx.tcx, self.param_env)
fn fold_const(
&mut self,
constant: &'tcx ty::Const<'tcx>,
) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
let constant = constant.super_fold_with(self)?;
Ok(constant.eval(self.infcx.tcx, self.param_env))
}
fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
fn fold_mir_const(
&mut self,
constant: mir::ConstantKind<'tcx>,
) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
constant.super_fold_with(self)
}
}