Skip to content

Confusing error message when matching on &str in const fn #90237

Description

@ilyvion

Given the following code: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=bc51fb79544b1be00dd8a4285103ff07

const fn foo(input: &'static str) {
    match input {
        "a" => (),
        _ => (),
    }
}

The current output is:

error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 --> src/lib.rs:3:9
  |
3 |         "a" => (),
  |         ^^^

I feel like it's pretty self-explanatory, but this is obviously a very confusing error. A match arm for a string literal is not a "call" by any usual meaning of the word. In fact, I have no idea what actual objection rustc has to this code, if any.

As far as I can tell, this error is the same on all current versions of the compiler (stable, beta, nightly) per the submission of this issue.

Activity

  1. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Oct 24, 2021
  2. PatchMixolydic commented on Oct 25, 2021

    @PatchMixolydic
    Contributor

    I'm not familiar with how matching on &str is implemented, so this is pure conjecture, but the "call" might be an implicit call to input.eq("a"). The == operator issues the same confusing diagnostic (playground):

    const fn foo(input: &'static str) {
        input == "a";
    }
    error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
     --> src/lib.rs:2:5
      |
    2 |     input == "a";
      |     ^^^^^^^^^^^^
    

    @rustbot modify labels: +A-const-eval +D-confusing

  3. added
    A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)
    D-confusingDiagnostics: Confusing error or lint that should be reworked.
    on Oct 25, 2021
  4. self-assigned this
    on Nov 3, 2021
  5. detly commented on Sep 29, 2022

    @detly

    Note also that a byte string literal is fine:

    const fn decode_bytes(b: &[u8]) -> Option<u8> {
        match b {
            b"0" => Some(0),
            _ => None,
        }
    }

    ☝️ compiles on 1.64, but

    const fn decode_string(s: &str) -> Option<u8> {
        match s {
            "0" => Some(0),
            _ => None,
        }
    }

    ...fails with:

    error[[E0015]](https://doc.rust-lang.org/stable/error-index.html#E0015): cannot call non-const operator in constant functions
     --> src/lib.rs:3:9
      |
    3 |         "0" => Some(0),
      |         ^^^
      |
      = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    
    For more information about this error, try `rustc --explain E0015`.
    error: could not compile `playground` due to previous error
    
  6. jnnnnn commented on May 17, 2023

    @jnnnnn

    I ran into this as well. It's definitely calling <str as PartialEq>::eq as part of the match. The way to prove so is to look at the MIR (and remove const so the code compiles).

    The const_str crate gets around this by converting to bytes for the comparison.

    Here's a working example: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=286b897bb518dec6617d3da197cd318b

    Note, this seems related to #103040 . <str as PartialEq>::eq probably can't be const until #67792 lands.

  7. added a commit that references this issue on Jun 18, 2023
    7b91275
  8. added a commit that references this issue on Jun 20, 2023
    31d1fbf
  9. added a commit that references this issue on Jun 30, 2023
    9a65f46
  10. added a commit that references this issue on Jul 22, 2023
    7ba31b9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)A-diagnosticsArea: Messages for errors, warnings, and lintsD-confusingDiagnostics: Confusing error or lint that should be reworked.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