1
Fork 0

Rollup merge of #90395 - b-naber:const-expr-type-relation, r=oli-obk

Restrict liveness of mutable borrow of inner infcx in ConstInferUnifier::consts

Fixes https://github.com/rust-lang/rust/issues/89304

r? ``@oli-obk``
This commit is contained in:
Matthias Krüger 2021-10-30 14:37:02 +02:00 committed by GitHub
commit 88e0bea7ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 9 deletions

View file

@ -866,6 +866,7 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?)) Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
} }
#[tracing::instrument(level = "debug", skip(self))]
fn tys(&mut self, t: Ty<'tcx>, _t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { fn tys(&mut self, t: Ty<'tcx>, _t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
debug_assert_eq!(t, _t); debug_assert_eq!(t, _t);
debug!("ConstInferUnifier: t={:?}", t); debug!("ConstInferUnifier: t={:?}", t);
@ -941,6 +942,7 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
} }
} }
#[tracing::instrument(level = "debug", skip(self))]
fn consts( fn consts(
&mut self, &mut self,
c: &'tcx ty::Const<'tcx>, c: &'tcx ty::Const<'tcx>,
@ -951,29 +953,38 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
match c.val { match c.val {
ty::ConstKind::Infer(InferConst::Var(vid)) => { ty::ConstKind::Infer(InferConst::Var(vid)) => {
let mut inner = self.infcx.inner.borrow_mut();
let variable_table = &mut inner.const_unification_table();
// Check if the current unification would end up // Check if the current unification would end up
// unifying `target_vid` with a const which contains // unifying `target_vid` with a const which contains
// an inference variable which is unioned with `target_vid`. // an inference variable which is unioned with `target_vid`.
// //
// Not doing so can easily result in stack overflows. // Not doing so can easily result in stack overflows.
if variable_table.unioned(self.target_vid, vid) { if self
.infcx
.inner
.borrow_mut()
.const_unification_table()
.unioned(self.target_vid, vid)
{
return Err(TypeError::CyclicConst(c)); return Err(TypeError::CyclicConst(c));
} }
let var_value = variable_table.probe_value(vid); let var_value =
self.infcx.inner.borrow_mut().const_unification_table().probe_value(vid);
match var_value.val { match var_value.val {
ConstVariableValue::Known { value: u } => self.consts(u, u), ConstVariableValue::Known { value: u } => self.consts(u, u),
ConstVariableValue::Unknown { universe } => { ConstVariableValue::Unknown { universe } => {
if self.for_universe.can_name(universe) { if self.for_universe.can_name(universe) {
Ok(c) Ok(c)
} else { } else {
let new_var_id = variable_table.new_key(ConstVarValue { let new_var_id =
origin: var_value.origin, self.infcx.inner.borrow_mut().const_unification_table().new_key(
val: ConstVariableValue::Unknown { universe: self.for_universe }, ConstVarValue {
}); origin: var_value.origin,
val: ConstVariableValue::Unknown {
universe: self.for_universe,
},
},
);
Ok(self.tcx().mk_const_var(new_var_id, c.ty)) Ok(self.tcx().mk_const_var(new_var_id, c.ty))
} }
} }

View file

@ -0,0 +1,20 @@
// check-pass
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
struct GenericStruct<const T: usize> { val: i64 }
impl<const T: usize> From<GenericStruct<T>> for GenericStruct<{T + 1}> {
fn from(other: GenericStruct<T>) -> Self {
Self { val: other.val }
}
}
impl<const T: usize> From<GenericStruct<{T + 1}>> for GenericStruct<T> {
fn from(other: GenericStruct<{T + 1}>) -> Self {
Self { val: other.val }
}
}
fn main() {}