about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs16
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs14
-rw-r--r--tests/ui/const-generics/adt_const_params/check-type-in-mir.rs16
-rw-r--r--tests/ui/const-generics/adt_const_params/check-type-in-mir.stderr14
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.rs12
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.stderr27
6 files changed, 99 insertions, 0 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index d2eb7a52f78..d6a80e22602 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1773,6 +1773,22 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 {
                     span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
                 }
+            } else if let Const::Ty(_, ct) = constant.const_
+                && let ty::ConstKind::Param(p) = ct.kind()
+            {
+                let body_def_id = self.universal_regions.defining_ty.def_id();
+                let const_param = tcx.generics_of(body_def_id).const_param(p, tcx);
+                self.ascribe_user_type(
+                    constant.const_.ty(),
+                    ty::UserType::new(ty::UserTypeKind::TypeOf(
+                        const_param.def_id,
+                        UserArgs {
+                            args: self.universal_regions.defining_ty.args(),
+                            user_self_ty: None,
+                        },
+                    )),
+                    locations.span(self.body),
+                );
             }
 
             if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() {
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index cfac9b36832..994a5ad32b3 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -184,6 +184,20 @@ impl<'tcx> DefiningTy<'tcx> {
             | DefiningTy::GlobalAsm(def_id) => def_id,
         }
     }
+
+    /// Returns the args of the `DefiningTy`. These are equivalent to the identity
+    /// substs of the body, but replaced with region vids.
+    pub(crate) fn args(&self) -> ty::GenericArgsRef<'tcx> {
+        match *self {
+            DefiningTy::Closure(_, args)
+            | DefiningTy::Coroutine(_, args)
+            | DefiningTy::CoroutineClosure(_, args)
+            | DefiningTy::FnDef(_, args)
+            | DefiningTy::Const(_, args)
+            | DefiningTy::InlineConst(_, args) => args,
+            DefiningTy::GlobalAsm(_) => ty::List::empty(),
+        }
+    }
 }
 
 #[derive(Debug)]
diff --git a/tests/ui/const-generics/adt_const_params/check-type-in-mir.rs b/tests/ui/const-generics/adt_const_params/check-type-in-mir.rs
new file mode 100644
index 00000000000..bec485b001c
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/check-type-in-mir.rs
@@ -0,0 +1,16 @@
+// Ensure that we actually treat `N`'s type as `Invariant<'static>` in MIR typeck.
+
+#![feature(adt_const_params)]
+
+use std::marker::ConstParamTy;
+use std::ops::Deref;
+
+#[derive(ConstParamTy, PartialEq, Eq)]
+struct Invariant<'a>(<&'a () as Deref>::Target);
+
+fn test<'a, const N: Invariant<'static>>() {
+    let x: Invariant<'a> = N;
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/check-type-in-mir.stderr b/tests/ui/const-generics/adt_const_params/check-type-in-mir.stderr
new file mode 100644
index 00000000000..7e265f33f35
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/check-type-in-mir.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+  --> $DIR/check-type-in-mir.rs:12:28
+   |
+LL | fn test<'a, const N: Invariant<'static>>() {
+   |         -- lifetime `'a` defined here
+LL |     let x: Invariant<'a> = N;
+   |                            ^ assignment requires that `'a` must outlive `'static`
+   |
+   = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Invariant<'a>` is invariant over the parameter `'a`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.rs b/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.rs
new file mode 100644
index 00000000000..d3bc544ed6c
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.rs
@@ -0,0 +1,12 @@
+// Ensure that we actually treat `N`'s type as `&'a u32` in MIR typeck.
+
+#![feature(unsized_const_params, adt_const_params, generic_const_parameter_types)]
+//~^ WARN the feature `unsized_const_params` is incomplete
+//~| WARN the feature `generic_const_parameter_types` is incomplete
+
+fn foo<'a, const N: &'a u32>() {
+    let b: &'static u32 = N;
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.stderr b/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.stderr
new file mode 100644
index 00000000000..3dc7ce438fa
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.stderr
@@ -0,0 +1,27 @@
+warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/check-type-in-mir.rs:3:12
+   |
+LL | #![feature(unsized_const_params, adt_const_params, generic_const_parameter_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: the feature `generic_const_parameter_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/check-type-in-mir.rs:3:52
+   |
+LL | #![feature(unsized_const_params, adt_const_params, generic_const_parameter_types)]
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #137626 <https://github.com/rust-lang/rust/issues/137626> for more information
+
+error: lifetime may not live long enough
+  --> $DIR/check-type-in-mir.rs:8:12
+   |
+LL | fn foo<'a, const N: &'a u32>() {
+   |        -- lifetime `'a` defined here
+LL |     let b: &'static u32 = N;
+   |            ^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 1 previous error; 2 warnings emitted
+