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

Suggest using match or matches! instead of == for composite data structures known at compile time (tuples, structs, arrays, ...) #13791

Open
gaesa opened this issue Dec 7, 2024 · 0 comments
Labels
A-lint Area: New lints

Comments

@gaesa
Copy link

gaesa commented Dec 7, 2024

What it does

This lint would suggest using match or matches! instead of the == operator when comparing a variable with a composite data structure (such as tuples, structs, arrays) that are known at compile time.

Advantage

  • Improved efficiency: Using match or matches! avoids unnecessary static data and SIMD overhead that might be introduced by the == operator.
  • Faster compilation: Less assembly code is generated, potentially reducing the target size and speeding up compilation times.
  • Scalability: This approach scales better and provides an easier framework for developers to add additional comparison logic in the future.
Evidence

You can see the performance difference using Godbolt by examining the assembly outputs (under -C opt-level=2) for both the == operator and the matches! macro. The following Rust code compares a slice with an array using both approaches:

#[no_mangle]
fn test_eq(slice: &[usize]) -> bool {
    return slice == [1, 2];
}

#[no_mangle]
fn test_match(slice: &[usize]) -> bool {
    return matches!(slice, [1, 2]);
}

Assembly Output for test_eq (using ==):

.LCPI0_0:
    .byte   1
    .byte   0
    .byte   0
    .byte   0
    .byte   0
    .byte   0
    .byte   0
    .byte   0
    .byte   2
    .byte   0
    .byte   0
    .byte   0
    .byte   0
    .byte   0
    .byte   0
test_eq:
    cmp     rsi, 2
    jne     .LBB0_1
    movdqu  xmm0, xmmword ptr [rdi]
    pcmpeqb xmm0, xmmword ptr [rip + .LCPI0_0]
    pmovmskb        eax, xmm0
    cmp     eax, 65535
    sete    al
    ret
.LBB0_1:
    xor     eax, eax
    ret

Assembly Output for test_match (using matches!):

test_match:
    cmp     rsi, 2
    jne     .LBB1_4
    cmp     qword ptr [rdi], 1
    jne     .LBB1_4
    cmp     qword ptr [rdi + 8], 2
    sete    al
    ret
.LBB1_4:
    xor     eax, eax
    ret

Drawbacks

This lint may create unnecessary noise.

Example

d1 == [1, 2];
d2 == Foo { first: 1, second: 2 };
d3 == (1, 2) || d3 == (2, 3);

Could be written as:

matches!(d1, [1, 2]);
matches!(d2, Foo { first: 1, second: 2 });
matches!(d3, (1, 2) | (2, 3))
@gaesa gaesa added the A-lint Area: New lints label Dec 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints
Projects
None yet
Development

No branches or pull requests

1 participant