Skip to content

Commit

Permalink
typeck: suggest use of match_default_bindings feature
Browse files Browse the repository at this point in the history
Fixes #45383.
Updates #42640.
  • Loading branch information
tamird committed Oct 30, 2017
1 parent f0fe716 commit 9844777
Show file tree
Hide file tree
Showing 15 changed files with 74 additions and 21 deletions.
29 changes: 22 additions & 7 deletions src/librustc_typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::cmp;
use syntax::ast;
use syntax::codemap::Spanned;
use syntax::feature_gate;
use syntax::ptr::P;
use syntax_pos::Span;

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

Expand Down Expand Up @@ -113,10 +114,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
};
if pat_adjustments.len() > 0 {
debug!("default binding mode is now {:?}", def_bm);
self.inh.tables.borrow_mut()
.pat_adjustments_mut()
.insert(pat.hir_id, pat_adjustments);
if tcx.sess.features.borrow().match_default_bindings {
debug!("default binding mode is now {:?}", def_bm);
self.inh.tables.borrow_mut()
.pat_adjustments_mut()
.insert(pat.hir_id, pat_adjustments);
} else {
let mut err = feature_gate::feature_err(
&tcx.sess.parse_sess,
"match_default_bindings",
pat.span,
feature_gate::GateIssue::Language,
"non-reference pattern used to match a reference",
);
if let Ok(snippet) = tcx.sess.codemap().span_to_snippet(pat.span) {
err.span_suggestion(pat.span, "consider using", format!("&{}", &snippet));
}
err.emit();
}
}
}

Expand Down Expand Up @@ -325,8 +340,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if let Some(mut err) = err {
if is_arg {
if let PatKind::Binding(..) = inner.node {
if let Ok(snippet) = self.sess().codemap()
.span_to_snippet(pat.span)
if let Ok(snippet) = tcx.sess.codemap()
.span_to_snippet(pat.span)
{
err.help(&format!("did you mean `{}: &{}`?",
&snippet[1..],
Expand Down
1 change: 1 addition & 0 deletions src/test/compile-fail/E0029.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ fn main() {
//~| NOTE ranges require char or numeric types
//~| NOTE start type: &'static str
//~| NOTE end type: &'static str
//~| ERROR non-reference pattern used to match a reference
_ => {}
}
}
3 changes: 2 additions & 1 deletion src/test/compile-fail/feature-gate-match_default_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

pub fn main() {
match &Some(3) {
Some(n) => {}, //~ ERROR mismatched types [E0308]
Some(n) => {},
//~^ ERROR non-reference pattern used to match a reference
_ => panic!(),
}
}
3 changes: 1 addition & 2 deletions src/test/compile-fail/issue-16338.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ struct Slice<T> {
fn main() {
let Slice { data: data, len: len } = "foo";
//~^ ERROR mismatched types
//~| expected type `&str`
//~| found type `Slice<_>`
//~| expected &str, found struct `Slice`
//~| ERROR non-reference pattern used to match a reference
}
3 changes: 2 additions & 1 deletion src/test/compile-fail/issue-20261.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

fn main() {
// NB: this (almost) typechecks when default binding modes are enabled.
for (ref i,) in [].iter() { //~ ERROR mismatched types [E0308]
for (ref i,) in [].iter() {
//~^ ERROR non-reference pattern used to match a reference
i.clone();
}
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/keyword-false-as-identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
// except according to those terms.

fn main() {
let false = "foo"; //~ error: mismatched types
let false = 22; //~ error: mismatched types
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/keyword-self-as-identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
// except according to those terms.

fn main() {
let Self = "foo"; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
let Self = 22; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/keyword-super-as-identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
// except according to those terms.

fn main() {
let super = "foo"; //~ ERROR failed to resolve. There are too many initial `super`s
let super = 22; //~ ERROR failed to resolve. There are too many initial `super`s
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/keyword-true-as-identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
// except according to those terms.

fn main() {
let true = "foo"; //~ error: mismatched types
let true = 22; //~ error: mismatched types
}
2 changes: 2 additions & 0 deletions src/test/compile-fail/match-range-fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ fn main() {
//~^^ ERROR only char and numeric types are allowed in range
//~| start type: &'static str
//~| end type: &'static str
//~| ERROR non-reference pattern used to match a reference

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

match 5 {
'c' ... 100 => { }
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/match-vec-mismatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() {

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

match &[0, 1, 2] {
Expand Down
5 changes: 3 additions & 2 deletions src/test/compile-fail/pat-slice-old-style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ fn slice_pat(x: &[u8]) {
// OLD!
match x {
[a, b..] => {},
//~^ ERROR expected an array or slice, found `&[u8]`
//~| HELP the semantics of slice patterns changed recently; see issue #23121
//~^ ERROR non-reference pattern used to match a reference
//~| HELP add #![feature(match_default_bindings)] to the crate attributes to enable
//~| HELP consider using
_ => panic!(),
}
}
Expand Down
14 changes: 11 additions & 3 deletions src/test/ui/mismatched_types/closure-arg-count.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,21 @@ error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
| |
| expected closure that takes 2 arguments

error: non-reference pattern used to match a reference (see issue #42640)
--> $DIR/closure-arg-count.rs:17:24
|
17 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
| ^^^^^^^^^^^^^^^ help: consider using: `&(tuple, tuple2)`
|
= help: add #![feature(match_default_bindings)] to the crate attributes to enable

error[E0308]: mismatched types
--> $DIR/closure-arg-count.rs:17:24
|
17 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
| ^^^^^^^^^^^^^^^ expected &{integer}, found tuple
| ^^^^^^^^^^^^^^^ expected integral variable, found tuple
|
= note: expected type `&{integer}`
= note: expected type `{integer}`
found type `(_, _)`

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

error: aborting due to 8 previous errors
error: aborting due to 9 previous errors

15 changes: 15 additions & 0 deletions src/test/ui/rfc-2005-default-binding-mode/suggestion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() {
if let Some(y) = &Some(22) {
println!("{}", y);
}
}
10 changes: 10 additions & 0 deletions src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: non-reference pattern used to match a reference (see issue #42640)
--> $DIR/suggestion.rs:12:12
|
12 | if let Some(y) = &Some(22) {
| ^^^^^^^ help: consider using: `&Some(y)`
|
= help: add #![feature(match_default_bindings)] to the crate attributes to enable

error: aborting due to previous error

0 comments on commit 9844777

Please sign in to comment.