Variables bound with different modes in patterns
The following doesn't compile:
enum Test<'a> {
A(&'a u64),
B(u64),
}
fn foo(test: Test) {
match test {
Test::A(r) | Test::B(ref r) => println!("{}", r)
}
}
fn main() {
foo(Test::A(&0));
foo(Test::B(1));
}
failing with the following error:
test.rs:7:30: 7:35 error: variable `r` is bound with different mode in pattern #2 than in pattern #1
test.rs:7 Test::A(r) | Test::B(ref r) => println!("{}", r)
^~~~~
error: aborting due to previous error
However, the following does work:
enum Test<'a> {
A(&'a u64),
B(u64),
}
fn foo(test: Test) {
match test {
Test::A(&ref r) | Test::B(ref r) => println!("{}", r)
}
}
fn main() {
foo(Test::A(&0));
foo(Test::B(1));
}
Is there any reason rust can't just perform this reborrow automatically? &ref is a very cryptic pattern.
Is there any reason we put in this restriction in the first place in https://github.com/rust-lang/rust/commit/a6a5c48c6461b67ba84eaab66a38938226bfe739? Seems like the type equality restriction on bindings should be enough.
cc @nikomatsakis
Deleted user at 2015-03-24 23:28:46
this error still occur in rustc 1.11.0 (9b21dcd6a 2016-08-15)
kdeeee at 2016-09-30 14:56:31
@nikomatsakis Is there a chance the
&refpattern is actually bypassing the match checking that is intended to not allow binding both by-move and by-reference in the same arm? It seems to be, so... perhaps this is a problem in a wider sense?Mark Rousskov at 2017-05-14 15:03:30
@Mark-Simulacrum
Is there a chance the
&refpattern is actually bypassing the match checking that is intended to not allow binding both by-move and by-reference in the same arm?I don't understand what you mean here -- we have two bindings, both are "by reference", so how is the current code mixing by-move and by-ref in the same pattern?
Niko Matsakis at 2017-05-25 17:42:11
I think that in principle we do not need to require all bindings to be in the same mode; in that sense I agree with @ghost. However, I'm not sure how hard it would be to keep current code "up and going" without that simplifying restriction. I'd have to dig in in more detail. I think that once we are doing borrowck on MIR, things ought to be simpler, since most of the rules we have to keep borrowck + match sound could go away.
Niko Matsakis at 2017-05-25 17:43:50
Oh, I think I misread about the two bindings being by-move and by-reference -- never mind.
I agree that we should probably leave this for after MIR borrowck (which might in its implementation resolve these sorts of issues on its own, I don't know).
Mark Rousskov at 2017-05-25 19:44:30
Triage: MIR borrowcheck has now landed, but this still gives this error.
Steve Klabnik at 2018-12-20 19:14:17
-
error[E0409]: variable `r` is bound inconsistently across alternatives separated by `|` --> src/main.rs:7:34 | 7 | Test::A(r) | Test::B(ref r) => println!("{}", r) | - first binding ^ bound in different ways For more information about this error, try `rustc --explain E0409`Dylan DPC at 2023-11-19 05:52:02