Skip to content

Fails to fully optimize logically equivalent match patterns with nested #139787

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

Closed
ZhonghaoPan-nju opened this issue Apr 14, 2025 · 2 comments
Closed
Labels
C-discussion Category: Discussion or questions that doesn't represent real issues.

Comments

@ZhonghaoPan-nju
Copy link

I tried these codes: (opt-level=3)
https://godbolt.org/z/b3je31qea

pub fn main() {
    let x = 1;
    let y = 2;

    assert_eq!(
        3,
        match (x, y) {
            (1, 1) => 1,
            (2, 2) => 2,
            (1..=2, 2) => 3,
            _ => 4,
        }
    );

    assert_eq!(
        3,
        match ((x, y),) {
            ((1, 1),) => 1,
            ((2, 2),) => 2,
            ((1..=2, 2),) => 3,
            _ => 4,
        }
    );
}

and:

pub fn main() {
    let mut x = (2 - 1);
    x += 1727276569 - 101200722;	
    x -= 1626075847;
    {
        let mut y = 3;
        y *= 2057990635 / 1;
        y /= 2057990635;
        assert_eq!(3, match (x, y) {
            (1, 1) => 1,
            (2, 2) => 2,
            (1..=2, 2) => 3,
            _ => 4,
        });
        assert_eq!(3, match ((x, y),) {
            ((1, 1),) => 1,
            ((2, 2),) => 2,
            ((1..=2, 2),) => 3,
            _ => 4,
        });
    }
}

I expected to see this happen:

example::main::h0b7eacf4acc29bea:
        ret

Instead, this happened:

example::main::h0b7eacf4acc29bea:
        sub     rsp, 56
        mov     dword ptr [rsp + 4], 4
        mov     qword ptr [rsp + 8], 0
        lea     rsi, [rip + .Lanon.a978cc5b56b2e232a190db3ec3b8f702.0]
        lea     r8, [rip + .Lanon.a978cc5b56b2e232a190db3ec3b8f702.2]
        lea     rdx, [rsp + 4]
        lea     rcx, [rsp + 8]
        xor     edi, edi
        call    qword ptr [rip + core::panicking::assert_failed::haa00447c26f4b1ca@GOTPCREL]

The compiler fails to recognize that let mut x and let mut y ultimately resolve to constant values 1 and 2 respectively in the second code example. While rustc's constant propagation typically handles such cases effectively, this particular pattern involving mutable variables with arithmetic operations appears to prevent the optimization.
I'd appreciate any insights into why the compiler can't deduce the final constant values in this scenario.

Meta

rustc 1.85.0-nightly (d117b7f21 2024-12-31)
binary: rustc
commit-hash: d117b7f211835282b3b177dc64245fff0327c04c
commit-date: 2024-12-31
host: x86_64-unknown-linux-gnu
release: 1.85.0-nightly
LLVM version: 19.1.6
@ZhonghaoPan-nju ZhonghaoPan-nju added the C-bug Category: This is a bug. label Apr 14, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Apr 14, 2025
@theemathas
Copy link
Contributor

theemathas commented Apr 14, 2025

Not a bug. Rust integers default to being i32 unless some type information forces it to be some other type.

In your second code, when you do y *= 2057990635 / 1;. You are computing 3 * 2057990635. The result of this operation is 6173971905, which doesn't fit in an i32, which can hold values at most 2147483647. Therefore, your code has an integer overflow.

In debug mode, rust will panic as soon as you do this multiplication. In release mode, which is what your godbolt link uses, the result "wraps around". Therefore, after the multiplication, y is not equal to 6173971905, but is instead equal to 1879004609. Then, after y /= 2057990635;, y is set to 0. As a result, the assertion fails, so the assembly reflects this behavior.

You can check this by actually running the code, as opposed to inspecting the assembly. You will see that it does, in fact, panic from overflow in debug mode, and panic from failing the assertion in release mode.

@ZhonghaoPan-nju
Copy link
Author

@theemathas Thank you for your patient explanations - they've helped me better understand Rust's behavior! I'll go ahead and close this issue now.

@jieyouxu jieyouxu added C-discussion Category: Discussion or questions that doesn't represent real issues. and removed C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Apr 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-discussion Category: Discussion or questions that doesn't represent real issues.
Projects
None yet
Development

No branches or pull requests

4 participants