about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-03-11 19:35:32 +0100
committerGitHub <noreply@github.com>2025-03-11 19:35:32 +0100
commit16ff824133a0d7473a68066969fabceb522c8109 (patch)
tree89a54f4e44a65cabdc3b0e16ea8d7527fd92e8de
parent4ff58c910359ee334c3551728c3132724da6b862 (diff)
parent8ab05adc37667c3169fb120b3a9f53be9a909c3b (diff)
downloadrust-16ff824133a0d7473a68066969fabceb522c8109.tar.gz
rust-16ff824133a0d7473a68066969fabceb522c8109.zip
Rollup merge of #138284 - compiler-errors:const-param-ty-annotation, r=BoxyUwU
Do not write user type annotation for const param value path

As I noted in the code comment, `DefKind::ConstParam` isn't actually *generic* over its own args, we just use the identity args from the body when lowering the value path so we have something to plug into the `EarlyBinder` we get back from `type_of` for the const param. So skip over it in `write_user_type_annotation_from_args`.

Somewhat unrelated, but I left an explanation for a somewhat mysterious quirk in the THIR lowering of user type annotations for patterns having to do with ctors and their `type_of` not actually being the type of the pattern node it's ascribing.

Fixes #138048

r? ``@BoxyUwU``
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs7
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/util.rs22
-rw-r--r--tests/crashes/138048.rs8
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.rs10
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.stderr11
7 files changed, 51 insertions, 11 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index c46a42c5de1..36ad0ae1c30 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -220,6 +220,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         debug!("fcx {}", self.tag());
 
+        // Don't write user type annotations for const param types, since we give them
+        // identity args just so that we can trivially substitute their `EarlyBinder`.
+        // We enforce that they match their type in MIR later on.
+        if matches!(self.tcx.def_kind(def_id), DefKind::ConstParam) {
+            return;
+        }
+
         if Self::can_contain_user_lifetime_bounds((args, user_self_ty)) {
             let canonicalized = self.canonicalize_user_type_annotation(ty::UserType::new(
                 ty::UserTypeKind::TypeOf(def_id, UserArgs { args, user_self_ty }),
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 2e069cae426..3d55c1401b6 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -207,7 +207,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
         &self,
         hir_id: HirId,
     ) -> Option<ty::CanonicalUserType<'tcx>> {
-        crate::thir::util::user_args_applied_to_ty_of_hir_id(self.typeck_results, hir_id)
+        crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id)
     }
 }
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 8dc3f998e09..4bfeab44bf4 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -539,7 +539,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         &self,
         hir_id: hir::HirId,
     ) -> Option<ty::CanonicalUserType<'tcx>> {
-        crate::thir::util::user_args_applied_to_ty_of_hir_id(self.typeck_results, hir_id)
+        crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id)
     }
 
     /// Takes a HIR Path. If the path is a constant, evaluates it and feeds
diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs
index 60a47a94e3a..457957f5fce 100644
--- a/compiler/rustc_mir_build/src/thir/util.rs
+++ b/compiler/rustc_mir_build/src/thir/util.rs
@@ -1,12 +1,16 @@
+use std::assert_matches::assert_matches;
+
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_middle::bug;
-use rustc_middle::ty::{self, CanonicalUserType};
+use rustc_middle::ty::{self, CanonicalUserType, TyCtxt};
 use tracing::debug;
 
 /// Looks up the type associated with this hir-id and applies the
 /// user-given generic parameters; the hir-id must map to a suitable
 /// type.
 pub(crate) fn user_args_applied_to_ty_of_hir_id<'tcx>(
+    tcx: TyCtxt<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     hir_id: hir::HirId,
 ) -> Option<CanonicalUserType<'tcx>> {
@@ -16,7 +20,23 @@ pub(crate) fn user_args_applied_to_ty_of_hir_id<'tcx>(
     let ty = typeck_results.node_type(hir_id);
     match ty.kind() {
         ty::Adt(adt_def, ..) => {
+            // This "fixes" user type annotations for tupled ctor patterns for ADTs.
+            // That's because `type_of(ctor_did)` returns a FnDef, but we actually
+            // want to be annotating the type of the ADT itself. It's a bit goofy,
+            // but it's easier to adjust this here rather than in the path lowering
+            // code for patterns in HIR.
             if let ty::UserTypeKind::TypeOf(did, _) = &mut user_ty.value.kind {
+                // This is either already set up correctly (struct, union, enum, or variant),
+                // or needs adjusting (ctor). Make sure we don't start adjusting other
+                // user annotations like consts or fn calls.
+                assert_matches!(
+                    tcx.def_kind(*did),
+                    DefKind::Ctor(..)
+                        | DefKind::Struct
+                        | DefKind::Enum
+                        | DefKind::Union
+                        | DefKind::Variant
+                );
                 *did = adt_def.did();
             }
             Some(user_ty)
diff --git a/tests/crashes/138048.rs b/tests/crashes/138048.rs
deleted file mode 100644
index fd59f46c752..00000000000
--- a/tests/crashes/138048.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ known-bug: #138048
-struct Foo;
-
-impl<'b> Foo {
-    fn bar<const V: u8>() {
-        let V;
-    }
-}
diff --git a/tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.rs b/tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.rs
new file mode 100644
index 00000000000..bc54aad59ba
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.rs
@@ -0,0 +1,10 @@
+struct Foo<'a>(&'a ());
+
+// We need a lifetime in scope or else we do not write a user type annotation as a fast-path.
+impl<'a> Foo<'a> {
+    fn bar<const V: u8>() {
+        let V;
+        //~^ ERROR constant parameters cannot be referenced in patterns
+    }
+}
+fn main() {}
diff --git a/tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.stderr b/tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.stderr
new file mode 100644
index 00000000000..299ff4165e0
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.stderr
@@ -0,0 +1,11 @@
+error[E0158]: constant parameters cannot be referenced in patterns
+  --> $DIR/bad-param-in-pat.rs:6:13
+   |
+LL |     fn bar<const V: u8>() {
+   |            ----------- constant defined here
+LL |         let V;
+   |             ^ can't be used in patterns
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0158`.