Skip to content

seemingly incorrect nontrivial_structural_match warning #110508

Open
@jmhain

Description

@jmhain

For the following code, I get a compiler warning:

#[derive(PartialEq, Eq)]
pub enum Thing { Foo(bool), Bar(Vec<()>) }

impl Thing {
    pub const FOO: Thing = Self::Foo(true);
}

pub fn foo(thing: Thing) {
    match thing {
        Thing::FOO => {},
        _ => {},
    }
}

Playground link

And the warning:

warning: to use a constant of type `Vec<()>` in a pattern, the constant's initializer must be trivial or `Vec<()>` must be annotated with `#[derive(PartialEq, Eq)]`
  --> src/lib.rs:10:9
   |
10 |         Thing::FOO => {},
   |         ^^^^^^^^^^
   |
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, [see issue #73448 <https://github.com/rust-lang/rust/issues/73448>](https://github.com/rust-lang/rust/issues/73448)
   = note: `#[warn(nontrivial_structural_match)]` on by default

What makes me think this warning is incorrect is that the constant's initializer does not produce the Vec-containing variant like the warning suggests, and changing Self:: to Thing:: in the initializer resolves the error despite those (afaik) being equivalent.

Activity

compiler-errors

compiler-errors commented on Apr 19, 2023

@compiler-errors
Member

changing Self:: to Thing:: in the initializer resolves the error despite those (afaik) being equivalent.

Strange... Given:

#[derive(PartialEq, Eq)]
pub enum Thing { Foo(bool), Bar(Vec<()>) }

impl Thing {
    pub const FOO: Thing = Thing::Foo(true);
    pub const BAR: Thing = Self::Foo(true);
}

fn main() {}

The MIR we generate for either associated const is quite different...

const <impl at [src/main.rs:4:1: 4:11](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021#)>::FOO: Thing = {
    let mut _0: Thing;                   // return place in scope 0 at [src/main.rs:5:20: 5:25](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021#)

    bb0: {
        Deinit(_0);                      // scope 0 at [src/main.rs:5:28: 5:44](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021#)
        ((_0 as Foo).0: bool) = const true; // scope 0 at [src/main.rs:5:28: 5:44](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021#)
        discriminant(_0) = 0;            // scope 0 at [src/main.rs:5:28: 5:44](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021#)
        return;                          // scope 0 at [src/main.rs:5:5: 5:45](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021#)
    }
}

const <impl at [src/main.rs:4:1: 4:11](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021#)>::BAR: Thing = {
    let mut _0: Thing;                   // return place in scope 0 at [src/main.rs:6:20: 6:25](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021#)

    bb0: {
        _0 = Thing::Foo(const true) -> bb1; // scope 0 at [src/main.rs:6:28: 6:43](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021#)
                                         // mir::Constant
                                         // + span: [src/main.rs:6:28: 6:37](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021#)
                                         // + literal: Const { ty: fn(bool) -> Thing {Thing::Foo}, val: Value(<ZST>) }
    }

    bb1: {
        return;                          // scope 0 at [src/main.rs:6:5: 6:44](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021#)
    }
}

🤔

added
A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html
A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)
A-patternsRelating to patterns and pattern matching
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Apr 20, 2023
ericmarkmartin

ericmarkmartin commented on Jun 26, 2023

@ericmarkmartin
Contributor

I'd like to take a swing at this

ericmarkmartin

ericmarkmartin commented on Jun 29, 2023

@ericmarkmartin
Contributor

@rustbot claim

ericmarkmartin

ericmarkmartin commented on Jun 29, 2023

@ericmarkmartin
Contributor

@compiler-errors I looked at the thir generated for your program

#[derive(PartialEq, Eq)]
pub enum Thing { Foo(bool), Bar(Vec<()>) }

impl Thing {
    pub const FOO: Thing = Thing::Foo(true);
    pub const BAR: Thing = Self::Foo(true);
}

fn main() {}

and FOO and BAR are already different. FOO has kind Adt whereas BAR has kind Call.

added 2 commits that reference this issue on Jul 8, 2023

Rollup merge of rust-lang#113217 - ericmarkmartin:lower-type-relative…

8c4a459

Rollup merge of rust-lang#113217 - ericmarkmartin:lower-type-relative…

b637be7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlA-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)A-patternsRelating to patterns and pattern matchingC-bugCategory: This is a bug.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

      Participants

      @jmhain@compiler-errors@ericmarkmartin@jyn514

      Issue actions

        seemingly incorrect nontrivial_structural_match warning · Issue #110508 · rust-lang/rust