Ban indirect references to Self too.

This commit is contained in:
Camille GILLOT 2022-08-07 22:02:02 +02:00
parent e1e25a845c
commit 0df84ae67c
3 changed files with 50 additions and 7 deletions

View File

@ -43,7 +43,7 @@ use rustc_trait_selection::traits::error_reporting::{
}; };
use rustc_trait_selection::traits::wf::object_region_bounds; use rustc_trait_selection::traits::wf::object_region_bounds;
use smallvec::SmallVec; use smallvec::{smallvec, SmallVec};
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::slice; 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 // 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. // could not be done at path creation, since we need to see through trait aliases.
let mut missing_type_params = vec![]; let mut missing_type_params = vec![];
let mut references_self = false;
let generics = tcx.generics_of(trait_ref.def_id); let generics = tcx.generics_of(trait_ref.def_id);
let substs: Vec<_> = trait_ref let substs: Vec<_> = trait_ref
.substs .substs
@ -1451,12 +1452,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.enumerate() .enumerate()
.skip(1) // Remove `Self` for `ExistentialPredicate`. .skip(1) // Remove `Self` for `ExistentialPredicate`.
.map(|(index, arg)| { .map(|(index, arg)| {
if let ty::GenericArgKind::Type(ty) = arg.unpack() if let ty::GenericArgKind::Type(ty) = arg.unpack() {
&& ty == dummy_self debug!(?ty);
{ if ty == dummy_self {
let param = &generics.params[index]; let param = &generics.params[index];
missing_type_params.push(param.name); missing_type_params.push(param.name);
tcx.ty_error().into() tcx.ty_error().into()
} else if ty.walk().any(|arg| arg == dummy_self.into()) {
references_self = true;
tcx.ty_error().into()
} else {
arg
}
} else { } else {
arg arg
} }
@ -1476,6 +1483,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
empty_generic_args, 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 } ty::ExistentialTraitRef { def_id: trait_ref.def_id, substs }
}) })
}); });

View File

@ -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() {}

View File

@ -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`.