Skip to content

Commit 2bf82e1

Browse files
compiler-errorsJules-Bertholet
authored andcommitted
Allow dropping dyn principal
1 parent b215beb commit 2bf82e1

File tree

7 files changed

+77
-4
lines changed

7 files changed

+77
-4
lines changed

compiler/rustc_codegen_cranelift/src/unsize.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ pub(crate) fn unsized_info<'tcx>(
3333
{
3434
let old_info =
3535
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
36-
if data_a.principal_def_id() == data_b.principal_def_id() {
36+
let b_principal_def_id = data_b.principal_def_id();
37+
if data_a.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
3738
// A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables.
3839
return old_info;
3940
}

compiler/rustc_codegen_ssa/src/base.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
156156
{
157157
let old_info =
158158
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
159-
if data_a.principal_def_id() == data_b.principal_def_id() {
159+
let b_principal_def_id = data_b.principal_def_id();
160+
if data_a.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
160161
// A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables.
161162
return old_info;
162163
}

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,8 @@ where
775775
let mut responses = vec![];
776776
// If the principal def ids match (or are both none), then we're not doing
777777
// trait upcasting. We're just removing auto traits (or shortening the lifetime).
778-
if a_data.principal_def_id() == b_data.principal_def_id() {
778+
let b_principal_def_id = b_data.principal_def_id();
779+
if a_data.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
779780
responses.extend(self.consider_builtin_upcast_to_principal(
780781
goal,
781782
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -998,7 +998,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
998998
// #2 (region bounds).
999999
let principal_def_id_a = a_data.principal_def_id();
10001000
let principal_def_id_b = b_data.principal_def_id();
1001-
if principal_def_id_a == principal_def_id_b {
1001+
if principal_def_id_a == principal_def_id_b || principal_def_id_b.is_none() {
10021002
// We may upcast to auto traits that are either explicitly listed in
10031003
// the object type's bounds, or implied by the principal trait ref's
10041004
// supertraits.

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

+4
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11411141
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
11421142
let iter = data_a
11431143
.principal()
1144+
.filter(|_| {
1145+
// optionally drop the principal, if we're unsizing to no principal
1146+
data_b.principal().is_some()
1147+
})
11441148
.map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
11451149
.into_iter()
11461150
.chain(

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

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//@ run-pass
2+
//@ check-run-results
3+
4+
use std::any::Any;
5+
6+
const fn yeet_principal(x: Box<dyn Any + Send>) -> Box<dyn Send> {
7+
x
8+
}
9+
10+
trait Bar: Send + Sync {}
11+
12+
impl<T: Send + Sync> Bar for T {}
13+
14+
const fn yeet_principal_2(x: Box<dyn Bar>) -> Box<dyn Send> {
15+
x
16+
}
17+
18+
struct CallMe<F: FnOnce()>(Option<F>);
19+
20+
impl<F: FnOnce()> CallMe<F> {
21+
fn new(f: F) -> Self {
22+
CallMe(Some(f))
23+
}
24+
}
25+
26+
impl<F: FnOnce()> Drop for CallMe<F> {
27+
fn drop(&mut self) {
28+
(self.0.take().unwrap())();
29+
}
30+
}
31+
32+
fn goodbye() {
33+
println!("goodbye");
34+
}
35+
36+
fn main() {
37+
let x = Box::new(CallMe::new(goodbye)) as Box<dyn Any + Send>;
38+
let y = yeet_principal(x);
39+
println!("before");
40+
drop(y);
41+
42+
let x = Box::new(CallMe::new(goodbye)) as Box<dyn Bar>;
43+
let y = yeet_principal_2(x);
44+
println!("before");
45+
drop(y);
46+
}
47+
48+
// Test that upcast works in `const`
49+
50+
const fn yeet_principal_3(x: &(dyn Any + Send + Sync)) -> &(dyn Send + Sync) {
51+
x
52+
}
53+
54+
#[used]
55+
pub static FOO: &(dyn Send + Sync) = yeet_principal_3(&false);
56+
57+
const fn yeet_principal_4(x: &dyn Bar) -> &(dyn Send + Sync) {
58+
x
59+
}
60+
61+
#[used]
62+
pub static BAR: &(dyn Send + Sync) = yeet_principal_4(&false);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
before
2+
goodbye
3+
before
4+
goodbye

0 commit comments

Comments
 (0)