about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs30
-rw-r--r--tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.rs21
-rw-r--r--tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.stderr31
4 files changed, 76 insertions, 9 deletions
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 757034fe30a..f95635370dc 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -325,6 +325,9 @@ impl<'tcx> Const<'tcx> {
 
                 match c.kind() {
                     ConstKind::Value(ty, val) => Ok(tcx.valtree_to_const_val((ty, val))),
+                    ConstKind::Expr(_) => {
+                        bug!("Normalization of `ty::ConstKind::Expr` is unimplemented")
+                    }
                     _ => Err(tcx.dcx().delayed_bug("Unevaluated `ty::Const` in MIR body").into()),
                 }
             }
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 17636d432ae..fe90066b4e7 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -578,16 +578,28 @@ pub fn try_evaluate_const<'tcx>(
                         (args, param_env)
                     }
                 }
-            } else {
-                // FIXME: We don't check anything on stable as the only way we can wind up with
-                // an unevaluated constant containing generic parameters is through array repeat
-                // expression counts which have a future compat lint for usage of generic parameters
-                // instead of a hard error.
+            } else if tcx.def_kind(uv.def) == DefKind::AnonConst && uv.has_non_region_infer() {
+                // FIXME: remove this when `const_evaluatable_unchecked` is a hard error.
+                //
+                // Diagnostics will sometimes replace the identity args of anon consts in
+                // array repeat expr counts with inference variables so we have to handle this
+                // even though it is not something we should ever actually encounter.
                 //
-                // This codepath is however also reachable by `generic_const_exprs` and some other
-                // feature gates which allow constants in the type system to use generic parameters.
-                // In theory we should be checking for generic parameters here and returning an error
-                // in such cases.
+                // Array repeat expr counts are allowed to syntactically use generic parameters
+                // but must not actually depend on them in order to evalaute succesfully. This means
+                // that it is actually fine to evalaute them in their own environment rather than with
+                // the actually provided generic arguments.
+                tcx.dcx().delayed_bug(
+                    "Encountered anon const with inference variable args but no error reported",
+                );
+
+                let args = GenericArgs::identity_for_item(tcx, uv.def);
+                let param_env = tcx.param_env(uv.def);
+                (args, param_env)
+            } else {
+                // FIXME: This codepath is reachable under `associated_const_equality` and in the
+                // future will be reachable by `min_generic_const_args`. We should handle inference
+                // variables and generic parameters properly instead of doing nothing.
                 (uv.args, param_env)
             };
             let uv = ty::UnevaluatedConst::new(uv.def, args);
diff --git a/tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.rs b/tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.rs
new file mode 100644
index 00000000000..346ef64a8a6
--- /dev/null
+++ b/tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.rs
@@ -0,0 +1,21 @@
+// Regression test for #132955 checking that we handle anon consts with
+// inference variables in their generic arguments correctly.
+//
+// This arose via diagnostics where we would have some failing goal such
+// as `[u8; AnonConst<Self>]: PartialEq<Self::A>`, then as part of diagnostics
+// we would replace all generic parameters with inference vars which would yield
+// a self type of `[u8; AnonConst<?x>]` and then attempt to normalize `AnonConst<?x>`.
+
+pub trait T {
+    type A;
+    const P: Self::A;
+
+    fn a() {
+        [0u8; std::mem::size_of::<Self::A>()] == Self::P;
+        //~^ ERROR: can't compare
+        //~| ERROR: constant expression depends on a generic parameter
+        //~| ERROR: constant expression depends on a generic parameter
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.stderr b/tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.stderr
new file mode 100644
index 00000000000..12de4f1dc30
--- /dev/null
+++ b/tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.stderr
@@ -0,0 +1,31 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/failing_goal_with_repeat_expr_anon_const.rs:14:15
+   |
+LL |         [0u8; std::mem::size_of::<Self::A>()] == Self::P;
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/failing_goal_with_repeat_expr_anon_const.rs:14:47
+   |
+LL |         [0u8; std::mem::size_of::<Self::A>()] == Self::P;
+   |                                               ^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error[E0277]: can't compare `[u8; std::mem::size_of::<Self::A>()]` with `<Self as T>::A`
+  --> $DIR/failing_goal_with_repeat_expr_anon_const.rs:14:47
+   |
+LL |         [0u8; std::mem::size_of::<Self::A>()] == Self::P;
+   |                                               ^^ no implementation for `[u8; std::mem::size_of::<Self::A>()] == <Self as T>::A`
+   |
+   = help: the trait `PartialEq<<Self as T>::A>` is not implemented for `[u8; std::mem::size_of::<Self::A>()]`
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | pub trait T where [u8; std::mem::size_of::<Self::A>()]: PartialEq<<Self as T>::A> {
+   |             +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.