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:
commit
88e0bea7ca
2 changed files with 40 additions and 9 deletions
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
src/test/ui/const-generics/issues/issue-89304.rs
Normal file
20
src/test/ui/const-generics/issues/issue-89304.rs
Normal 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() {}
|
Loading…
Add table
Add a link
Reference in a new issue