Skip to content

Commit 97abd86

Browse files
Skip PhantomData in Unsize checks
This patch proposes relaxation on the type unsizing condition. `PhantomData` has been in the current type system exempted from being treated as carrying any data, including dropck, virtual call dispatch by `DispatchFromDyn` and unsizing container by `CoerceUnsize`. `PhantomData` is a special 1-ZST that really carries no "data" of the types it captures. I propose that we should also extend this interpretation to `Unsize`. Signed-off-by: Xiangfei Ding <dingxiangfei2009@protonmail.ch>
1 parent 430d829 commit 97abd86

4 files changed

Lines changed: 42 additions & 5 deletions

File tree

compiler/rustc_ty_utils/src/ty.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,11 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> DenseBitSe
332332
// Ensure none of the other fields mention the parameters used
333333
// in unsizing.
334334
for field in prefix_fields {
335-
for arg in tcx.type_of(field.did).instantiate_identity().walk() {
335+
let field_ty = tcx.type_of(field.did).instantiate_identity();
336+
if field_ty.is_phantom_data() {
337+
continue;
338+
}
339+
for arg in field_ty.walk() {
336340
if let Some(i) = maybe_unsizing_param_idx(arg) {
337341
unsizing_params.remove(i);
338342
}

library/core/src/marker.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ pub trait PointeeSized {
218218
/// - Structs `Foo<..., T1, ..., Tn, ...>` implement `Unsize<Foo<..., U1, ..., Un, ...>>`
219219
/// where any number of (type and const) parameters may be changed if all of these conditions
220220
/// are met:
221-
/// - Only the last field of `Foo` has a type involving the parameters `T1`, ..., `Tn`.
221+
/// - Other than `PhantomData<_>` fields, only the last field of `Foo` has a type involving the parameters `T1`, ..., `Tn`.
222222
/// - All other parameters of the struct are equal.
223223
/// - `Field<T1, ..., Tn>: Unsize<Field<U1, ..., Un>>`, where `Field<...>` stands for the actual
224224
/// type of the struct's last field.

tests/ui/traits/dispatch-from-dyn-invalid-impls.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,16 @@ where
6868
{
6969
}
7070

71+
struct Ptr<T: ?Sized>(Box<T>);
72+
73+
impl<'a, T: ?Sized, U: ?Sized> DispatchFromDyn<&'a Ptr<U>> for &'a Ptr<T> {}
74+
//~^ ERROR conflicting implementations of trait `DispatchFromDyn<&Ptr<_>>` for type `&Ptr<_>`
75+
76+
struct Inner<T: ?Sized>(T);
77+
#[repr(transparent)]
78+
struct Outer<T: ?Sized>(PhantomData<T>, Inner<T>);
79+
80+
impl<'a, T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<&'a Outer<U>> for &'a Outer<T> {}
81+
//~^ ERROR conflicting implementations of trait `DispatchFromDyn<&Outer<_>>` for type `&Outer<_>`
82+
7183
fn main() {}

tests/ui/traits/dispatch-from-dyn-invalid-impls.stderr

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
error[E0119]: conflicting implementations of trait `DispatchFromDyn<&Ptr<_>>` for type `&Ptr<_>`
2+
--> $DIR/dispatch-from-dyn-invalid-impls.rs:73:1
3+
|
4+
LL | impl<'a, T: ?Sized, U: ?Sized> DispatchFromDyn<&'a Ptr<U>> for &'a Ptr<T> {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: conflicting implementation in crate `core`:
8+
- impl<'a, T, U> DispatchFromDyn<&'a U> for &'a T
9+
where T: Unsize<U>, T: ?Sized, U: ?Sized;
10+
= note: downstream crates may implement trait `std::marker::Unsize<std::boxed::Box<_>>` for type `std::boxed::Box<_>`
11+
12+
error[E0119]: conflicting implementations of trait `DispatchFromDyn<&Outer<_>>` for type `&Outer<_>`
13+
--> $DIR/dispatch-from-dyn-invalid-impls.rs:80:1
14+
|
15+
LL | impl<'a, T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<&'a Outer<U>> for &'a Outer<T> {}
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17+
|
18+
= note: conflicting implementation in crate `core`:
19+
- impl<'a, T, U> DispatchFromDyn<&'a U> for &'a T
20+
where T: Unsize<U>, T: ?Sized, U: ?Sized;
21+
122
error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else
223
--> $DIR/dispatch-from-dyn-invalid-impls.rs:19:1
324
|
@@ -54,7 +75,7 @@ LL | | T: Unsize<U>
5475
|
5576
= note: extra field `1` of type `OverAlignedZst` is not allowed
5677

57-
error: aborting due to 5 previous errors
78+
error: aborting due to 7 previous errors
5879

59-
Some errors have detailed explanations: E0374, E0375, E0378.
60-
For more information about an error, try `rustc --explain E0374`.
80+
Some errors have detailed explanations: E0119, E0374, E0375, E0378.
81+
For more information about an error, try `rustc --explain E0119`.

0 commit comments

Comments
 (0)