move hack to normalize_param_env_or_error
This commit is contained in:
parent
9610dfe5a9
commit
1e9b69bf3f
@ -589,17 +589,6 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||
debug!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
|
||||
let tcx = relation.tcx();
|
||||
|
||||
// HACK(const_generics): We still need to eagerly evaluate consts when
|
||||
// relating them because during `normalize_param_env_or_error`,
|
||||
// we may relate an evaluated constant in a obligation against
|
||||
// an unnormalized (i.e. unevaluated) const in the param-env.
|
||||
// FIXME(generic_const_exprs): Once we always lazily unify unevaluated constants
|
||||
// these `eval` calls can be removed.
|
||||
if !tcx.features().generic_const_exprs {
|
||||
a = a.eval(tcx, relation.param_env());
|
||||
b = b.eval(tcx, relation.param_env());
|
||||
}
|
||||
|
||||
if tcx.features().generic_const_exprs {
|
||||
a = tcx.expand_abstract_consts(a);
|
||||
b = tcx.expand_abstract_consts(b);
|
||||
|
@ -32,7 +32,7 @@
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeSuperVisitable};
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFolder, TypeSuperVisitable};
|
||||
use rustc_middle::ty::{InternalSubsts, SubstsRef};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::Span;
|
||||
@ -272,8 +272,62 @@ pub fn normalize_param_env_or_error<'tcx>(
|
||||
// parameter environments once for every fn as it goes,
|
||||
// and errors will get reported then; so outside of type inference we
|
||||
// can be sure that no errors should occur.
|
||||
let mut predicates: Vec<_> =
|
||||
util::elaborate(tcx, unnormalized_env.caller_bounds().into_iter()).collect();
|
||||
let mut predicates: Vec<_> = util::elaborate(
|
||||
tcx,
|
||||
unnormalized_env.caller_bounds().into_iter().map(|predicate| {
|
||||
if tcx.features().generic_const_exprs {
|
||||
return predicate;
|
||||
}
|
||||
|
||||
struct ConstNormalizer<'tcx>(TyCtxt<'tcx>);
|
||||
|
||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ConstNormalizer<'tcx> {
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
// While it is pretty sus to be evaluating things with an empty param env, it
|
||||
// should actually be okay since without `feature(generic_const_exprs)` the only
|
||||
// const arguments that have a non-empty param env are array repeat counts. These
|
||||
// do not appear in the type system though.
|
||||
c.eval(self.0, ty::ParamEnv::empty())
|
||||
}
|
||||
}
|
||||
|
||||
// This whole normalization step is a hack to work around the fact that
|
||||
// `normalize_param_env_or_error` is fundamentally broken from using an
|
||||
// unnormalized param env with a trait solver that expects the param env
|
||||
// to be normalized.
|
||||
//
|
||||
// When normalizing the param env we can end up evaluating obligations
|
||||
// that have been normalized but can only be proven via a where clause
|
||||
// which is still in its unnormalized form. example:
|
||||
//
|
||||
// Attempting to prove `T: Trait<<u8 as Identity>::Assoc>` in a param env
|
||||
// with a `T: Trait<<u8 as Identity>::Assoc>` where clause will fail because
|
||||
// we first normalize obligations before proving them so we end up proving
|
||||
// `T: Trait<u8>`. Since lazy normalization is not implemented equating `u8`
|
||||
// with `<u8 as Identity>::Assoc` fails outright so we incorrectly believe that
|
||||
// we cannot prove `T: Trait<u8>`.
|
||||
//
|
||||
// The same thing is true for const generics- attempting to prove
|
||||
// `T: Trait<ConstKind::Unevaluated(...)>` with the same thing as a where clauses
|
||||
// will fail. After normalization we may be attempting to prove `T: Trait<4>` with
|
||||
// the unnormalized where clause `T: Trait<ConstKind::Unevaluated(...)>`. In order
|
||||
// for the obligation to hold `4` must be equal to `ConstKind::Unevaluated(...)`
|
||||
// but as we do not have lazy norm implemented, equating the two consts fails outright.
|
||||
//
|
||||
// Ideally we would not normalize consts here at all but it is required for backwards
|
||||
// compatibility. Eventually when lazy norm is implemented this can just be removed.
|
||||
// We do not normalize types here as there is no backwards compatibility requirement
|
||||
// for us to do so.
|
||||
//
|
||||
// FIXME(-Ztrait-solver=next): remove this hack since we have deferred projection equality
|
||||
predicate.fold_with(&mut ConstNormalizer(tcx))
|
||||
}),
|
||||
)
|
||||
.collect();
|
||||
|
||||
debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user