1
Fork 0

Auto merge of #100315 - compiler-errors:norm-ct-in-proj, r=lcnr

Keep going if normalized projection has unevaluated consts in `QueryNormalizer`

#100312 was the wrong approach, I think this is the right one.

When normalizing a type, if we see that it's a projection, we currently defer to `tcx.normalize_projection_ty`, which normalizes the projections away but doesn't touch the unevaluated constants. So now we just continue to fold the type if it has unevaluated constants so we make sure to evaluate those too, if we can.

Fixes #100217
Fixes #83972
Fixes #84669
Fixes #86710
Fixes #82268
Fixes #73298
This commit is contained in:
bors 2022-08-11 10:47:48 +00:00
commit aeb5067967
7 changed files with 299 additions and 3 deletions

View file

@ -266,7 +266,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
debug!("QueryNormalizer: result = {:#?}", result);
debug!("QueryNormalizer: obligations = {:#?}", obligations);
self.obligations.extend(obligations);
Ok(result.normalized_ty)
let res = result.normalized_ty;
// `tcx.normalize_projection_ty` may normalize to a type that still has
// unevaluated consts, so keep normalizing here if that's the case.
if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
Ok(res.try_super_fold_with(self)?)
} else {
Ok(res)
}
}
ty::Projection(data) => {
@ -305,18 +313,27 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
debug!("QueryNormalizer: result = {:#?}", result);
debug!("QueryNormalizer: obligations = {:#?}", obligations);
self.obligations.extend(obligations);
Ok(crate::traits::project::PlaceholderReplacer::replace_placeholders(
let res = crate::traits::project::PlaceholderReplacer::replace_placeholders(
infcx,
mapped_regions,
mapped_types,
mapped_consts,
&self.universes,
result.normalized_ty,
))
);
// `tcx.normalize_projection_ty` may normalize to a type that still has
// unevaluated consts, so keep normalizing here if that's the case.
if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
Ok(res.try_super_fold_with(self)?)
} else {
Ok(res)
}
}
_ => ty.try_super_fold_with(self),
})()?;
self.cache.insert(ty, res);
Ok(res)
}