Skip to content

Modifying a single subpattern in match changes MIR dramatically #92766

Open
@fee1-dead

Description

@fee1-dead

This is originated from ~const Drop, but is applicable to non-const functions as well. The problem is best seen as the MIR output for two implementations of Result::ok with a minor change: (play)

pub fn wildcard<T, E>(res: Result<T, E>) -> Option<T> {
    match res {
        Ok(x) => Some(x),
        Err(_) => None,
    }
}

pub fn bind_to_variable<T, E>(res: Result<T, E>) -> Option<T> {
    match res {
        Ok(x) => Some(x),
        Err(_x) => None,
    }
}

I won't post the whole MIR output here, but let me illustrate this issue with a handwritten control flow graph:

           wildcard
              |
switch on discriminant for `res` ------------ `Ok(x)`
              |                                 |
            `Err`             Move `x` into return value as `Some(x)`
              |                                 |
Set return value as `None`                      /
              |---------------------------------
              |
switch on discriminant for `res` ------------ `Ok`
              |                                 |
            `Err`                               |
              |                                 |
    `drop(res: Result<T, E>)`                   /
              |---------------------------------
              |
            return



       bind_to_variable
              |
switch on discriminant for `res` ------------- `Ok(x)`
              |                                  |
            `Err`             Move `x` into return value as `Some(x)`
              |                                  |
   Move value in `Err` to `_x`                   |
              |                                  |
        `drop(_x: E)`                            |
              |                                  |
    Set return value as `None`                   /
              |----------------------------------
              |
            return

wildcard is unexpectedly more complex and performs switchInt on x for two times instead of one. I think ideally we should always generate MIR as the second graph.

See #92433 (comment) and Zulip

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlC-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