Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

‘reference to packed field is unaligned’ in nested field of match pattern #137250

Closed
Sirraide opened this issue Feb 19, 2025 · 5 comments · Fixed by #137257
Closed

‘reference to packed field is unaligned’ in nested field of match pattern #137250

Sirraide opened this issue Feb 19, 2025 · 5 comments · Fixed by #137257
Assignees
Labels
A-patterns Relating to patterns and pattern matching C-bug Category: This is a bug. S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Sirraide
Copy link

Consider (https://godbolt.org/z/x39GzMKz4):

#[repr(packed)]
#[derive(PartialEq)]
pub struct Packed(i32);

enum Y {
    Foo { id: Packed, },
    Bar(i32)
}

fn pred(_: &i32) -> bool {
    return true;
}

fn f(x: Y) {
    match &x {
        Y::Foo { id: Packed(4), .. } => {},
        Y::Bar(s) if pred(s) => {},
        _ => {}
    }
}

This results in an error:

error[E0793]: reference to packed field is unaligned
  --> <source>:14:11
   |
14 |     match &x {
   |           ^^
   |

I don’t really know what the problem is here, but it might be the match on the id field in the first match arm that triggers the error. Moving Packed(4) into a local variable works, but if I declare it as a const variable instead the error resurfaces. Alternatively, removing the Y::Bar match arm for some reason also makes the error go away.

This currently errors on nightly and some testing on godbolt shows that this code results in an error since Rust 1.62. Before that, we still get the same diagnostic; it’s just treated as a warning instead.

@Sirraide Sirraide added the C-bug Category: This is a bug. label Feb 19, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Feb 19, 2025
@theemathas
Copy link
Contributor

What do you mean by "Moving Packed(4) into a local variable works"? Could you provide example code?

@Sirraide
Copy link
Author

What do you mean by "Moving Packed(4) into a local variable works"? Could you provide example code?

Sure, what I mean is that if I modify f like this, then it compiles just fine (https://godbolt.org/z/cfWoWYPWM):

fn f(x: Y) {
    let foo = Packed(4);
    match &x {
        Y::Foo { id: foo, .. } => {},
        Y::Bar(s) if pred(s) => {},
        _ => {}
    }
}

But if I then replace the let w/ const, it goes back to not compiling.

@theemathas
Copy link
Contributor

This modified code you provided does not do what you want. It declares a second variable also named foo and assigns the contents of the id field to it, regardless of whether it's 4 or some other value.

@Sirraide
Copy link
Author

Right, because the behaviour of that syntax is different depending on whether the identifier to the right of the colon names a constant or not; not the first time this has confused me. Well, I suppose that explains why that ‘fixes’ it, but it’s still weird that it errors when I try to match against a constant.

@theemathas
Copy link
Contributor

theemathas commented Feb 19, 2025

Smaller reproduction of this issue:

#[repr(packed)]
pub struct Packed(i32);

fn f(x: Packed) {
    match &x {
        Packed(4) => {},
        _ if true => {},
        _ => {}
    }
}

Yes, the if true is needed to reproduce the issue for some reason.

Even changing the code to match x gives the same error???

#[repr(packed)]
pub struct Packed(i32);

fn f(x: Packed) {
    match x {
        Packed(4) => {},
        _ if true => {},
        _ => {}
    }
}

@compiler-errors compiler-errors self-assigned this Feb 19, 2025
@jieyouxu jieyouxu added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue A-patterns Relating to patterns and pattern matching and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Feb 20, 2025
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Feb 21, 2025
…ked-field, r=oli-obk

Ignore fake borrows for packed field check

We should not emit unaligned packed field reference errors for the fake borrows that we generate during match lowering.

These fake borrows are there to ensure in *borrow-checking* that we don't modify the value being matched (which is why this only occurs when there's a match guard, in this case `if true`), but they are removed after the MIR is processed by `CleanupPostBorrowck`, since they're really just there to cause borrowck errors if necessary.

I modified `PlaceContext::is_borrow` since that's used by the packed field check:
https://github.com/rust-lang/rust/blob/17c1c329a5512d718b67ef6797538b154016cd34/compiler/rustc_mir_transform/src/check_packed_ref.rs#L40

It's only used in one other place, in the SROA optimization (by which fake borrows are removed, so it doesn't matter):
https://github.com/rust-lang/rust/blob/17c1c329a5512d718b67ef6797538b154016cd34/compiler/rustc_mir_dataflow/src/value_analysis.rs#L922

Fixes rust-lang#137250
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Feb 21, 2025
…ked-field, r=oli-obk

Ignore fake borrows for packed field check

We should not emit unaligned packed field reference errors for the fake borrows that we generate during match lowering.

These fake borrows are there to ensure in *borrow-checking* that we don't modify the value being matched (which is why this only occurs when there's a match guard, in this case `if true`), but they are removed after the MIR is processed by `CleanupPostBorrowck`, since they're really just there to cause borrowck errors if necessary.

I modified `PlaceContext::is_borrow` since that's used by the packed field check:
https://github.com/rust-lang/rust/blob/17c1c329a5512d718b67ef6797538b154016cd34/compiler/rustc_mir_transform/src/check_packed_ref.rs#L40

It's only used in one other place, in the SROA optimization (by which fake borrows are removed, so it doesn't matter):
https://github.com/rust-lang/rust/blob/17c1c329a5512d718b67ef6797538b154016cd34/compiler/rustc_mir_dataflow/src/value_analysis.rs#L922

Fixes rust-lang#137250
@bors bors closed this as completed in fa62fbe Feb 22, 2025
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Feb 22, 2025
Rollup merge of rust-lang#137257 - compiler-errors:fake-borrow-of-packed-field, r=oli-obk

Ignore fake borrows for packed field check

We should not emit unaligned packed field reference errors for the fake borrows that we generate during match lowering.

These fake borrows are there to ensure in *borrow-checking* that we don't modify the value being matched (which is why this only occurs when there's a match guard, in this case `if true`), but they are removed after the MIR is processed by `CleanupPostBorrowck`, since they're really just there to cause borrowck errors if necessary.

I modified `PlaceContext::is_borrow` since that's used by the packed field check:
https://github.com/rust-lang/rust/blob/17c1c329a5512d718b67ef6797538b154016cd34/compiler/rustc_mir_transform/src/check_packed_ref.rs#L40

It's only used in one other place, in the SROA optimization (by which fake borrows are removed, so it doesn't matter):
https://github.com/rust-lang/rust/blob/17c1c329a5512d718b67ef6797538b154016cd34/compiler/rustc_mir_dataflow/src/value_analysis.rs#L922

Fixes rust-lang#137250
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-patterns Relating to patterns and pattern matching C-bug Category: This is a bug. S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants