Skip to content

Commit abbdc26

Browse files
Allow dropping dyn principal
1 parent ffaa32b commit abbdc26

File tree

6 files changed

+44
-3
lines changed

6 files changed

+44
-3
lines changed

compiler/rustc_codegen_ssa/src/base.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,9 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
154154
) if src_dyn_kind == target_dyn_kind => {
155155
let old_info =
156156
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
157-
if data_a.principal_def_id() == data_b.principal_def_id() {
157+
if data_a.principal_def_id() == data_b.principal_def_id()
158+
|| data_b.principal().is_none()
159+
{
158160
// A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables.
159161
return old_info;
160162
}

compiler/rustc_trait_selection/src/solve/trait_goals.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
537537
let mut responses = vec![];
538538
// If the principal def ids match (or are both none), then we're not doing
539539
// trait upcasting. We're just removing auto traits (or shortening the lifetime).
540-
if a_data.principal_def_id() == b_data.principal_def_id() {
540+
if a_data.principal_def_id() == b_data.principal_def_id() || b_data.principal().is_none() {
541541
if let Ok(resp) = self.consider_builtin_upcast_to_principal(
542542
goal,
543543
a_data,

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
767767
if auto_traits_compatible {
768768
let principal_def_id_a = a_data.principal_def_id();
769769
let principal_def_id_b = b_data.principal_def_id();
770-
if principal_def_id_a == principal_def_id_b {
770+
if principal_def_id_a == principal_def_id_b || principal_def_id_b.is_none() {
771771
// no cyclic
772772
candidates.vec.push(BuiltinUnsizeCandidate);
773773
} else if principal_def_id_a.is_some() && principal_def_id_b.is_some() {

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+4
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
954954
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
955955
let iter = data_a
956956
.principal()
957+
.filter(|_| {
958+
// optionally drop the principal, if we're unsizing to no principal
959+
data_b.principal().is_some()
960+
})
957961
.map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
958962
.into_iter()
959963
.chain(

tests/ui/traits/dyn-drop-principal.rs

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// run-pass
2+
// check-run-results
3+
4+
#![feature(trait_upcasting)]
5+
6+
use std::any::Any;
7+
8+
fn yeet_principal(x: Box<dyn Any + Send>) -> Box<dyn Send> { x }
9+
10+
struct CallMe<F: FnOnce()>(Option<F>);
11+
12+
impl<F: FnOnce()> CallMe<F> {
13+
fn new(f: F) -> Self {
14+
CallMe(Some(f))
15+
}
16+
}
17+
18+
impl<F: FnOnce()> Drop for CallMe<F> {
19+
fn drop(&mut self) {
20+
(self.0.take().unwrap())();
21+
}
22+
}
23+
24+
fn goodbye() {
25+
println!("goodbye");
26+
}
27+
28+
fn main() {
29+
let x = Box::new(CallMe::new(goodbye)) as Box<dyn Any + Send>;
30+
let y = yeet_principal(x);
31+
println!("before");
32+
drop(y);
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
before
2+
goodbye

0 commit comments

Comments
 (0)