Skip to content

Commit

Permalink
Rollup merge of rust-lang#123003 - maurer:dyn-empty, r=compiler-errors
Browse files Browse the repository at this point in the history
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 rust-lang#122998

r? workingjubilee
  • Loading branch information
matthiaskrgr authored Mar 25, 2024
2 parents 1970644 + ea45185 commit 5ce2a15
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 13 deletions.
27 changes: 14 additions & 13 deletions compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -747,9 +747,8 @@ fn transform_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
predicates: &List<ty::PolyExistentialPredicate<'tcx>>,
) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> {
let predicates: Vec<ty::PolyExistentialPredicate<'tcx>> = predicates
.iter()
.filter_map(|predicate| match predicate.skip_binder() {
tcx.mk_poly_existential_predicates_from_iter(predicates.iter().filter_map(|predicate| {
match predicate.skip_binder() {
ty::ExistentialPredicate::Trait(trait_ref) => {
let trait_ref = ty::TraitRef::identity(tcx, trait_ref.def_id);
Some(ty::Binder::dummy(ty::ExistentialPredicate::Trait(
Expand All @@ -758,9 +757,8 @@ fn transform_predicates<'tcx>(
}
ty::ExistentialPredicate::Projection(..) => None,
ty::ExistentialPredicate::AutoTrait(..) => Some(predicate),
})
.collect();
tcx.mk_poly_existential_predicates(&predicates)
}
}))
}

/// Transforms args for being encoded and used in the substitution dictionary.
Expand Down Expand Up @@ -1171,14 +1169,17 @@ fn strip_receiver_auto<'tcx>(
let ty::Dynamic(preds, lifetime, kind) = ty.kind() else {
bug!("Tried to strip auto traits from non-dynamic type {ty}");
};
let filtered_preds =
if preds.principal().is_some() {
let new_rcvr = if preds.principal().is_some() {
let filtered_preds =
tcx.mk_poly_existential_predicates_from_iter(preds.into_iter().filter(|pred| {
!matches!(pred.skip_binder(), ty::ExistentialPredicate::AutoTrait(..))
}))
} else {
ty::List::empty()
};
let new_rcvr = Ty::new_dynamic(tcx, filtered_preds, *lifetime, *kind);
}));
Ty::new_dynamic(tcx, filtered_preds, *lifetime, *kind)
} else {
// If there's no principal type, re-encode it as a unit, since we don't know anything
// 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))
}
21 changes: 21 additions & 0 deletions tests/ui/sanitizer/cfi-drop-no-principal.rs
Original file line number Diff line number Diff line change
@@ -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>;
}

0 comments on commit 5ce2a15

Please sign in to comment.