Auto merge of #103279 - compiler-errors:normalize-hack-back, r=lcnr
Add eval hack in `super_relate_consts` back
Partially reverts 01adb7e98d
.
This extra eval call *still* needs to happen, for example, in `normalize_param_env_or_error` when a param-env predicate has an unnormalized constant, since the param-env candidates never get normalized during candidate assembly (everywhere else we can assume that they are normalized fully).
r? `@lcnr,` though I feel like I've assigned quite a few PRs to you in the last few days, so feel free to reassign to someone else familiar with this code if you're busy!
cc #103243 (fixes the issue, but don't want to auto-close that until a backport is performed).
This commit is contained in:
commit
d49e7e7fa1
4 changed files with 58 additions and 4 deletions
|
@ -554,6 +554,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
val: &mir::ConstantKind<'tcx>,
|
val: &mir::ConstantKind<'tcx>,
|
||||||
layout: Option<TyAndLayout<'tcx>>,
|
layout: Option<TyAndLayout<'tcx>>,
|
||||||
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
||||||
|
// FIXME(const_prop): normalization needed b/c const prop lint in
|
||||||
|
// `mir_drops_elaborated_and_const_checked`, which happens before
|
||||||
|
// optimized MIR. Only after optimizing the MIR can we guarantee
|
||||||
|
// that the `RevealAll` pass has happened and that the body's consts
|
||||||
|
// are normalized, so any call to resolve before that needs to be
|
||||||
|
// manually normalized.
|
||||||
|
let val = self.tcx.normalize_erasing_regions(self.param_env, *val);
|
||||||
match val {
|
match val {
|
||||||
mir::ConstantKind::Ty(ct) => {
|
mir::ConstantKind::Ty(ct) => {
|
||||||
match ct.kind() {
|
match ct.kind() {
|
||||||
|
@ -585,7 +592,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, *ty, layout),
|
mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout),
|
||||||
mir::ConstantKind::Unevaluated(uv, _) => {
|
mir::ConstantKind::Unevaluated(uv, _) => {
|
||||||
let instance = self.resolve(uv.def, uv.substs)?;
|
let instance = self.resolve(uv.def, uv.substs)?;
|
||||||
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
|
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
|
||||||
|
|
|
@ -574,8 +574,8 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
||||||
/// it.
|
/// it.
|
||||||
pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||||
relation: &mut R,
|
relation: &mut R,
|
||||||
a: ty::Const<'tcx>,
|
mut a: ty::Const<'tcx>,
|
||||||
b: ty::Const<'tcx>,
|
mut b: ty::Const<'tcx>,
|
||||||
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
||||||
debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
|
debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
|
||||||
let tcx = relation.tcx();
|
let tcx = relation.tcx();
|
||||||
|
@ -596,6 +596,17 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'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 !relation.tcx().features().generic_const_exprs {
|
||||||
|
a = a.eval(tcx, relation.param_env());
|
||||||
|
b = b.eval(tcx, relation.param_env());
|
||||||
|
}
|
||||||
|
|
||||||
// Currently, the values that can be unified are primitive types,
|
// Currently, the values that can be unified are primitive types,
|
||||||
// and those that derive both `PartialEq` and `Eq`, corresponding
|
// and those that derive both `PartialEq` and `Eq`, corresponding
|
||||||
// to structural-match types.
|
// to structural-match types.
|
||||||
|
|
|
@ -483,7 +483,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||||
// Use `Reveal::All` here because patterns are always monomorphic even if their function
|
// Use `Reveal::All` here because patterns are always monomorphic even if their function
|
||||||
// isn't.
|
// isn't.
|
||||||
let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx);
|
let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx);
|
||||||
let substs = self.typeck_results.node_substs(id);
|
// N.B. There is no guarantee that substs collected in typeck results are fully normalized,
|
||||||
|
// so they need to be normalized in order to pass to `Instance::resolve`, which will ICE
|
||||||
|
// if given unnormalized types.
|
||||||
|
let substs = self
|
||||||
|
.tcx
|
||||||
|
.normalize_erasing_regions(param_env_reveal_all, self.typeck_results.node_substs(id));
|
||||||
let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) {
|
let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) {
|
||||||
Ok(Some(i)) => i,
|
Ok(Some(i)) => i,
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
|
|
31
src/test/ui/consts/unnormalized-param-env.rs
Normal file
31
src/test/ui/consts/unnormalized-param-env.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
pub trait CSpace<const N: usize> {
|
||||||
|
type Traj;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Const<const R: usize>;
|
||||||
|
|
||||||
|
pub trait Obstacle<CS, const N: usize> {
|
||||||
|
fn trajectory_free<FT, S1>(&self, t: &FT)
|
||||||
|
where
|
||||||
|
CS::Traj: Sized,
|
||||||
|
CS: CSpace<N>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----
|
||||||
|
|
||||||
|
const N: usize = 4;
|
||||||
|
|
||||||
|
struct ObstacleSpace2df32;
|
||||||
|
|
||||||
|
impl<CS> Obstacle<CS, N> for ObstacleSpace2df32 {
|
||||||
|
fn trajectory_free<TF, S1>(&self, t: &TF)
|
||||||
|
where
|
||||||
|
CS::Traj: Sized,
|
||||||
|
CS: CSpace<N>,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue