about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2022-08-07 22:02:02 +0200
committerCamille GILLOT <gillot.camille@gmail.com>2022-08-10 18:33:06 +0200
commit0df84ae67c01d44c3d6c0887333bafca1ea7f060 (patch)
tree7057fd2da93ed2ee256a66eef08f95e73ceda61b
parente1e25a845c2d190afad0c98029cbe368f5bad427 (diff)
downloadrust-0df84ae67c01d44c3d6c0887333bafca1ea7f060.tar.gz
rust-0df84ae67c01d44c3d6c0887333bafca1ea7f060.zip
Ban indirect references to `Self` too.
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs38
-rw-r--r--src/test/ui/traits/alias/self-in-generics.rs8
-rw-r--r--src/test/ui/traits/alias/self-in-generics.stderr11
3 files changed, 50 insertions, 7 deletions
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 0951713e5db..9ec3002e3aa 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -43,7 +43,7 @@ use rustc_trait_selection::traits::error_reporting::{
 };
 use rustc_trait_selection::traits::wf::object_region_bounds;
 
-use smallvec::SmallVec;
+use smallvec::{smallvec, SmallVec};
 use std::collections::BTreeSet;
 use std::slice;
 
@@ -1444,6 +1444,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 // Verify that `dummy_self` did not leak inside default type parameters.  This
                 // could not be done at path creation, since we need to see through trait aliases.
                 let mut missing_type_params = vec![];
+                let mut references_self = false;
                 let generics = tcx.generics_of(trait_ref.def_id);
                 let substs: Vec<_> = trait_ref
                     .substs
@@ -1451,12 +1452,18 @@ 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()
-                            && ty == dummy_self
-                        {
-                            let param = &generics.params[index];
-                            missing_type_params.push(param.name);
-                            tcx.ty_error().into()
+                        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
                         }
@@ -1476,6 +1483,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     empty_generic_args,
                 );
 
+                if references_self {
+                    let def_id = i.bottom().0.def_id();
+                    let mut err = struct_span_err!(
+                        tcx.sess,
+                        i.bottom().1,
+                        E0038,
+                        "the {} `{}` cannot be made into an object",
+                        tcx.def_kind(def_id).descr(def_id),
+                        tcx.item_name(def_id),
+                    );
+                    err.note(
+                        rustc_middle::traits::ObjectSafetyViolation::SupertraitSelf(smallvec![])
+                            .error_msg(),
+                    );
+                    err.emit();
+                }
+
                 ty::ExistentialTraitRef { def_id: trait_ref.def_id, substs }
             })
         });
diff --git a/src/test/ui/traits/alias/self-in-generics.rs b/src/test/ui/traits/alias/self-in-generics.rs
new file mode 100644
index 00000000000..6b99431f5bb
--- /dev/null
+++ b/src/test/ui/traits/alias/self-in-generics.rs
@@ -0,0 +1,8 @@
+#![feature(trait_alias)]
+
+pub trait SelfInput = Fn(&mut Self);
+
+pub fn f(_f: &dyn SelfInput) {}
+//~^ ERROR the trait alias `SelfInput` cannot be made into an object [E0038]
+
+fn main() {}
diff --git a/src/test/ui/traits/alias/self-in-generics.stderr b/src/test/ui/traits/alias/self-in-generics.stderr
new file mode 100644
index 00000000000..a1056872ea6
--- /dev/null
+++ b/src/test/ui/traits/alias/self-in-generics.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait alias `SelfInput` cannot be made into an object
+  --> $DIR/self-in-generics.rs:5:19
+   |
+LL | pub fn f(_f: &dyn SelfInput) {}
+   |                   ^^^^^^^^^
+   |
+   = 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`.