Skip to content

Commit

Permalink
Ban indirect references to Self too.
Browse files Browse the repository at this point in the history
  • Loading branch information
cjgillot committed Aug 10, 2022
1 parent e1e25a8 commit 0df84ae
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 7 deletions.
38 changes: 31 additions & 7 deletions compiler/rustc_typeck/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -1444,19 +1444,26 @@ 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
.iter()
.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
}
Expand All @@ -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 }
})
});
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/traits/alias/self-in-generics.rs
Original file line number Diff line number Diff line change
@@ -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() {}
11 changes: 11 additions & 0 deletions src/test/ui/traits/alias/self-in-generics.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 0df84ae

Please sign in to comment.