Skip to content

Commit 70a64f9

Browse files
lilyballJakub Wieczorek
authored andcommitted
---
yaml --- r: 136821 b: refs/heads/dist-snap c: 976438f h: refs/heads/master i: 136819: c2a81c2 v: v3
1 parent 982c7f9 commit 70a64f9

File tree

21 files changed

+116
-24
lines changed

21 files changed

+116
-24
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ refs/heads/try: 189b7332968972f34cdbbbd9b62d97ababf53059
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c
9-
refs/heads/dist-snap: 1bc407fb8413b6e7f05a9d38b0d0a770e67dde5a
9+
refs/heads/dist-snap: 976438f78fdce8092430f4c81ca272293c48f1a0
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
1212
refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0

branches/dist-snap/src/librustc/diagnostics.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ register_diagnostic!(E0001, r##"
1919
one is too specific or the ordering is incorrect.
2020
"##)
2121

22+
register_diagnostic!(E0162, r##"
23+
This error is produced by an `if let` expression where the pattern is irrefutable.
24+
An `if let` that can never fail is considered an error.
25+
"##)
26+
2227
register_diagnostics!(
2328
E0002,
2429
E0003,

branches/dist-snap/src/librustc/lint/builtin.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,7 +1091,10 @@ impl LintPass for UnnecessaryParens {
10911091
let (value, msg, struct_lit_needs_parens) = match e.node {
10921092
ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true),
10931093
ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true),
1094-
ast::ExprMatch(ref head, _) => (head, "`match` head expression", true),
1094+
ast::ExprMatch(ref head, _, source) => match source {
1095+
ast::MatchNormal => (head, "`match` head expression", true),
1096+
ast::MatchIfLetDesugar => (head, "`if let` head expression", true)
1097+
},
10951098
ast::ExprRet(Some(ref value)) => (value, "`return` value", false),
10961099
ast::ExprAssign(_, ref value) => (value, "assigned value", false),
10971100
ast::ExprAssignOp(_, _, ref value) => (value, "assigned value", false),
@@ -1241,7 +1244,7 @@ impl LintPass for UnusedMut {
12411244

12421245
fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
12431246
match e.node {
1244-
ast::ExprMatch(_, ref arms) => {
1247+
ast::ExprMatch(_, ref arms, _) => {
12451248
for a in arms.iter() {
12461249
self.check_unused_mut_pat(cx, a.pats.as_slice())
12471250
}

branches/dist-snap/src/librustc/middle/cfg/construct.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
324324
expr_exit
325325
}
326326

327-
ast::ExprMatch(ref discr, ref arms) => {
327+
ast::ExprMatch(ref discr, ref arms, _) => {
328328
//
329329
// [pred]
330330
// |

branches/dist-snap/src/librustc/middle/check_match.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ pub fn check_crate(tcx: &ty::ctxt) {
147147
fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
148148
visit::walk_expr(cx, ex);
149149
match ex.node {
150-
ExprMatch(ref scrut, ref arms) => {
150+
ExprMatch(ref scrut, ref arms, source) => {
151151
// First, check legality of move bindings.
152152
for arm in arms.iter() {
153153
check_legality_of_move_bindings(cx,
@@ -184,7 +184,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
184184
}
185185

186186
// Fourth, check for unreachable arms.
187-
check_arms(cx, inlined_arms.as_slice());
187+
check_arms(cx, inlined_arms.as_slice(), source);
188188

189189
// Finally, check if the whole match expression is exhaustive.
190190
// Check for empty enum, because is_useful only works on inhabited types.
@@ -252,13 +252,31 @@ fn check_for_static_nan(cx: &MatchCheckCtxt, pats: &[P<Pat>]) {
252252
}
253253

254254
// Check for unreachable patterns
255-
fn check_arms(cx: &MatchCheckCtxt, arms: &[(Vec<P<Pat>>, Option<&Expr>)]) {
255+
fn check_arms(cx: &MatchCheckCtxt, arms: &[(Vec<P<Pat>>, Option<&Expr>)], source: MatchSource) {
256256
let mut seen = Matrix(vec![]);
257+
let mut printed_if_let_err = false;
257258
for &(ref pats, guard) in arms.iter() {
258259
for pat in pats.iter() {
259260
let v = vec![&**pat];
261+
260262
match is_useful(cx, &seen, v.as_slice(), LeaveOutWitness) {
261-
NotUseful => span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern"),
263+
NotUseful => {
264+
if source == MatchIfLetDesugar {
265+
if printed_if_let_err {
266+
// we already printed an irrefutable if-let pattern error.
267+
// We don't want two, that's just confusing.
268+
} else {
269+
// find the first arm pattern so we can use its span
270+
let &(ref first_arm_pats, _) = &arms[0]; // we know there's at least 1 arm
271+
let first_pat = first_arm_pats.get(0); // and it's safe to assume 1 pat
272+
let span = first_pat.span;
273+
span_err!(cx.tcx.sess, span, E0162, "irrefutable if-let pattern");
274+
printed_if_let_err = true;
275+
}
276+
} else {
277+
span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern");
278+
}
279+
}
262280
Useful => (),
263281
UsefulWithWitness(_) => unreachable!()
264282
}

branches/dist-snap/src/librustc/middle/expr_use_visitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
376376

377377
ast::ExprIfLet(..) => fail!("non-desugared ExprIfLet"),
378378

379-
ast::ExprMatch(ref discr, ref arms) => {
379+
ast::ExprMatch(ref discr, ref arms, _) => {
380380
let discr_cmt = return_if_err!(self.mc.cat_expr(&**discr));
381381
self.borrow_expr(&**discr, ty::ReEmpty, ty::ImmBorrow, MatchDiscriminant);
382382

branches/dist-snap/src/librustc/middle/liveness.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
10291029
self.propagate_through_loop(expr, LoopLoop, &**blk, succ)
10301030
}
10311031

1032-
ExprMatch(ref e, ref arms) => {
1032+
ExprMatch(ref e, ref arms, _) => {
10331033
//
10341034
// (e)
10351035
// |

branches/dist-snap/src/librustc/middle/trans/debuginfo.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3659,7 +3659,7 @@ fn populate_scope_map(cx: &CrateContext,
36593659
}
36603660
}
36613661

3662-
ast::ExprMatch(ref discriminant_exp, ref arms) => {
3662+
ast::ExprMatch(ref discriminant_exp, ref arms, _) => {
36633663
walk_expr(cx, &**discriminant_exp, scope_stack, scope_map);
36643664

36653665
// For each arm we have to first walk the pattern as these might

branches/dist-snap/src/librustc/middle/trans/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
10131013
ast::ExprIf(ref cond, ref thn, ref els) => {
10141014
controlflow::trans_if(bcx, expr.id, &**cond, &**thn, els.as_ref().map(|e| &**e), dest)
10151015
}
1016-
ast::ExprMatch(ref discr, ref arms) => {
1016+
ast::ExprMatch(ref discr, ref arms, _) => {
10171017
_match::trans_match(bcx, expr, &**discr, arms.as_slice(), dest)
10181018
}
10191019
ast::ExprBlock(ref blk) => {

branches/dist-snap/src/librustc/middle/typeck/check/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4144,7 +4144,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
41444144
fcx.write_nil(id);
41454145
}
41464146
}
4147-
ast::ExprMatch(ref discrim, ref arms) => {
4147+
ast::ExprMatch(ref discrim, ref arms, _) => {
41484148
_match::check_match(fcx, expr, &**discrim, arms.as_slice());
41494149
}
41504150
ast::ExprFnBlock(_, ref decl, ref body) => {

branches/dist-snap/src/librustc/middle/typeck/check/regionck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
725725
visit::walk_expr(rcx, expr);
726726
}
727727

728-
ast::ExprMatch(ref discr, ref arms) => {
728+
ast::ExprMatch(ref discr, ref arms, _) => {
729729
link_match(rcx, &**discr, arms.as_slice());
730730

731731
visit::walk_expr(rcx, expr);

branches/dist-snap/src/librustc/util/ppaux.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
9292
ast::ExprMethodCall(..) => {
9393
explain_span(cx, "method call", expr.span)
9494
},
95+
ast::ExprMatch(_, _, ast::MatchIfLetDesugar) => explain_span(cx, "if let", expr.span),
9596
ast::ExprMatch(..) => explain_span(cx, "match", expr.span),
9697
_ => explain_span(cx, "expression", expr.span)
9798
}

branches/dist-snap/src/libsyntax/ast.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ pub enum Expr_ {
529529
// Conditionless loop (can be exited with break, cont, or ret)
530530
// FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
531531
ExprLoop(P<Block>, Option<Ident>),
532-
ExprMatch(P<Expr>, Vec<Arm>),
532+
ExprMatch(P<Expr>, Vec<Arm>, MatchSource),
533533
ExprFnBlock(CaptureClause, P<FnDecl>, P<Block>),
534534
ExprProc(P<FnDecl>, P<Block>),
535535
ExprUnboxedFn(CaptureClause, UnboxedClosureKind, P<FnDecl>, P<Block>),
@@ -577,6 +577,12 @@ pub struct QPath {
577577
pub item_name: Ident,
578578
}
579579

580+
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
581+
pub enum MatchSource {
582+
MatchNormal,
583+
MatchIfLetDesugar
584+
}
585+
580586
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
581587
pub enum CaptureClause {
582588
CaptureByValue,

branches/dist-snap/src/libsyntax/config.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,10 @@ fn fold_expr(cx: &mut Context, expr: P<ast::Expr>) -> P<ast::Expr> {
210210
fold::noop_fold_expr(ast::Expr {
211211
id: id,
212212
node: match node {
213-
ast::ExprMatch(m, arms) => {
213+
ast::ExprMatch(m, arms, source) => {
214214
ast::ExprMatch(m, arms.into_iter()
215215
.filter(|a| (cx.in_cfg)(a.attrs.as_slice()))
216-
.collect())
216+
.collect(), source)
217217
}
218218
_ => node
219219
},

branches/dist-snap/src/libsyntax/ext/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
845845
}
846846

847847
fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: Vec<ast::Arm>) -> P<Expr> {
848-
self.expr(span, ast::ExprMatch(arg, arms))
848+
self.expr(span, ast::ExprMatch(arg, arms, ast::MatchNormal))
849849
}
850850

851851
fn expr_if(&self, span: Span, cond: P<ast::Expr>,

branches/dist-snap/src/libsyntax/ext/expand.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
127127
arms.push_all_move(else_if_arms);
128128
arms.push(else_arm);
129129

130-
let match_expr = fld.cx.expr_match(span, expr, arms);
130+
let match_expr = fld.cx.expr(span, ast::ExprMatch(expr, arms, ast::MatchIfLetDesugar));
131131
fld.fold_expr(match_expr)
132132
}
133133

branches/dist-snap/src/libsyntax/fold.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,9 +1226,10 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
12261226
ExprLoop(folder.fold_block(body),
12271227
opt_ident.map(|i| folder.fold_ident(i)))
12281228
}
1229-
ExprMatch(expr, arms) => {
1229+
ExprMatch(expr, arms, source) => {
12301230
ExprMatch(folder.fold_expr(expr),
1231-
arms.move_map(|x| folder.fold_arm(x)))
1231+
arms.move_map(|x| folder.fold_arm(x)),
1232+
source)
12321233
}
12331234
ExprFnBlock(capture_clause, decl, body) => {
12341235
ExprFnBlock(capture_clause,

branches/dist-snap/src/libsyntax/parse/parser.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy};
3838
use ast::{LifetimeDef, Lit, Lit_};
3939
use ast::{LitBool, LitChar, LitByte, LitBinary};
4040
use ast::{LitNil, LitStr, LitInt, Local, LocalLet};
41-
use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, Matcher, MatchNonterminal};
41+
use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, Matcher, MatchNonterminal, MatchNormal};
4242
use ast::{MatchSeq, MatchTok, Method, MutTy, BiMul, Mutability};
4343
use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot};
4444
use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct};
@@ -2973,7 +2973,7 @@ impl<'a> Parser<'a> {
29732973
}
29742974
let hi = self.span.hi;
29752975
self.bump();
2976-
return self.mk_expr(lo, hi, ExprMatch(discriminant, arms));
2976+
return self.mk_expr(lo, hi, ExprMatch(discriminant, arms, MatchNormal));
29772977
}
29782978

29792979
pub fn parse_arm(&mut self) -> Arm {

branches/dist-snap/src/libsyntax/print/pprust.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1535,7 +1535,7 @@ impl<'a> State<'a> {
15351535
try!(space(&mut self.s));
15361536
try!(self.print_block(&**blk));
15371537
}
1538-
ast::ExprMatch(ref expr, ref arms) => {
1538+
ast::ExprMatch(ref expr, ref arms, _) => {
15391539
try!(self.cbox(indent_unit));
15401540
try!(self.ibox(4));
15411541
try!(self.word_nbsp("match"));
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2014 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+
#![feature(macro_rules)]
12+
13+
fn macros() {
14+
macro_rules! foo{
15+
($p:pat, $e:expr, $b:block) => {{
16+
if let $p = $e $b
17+
}}
18+
}
19+
macro_rules! bar{
20+
($p:pat, $e:expr, $b:block) => {{
21+
foo!($p, $e, $b)
22+
}}
23+
}
24+
25+
foo!(a, 1i, { //~ ERROR irrefutable if-let
26+
println!("irrefutable pattern");
27+
});
28+
bar!(a, 1i, { //~ ERROR irrefutable if-let
29+
println!("irrefutable pattern");
30+
});
31+
}
32+
33+
pub fn main() {
34+
if let a = 1i { //~ ERROR irrefutable if-let
35+
println!("irrefutable pattern");
36+
}
37+
38+
if let a = 1i { //~ ERROR irrefutable if-let
39+
println!("irrefutable pattern");
40+
} else if true {
41+
println!("else-if in irrefutable if-let");
42+
} else {
43+
println!("else in irrefutable if-let");
44+
}
45+
46+
if let 1i = 2i {
47+
println!("refutable pattern");
48+
} else if let a = 1i { //~ ERROR irrefutable if-let
49+
println!("irrefutable pattern");
50+
}
51+
52+
if true {
53+
println!("if");
54+
} else if let a = 1i { //~ ERROR irrefutable if-let
55+
println!("irrefutable pattern");
56+
}
57+
}

branches/dist-snap/src/test/compile-fail/lint-unnecessary-parens.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ fn main() {
3232
match (true) { //~ ERROR unnecessary parentheses around `match` head expression
3333
_ => {}
3434
}
35+
if let 1i = (1i) {} //~ ERROR unnecessary parentheses around `if let` head expression
3536
let v = X { y: false };
3637
// struct lits needs parens, so these shouldn't warn.
3738
if (v == X { y: true }) {}

0 commit comments

Comments
 (0)