Skip to content

Commit 0df84ae

Browse files
committed
Ban indirect references to Self too.
1 parent e1e25a8 commit 0df84ae

File tree

3 files changed

+50
-7
lines changed

3 files changed

+50
-7
lines changed

compiler/rustc_typeck/src/astconv/mod.rs

+31-7
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use rustc_trait_selection::traits::error_reporting::{
4343
};
4444
use rustc_trait_selection::traits::wf::object_region_bounds;
4545

46-
use smallvec::SmallVec;
46+
use smallvec::{smallvec, SmallVec};
4747
use std::collections::BTreeSet;
4848
use std::slice;
4949

@@ -1444,19 +1444,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14441444
// Verify that `dummy_self` did not leak inside default type parameters. This
14451445
// could not be done at path creation, since we need to see through trait aliases.
14461446
let mut missing_type_params = vec![];
1447+
let mut references_self = false;
14471448
let generics = tcx.generics_of(trait_ref.def_id);
14481449
let substs: Vec<_> = trait_ref
14491450
.substs
14501451
.iter()
14511452
.enumerate()
14521453
.skip(1) // Remove `Self` for `ExistentialPredicate`.
14531454
.map(|(index, arg)| {
1454-
if let ty::GenericArgKind::Type(ty) = arg.unpack()
1455-
&& ty == dummy_self
1456-
{
1457-
let param = &generics.params[index];
1458-
missing_type_params.push(param.name);
1459-
tcx.ty_error().into()
1455+
if let ty::GenericArgKind::Type(ty) = arg.unpack() {
1456+
debug!(?ty);
1457+
if ty == dummy_self {
1458+
let param = &generics.params[index];
1459+
missing_type_params.push(param.name);
1460+
tcx.ty_error().into()
1461+
} else if ty.walk().any(|arg| arg == dummy_self.into()) {
1462+
references_self = true;
1463+
tcx.ty_error().into()
1464+
} else {
1465+
arg
1466+
}
14601467
} else {
14611468
arg
14621469
}
@@ -1476,6 +1483,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14761483
empty_generic_args,
14771484
);
14781485

1486+
if references_self {
1487+
let def_id = i.bottom().0.def_id();
1488+
let mut err = struct_span_err!(
1489+
tcx.sess,
1490+
i.bottom().1,
1491+
E0038,
1492+
"the {} `{}` cannot be made into an object",
1493+
tcx.def_kind(def_id).descr(def_id),
1494+
tcx.item_name(def_id),
1495+
);
1496+
err.note(
1497+
rustc_middle::traits::ObjectSafetyViolation::SupertraitSelf(smallvec![])
1498+
.error_msg(),
1499+
);
1500+
err.emit();
1501+
}
1502+
14791503
ty::ExistentialTraitRef { def_id: trait_ref.def_id, substs }
14801504
})
14811505
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(trait_alias)]
2+
3+
pub trait SelfInput = Fn(&mut Self);
4+
5+
pub fn f(_f: &dyn SelfInput) {}
6+
//~^ ERROR the trait alias `SelfInput` cannot be made into an object [E0038]
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0038]: the trait alias `SelfInput` cannot be made into an object
2+
--> $DIR/self-in-generics.rs:5:19
3+
|
4+
LL | pub fn f(_f: &dyn SelfInput) {}
5+
| ^^^^^^^^^
6+
|
7+
= note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0038`.

0 commit comments

Comments
 (0)