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

@ -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]

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
// 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,
}
})
}
}

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)
}
@ -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,

View file

@ -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
}

View file

@ -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)
}
}

View file

@ -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();