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:
commit
e6d2de9483
45 changed files with 908 additions and 794 deletions
|
@ -22,6 +22,7 @@
|
|||
#![feature(never_type)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(unwrap_infallible)]
|
||||
#![recursion_limit = "512"] // For rustdoc
|
||||
|
||||
#[macro_use]
|
||||
|
|
|
@ -65,14 +65,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
// Convert the type from the function into a type valid outside
|
||||
// the function, by replacing invalid regions with 'static,
|
||||
// after producing an error for each of them.
|
||||
let definition_ty = instantiated_ty.fold_with(&mut ReverseMapper::new(
|
||||
self.tcx,
|
||||
self.is_tainted_by_errors(),
|
||||
def_id,
|
||||
map,
|
||||
instantiated_ty,
|
||||
span,
|
||||
));
|
||||
let definition_ty = instantiated_ty
|
||||
.fold_with(&mut ReverseMapper::new(
|
||||
self.tcx,
|
||||
self.is_tainted_by_errors(),
|
||||
def_id,
|
||||
map,
|
||||
instantiated_ty,
|
||||
span,
|
||||
))
|
||||
.into_ok();
|
||||
debug!(?definition_ty);
|
||||
|
||||
definition_ty
|
||||
|
@ -123,14 +125,14 @@ impl ReverseMapper<'tcx> {
|
|||
) -> GenericArg<'tcx> {
|
||||
assert!(!self.map_missing_regions_to_empty);
|
||||
self.map_missing_regions_to_empty = true;
|
||||
let kind = kind.fold_with(self);
|
||||
let kind = kind.fold_with(self).into_ok();
|
||||
self.map_missing_regions_to_empty = false;
|
||||
kind
|
||||
}
|
||||
|
||||
fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
|
||||
assert!(!self.map_missing_regions_to_empty);
|
||||
kind.fold_with(self)
|
||||
kind.fold_with(self).into_ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,17 +142,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 +167,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 +182,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 +198,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 +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) => {
|
||||
|
@ -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) => {
|
||||
|
@ -262,7 +264,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 +280,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
|||
)
|
||||
.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);
|
||||
// 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 +322,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
|||
}
|
||||
|
||||
_ => ct,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
@ -1916,8 +1916,9 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
self.probe(|_| {
|
||||
let mut selcx = SelectionContext::new(self);
|
||||
|
||||
let cleaned_pred =
|
||||
pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
|
||||
let cleaned_pred = pred
|
||||
.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() })
|
||||
.into_ok();
|
||||
|
||||
let cleaned_pred = super::project::normalize(
|
||||
&mut selcx,
|
||||
|
|
|
@ -339,7 +339,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
|
|||
if !needs_normalization(&value, self.param_env.reveal()) {
|
||||
value
|
||||
} else {
|
||||
value.fold_with(self)
|
||||
value.fold_with(self).into_ok()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -550,7 +555,7 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
|
|||
universe_indices,
|
||||
};
|
||||
|
||||
let value = value.super_fold_with(&mut replacer);
|
||||
let value = value.super_fold_with(&mut replacer).into_ok();
|
||||
|
||||
(value, replacer.mapped_regions, replacer.mapped_types, replacer.mapped_consts)
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -673,7 +681,7 @@ impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> {
|
|||
universe_indices,
|
||||
current_index: ty::INNERMOST,
|
||||
};
|
||||
value.super_fold_with(&mut replacer)
|
||||
value.super_fold_with(&mut replacer).into_ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -1534,7 +1546,8 @@ fn confirm_candidate<'cx, 'tcx>(
|
|||
// when possible for this to work. See `auto-trait-projection-recursion.rs`
|
||||
// for a case where this matters.
|
||||
if progress.ty.has_infer_regions() {
|
||||
progress.ty = OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty);
|
||||
progress.ty =
|
||||
OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty).into_ok();
|
||||
}
|
||||
progress
|
||||
}
|
||||
|
|
|
@ -61,7 +61,6 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
|
|||
cause: self.cause,
|
||||
param_env: self.param_env,
|
||||
obligations: vec![],
|
||||
error: false,
|
||||
cache: SsoHashMap::new(),
|
||||
anon_depth: 0,
|
||||
universes: vec![],
|
||||
|
@ -100,11 +99,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
|
|||
std::any::type_name::<T>(),
|
||||
normalizer.obligations,
|
||||
);
|
||||
if normalizer.error {
|
||||
Err(NoSolution)
|
||||
} else {
|
||||
Ok(Normalized { value: result, obligations: normalizer.obligations })
|
||||
}
|
||||
result.map(|value| Normalized { value, obligations: normalizer.obligations })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,12 +166,13 @@ struct QueryNormalizer<'cx, 'tcx> {
|
|||
param_env: ty::ParamEnv<'tcx>,
|
||||
obligations: Vec<PredicateObligation<'tcx>>,
|
||||
cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
|
||||
error: bool,
|
||||
anon_depth: usize,
|
||||
universes: Vec<Option<ty::UniverseIndex>>,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||
type Error = NoSolution;
|
||||
|
||||
fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
@ -184,7 +180,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 +188,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 +211,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 +248,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,
|
||||
|
@ -262,39 +258,22 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
|||
.canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
|
||||
debug!("QueryNormalizer: c_data = {:#?}", c_data);
|
||||
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
|
||||
match tcx.normalize_projection_ty(c_data) {
|
||||
Ok(result) => {
|
||||
// We don't expect ambiguity.
|
||||
if result.is_ambiguous() {
|
||||
self.error = true;
|
||||
return ty.super_fold_with(self);
|
||||
}
|
||||
|
||||
match self.infcx.instantiate_query_response_and_region_obligations(
|
||||
self.cause,
|
||||
self.param_env,
|
||||
&orig_values,
|
||||
result,
|
||||
) {
|
||||
Ok(InferOk { value: result, obligations }) => {
|
||||
debug!("QueryNormalizer: result = {:#?}", result);
|
||||
debug!("QueryNormalizer: obligations = {:#?}", obligations);
|
||||
self.obligations.extend(obligations);
|
||||
result.normalized_ty
|
||||
}
|
||||
|
||||
Err(_) => {
|
||||
self.error = true;
|
||||
ty.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(NoSolution) => {
|
||||
self.error = true;
|
||||
ty.super_fold_with(self)
|
||||
}
|
||||
let result = tcx.normalize_projection_ty(c_data)?;
|
||||
// We don't expect ambiguity.
|
||||
if result.is_ambiguous() {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
let InferOk { value: result, obligations } =
|
||||
self.infcx.instantiate_query_response_and_region_obligations(
|
||||
self.cause,
|
||||
self.param_env,
|
||||
&orig_values,
|
||||
result,
|
||||
)?;
|
||||
debug!("QueryNormalizer: result = {:#?}", result);
|
||||
debug!("QueryNormalizer: obligations = {:#?}", obligations);
|
||||
self.obligations.extend(obligations);
|
||||
Ok(result.normalized_ty)
|
||||
}
|
||||
|
||||
ty::Projection(data) => {
|
||||
|
@ -308,7 +287,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,
|
||||
|
@ -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);
|
||||
debug!("QueryNormalizer: c_data = {:#?}", c_data);
|
||||
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
|
||||
match tcx.normalize_projection_ty(c_data) {
|
||||
Ok(result) => {
|
||||
// We don't expect ambiguity.
|
||||
if result.is_ambiguous() {
|
||||
self.error = true;
|
||||
return ty.super_fold_with(self);
|
||||
}
|
||||
match self.infcx.instantiate_query_response_and_region_obligations(
|
||||
self.cause,
|
||||
self.param_env,
|
||||
&orig_values,
|
||||
result,
|
||||
) {
|
||||
Ok(InferOk { value: result, obligations }) => {
|
||||
debug!("QueryNormalizer: result = {:#?}", result);
|
||||
debug!("QueryNormalizer: obligations = {:#?}", obligations);
|
||||
self.obligations.extend(obligations);
|
||||
crate::traits::project::PlaceholderReplacer::replace_placeholders(
|
||||
infcx,
|
||||
mapped_regions,
|
||||
mapped_types,
|
||||
mapped_consts,
|
||||
&self.universes,
|
||||
result.normalized_ty,
|
||||
)
|
||||
}
|
||||
Err(_) => {
|
||||
self.error = true;
|
||||
ty.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(NoSolution) => {
|
||||
self.error = true;
|
||||
ty.super_fold_with(self)
|
||||
}
|
||||
let result = tcx.normalize_projection_ty(c_data)?;
|
||||
// We don't expect ambiguity.
|
||||
if result.is_ambiguous() {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
let InferOk { value: result, obligations } =
|
||||
self.infcx.instantiate_query_response_and_region_obligations(
|
||||
self.cause,
|
||||
self.param_env,
|
||||
&orig_values,
|
||||
result,
|
||||
)?;
|
||||
debug!("QueryNormalizer: result = {:#?}", result);
|
||||
debug!("QueryNormalizer: obligations = {:#?}", obligations);
|
||||
self.obligations.extend(obligations);
|
||||
Ok(crate::traits::project::PlaceholderReplacer::replace_placeholders(
|
||||
infcx,
|
||||
mapped_regions,
|
||||
mapped_types,
|
||||
mapped_consts,
|
||||
&self.universes,
|
||||
result.normalized_ty,
|
||||
))
|
||||
}
|
||||
|
||||
_ => ty.super_fold_with(self),
|
||||
})();
|
||||
})()?;
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2222,6 +2222,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
.predicate
|
||||
.to_poly_trait_ref()
|
||||
.fold_with(&mut self.freshener)
|
||||
.into_ok()
|
||||
.with_constness(obligation.predicate.skip_binder().constness);
|
||||
|
||||
let dfn = previous_stack.cache.next_dfn();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue