Skip to content

if matches!(...) results in worse mir than if let ... #77355

Closed
@lcnr

Description

@lcnr

This is probably something we can and should optimize:

pub enum Foo {
    A,
    B,
    C,
    D,
    E,
    F,
}

pub fn matches(num: Foo) -> u32 {
    if matches!(num, Foo::B | Foo::C) {
        23
    } else {
        42
    }
}


pub fn if_let(num: Foo) -> u32 {
    if let Foo::B | Foo::C = num {
        23
    } else {
        42
    }
}

results in

fn matches(_1: Foo) -> u32 {
    debug num => _1;                     // in scope 0 at ./example.rs:10:16: 10:19
    let mut _0: u32;                     // return place in scope 0 at ./example.rs:10:29: 10:32
    let mut _2: bool;                    // in scope 0 at /rustc/7f7a1cbfd3b55daee191247770627afab09eece2/library/core/src/macros/mod.rs:246:9: 249:10
    let mut _3: isize;                   // in scope 0 at ./example.rs:11:22: 11:28

    bb0: {
        StorageLive(_2);                 // scope 0 at /rustc/7f7a1cbfd3b55daee191247770627afab09eece2/library/core/src/macros/mod.rs:246:9: 249:10
        _3 = discriminant(_1);           // scope 0 at ./example.rs:11:22: 11:28
        switchInt(move _3) -> [1_isize: bb2, 2_isize: bb2, otherwise: bb1]; // scope 0 at ./example.rs:11:22: 11:28
    }

    bb1: {
        _2 = const false;                // scope 0 at /rustc/7f7a1cbfd3b55daee191247770627afab09eece2/library/core/src/macros/mod.rs:248:18: 248:23
        goto -> bb3;                     // scope 0 at /rustc/7f7a1cbfd3b55daee191247770627afab09eece2/library/core/src/macros/mod.rs:246:9: 249:10
    }

    bb2: {
        _2 = const true;                 // scope 0 at /rustc/7f7a1cbfd3b55daee191247770627afab09eece2/library/core/src/macros/mod.rs:247:48: 247:52
        goto -> bb3;                     // scope 0 at /rustc/7f7a1cbfd3b55daee191247770627afab09eece2/library/core/src/macros/mod.rs:246:9: 249:10
    }

    bb3: {
        switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at ./example.rs:11:5: 15:6
    }

    bb4: {
        _0 = const 42_u32;               // scope 0 at ./example.rs:14:9: 14:11
        goto -> bb6;                     // scope 0 at ./example.rs:11:5: 15:6
    }

    bb5: {
        _0 = const 23_u32;               // scope 0 at ./example.rs:12:9: 12:11
        goto -> bb6;                     // scope 0 at ./example.rs:11:5: 15:6
    }

    bb6: {
        StorageDead(_2);                 // scope 0 at ./example.rs:16:1: 16:2
        return;                          // scope 0 at ./example.rs:16:2: 16:2
    }
}

fn if_let(_1: Foo) -> u32 {
    debug num => _1;                     // in scope 0 at ./example.rs:19:15: 19:18
    let mut _0: u32;                     // return place in scope 0 at ./example.rs:19:28: 19:31
    let mut _2: isize;                   // in scope 0 at ./example.rs:20:12: 20:18

    bb0: {
        _2 = discriminant(_1);           // scope 0 at ./example.rs:20:12: 20:18
        switchInt(move _2) -> [1_isize: bb2, 2_isize: bb2, otherwise: bb1]; // scope 0 at ./example.rs:20:12: 20:18
    }

    bb1: {
        _0 = const 42_u32;               // scope 0 at ./example.rs:23:9: 23:11
        goto -> bb3;                     // scope 0 at ./example.rs:20:5: 24:6
    }

    bb2: {
        _0 = const 23_u32;               // scope 0 at ./example.rs:21:9: 21:11
        goto -> bb3;                     // scope 0 at ./example.rs:20:5: 24:6
    }

    bb3: {
        return;                          // scope 0 at ./example.rs:25:2: 25:2
    }
}

https://godbolt.org/z/8K79o8

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-mir-optArea: MIR optimizationsA-patternsRelating to patterns and pattern matchingC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions