diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 0951713e5db18..9ec3002e3aaf1 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 0000000000000..6b99431f5bbcf --- /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 0000000000000..a1056872ea641 --- /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`.