Skip to content

Commit 11bc805

Browse files
Don't allow DispatchFromDyn impls that transmute ZST to non-ZST
1 parent 3c31861 commit 11bc805

File tree

3 files changed

+54
-13
lines changed

3 files changed

+54
-13
lines changed

compiler/rustc_hir_analysis/src/coherence/builtin.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -267,20 +267,20 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
267267
let ty_a = field.ty(tcx, args_a);
268268
let ty_b = field.ty(tcx, args_b);
269269

270-
// Allow 1-ZSTs that don't mention type params.
271-
//
272-
// Allowing type params here would allow us to possibly transmute
273-
// between ZSTs, which may be used to create library unsoundness.
274-
if let Ok(layout) =
275-
tcx.layout_of(infcx.typing_env(param_env).as_query_input(ty_a))
276-
&& layout.is_1zst()
277-
&& !ty_a.has_non_region_param()
278-
{
279-
// ignore 1-ZST fields
280-
return false;
281-
}
282-
283270
if ty_a == ty_b {
271+
// Allow 1-ZSTs that don't mention type params.
272+
//
273+
// Allowing type params here would allow us to possibly transmute
274+
// between ZSTs, which may be used to create library unsoundness.
275+
if let Ok(layout) =
276+
tcx.layout_of(infcx.typing_env(param_env).as_query_input(ty_a))
277+
&& layout.is_1zst()
278+
&& !ty_a.has_non_region_param()
279+
{
280+
// ignore 1-ZST fields
281+
return false;
282+
}
283+
284284
res = Err(tcx.dcx().emit_err(errors::DispatchFromDynZST {
285285
span,
286286
name: field.name,
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// We used to allow erroneous `DispatchFromDyn` impls whose RHS type contained
2+
// fields that weren't ZSTs. I don't believe this was possible to abuse, but
3+
// it's at least nice to give users better errors.
4+
5+
#![feature(arbitrary_self_types)]
6+
#![feature(unsize)]
7+
#![feature(dispatch_from_dyn)]
8+
9+
use std::marker::Unsize;
10+
use std::ops::DispatchFromDyn;
11+
12+
struct Dispatchable<T: ?Sized, Z> {
13+
_ptr: Box<T>,
14+
z: Z,
15+
}
16+
17+
impl<T, U> DispatchFromDyn<Dispatchable<U, i32>> for Dispatchable<T, ()>
18+
//~^ ERROR implementing the `DispatchFromDyn` trait requires multiple coercions
19+
where
20+
T: Unsize<U> + ?Sized,
21+
U: ?Sized,
22+
{
23+
}
24+
25+
fn main() {}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0378]: implementing the `DispatchFromDyn` trait requires multiple coercions
2+
--> $DIR/dispatch-from-dyn-zst-transmute-zst-nonzst.rs:17:1
3+
|
4+
LL | / impl<T, U> DispatchFromDyn<Dispatchable<U, i32>> for Dispatchable<T, ()>
5+
LL | |
6+
LL | | where
7+
LL | | T: Unsize<U> + ?Sized,
8+
LL | | U: ?Sized,
9+
| |______________^
10+
|
11+
= note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
12+
= note: currently, 2 fields need coercions: `_ptr` (`Box<T>` to `Box<U>`), `z` (`()` to `i32`)
13+
14+
error: aborting due to 1 previous error
15+
16+
For more information about this error, try `rustc --explain E0378`.

0 commit comments

Comments
 (0)