Skip to content

Commit 4b16214

Browse files
committed
Ban references to Self in trait object substs for projection predicates too.
1 parent 75b7e52 commit 4b16214

File tree

3 files changed

+41
-14
lines changed

3 files changed

+41
-14
lines changed

compiler/rustc_typeck/src/astconv/mod.rs

Lines changed: 33 additions & 13 deletions
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;
@@ -1458,16 +1458,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14581458
if ty == dummy_self {
14591459
let param = &generics.params[index];
14601460
missing_type_params.push(param.name);
1461-
tcx.ty_error().into()
1461+
return tcx.ty_error().into();
14621462
} else if ty.walk().any(|arg| arg == dummy_self.into()) {
14631463
references_self = true;
1464-
tcx.ty_error().into()
1465-
} else {
1466-
arg
1464+
return tcx.ty_error().into();
14671465
}
1468-
} else {
1469-
arg
14701466
}
1467+
arg
14711468
})
14721469
.collect();
14731470
let substs = tcx.intern_substs(&substs[..]);
@@ -1506,13 +1503,36 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
15061503
});
15071504

15081505
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-
);
1506+
bound.map_bound(|mut b| {
1507+
assert_eq!(b.projection_ty.self_ty(), dummy_self);
1508+
1509+
// Like for trait refs, verify that `dummy_self` did not leak inside default type
1510+
// parameters.
1511+
let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
1512+
if let ty::GenericArgKind::Type(ty) = arg.unpack() {
1513+
if ty == dummy_self || ty.walk().any(|arg| arg == dummy_self.into()) {
1514+
return true;
1515+
}
1516+
}
1517+
false
1518+
});
1519+
if references_self {
1520+
tcx.sess
1521+
.delay_span_bug(span, "trait object projection bounds reference `Self`");
1522+
let substs: Vec<_> = b
1523+
.projection_ty
1524+
.substs
1525+
.iter()
1526+
.map(|arg| {
1527+
if let ty::GenericArgKind::Type(_) = arg.unpack() {
1528+
return tcx.ty_error().into();
1529+
}
1530+
arg
1531+
})
1532+
.collect();
1533+
b.projection_ty.substs = tcx.intern_substs(&substs[..]);
15151534
}
1535+
15161536
ty::ExistentialProjection::erase_self_ty(tcx, b)
15171537
})
15181538
});

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

Lines changed: 7 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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)