Ban references to Self in trait object substs for projection predicates too.

This commit is contained in:
Camille GILLOT 2022-08-13 18:39:30 +02:00
parent 75b7e52e92
commit 4b16214163
3 changed files with 41 additions and 14 deletions

View file

@ -35,7 +35,7 @@ use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECT
use rustc_span::edition::Edition;
use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_span::Span;
use rustc_target::spec::abi;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::astconv_object_safety_violations;
@ -1458,16 +1458,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if ty == dummy_self {
let param = &generics.params[index];
missing_type_params.push(param.name);
tcx.ty_error().into()
return tcx.ty_error().into();
} else if ty.walk().any(|arg| arg == dummy_self.into()) {
references_self = true;
tcx.ty_error().into()
} else {
arg
return tcx.ty_error().into();
}
} else {
arg
}
arg
})
.collect();
let substs = tcx.intern_substs(&substs[..]);
@ -1506,13 +1503,36 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
});
let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
bound.map_bound(|b| {
if b.projection_ty.self_ty() != dummy_self {
tcx.sess.delay_span_bug(
DUMMY_SP,
&format!("trait_ref_to_existential called on {:?} with non-dummy Self", b),
);
bound.map_bound(|mut b| {
assert_eq!(b.projection_ty.self_ty(), dummy_self);
// Like for trait refs, verify that `dummy_self` did not leak inside default type
// parameters.
let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
if let ty::GenericArgKind::Type(ty) = arg.unpack() {
if ty == dummy_self || ty.walk().any(|arg| arg == dummy_self.into()) {
return true;
}
}
false
});
if references_self {
tcx.sess
.delay_span_bug(span, "trait object projection bounds reference `Self`");
let substs: Vec<_> = b
.projection_ty
.substs
.iter()
.map(|arg| {
if let ty::GenericArgKind::Type(_) = arg.unpack() {
return tcx.ty_error().into();
}
arg
})
.collect();
b.projection_ty.substs = tcx.intern_substs(&substs[..]);
}
ty::ExistentialProjection::erase_self_ty(tcx, b)
})
});

View file

@ -1,3 +1,10 @@
// astconv uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects.
// This `FreshTy(0)` can leak into substs, causing ICEs in several places.
// Using `save-analysis` triggers type-checking `f` that would be normally skipped
// as `type_of` emitted an error.
//
// compile-flags: -Zsave-analysis
#![feature(trait_alias)]
pub trait SelfInput = Fn(&mut Self);

View file

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