about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs46
-rw-r--r--src/test/ui/traits/alias/self-in-generics.rs7
-rw-r--r--src/test/ui/traits/alias/self-in-generics.stderr2
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 1e6cb53f3ee..ff81747cafe 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 6b99431f5bb..0bb6335f91e 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 a1056872ea6..110d60e6e91 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) {}
    |                   ^^^^^^^^^