about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2021-10-30 14:37:02 +0200
committerGitHub <noreply@github.com>2021-10-30 14:37:02 +0200
commit88e0bea7ca8966c5ee57915cf5afa128168595b2 (patch)
tree80c547167275c0298df4f2c20823d9ef5d26eb08
parentb531364a1a8af28ad78e52cf0a9bf657640aa17c (diff)
parenta39c50b64caca297b3e98ebf7cdb68c96ca0f3c1 (diff)
downloadrust-88e0bea7ca8966c5ee57915cf5afa128168595b2.tar.gz
rust-88e0bea7ca8966c5ee57915cf5afa128168595b2.zip
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``
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs29
-rw-r--r--src/test/ui/const-generics/issues/issue-89304.rs20
2 files changed, 40 insertions, 9 deletions
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 3f54247ecef..09bfb3290f4 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -866,6 +866,7 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
         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>> {
         debug_assert_eq!(t, _t);
         debug!("ConstInferUnifier: t={:?}", t);
@@ -941,6 +942,7 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
         }
     }
 
+    #[tracing::instrument(level = "debug", skip(self))]
     fn consts(
         &mut self,
         c: &'tcx ty::Const<'tcx>,
@@ -951,29 +953,38 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
 
         match c.val {
             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
                 // unifying `target_vid` with a const which contains
                 // an inference variable which is unioned with `target_vid`.
                 //
                 // 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));
                 }
 
-                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 {
                     ConstVariableValue::Known { value: u } => self.consts(u, u),
                     ConstVariableValue::Unknown { universe } => {
                         if self.for_universe.can_name(universe) {
                             Ok(c)
                         } else {
-                            let new_var_id = variable_table.new_key(ConstVarValue {
-                                origin: var_value.origin,
-                                val: ConstVariableValue::Unknown { universe: self.for_universe },
-                            });
+                            let new_var_id =
+                                self.infcx.inner.borrow_mut().const_unification_table().new_key(
+                                    ConstVarValue {
+                                        origin: var_value.origin,
+                                        val: ConstVariableValue::Unknown {
+                                            universe: self.for_universe,
+                                        },
+                                    },
+                                );
                             Ok(self.tcx().mk_const_var(new_var_id, c.ty))
                         }
                     }
diff --git a/src/test/ui/const-generics/issues/issue-89304.rs b/src/test/ui/const-generics/issues/issue-89304.rs
new file mode 100644
index 00000000000..d544d637cc4
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-89304.rs
@@ -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() {}