]> git.lizzy.rs Git - rust.git/commitdiff
fix min_const_generics oversight
authorlcnr <rust@lcnr.de>
Wed, 9 Feb 2022 11:29:43 +0000 (12:29 +0100)
committerlcnr <rust@lcnr.de>
Thu, 10 Feb 2022 07:27:29 +0000 (08:27 +0100)
compiler/rustc_typeck/src/astconv/mod.rs
src/test/ui/const-generics/min_const_generics/forbid-self-no-normalize.rs [new file with mode: 0644]
src/test/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr [new file with mode: 0644]

index 0ad2242f6677c7044fc8592bd1bb1c349c52dbf4..aa054043c4e886e0d9a60a0b4e2fef0286b3a3ea 100644 (file)
@@ -2281,8 +2281,27 @@ pub fn res_to_ty(
                 assert_eq!(opt_self_ty, None);
                 self.prohibit_generics(path.segments);
                 // Try to evaluate any array length constants.
-                let normalized_ty = self.normalize_ty(span, tcx.at(span).type_of(def_id));
-                if forbid_generic && normalized_ty.needs_subst() {
+                let ty = tcx.at(span).type_of(def_id);
+                // HACK(min_const_generics): Forbid generic `Self` types
+                // here as we can't easily do that during nameres.
+                //
+                // We do this before normalization as we otherwise allow
+                // ```rust
+                // trait AlwaysApplicable { type Assoc; }
+                // impl<T: ?Sized> AlwaysApplicable for T { type Assoc = usize; }
+                //
+                // trait BindsParam<T> {
+                //     type ArrayTy;
+                // }
+                // impl<T> BindsParam<T> for <T as AlwaysApplicable>::Assoc {
+                //    type ArrayTy = [u8; Self::MAX];
+                // }
+                // ```
+                // Note that the normalization happens in the param env of
+                // the anon const, which is empty. This is why the
+                // `AlwaysApplicable` impl needs a `T: ?Sized` bound for
+                // this to compile if we were to normalize here.
+                if forbid_generic && ty.needs_subst() {
                     let mut err = tcx.sess.struct_span_err(
                         path.span,
                         "generic `Self` types are currently not permitted in anonymous constants",
@@ -2297,7 +2316,7 @@ pub fn res_to_ty(
                     err.emit();
                     tcx.ty_error()
                 } else {
-                    normalized_ty
+                    self.normalize_ty(span, ty)
                 }
             }
             Res::Def(DefKind::AssocTy, def_id) => {
diff --git a/src/test/ui/const-generics/min_const_generics/forbid-self-no-normalize.rs b/src/test/ui/const-generics/min_const_generics/forbid-self-no-normalize.rs
new file mode 100644 (file)
index 0000000..e1cf7b5
--- /dev/null
@@ -0,0 +1,15 @@
+trait AlwaysApplicable {
+    type Assoc;
+}
+impl<T: ?Sized> AlwaysApplicable for T {
+    type Assoc = usize;
+}
+
+trait BindsParam<T> {
+    type ArrayTy;
+}
+impl<T> BindsParam<T> for <T as AlwaysApplicable>::Assoc {
+    type ArrayTy = [u8; Self::MAX]; //~ ERROR generic `Self` types
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr b/src/test/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr
new file mode 100644 (file)
index 0000000..bda8859
--- /dev/null
@@ -0,0 +1,14 @@
+error: generic `Self` types are currently not permitted in anonymous constants
+  --> $DIR/forbid-self-no-normalize.rs:12:25
+   |
+LL |     type ArrayTy = [u8; Self::MAX];
+   |                         ^^^^
+   |
+note: not a concrete type
+  --> $DIR/forbid-self-no-normalize.rs:11:27
+   |
+LL | impl<T> BindsParam<T> for <T as AlwaysApplicable>::Assoc {
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+