Skip to content

Commit 33a4029

Browse files
authored
Rollup merge of #100500 - cjgillot:verify-self-predicate, r=lcnr
Ban references to `Self` in trait object substs for projection predicates too. Fixes #100484 Fixes #100485 r? ````@lcnr````
2 parents e93edf3 + 72acd94 commit 33a4029

File tree

5 files changed

+67
-22
lines changed

5 files changed

+67
-22
lines changed

compiler/rustc_typeck/src/astconv/mod.rs

+36-21
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECT
3535
use rustc_span::edition::Edition;
3636
use rustc_span::lev_distance::find_best_match_for_name;
3737
use rustc_span::symbol::{kw, Ident, Symbol};
38-
use rustc_span::{Span, DUMMY_SP};
38+
use rustc_span::Span;
3939
use rustc_target::spec::abi;
4040
use rustc_trait_selection::traits;
4141
use rustc_trait_selection::traits::astconv_object_safety_violations;
@@ -1453,21 +1453,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14531453
.enumerate()
14541454
.skip(1) // Remove `Self` for `ExistentialPredicate`.
14551455
.map(|(index, arg)| {
1456-
if let ty::GenericArgKind::Type(ty) = arg.unpack() {
1457-
debug!(?ty);
1458-
if ty == dummy_self {
1459-
let param = &generics.params[index];
1460-
missing_type_params.push(param.name);
1461-
tcx.ty_error().into()
1462-
} else if ty.walk().any(|arg| arg == dummy_self.into()) {
1463-
references_self = true;
1464-
tcx.ty_error().into()
1465-
} else {
1466-
arg
1467-
}
1468-
} else {
1469-
arg
1456+
if arg == dummy_self.into() {
1457+
let param = &generics.params[index];
1458+
missing_type_params.push(param.name);
1459+
return tcx.ty_error().into();
1460+
} else if arg.walk().any(|arg| arg == dummy_self.into()) {
1461+
references_self = true;
1462+
return tcx.ty_error().into();
14701463
}
1464+
arg
14711465
})
14721466
.collect();
14731467
let substs = tcx.intern_substs(&substs[..]);
@@ -1506,13 +1500,34 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
15061500
});
15071501

15081502
let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
1509-
bound.map_bound(|b| {
1510-
if b.projection_ty.self_ty() != dummy_self {
1511-
tcx.sess.delay_span_bug(
1512-
DUMMY_SP,
1513-
&format!("trait_ref_to_existential called on {:?} with non-dummy Self", b),
1514-
);
1503+
bound.map_bound(|mut b| {
1504+
assert_eq!(b.projection_ty.self_ty(), dummy_self);
1505+
1506+
// Like for trait refs, verify that `dummy_self` did not leak inside default type
1507+
// parameters.
1508+
let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
1509+
if arg.walk().any(|arg| arg == dummy_self.into()) {
1510+
return true;
1511+
}
1512+
false
1513+
});
1514+
if references_self {
1515+
tcx.sess
1516+
.delay_span_bug(span, "trait object projection bounds reference `Self`");
1517+
let substs: Vec<_> = b
1518+
.projection_ty
1519+
.substs
1520+
.iter()
1521+
.map(|arg| {
1522+
if arg.walk().any(|arg| arg == dummy_self.into()) {
1523+
return tcx.ty_error().into();
1524+
}
1525+
arg
1526+
})
1527+
.collect();
1528+
b.projection_ty.substs = tcx.intern_substs(&substs[..]);
15151529
}
1530+
15161531
ty::ExistentialProjection::erase_self_ty(tcx, b)
15171532
})
15181533
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![allow(incomplete_features)]
2+
#![feature(generic_const_exprs)]
3+
#![feature(trait_alias)]
4+
5+
trait Bar<const N: usize> {}
6+
7+
trait BB = Bar<{ 2 + 1 }>;
8+
9+
fn foo(x: &dyn BB) {}
10+
//~^ ERROR the trait alias `BB` cannot be made into an object [E0038]
11+
12+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0038]: the trait alias `BB` cannot be made into an object
2+
--> $DIR/self-in-const-generics.rs:9:16
3+
|
4+
LL | fn foo(x: &dyn BB) {}
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`.

src/test/ui/traits/alias/self-in-generics.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
// astconv uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects.
2+
// This `FreshTy(0)` can leak into substs, causing ICEs in several places.
3+
// Using `save-analysis` triggers type-checking `f` that would be normally skipped
4+
// as `type_of` emitted an error.
5+
//
6+
// compile-flags: -Zsave-analysis
7+
18
#![feature(trait_alias)]
29

310
pub trait SelfInput = Fn(&mut Self);

src/test/ui/traits/alias/self-in-generics.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0038]: the trait alias `SelfInput` cannot be made into an object
2-
--> $DIR/self-in-generics.rs:5:19
2+
--> $DIR/self-in-generics.rs:12:19
33
|
44
LL | pub fn f(_f: &dyn SelfInput) {}
55
| ^^^^^^^^^

0 commit comments

Comments
 (0)