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

Cannot match on reference in slice pattern #55175

Closed
sunjay opened this issue Oct 18, 2018 · 4 comments
Closed

Cannot match on reference in slice pattern #55175

sunjay opened this issue Oct 18, 2018 · 4 comments
Labels
A-slice-patterns Area: Slice patterns, https://github.com/rust-lang/rust/issues/23121 T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@sunjay
Copy link
Member

sunjay commented Oct 18, 2018

Here's a minimal reproduction: (Rust Playground)

fn main() {
    let x = vec![1i32];
    let value: i32 = match &x[..] {
        [&v] => v,
        _ => panic!(),
    };
}

Since the type of &x[..] is &[i32], I expect its contents to be &i32 (or else we would move unexpectedly). However, trying to match on that reference to force a copy here does not work because the error message indicates that the type of v inside the pattern is in fact i32, not &i32.

error[E0308]: mismatched types
 --> src/main.rs:4:10
  |
4 |         [&v] => v,
  |          ^^ expected i32, found reference
  |
  = note: expected type `i32`
             found type `&_`
  = help: did you mean `v: &i32`?

Note: If you noticed the weird help message, I filed an issue for that already: #55174

This is further complicated by the fact that if you remove the & from v (since it's type is i32 right??), it still doesn't work because the type of v is actually &i32 like I originally expected.

error[E0308]: match arms have incompatible types
 --> src/main.rs:3:22
  |
3 |       let value: i32 = match &x[..] {
  |  ______________________^
4 | |         [v] => v,
  | |                - match arm with an incompatible type
5 | |         _ => panic!(),
6 | |     };
  | |_____^ expected i32, found &i32
  |
  = note: expected type `i32`
             found type `&i32`

Both the type of v in the pattern and the type of v on that is returned into value should probably be the same.

Could this be a weird interaction with the match ergonomics features added recently?

@csmoe csmoe added the A-slice-patterns Area: Slice patterns, https://github.com/rust-lang/rust/issues/23121 label Oct 18, 2018
@jonas-schievink jonas-schievink added C-bug Category: This is a bug. T-lang Relevant to the language team, which will review and decide on the PR/issue. and removed C-bug Category: This is a bug. labels Mar 24, 2019
@estebank
Copy link
Contributor

For anyone looking around for help on this case in particular, the appropriate code would be either

fn main() {
    let x = vec![1i32];
    let value: i32 = match &x[..] {
        &[v] => v,
        _ => panic!(),
    };
}

or

fn main() {
    let x = vec![1i32];
    let value: i32 = match &x[..] {
        [v] => *v,
        _ => panic!(),
    };
}

which is now suggested:

error[E0308]: mismatched types
 --> src/main.rs:4:16
  |
4 |         [v] => v,
  |                ^
  |                |
  |                expected i32, found &i32
  |                help: consider dereferencing the borrow: `*v`
  |
  = note: expected type `i32`
             found type `&i32`

@sunjay
Copy link
Member Author

sunjay commented Apr 30, 2019

If this is just a fix for the error message, did you mean to close #55174?

@estebank
Copy link
Contributor

estebank commented Apr 30, 2019

I have a PR out to fix #55174 (do not suggest v: &i32). That suggestion will mean that the code you will end up is your second example. Once you are there, you get the suggestion to dereference the borrow, after which you end up with working code. Am I misunderstanding the problem? I don't think that we should accept [&v] as a valid pattern here, we would if it was a &[&i32], but it is a &[i32].

I misunderstood anything, feel free to reopen.

@sunjay
Copy link
Member Author

sunjay commented Apr 30, 2019

I guess my intuition is that since the match ergonomics feature makes the element &i32, we should be able to match on that reference and get i32, but after some testing I see that this doesn't work in general even for structs.

struct Foo(i32);

fn main() {
    let foo = Foo(5);
    
    match &foo {
        // To dereference and copy bar, match on the reference
        Foo(&bar) => {
            let _: i32 = bar;
        },
    }
}

Gives you:

error[E0308]: mismatched types
 --> src/main.rs:8:13
  |
8 |         Foo(&bar) => {
  |             ^^^^ expected i32, found reference
  |
  = note: expected type `i32`
             found type `&_`
  = help: did you mean `bar: &i32`?

So I think you are understanding the problem and your fix for the error message is probably sufficient. As long as we're being consistent I'm okay with this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-slice-patterns Area: Slice patterns, https://github.com/rust-lang/rust/issues/23121 T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants