Rollup merge of #123066 - maurer:cfi-erased-lifetime-ice, r=compiler-errors

CFI: (actually) check that methods are object-safe before projecting their receivers to `dyn Trait` in CFI

`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: #123053

r? `@compiler-errors`
This commit is contained in:
Matthias Krüger 2024-03-26 17:06:40 +01:00 committed by GitHub
commit 1fd3ee0660
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 46 additions and 3 deletions

View File

@ -1124,7 +1124,10 @@ pub fn typeid_for_instance<'tcx>(
.trait_item_def_id
.expect("Part of a trait implementation, but not linked to the def_id?");
let trait_method = tcx.associated_item(method_id);
if traits::is_vtable_safe_method(tcx, trait_ref.skip_binder().def_id, trait_method) {
let trait_id = trait_ref.skip_binder().def_id;
if traits::is_vtable_safe_method(tcx, trait_id, trait_method)
&& tcx.object_safety_violations(trait_id).is_empty()
{
// Trait methods will have a Self polymorphic parameter, where the concreteized
// implementatation will not. We need to walk back to the more general trait method
let trait_ref = tcx.instantiate_and_normalize_erasing_regions(
@ -1152,8 +1155,8 @@ pub fn typeid_for_instance<'tcx>(
let fn_abi = tcx
.fn_abi_of_instance(tcx.param_env(instance.def_id()).and((instance, ty::List::empty())))
.unwrap_or_else(|instance| {
bug!("typeid_for_instance: couldn't get fn_abi of instance {:?}", instance)
.unwrap_or_else(|error| {
bug!("typeid_for_instance: couldn't get fn_abi of instance {instance:?}: {error:?}")
});
typeid_for_fnabi(tcx, fn_abi, options)
@ -1182,6 +1185,7 @@ fn strip_receiver_auto<'tcx>(
tcx.mk_args_trait(new_rcvr, args.into_iter().skip(1))
}
#[instrument(skip(tcx), ret)]
fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx> {
assert!(!poly_trait_ref.has_non_region_param());
let principal_pred = poly_trait_ref.map_bound(|trait_ref| {
@ -1199,6 +1203,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc
ty::ParamEnv::reveal_all(),
alias_ty.to_ty(tcx),
);
debug!("Resolved {:?} -> {resolved}", alias_ty.to_ty(tcx));
ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
def_id: assoc_ty.def_id,
args: ty::ExistentialTraitRef::erase_self_ty(tcx, super_trait_ref).args,

View File

@ -0,0 +1,38 @@
// Regression test for issue 123053, where associated types with lifetimes caused generation of the
// trait object type to fail, causing an ICE.
//
//@ needs-sanitizer-cfi
//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi --edition=2021
//@ no-prefer-dynamic
//@ only-x86_64-unknown-linux-gnu
//@ build-pass
trait Iterable {
type Item<'a>
where
Self: 'a;
type Iter<'a>: Iterator<Item = Self::Item<'a>>
where
Self: 'a;
fn iter<'a>(&'a self) -> Self::Iter<'a>;
}
impl<T> Iterable for [T] {
type Item<'a> = <std::slice::Iter<'a, T> as Iterator>::Item where T: 'a;
type Iter<'a> = std::slice::Iter<'a, T> where T: 'a;
fn iter<'a>(&'a self) -> Self::Iter<'a> {
self.iter()
}
}
fn get_first<'a, I: Iterable + ?Sized>(it: &'a I) -> Option<I::Item<'a>> {
it.iter().next()
}
fn main() {
let v = vec![1, 2, 3];
assert_eq!(Some(&1), get_first(&*v));
}