Rollup merge of #123003 - maurer:dyn-empty, r=compiler-errors

CFI: Handle dyn with no principal

In user-facing Rust, `dyn` always has at least one predicate following it. Unfortunately, because we filter out marker traits from receivers at callsites and `dyn Sync` is, for example, legal, this results in us having `dyn` types with no predicates on occasion in our alias set encoding. This patch handles cases where there are no predicates in a `dyn` type which are relevant to its alias set.

Fixes #122998

r? workingjubilee
This commit is contained in:
Matthias Krüger 2024-03-25 11:00:14 +01:00 committed by GitHub
commit 84ec66e15b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 13 deletions

View File

@ -747,9 +747,8 @@ fn transform_predicates<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
predicates: &List<ty::PolyExistentialPredicate<'tcx>>, predicates: &List<ty::PolyExistentialPredicate<'tcx>>,
) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> { ) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> {
let predicates: Vec<ty::PolyExistentialPredicate<'tcx>> = predicates tcx.mk_poly_existential_predicates_from_iter(predicates.iter().filter_map(|predicate| {
.iter() match predicate.skip_binder() {
.filter_map(|predicate| match predicate.skip_binder() {
ty::ExistentialPredicate::Trait(trait_ref) => { ty::ExistentialPredicate::Trait(trait_ref) => {
let trait_ref = ty::TraitRef::identity(tcx, trait_ref.def_id); let trait_ref = ty::TraitRef::identity(tcx, trait_ref.def_id);
Some(ty::Binder::dummy(ty::ExistentialPredicate::Trait( Some(ty::Binder::dummy(ty::ExistentialPredicate::Trait(
@ -758,9 +757,8 @@ fn transform_predicates<'tcx>(
} }
ty::ExistentialPredicate::Projection(..) => None, ty::ExistentialPredicate::Projection(..) => None,
ty::ExistentialPredicate::AutoTrait(..) => Some(predicate), ty::ExistentialPredicate::AutoTrait(..) => Some(predicate),
}) }
.collect(); }))
tcx.mk_poly_existential_predicates(&predicates)
} }
/// Transforms args for being encoded and used in the substitution dictionary. /// Transforms args for being encoded and used in the substitution dictionary.
@ -1171,14 +1169,17 @@ fn strip_receiver_auto<'tcx>(
let ty::Dynamic(preds, lifetime, kind) = ty.kind() else { let ty::Dynamic(preds, lifetime, kind) = ty.kind() else {
bug!("Tried to strip auto traits from non-dynamic type {ty}"); bug!("Tried to strip auto traits from non-dynamic type {ty}");
}; };
let filtered_preds = let new_rcvr = if preds.principal().is_some() {
if preds.principal().is_some() { let filtered_preds =
tcx.mk_poly_existential_predicates_from_iter(preds.into_iter().filter(|pred| { tcx.mk_poly_existential_predicates_from_iter(preds.into_iter().filter(|pred| {
!matches!(pred.skip_binder(), ty::ExistentialPredicate::AutoTrait(..)) !matches!(pred.skip_binder(), ty::ExistentialPredicate::AutoTrait(..))
})) }));
} else { Ty::new_dynamic(tcx, filtered_preds, *lifetime, *kind)
ty::List::empty() } else {
}; // If there's no principal type, re-encode it as a unit, since we don't know anything
let new_rcvr = Ty::new_dynamic(tcx, filtered_preds, *lifetime, *kind); // about it. This technically discards the knowledge that it was a type that was made
// into a trait object at some point, but that's not a lot.
tcx.types.unit
};
tcx.mk_args_trait(new_rcvr, args.into_iter().skip(1)) tcx.mk_args_trait(new_rcvr, args.into_iter().skip(1))
} }

View File

@ -0,0 +1,21 @@
// Check that dropping a trait object without a principal trait succeeds
//@ needs-sanitizer-cfi
// FIXME(#122848) Remove only-linux once OSX CFI binaries works
//@ only-linux
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
//@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0
// FIXME(#118761) Should be run-pass once the labels on drop are compatible.
// This test is being landed ahead of that to test that the compiler doesn't ICE while labeling the
// callsite for a drop, but the vtable doesn't have the correct label yet.
//@ build-pass
struct CustomDrop;
impl Drop for CustomDrop {
fn drop(&mut self) {}
}
fn main() {
let _ = Box::new(CustomDrop) as Box<dyn Send>;
}