Skip to content

Commit 80da5a5

Browse files
authored
Rollup merge of rust-lang#60369 - TimDiekmann:dispatch-zst, r=eddyb
Support ZSTs in DispatchFromDyn Allows to use ZSTs with 1 byte alignment in `DispatchFromDyn` implementation. This is required for `Box<T, A: Alloc>` cc rust-lang#58457
2 parents 15e57b8 + 1b679e7 commit 80da5a5

File tree

4 files changed

+80
-8
lines changed

4 files changed

+80
-8
lines changed

src/librustc_typeck/coherence/builtin.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -223,19 +223,22 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>(
223223
let fields = &def_a.non_enum_variant().fields;
224224

225225
let coerced_fields = fields.iter().filter_map(|field| {
226-
if tcx.type_of(field.did).is_phantom_data() {
227-
// ignore PhantomData fields
228-
return None
229-
}
230-
231226
let ty_a = field.ty(tcx, substs_a);
232227
let ty_b = field.ty(tcx, substs_b);
228+
229+
if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
230+
if layout.is_zst() && layout.details.align.abi.bytes() == 1 {
231+
// ignore ZST fields with alignment of 1 byte
232+
return None;
233+
}
234+
}
235+
233236
if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) {
234237
if ok.obligations.is_empty() {
235238
create_err(
236239
"the trait `DispatchFromDyn` may only be implemented \
237240
for structs containing the field being coerced, \
238-
`PhantomData` fields, and nothing else"
241+
ZST fields with 1 byte alignment, and nothing else"
239242
).note(
240243
&format!(
241244
"extra field `{}` of type `{}` is not allowed",
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#![feature(unsize, dispatch_from_dyn, never_type)]
2+
3+
#![allow(dead_code)]
4+
5+
use std::{
6+
ops::DispatchFromDyn,
7+
marker::{Unsize, PhantomData},
8+
};
9+
10+
struct Zst;
11+
struct NestedZst(PhantomData<()>, Zst);
12+
13+
14+
struct WithUnit<T: ?Sized>(Box<T>, ());
15+
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithUnit<U>> for WithUnit<T>
16+
where T: Unsize<U> {}
17+
18+
struct WithPhantom<T: ?Sized>(Box<T>, PhantomData<()>);
19+
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithPhantom<U>> for WithPhantom<T>
20+
where T: Unsize<U> {}
21+
22+
struct WithNever<T: ?Sized>(Box<T>, !);
23+
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithNever<U>> for WithNever<T>
24+
where T: Unsize<U> {}
25+
26+
struct WithZst<T: ?Sized>(Box<T>, Zst);
27+
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithZst<U>> for WithZst<T>
28+
where T: Unsize<U> {}
29+
30+
struct WithNestedZst<T: ?Sized>(Box<T>, NestedZst);
31+
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithNestedZst<U>> for WithNestedZst<T>
32+
where T: Unsize<U> {}
33+
34+
35+
struct Generic<T: ?Sized, A>(Box<T>, A);
36+
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, ()>> for Generic<T, ()>
37+
where T: Unsize<U> {}
38+
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, PhantomData<()>>>
39+
for Generic<T, PhantomData<()>>
40+
where T: Unsize<U> {}
41+
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, !>> for Generic<T, !>
42+
where T: Unsize<U> {}
43+
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, Zst>> for Generic<T, Zst>
44+
where T: Unsize<U> {}
45+
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, NestedZst>> for Generic<T, NestedZst>
46+
where T: Unsize<U> {}
47+
48+
49+
fn main() {}

src/test/ui/invalid_dispatch_from_dyn_impls.rs

+9
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,13 @@ where
3939
T: Unsize<U>,
4040
{} //~^^^ ERROR [E0378]
4141

42+
#[repr(align(64))]
43+
struct OverAlignedZst;
44+
struct OverAligned<T: ?Sized>(Box<T>, OverAlignedZst);
45+
46+
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T>
47+
where
48+
T: Unsize<U>,
49+
{} //~^^^ ERROR [E0378]
50+
4251
fn main() {}

src/test/ui/invalid_dispatch_from_dyn_impls.stderr

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, `PhantomData` fields, and nothing else
1+
error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else
22
--> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1
33
|
44
LL | / impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
@@ -36,6 +36,17 @@ LL | | T: Unsize<U>,
3636
LL | | {}
3737
| |__^
3838

39-
error: aborting due to 4 previous errors
39+
error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else
40+
--> $DIR/invalid_dispatch_from_dyn_impls.rs:46:1
41+
|
42+
LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T>
43+
LL | | where
44+
LL | | T: Unsize<U>,
45+
LL | | {}
46+
| |__^
47+
|
48+
= note: extra field `1` of type `OverAlignedZst` is not allowed
49+
50+
error: aborting due to 5 previous errors
4051

4152
For more information about this error, try `rustc --explain E0378`.

0 commit comments

Comments
 (0)