From 4b162141631e900f760752eacdd6d5e510ac4e42 Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Sat, 13 Aug 2022 18:39:30 +0200
Subject: [PATCH 1/3] Ban references to `Self` in trait object substs for
 projection predicates too.

---
 compiler/rustc_typeck/src/astconv/mod.rs      | 46 +++++++++++++------
 src/test/ui/traits/alias/self-in-generics.rs  |  7 +++
 .../ui/traits/alias/self-in-generics.stderr   |  2 +-
 3 files changed, 41 insertions(+), 14 deletions(-)

diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 1e6cb53f3eeae..ff81747cafe6f 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -35,7 +35,7 @@ use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECT
 use rustc_span::edition::Edition;
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::symbol::{kw, Ident, Symbol};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
 use rustc_target::spec::abi;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::astconv_object_safety_violations;
@@ -1458,16 +1458,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             if ty == dummy_self {
                                 let param = &generics.params[index];
                                 missing_type_params.push(param.name);
-                                tcx.ty_error().into()
+                                return tcx.ty_error().into();
                             } else if ty.walk().any(|arg| arg == dummy_self.into()) {
                                 references_self = true;
-                                tcx.ty_error().into()
-                            } else {
-                                arg
+                                return tcx.ty_error().into();
                             }
-                        } else {
-                            arg
                         }
+                        arg
                     })
                     .collect();
                 let substs = tcx.intern_substs(&substs[..]);
@@ -1506,13 +1503,36 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         });
 
         let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
-            bound.map_bound(|b| {
-                if b.projection_ty.self_ty() != dummy_self {
-                    tcx.sess.delay_span_bug(
-                        DUMMY_SP,
-                        &format!("trait_ref_to_existential called on {:?} with non-dummy Self", b),
-                    );
+            bound.map_bound(|mut b| {
+                assert_eq!(b.projection_ty.self_ty(), dummy_self);
+
+                // Like for trait refs, verify that `dummy_self` did not leak inside default type
+                // parameters.
+                let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
+                    if let ty::GenericArgKind::Type(ty) = arg.unpack() {
+                        if ty == dummy_self || ty.walk().any(|arg| arg == dummy_self.into()) {
+                            return true;
+                        }
+                    }
+                    false
+                });
+                if references_self {
+                    tcx.sess
+                        .delay_span_bug(span, "trait object projection bounds reference `Self`");
+                    let substs: Vec<_> = b
+                        .projection_ty
+                        .substs
+                        .iter()
+                        .map(|arg| {
+                            if let ty::GenericArgKind::Type(_) = arg.unpack() {
+                                return tcx.ty_error().into();
+                            }
+                            arg
+                        })
+                        .collect();
+                    b.projection_ty.substs = tcx.intern_substs(&substs[..]);
                 }
+
                 ty::ExistentialProjection::erase_self_ty(tcx, b)
             })
         });
diff --git a/src/test/ui/traits/alias/self-in-generics.rs b/src/test/ui/traits/alias/self-in-generics.rs
index 6b99431f5bbcf..0bb6335f91e4b 100644
--- a/src/test/ui/traits/alias/self-in-generics.rs
+++ b/src/test/ui/traits/alias/self-in-generics.rs
@@ -1,3 +1,10 @@
+// astconv uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects.
+// This `FreshTy(0)` can leak into substs, causing ICEs in several places.
+// Using `save-analysis` triggers type-checking `f` that would be normally skipped
+// as `type_of` emitted an error.
+//
+// compile-flags: -Zsave-analysis
+
 #![feature(trait_alias)]
 
 pub trait SelfInput = Fn(&mut Self);
diff --git a/src/test/ui/traits/alias/self-in-generics.stderr b/src/test/ui/traits/alias/self-in-generics.stderr
index a1056872ea641..110d60e6e9116 100644
--- a/src/test/ui/traits/alias/self-in-generics.stderr
+++ b/src/test/ui/traits/alias/self-in-generics.stderr
@@ -1,5 +1,5 @@
 error[E0038]: the trait alias `SelfInput` cannot be made into an object
-  --> $DIR/self-in-generics.rs:5:19
+  --> $DIR/self-in-generics.rs:12:19
    |
 LL | pub fn f(_f: &dyn SelfInput) {}
    |                   ^^^^^^^^^

From be2641a61f2d34fe4f937a49dacfcb82bf0b9075 Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Wed, 17 Aug 2022 20:22:52 +0200
Subject: [PATCH 2/3] Fortify check for const generics.

---
 compiler/rustc_typeck/src/astconv/mod.rs | 25 ++++++++++--------------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index ff81747cafe6f..5bb02bc246caf 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -1453,16 +1453,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     .enumerate()
                     .skip(1) // Remove `Self` for `ExistentialPredicate`.
                     .map(|(index, arg)| {
-                        if let ty::GenericArgKind::Type(ty) = arg.unpack() {
-                            debug!(?ty);
-                            if ty == dummy_self {
-                                let param = &generics.params[index];
-                                missing_type_params.push(param.name);
-                                return tcx.ty_error().into();
-                            } else if ty.walk().any(|arg| arg == dummy_self.into()) {
-                                references_self = true;
-                                return tcx.ty_error().into();
-                            }
+                        if arg == dummy_self.into() {
+                            let param = &generics.params[index];
+                            missing_type_params.push(param.name);
+                            return tcx.ty_error().into();
+                        } else if arg.walk().any(|arg| arg == dummy_self.into()) {
+                            references_self = true;
+                            return tcx.ty_error().into();
                         }
                         arg
                     })
@@ -1509,10 +1506,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 // Like for trait refs, verify that `dummy_self` did not leak inside default type
                 // parameters.
                 let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
-                    if let ty::GenericArgKind::Type(ty) = arg.unpack() {
-                        if ty == dummy_self || ty.walk().any(|arg| arg == dummy_self.into()) {
-                            return true;
-                        }
+                    if arg.walk().any(|arg| arg == dummy_self.into()) {
+                        return true;
                     }
                     false
                 });
@@ -1524,7 +1519,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         .substs
                         .iter()
                         .map(|arg| {
-                            if let ty::GenericArgKind::Type(_) = arg.unpack() {
+                            if arg.walk().any(|arg| arg == dummy_self.into()) {
                                 return tcx.ty_error().into();
                             }
                             arg

From 72acd94117e784d4e7425e827c60d6a6748d7a88 Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Wed, 17 Aug 2022 21:50:59 +0200
Subject: [PATCH 3/3] Add const-generics test.

---
 src/test/ui/traits/alias/self-in-const-generics.rs   | 12 ++++++++++++
 .../ui/traits/alias/self-in-const-generics.stderr    | 11 +++++++++++
 2 files changed, 23 insertions(+)
 create mode 100644 src/test/ui/traits/alias/self-in-const-generics.rs
 create mode 100644 src/test/ui/traits/alias/self-in-const-generics.stderr

diff --git a/src/test/ui/traits/alias/self-in-const-generics.rs b/src/test/ui/traits/alias/self-in-const-generics.rs
new file mode 100644
index 0000000000000..b0de8ccd67847
--- /dev/null
+++ b/src/test/ui/traits/alias/self-in-const-generics.rs
@@ -0,0 +1,12 @@
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+#![feature(trait_alias)]
+
+trait Bar<const N: usize> {}
+
+trait BB = Bar<{ 2 + 1 }>;
+
+fn foo(x: &dyn BB) {}
+//~^ ERROR the trait alias `BB` cannot be made into an object [E0038]
+
+fn main() {}
diff --git a/src/test/ui/traits/alias/self-in-const-generics.stderr b/src/test/ui/traits/alias/self-in-const-generics.stderr
new file mode 100644
index 0000000000000..61cc217cfbce6
--- /dev/null
+++ b/src/test/ui/traits/alias/self-in-const-generics.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait alias `BB` cannot be made into an object
+  --> $DIR/self-in-const-generics.rs:9:16
+   |
+LL | fn foo(x: &dyn BB) {}
+   |                ^^
+   |
+   = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.