about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBoxy <supbscripter@gmail.com>2023-01-29 01:00:57 +0000
committerBoxy <supbscripter@gmail.com>2023-02-05 07:24:54 +0000
commitd85d906f8c44dd98bf6bc0e4b753aa241839c323 (patch)
tree2304fe8c3bff131573b1cd5e6de1b3fb1c0ce7ad
parent50d3ba5bcbf5c7e13d4ce068d3339710701dd603 (diff)
downloadrust-d85d906f8c44dd98bf6bc0e4b753aa241839c323.tar.gz
rust-d85d906f8c44dd98bf6bc0e4b753aa241839c323.zip
emit `ConstEquate` in `TypeRelating<D>`
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs13
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs30
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs18
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr20
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs12
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr20
6 files changed, 92 insertions, 21 deletions
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index f83219b8ee2..a2cfe8d8881 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -817,12 +817,13 @@ impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D>
 where
     D: TypeRelatingDelegate<'tcx>,
 {
-    fn const_equate_obligation(&mut self, _a: ty::Const<'tcx>, _b: ty::Const<'tcx>) {
-        // We don't have to worry about the equality of consts during borrow checking
-        // as consts always have a static lifetime.
-        // FIXME(oli-obk): is this really true? We can at least have HKL and with
-        // inline consts we may have further lifetimes that may be unsound to treat as
-        // 'static.
+    fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
+        self.delegate.register_obligations(vec![Obligation::new(
+            self.tcx(),
+            ObligationCause::dummy(),
+            self.param_env(),
+            ty::Binder::dummy(ty::PredicateKind::ConstEquate(a, b)),
+        )]);
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index fa87301df7e..890dabde1f7 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -629,6 +629,8 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
         b = tcx.expand_abstract_consts(b);
     }
 
+    debug!("{}.super_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
+
     // Currently, the values that can be unified are primitive types,
     // and those that derive both `PartialEq` and `Eq`, corresponding
     // to structural-match types.
@@ -665,30 +667,28 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
 
             // FIXME(generic_const_exprs): is it possible to relate two consts which are not identical
             // exprs? Should we care about that?
+            // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to
+            // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought
+            // of as being generic over the argument types, however this is implicit so these types don't get
+            // related when we relate the substs of the item this const arg is for.
             let expr = match (ae, be) {
-                (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br))
-                    if a_op == b_op && al.ty() == bl.ty() && ar.ty() == br.ty() =>
-                {
+                (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => {
+                    r.relate(al.ty(), bl.ty())?;
+                    r.relate(ar.ty(), br.ty())?;
                     Expr::Binop(a_op, r.consts(al, bl)?, r.consts(ar, br)?)
                 }
-                (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv))
-                    if a_op == b_op && av.ty() == bv.ty() =>
-                {
+                (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) if a_op == b_op => {
+                    r.relate(av.ty(), bv.ty())?;
                     Expr::UnOp(a_op, r.consts(av, bv)?)
                 }
-                (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt))
-                    if ak == bk && av.ty() == bv.ty() =>
-                {
+                (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) if ak == bk => {
+                    r.relate(av.ty(), bv.ty())?;
                     Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?)
                 }
                 (Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba))
-                    if aa.len() == ba.len()
-                        && af.ty() == bf.ty()
-                        && aa
-                            .iter()
-                            .zip(ba.iter())
-                            .all(|(a_arg, b_arg)| a_arg.ty() == b_arg.ty()) =>
+                    if aa.len() == ba.len() =>
                 {
+                    r.relate(af.ty(), bf.ty())?;
                     let func = r.consts(af, bf)?;
                     let mut related_args = Vec::with_capacity(aa.len());
                     for (a_arg, b_arg) in aa.iter().zip(ba.iter()) {
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs
new file mode 100644
index 00000000000..fd52fc35541
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs
@@ -0,0 +1,18 @@
+// checks that when we relate a `Expr::Binop` we also relate the types of the
+// const arguments.
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Bar<const B: bool>;
+
+const fn make_generic(_: usize, a: bool) -> bool {
+    a
+}
+
+fn foo<const N: usize>() -> Bar<{ make_generic(N, true == false) }> {
+    Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
+    //~^ error: mismatched types
+    //~| error: unconstrained generic constant
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr
new file mode 100644
index 00000000000..ba824e84a5a
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/relate_binop_arg_tys.rs:13:5
+   |
+LL |     Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ make_generic(N, true == false) }`, found `{ make_generic(N, 1_u8 == 0_u8) }`
+   |
+   = note: expected constant `{ make_generic(N, true == false) }`
+              found constant `{ make_generic(N, 1_u8 == 0_u8) }`
+
+error: unconstrained generic constant
+  --> $DIR/relate_binop_arg_tys.rs:13:11
+   |
+LL |     Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { make_generic(N, 1_u8 == 0_u8) }]:`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs
new file mode 100644
index 00000000000..bef9d4b9e99
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs
@@ -0,0 +1,12 @@
+// checks that when we relate a `Expr::Cast` we also relate the type of the
+// const argument.
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn foo<const N: usize>() -> [(); (true as usize) + N] {
+    [(); (1_u8 as usize) + N]
+    //~^ error: mismatched types
+    //~| error: unconstrained generic constant
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr
new file mode 100644
index 00000000000..d3ba870a2d7
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/relate_cast_arg_ty.rs:7:5
+   |
+LL |     [(); (1_u8 as usize) + N]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(true as usize) + N`, found `(1_u8 as usize) + N`
+   |
+   = note: expected constant `(true as usize) + N`
+              found constant `(1_u8 as usize) + N`
+
+error: unconstrained generic constant
+  --> $DIR/relate_cast_arg_ty.rs:7:10
+   |
+LL |     [(); (1_u8 as usize) + N]
+   |          ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); (1_u8 as usize) + N]:`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.