Skip to content

Commit abf73a6

Browse files
committed
Support ZSTs in DispatchFromDyn
1 parent 1b6caa7 commit abf73a6

File tree

3 files changed

+59
-7
lines changed

3 files changed

+59
-7
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() {
231+
// ignore ZST fields
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, 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.stderr

+1-1
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, 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>

0 commit comments

Comments
 (0)