Skip to content

Conversation

lukas-code
Copy link
Member

fixes #98064

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jun 13, 2022
@rust-highfive
Copy link
Contributor

r? @wesleywiser

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 13, 2022
@rust-log-analyzer

This comment has been minimized.

@lukas-code lukas-code force-pushed the repr-transparent-zero-array branch 2 times, most recently from 21c81a5 to 40fa282 Compare June 13, 2022 21:41
@lukas-code lukas-code force-pushed the repr-transparent-zero-array branch from 40fa282 to bd3d1ae Compare June 13, 2022 21:43
Comment on lines 1332 to 1336
let array_len = match ty.kind() {
Array(_, len) => len.try_eval_usize(tcx, param_env),
_ => None,
};
let zst = array_len == Some(0) || layout.map_or(false, |layout| layout.is_zst());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, doesn't this change the actual typechecking behavior?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, i guess not necessarily, because the align check below will still fail?

I would rather move this is-array check to line 1348, like if (zst || zero_sized_array) && align != Some(1) so we don't need to edit this logic, just in case?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've split zero_sized_array from zst, but the logic stays the same, otherwise we would get #98064 again.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also with a more complex zero-sized but non-trivially-aligned field, we still get the same wrong diagnostic:

struct ComplexZst<A, B> {
    a: [A; 0],
    b: [B; 0],
}

#[repr(transparent)]
struct Aligned<T, A, B> {
    align: ComplexZst<A, B>,
    value: T,
}
error[E0690]: transparent struct needs at most one non-zero-sized field, but has 2
 --> src/lib.rs:7:1
  |
7 | struct Aligned<T, A, B> {
  | ^^^^^^^^^^^^^^^^^^^^^^^ needs at most one non-zero-sized field, but has 2
8 |     align: ComplexZst<A, B>,
  |     ----------------------- this field is non-zero-sized
9 |     value: T,
  |     -------- this field is non-zero-sized

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

Is it worth trying to fix this? Should there be something like ty.is_zst(tcx, param_env)? I am not really experienced with rustc internals.

@lukas-code
Copy link
Member Author

I found a kind of related thing in #98104.
I think it should be possible to resolve #98064, #98104 and #98071 (comment) by editing SizeSkeleton to check for zero-sized arrays and then use it for the repr(transparent) check here.

@apiraino
Copy link
Contributor

Based on this comment, I assume that some work can be done here so I'm switching to waiting on author :) Feel free to request a review when ready, thanks!

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 30, 2022
@bors
Copy link
Collaborator

bors commented Jul 6, 2022

☔ The latest upstream changes (presumably #98206) made this pull request unmergeable. Please resolve the merge conflicts.

@JohnCSimon
Copy link
Member

@lukas-code
ping from triage - can you post your status on this PR? Thanks
FYI: when a PR is ready for review, send a message containing
@rustbot ready to switch to S-waiting-on-review so the PR is in the reviewer's backlog.

@JohnCSimon
Copy link
Member

@lukas-code
Ping from triage: I'm closing this due to inactivity, Please reopen when you are ready to continue with this.
Note: if you do please open the PR BEFORE you push to it, else you won't be able to reopen - this is a quirk of github.
Thanks for your contribution.

@rustbot label: +S-inactive

@JohnCSimon JohnCSimon closed this Oct 2, 2022
@rustbot rustbot added the S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs. label Oct 2, 2022
@lukas-code lukas-code deleted the repr-transparent-zero-array branch December 16, 2022 21:18
dvdhrm added a commit to dvdhrm/rust that referenced this pull request Jul 21, 2023
Include the computed alignment of the violating field when rejecting
transparent types with non-trivially aligned ZSTs.

ZST member fields in transparent types must have an alignment of 1 (to
ensure it does not raise the layout requirements of the transparent
field). The current error message looks like this:

 LL | struct Foobar(u32, [u32; 0]);
    |                    ^^^^^^^^ has alignment larger than 1

This patch changes the report to include the alignment of the violating
field:

 LL | struct Foobar(u32, [u32; 0]);
    |                    ^^^^^^^^ has alignment of 4, which is larger than 1

In case of unknown alignments, it will yield:

 LL | struct Foobar(u32, [u32; 0]);
    |                    ^^^^^^^^ may have alignment larger than 1

This allows developers to get a better grasp why a specific field is
rejected. Knowing the alignment of the violating field makes it easier
to judge where that alignment-requirement originates, and thus hopefully
provide better hints on how to mitigate the problem.

This idea was proposed in 2022 in rust-lang#98071 as part of a bigger change.
This commit simply extracts this error-message change, to decouple it
from the other diagnostic improvements.
dvdhrm added a commit to dvdhrm/rust that referenced this pull request Jul 21, 2023
Include the computed alignment of the violating field when rejecting
transparent types with non-trivially aligned ZSTs.

ZST member fields in transparent types must have an alignment of 1 (to
ensure it does not raise the layout requirements of the transparent
field). The current error message looks like this:

 LL | struct Foobar(u32, [u32; 0]);
    |                    ^^^^^^^^ has alignment larger than 1

This patch changes the report to include the alignment of the violating
field:

 LL | struct Foobar(u32, [u32; 0]);
    |                    ^^^^^^^^ has alignment of 4, which is larger than 1

In case of unknown alignments, it will yield:

 LL | struct Foobar<T>(u32, [T; 0]);
    |                       ^^^^^^ may have alignment larger than 1

This allows developers to get a better grasp why a specific field is
rejected. Knowing the alignment of the violating field makes it easier
to judge where that alignment-requirement originates, and thus hopefully
provide better hints on how to mitigate the problem.

This idea was proposed in 2022 in rust-lang#98071 as part of a bigger change.
This commit simply extracts this error-message change, to decouple it
from the other diagnostic improvements.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jul 21, 2023
error/E0691: include alignment in error message

Include the computed alignment of the violating field when rejecting transparent types with non-trivially aligned ZSTs.

ZST member fields in transparent types must have an alignment of 1 (to ensure it does not raise the layout requirements of the transparent field). The current error message looks like this:

```text
 LL | struct Foobar(u32, [u32; 0]);
    |                    ^^^^^^^^ has alignment larger than 1
```

This patch changes the report to include the alignment of the violating field:

```text
 LL | struct Foobar(u32, [u32; 0]);
    |                    ^^^^^^^^ has alignment of 4, which is larger than 1
```

In case of unknown alignments, it will yield:

```text
 LL | struct Foobar(u32, [u32; 0]);
    |                    ^^^^^^^^ may have alignment larger than 1
```

This allows developers to get a better grasp why a specific field is rejected. Knowing the alignment of the violating field makes it easier to judge where that alignment-requirement originates, and thus hopefully provide better hints on how to mitigate the problem.

This idea was proposed in 2022 in rust-lang#98071 as part of a bigger change. This commit simply extracts this error-message change, to decouple it from the other diagnostic improvements.

(Originally proposed by `@compiler-errors` in rust-lang#98071)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Wrong diagnostic for zero-sized array in transparent struct
9 participants