Skip to content

Commit 8ff0228

Browse files
committed
CFI: Pad out associated type resolution with erased lifetimes
`trait_object_ty` assumed that associated types would be fully determined by the trait. This is *almost* true - const parameters and type parameters are no longer allowed, but lifetime parameters are. Since we erase all lifetime parameters anyways, instantiate it with as many erased regions as it needs. Fixes: rust-lang#123053
1 parent 4600c4a commit 8ff0228

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,10 @@ pub fn typeid_for_instance<'tcx>(
11211121
.trait_item_def_id
11221122
.expect("Part of a trait implementation, but not linked to the def_id?");
11231123
let trait_method = tcx.associated_item(method_id);
1124-
if traits::is_vtable_safe_method(tcx, trait_ref.skip_binder().def_id, trait_method) {
1124+
let trait_id = trait_ref.skip_binder().def_id;
1125+
if traits::is_vtable_safe_method(tcx, trait_id, trait_method)
1126+
&& tcx.object_safety_violations(trait_id).is_empty()
1127+
{
11251128
// Trait methods will have a Self polymorphic parameter, where the concreteized
11261129
// implementatation will not. We need to walk back to the more general trait method
11271130
let trait_ref = tcx.normalize_erasing_regions(
@@ -1148,8 +1151,8 @@ pub fn typeid_for_instance<'tcx>(
11481151

11491152
let fn_abi = tcx
11501153
.fn_abi_of_instance(tcx.param_env(instance.def_id()).and((instance, ty::List::empty())))
1151-
.unwrap_or_else(|instance| {
1152-
bug!("typeid_for_instance: couldn't get fn_abi of instance {:?}", instance)
1154+
.unwrap_or_else(|error| {
1155+
bug!("typeid_for_instance: couldn't get fn_abi of instance {instance:?}: {error:?}")
11531156
});
11541157

11551158
typeid_for_fnabi(tcx, &fn_abi, options)
@@ -1178,6 +1181,7 @@ fn strip_receiver_auto<'tcx>(
11781181
tcx.mk_args_trait(new_rcvr, args.into_iter().skip(1))
11791182
}
11801183

1184+
#[instrument(skip(tcx), ret)]
11811185
fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx> {
11821186
assert!(!poly_trait_ref.has_non_region_param());
11831187
let principal_pred = poly_trait_ref.map_bound(|trait_ref| {
@@ -1195,6 +1199,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc
11951199
ty::ParamEnv::reveal_all(),
11961200
alias_ty.to_ty(tcx),
11971201
);
1202+
debug!("Resolved {:?} -> {resolved}", alias_ty.to_ty(tcx));
11981203
ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
11991204
def_id: assoc_ty.def_id,
12001205
args: ty::ExistentialTraitRef::erase_self_ty(tcx, super_trait_ref).args,
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Regression test for issue 123053, where associated types with lifetimes caused generation of the
2+
// trait object type to fail, causing an ICE.
3+
//
4+
// needs-sanitizer-cfi
5+
// compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi --edition=2021
6+
// no-prefer-dynamic
7+
// only-x86_64-unknown-linux-gnu
8+
// build-pass
9+
10+
trait Iterable {
11+
type Item<'a>
12+
where
13+
Self: 'a;
14+
type Iter<'a>: Iterator<Item = Self::Item<'a>>
15+
where
16+
Self: 'a;
17+
18+
fn iter<'a>(&'a self) -> Self::Iter<'a>;
19+
}
20+
21+
impl<T> Iterable for [T] {
22+
type Item<'a> = <std::slice::Iter<'a, T> as Iterator>::Item where T: 'a;
23+
type Iter<'a> = std::slice::Iter<'a, T> where T: 'a;
24+
25+
fn iter<'a>(&'a self) -> Self::Iter<'a> {
26+
self.iter()
27+
}
28+
}
29+
30+
fn get_first<'a, I: Iterable + ?Sized>(it: &'a I) -> Option<I::Item<'a>> {
31+
it.iter().next()
32+
}
33+
34+
fn main() {
35+
let v = vec![1, 2, 3];
36+
37+
assert_eq!(Some(&1), get_first(&*v));
38+
}

0 commit comments

Comments
 (0)