typeck: suggest use of match_default_bindings feature

Fixes #45383.
Updates #42640.
This commit is contained in:
Tamir Duberstein 2017-10-20 08:59:55 -04:00
parent f0fe716dbc
commit 9844777a50
No known key found for this signature in database
GPG key ID: 1C1E98CC8E17BB89
15 changed files with 74 additions and 21 deletions

View file

@ -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;
@ -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);
@ -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();
}
}
}
@ -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..],

View file

@ -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
_ => {}
}
}

View file

@ -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!(),
}
}

View file

@ -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
}

View file

@ -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();
}
}

View file

@ -9,5 +9,5 @@
// except according to those terms.
fn main() {
let false = "foo"; //~ error: mismatched types
let false = 22; //~ error: mismatched types
}

View file

@ -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
}

View file

@ -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
}

View file

@ -9,5 +9,5 @@
// except according to those terms.
fn main() {
let true = "foo"; //~ error: mismatched types
let true = 22; //~ error: mismatched types
}

View file

@ -15,6 +15,7 @@ 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" => ()
@ -22,6 +23,7 @@ fn main() {
//~^^ 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 => { }

View file

@ -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] {

View file

@ -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!(),
}
}

View file

@ -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
@ -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

View file

@ -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);
}
}

View file

@ -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