Skip to content

Commit

Permalink
Allow dropping dyn principal
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Aug 15, 2023
1 parent ffaa32b commit abbdc26
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 3 deletions.
4 changes: 3 additions & 1 deletion compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
) if src_dyn_kind == target_dyn_kind => {
let old_info =
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
if data_a.principal_def_id() == data_b.principal_def_id() {
if data_a.principal_def_id() == data_b.principal_def_id()
|| data_b.principal().is_none()
{
// A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables.
return old_info;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
let mut responses = vec![];
// If the principal def ids match (or are both none), then we're not doing
// trait upcasting. We're just removing auto traits (or shortening the lifetime).
if a_data.principal_def_id() == b_data.principal_def_id() {
if a_data.principal_def_id() == b_data.principal_def_id() || b_data.principal().is_none() {
if let Ok(resp) = self.consider_builtin_upcast_to_principal(
goal,
a_data,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -767,7 +767,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if auto_traits_compatible {
let principal_def_id_a = a_data.principal_def_id();
let principal_def_id_b = b_data.principal_def_id();
if principal_def_id_a == principal_def_id_b {
if principal_def_id_a == principal_def_id_b || principal_def_id_b.is_none() {
// no cyclic
candidates.vec.push(BuiltinUnsizeCandidate);
} else if principal_def_id_a.is_some() && principal_def_id_b.is_some() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
let iter = data_a
.principal()
.filter(|_| {
// optionally drop the principal, if we're unsizing to no principal
data_b.principal().is_some()
})
.map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
.into_iter()
.chain(
Expand Down
33 changes: 33 additions & 0 deletions tests/ui/traits/dyn-drop-principal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// run-pass
// check-run-results

#![feature(trait_upcasting)]

use std::any::Any;

fn yeet_principal(x: Box<dyn Any + Send>) -> Box<dyn Send> { x }

struct CallMe<F: FnOnce()>(Option<F>);

impl<F: FnOnce()> CallMe<F> {
fn new(f: F) -> Self {
CallMe(Some(f))
}
}

impl<F: FnOnce()> Drop for CallMe<F> {
fn drop(&mut self) {
(self.0.take().unwrap())();
}
}

fn goodbye() {
println!("goodbye");
}

fn main() {
let x = Box::new(CallMe::new(goodbye)) as Box<dyn Any + Send>;
let y = yeet_principal(x);
println!("before");
drop(y);
}
2 changes: 2 additions & 0 deletions tests/ui/traits/dyn-drop-principal.run.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
before
goodbye

0 comments on commit abbdc26

Please sign in to comment.