diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 0ad2242f6677c..aa054043c4e88 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2281,8 +2281,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { 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 AlwaysApplicable for T { type Assoc = usize; } + // + // trait BindsParam { + // type ArrayTy; + // } + // impl BindsParam for ::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 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { 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 index 0000000000000..e1cf7b579aa5a --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/forbid-self-no-normalize.rs @@ -0,0 +1,15 @@ +trait AlwaysApplicable { + type Assoc; +} +impl AlwaysApplicable for T { + type Assoc = usize; +} + +trait BindsParam { + type ArrayTy; +} +impl BindsParam for ::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 index 0000000000000..bda8859700680 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr @@ -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 BindsParam for ::Assoc { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error +