Skip to content

Commit 9844777

Browse files
committed
typeck: suggest use of match_default_bindings feature
Fixes #45383. Updates #42640.
1 parent f0fe716 commit 9844777

15 files changed

+74
-21
lines changed

src/librustc_typeck/check/_match.rs

+22-7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant};
2323
use std::cmp;
2424
use syntax::ast;
2525
use syntax::codemap::Spanned;
26+
use syntax::feature_gate;
2627
use syntax::ptr::P;
2728
use syntax_pos::Span;
2829

@@ -68,7 +69,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
6869
PatKind::Binding(..) |
6970
PatKind::Ref(..) => false,
7071
};
71-
if is_non_ref_pat && tcx.sess.features.borrow().match_default_bindings {
72+
if is_non_ref_pat {
7273
debug!("pattern is non reference pattern");
7374
let mut exp_ty = self.resolve_type_vars_with_obligations(&expected);
7475

@@ -113,10 +114,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
113114
}
114115
};
115116
if pat_adjustments.len() > 0 {
116-
debug!("default binding mode is now {:?}", def_bm);
117-
self.inh.tables.borrow_mut()
118-
.pat_adjustments_mut()
119-
.insert(pat.hir_id, pat_adjustments);
117+
if tcx.sess.features.borrow().match_default_bindings {
118+
debug!("default binding mode is now {:?}", def_bm);
119+
self.inh.tables.borrow_mut()
120+
.pat_adjustments_mut()
121+
.insert(pat.hir_id, pat_adjustments);
122+
} else {
123+
let mut err = feature_gate::feature_err(
124+
&tcx.sess.parse_sess,
125+
"match_default_bindings",
126+
pat.span,
127+
feature_gate::GateIssue::Language,
128+
"non-reference pattern used to match a reference",
129+
);
130+
if let Ok(snippet) = tcx.sess.codemap().span_to_snippet(pat.span) {
131+
err.span_suggestion(pat.span, "consider using", format!("&{}", &snippet));
132+
}
133+
err.emit();
134+
}
120135
}
121136
}
122137

@@ -325,8 +340,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
325340
if let Some(mut err) = err {
326341
if is_arg {
327342
if let PatKind::Binding(..) = inner.node {
328-
if let Ok(snippet) = self.sess().codemap()
329-
.span_to_snippet(pat.span)
343+
if let Ok(snippet) = tcx.sess.codemap()
344+
.span_to_snippet(pat.span)
330345
{
331346
err.help(&format!("did you mean `{}: &{}`?",
332347
&snippet[1..],

src/test/compile-fail/E0029.rs

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ fn main() {
1717
//~| NOTE ranges require char or numeric types
1818
//~| NOTE start type: &'static str
1919
//~| NOTE end type: &'static str
20+
//~| ERROR non-reference pattern used to match a reference
2021
_ => {}
2122
}
2223
}

src/test/compile-fail/feature-gate-match_default_bindings.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
pub fn main() {
1212
match &Some(3) {
13-
Some(n) => {}, //~ ERROR mismatched types [E0308]
13+
Some(n) => {},
14+
//~^ ERROR non-reference pattern used to match a reference
1415
_ => panic!(),
1516
}
1617
}

src/test/compile-fail/issue-16338.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ struct Slice<T> {
1616
fn main() {
1717
let Slice { data: data, len: len } = "foo";
1818
//~^ ERROR mismatched types
19-
//~| expected type `&str`
2019
//~| found type `Slice<_>`
21-
//~| expected &str, found struct `Slice`
20+
//~| ERROR non-reference pattern used to match a reference
2221
}

src/test/compile-fail/issue-20261.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
fn main() {
1212
// NB: this (almost) typechecks when default binding modes are enabled.
13-
for (ref i,) in [].iter() { //~ ERROR mismatched types [E0308]
13+
for (ref i,) in [].iter() {
14+
//~^ ERROR non-reference pattern used to match a reference
1415
i.clone();
1516
}
1617
}

src/test/compile-fail/keyword-false-as-identifier.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
let false = "foo"; //~ error: mismatched types
12+
let false = 22; //~ error: mismatched types
1313
}

src/test/compile-fail/keyword-self-as-identifier.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
let Self = "foo"; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
12+
let Self = 22; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
1313
}

src/test/compile-fail/keyword-super-as-identifier.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
let super = "foo"; //~ ERROR failed to resolve. There are too many initial `super`s
12+
let super = 22; //~ ERROR failed to resolve. There are too many initial `super`s
1313
}

src/test/compile-fail/keyword-true-as-identifier.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
let true = "foo"; //~ error: mismatched types
12+
let true = 22; //~ error: mismatched types
1313
}

src/test/compile-fail/match-range-fail.rs

+2
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ fn main() {
1515
//~^^ ERROR only char and numeric types are allowed in range
1616
//~| start type: &'static str
1717
//~| end type: &'static str
18+
//~| ERROR non-reference pattern used to match a reference
1819

1920
match "wow" {
2021
10 ... "what" => ()
2122
};
2223
//~^^ ERROR only char and numeric types are allowed in range
2324
//~| start type: {integer}
2425
//~| end type: &'static str
26+
//~| ERROR non-reference pattern used to match a reference
2527

2628
match 5 {
2729
'c' ... 100 => { }

src/test/compile-fail/match-vec-mismatch.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ fn main() {
1919

2020
// Note that this one works with default binding modes.
2121
match &[0, 1, 2] {
22-
[..] => {} //~ ERROR expected an array or slice, found `&[{integer}; 3]` [E0529]
22+
[..] => {} //~ ERROR non-reference pattern used to match a reference
2323
};
2424

2525
match &[0, 1, 2] {

src/test/compile-fail/pat-slice-old-style.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ fn slice_pat(x: &[u8]) {
1717
// OLD!
1818
match x {
1919
[a, b..] => {},
20-
//~^ ERROR expected an array or slice, found `&[u8]`
21-
//~| HELP the semantics of slice patterns changed recently; see issue #23121
20+
//~^ ERROR non-reference pattern used to match a reference
21+
//~| HELP add #![feature(match_default_bindings)] to the crate attributes to enable
22+
//~| HELP consider using
2223
_ => panic!(),
2324
}
2425
}

src/test/ui/mismatched_types/closure-arg-count.stderr

+11-3
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,21 @@ error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
1414
| |
1515
| expected closure that takes 2 arguments
1616

17+
error: non-reference pattern used to match a reference (see issue #42640)
18+
--> $DIR/closure-arg-count.rs:17:24
19+
|
20+
17 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
21+
| ^^^^^^^^^^^^^^^ help: consider using: `&(tuple, tuple2)`
22+
|
23+
= help: add #![feature(match_default_bindings)] to the crate attributes to enable
24+
1725
error[E0308]: mismatched types
1826
--> $DIR/closure-arg-count.rs:17:24
1927
|
2028
17 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
21-
| ^^^^^^^^^^^^^^^ expected &{integer}, found tuple
29+
| ^^^^^^^^^^^^^^^ expected integral variable, found tuple
2230
|
23-
= note: expected type `&{integer}`
31+
= note: expected type `{integer}`
2432
found type `(_, _)`
2533

2634
error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
@@ -65,5 +73,5 @@ error[E0593]: closure is expected to take a single 2-tuple as argument, but it t
6573
| |
6674
| expected closure that takes a single 2-tuple as argument
6775

68-
error: aborting due to 8 previous errors
76+
error: aborting due to 9 previous errors
6977

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
if let Some(y) = &Some(22) {
13+
println!("{}", y);
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: non-reference pattern used to match a reference (see issue #42640)
2+
--> $DIR/suggestion.rs:12:12
3+
|
4+
12 | if let Some(y) = &Some(22) {
5+
| ^^^^^^^ help: consider using: `&Some(y)`
6+
|
7+
= help: add #![feature(match_default_bindings)] to the crate attributes to enable
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)