about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-08-20 19:45:12 +0200
committerGitHub <noreply@github.com>2022-08-20 19:45:12 +0200
commit33a40297d3d81c39925d1ce613ded76af3bd8002 (patch)
tree0c6799855d1dc2ccef9a4f5e01dac16a98efde0e
parente93edf3335ef172274acb208d672db51d40eeb2f (diff)
parent72acd94117e784d4e7425e827c60d6a6748d7a88 (diff)
downloadrust-33a40297d3d81c39925d1ce613ded76af3bd8002.tar.gz
rust-33a40297d3d81c39925d1ce613ded76af3bd8002.zip
Rollup merge of #100500 - cjgillot:verify-self-predicate, r=lcnr
Ban references to `Self` in trait object substs for projection predicates too.

Fixes https://github.com/rust-lang/rust/issues/100484
Fixes https://github.com/rust-lang/rust/issues/100485

r? ````@lcnr````
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs57
-rw-r--r--src/test/ui/traits/alias/self-in-const-generics.rs12
-rw-r--r--src/test/ui/traits/alias/self-in-const-generics.stderr11
-rw-r--r--src/test/ui/traits/alias/self-in-generics.rs7
-rw-r--r--src/test/ui/traits/alias/self-in-generics.stderr2
5 files changed, 67 insertions, 22 deletions
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 1e6cb53f3ee..5bb02bc246c 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;
@@ -1453,21 +1453,15 @@ 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);
-                                tcx.ty_error().into()
-                            } else if ty.walk().any(|arg| arg == dummy_self.into()) {
-                                references_self = true;
-                                tcx.ty_error().into()
-                            } else {
-                                arg
-                            }
-                        } else {
-                            arg
+                        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
                     })
                     .collect();
                 let substs = tcx.intern_substs(&substs[..]);
@@ -1506,13 +1500,34 @@ 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 arg.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 arg.walk().any(|arg| arg == dummy_self.into()) {
+                                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-const-generics.rs b/src/test/ui/traits/alias/self-in-const-generics.rs
new file mode 100644
index 00000000000..b0de8ccd678
--- /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 00000000000..61cc217cfbc
--- /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`.
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) {}
    |                   ^^^^^^^^^