mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 06:51:58 +00:00
parent
a12a4ddcfa
commit
d283574558
@ -139,7 +139,6 @@ register_diagnostics!(
|
||||
E0120,
|
||||
E0121,
|
||||
E0122,
|
||||
E0123,
|
||||
E0124,
|
||||
E0125,
|
||||
E0126,
|
||||
@ -173,5 +172,6 @@ register_diagnostics!(
|
||||
E0154,
|
||||
E0155,
|
||||
E0156,
|
||||
E0157
|
||||
E0157,
|
||||
E0158
|
||||
)
|
||||
|
@ -23,7 +23,7 @@ use std::gc::{Gc, GC};
|
||||
use std::iter::AdditiveIterator;
|
||||
use std::iter::range_inclusive;
|
||||
use syntax::ast::*;
|
||||
use syntax::ast_util::{is_unguarded, walk_pat};
|
||||
use syntax::ast_util::walk_pat;
|
||||
use syntax::codemap::{Span, Spanned, DUMMY_SP};
|
||||
use syntax::fold::{Folder, noop_fold_pat};
|
||||
use syntax::print::pprust::pat_to_string;
|
||||
@ -159,13 +159,31 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
|
||||
}
|
||||
}
|
||||
|
||||
// Third, check for unreachable arms.
|
||||
check_arms(cx, arms.as_slice());
|
||||
let mut static_inliner = StaticInliner::new(cx.tcx);
|
||||
let inlined_arms = arms
|
||||
.iter()
|
||||
.map(|arm| Arm {
|
||||
pats: arm.pats.iter().map(|pat| {
|
||||
static_inliner.fold_pat(*pat)
|
||||
}).collect(),
|
||||
..arm.clone()
|
||||
})
|
||||
.collect::<Vec<Arm>>();
|
||||
|
||||
if static_inliner.failed {
|
||||
return;
|
||||
}
|
||||
|
||||
// Third, check if there are any references to NaN that we should warn about.
|
||||
check_for_static_nan(cx, inlined_arms.as_slice());
|
||||
|
||||
// Fourth, check for unreachable arms.
|
||||
check_arms(cx, inlined_arms.as_slice());
|
||||
|
||||
// Finally, check if the whole match expression is exhaustive.
|
||||
// Check for empty enum, because is_useful only works on inhabited types.
|
||||
let pat_ty = node_id_to_type(cx.tcx, scrut.id);
|
||||
if arms.is_empty() {
|
||||
if inlined_arms.is_empty() {
|
||||
if !type_is_empty(cx.tcx, pat_ty) {
|
||||
// We know the type is inhabited, so this must be wrong
|
||||
span_err!(cx.tcx.sess, ex.span, E0002,
|
||||
@ -177,19 +195,16 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut static_inliner = StaticInliner { tcx: cx.tcx };
|
||||
let matrix: Matrix = arms
|
||||
.iter()
|
||||
.filter(|&arm| is_unguarded(arm))
|
||||
.flat_map(|arm| arm.pats.iter())
|
||||
.map(|pat| vec![static_inliner.fold_pat(*pat)])
|
||||
let matrix: Matrix = inlined_arms
|
||||
.move_iter()
|
||||
.filter(|arm| arm.guard.is_none())
|
||||
.flat_map(|arm| arm.pats.move_iter())
|
||||
.map(|pat| vec![pat])
|
||||
.collect();
|
||||
check_exhaustive(cx, ex.span, &matrix);
|
||||
},
|
||||
ExprForLoop(ref pat, _, _, _) => {
|
||||
let mut static_inliner = StaticInliner {
|
||||
tcx: cx.tcx
|
||||
};
|
||||
let mut static_inliner = StaticInliner::new(cx.tcx);
|
||||
match is_refutable(cx, static_inliner.fold_pat(*pat)) {
|
||||
Some(uncovered_pat) => {
|
||||
cx.tcx.sess.span_err(
|
||||
@ -216,19 +231,14 @@ fn is_expr_const_nan(tcx: &ty::ctxt, expr: &Expr) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
// Check for unreachable patterns
|
||||
fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
|
||||
let mut seen = Matrix(vec!());
|
||||
let mut static_inliner = StaticInliner { tcx: cx.tcx };
|
||||
// Check that we do not match against a static NaN (#6804)
|
||||
fn check_for_static_nan(cx: &MatchCheckCtxt, arms: &[Arm]) {
|
||||
for arm in arms.iter() {
|
||||
for pat in arm.pats.iter() {
|
||||
let inlined = static_inliner.fold_pat(*pat);
|
||||
|
||||
// Check that we do not match against a static NaN (#6804)
|
||||
walk_pat(&*inlined, |p| {
|
||||
for &pat in arm.pats.iter() {
|
||||
walk_pat(&*pat, |p| {
|
||||
match p.node {
|
||||
PatLit(expr) if is_expr_const_nan(cx.tcx, &*expr) => {
|
||||
span_warn!(cx.tcx.sess, pat.span, E0003,
|
||||
span_warn!(cx.tcx.sess, p.span, E0003,
|
||||
"unmatchable NaN in pattern, \
|
||||
use the is_nan method in a guard instead");
|
||||
}
|
||||
@ -236,8 +246,16 @@ fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
|
||||
}
|
||||
true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let v = vec![inlined];
|
||||
// Check for unreachable patterns
|
||||
fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
|
||||
let mut seen = Matrix(vec!());
|
||||
for arm in arms.iter() {
|
||||
for &pat in arm.pats.iter() {
|
||||
let v = vec![pat];
|
||||
match is_useful(cx, &seen, v.as_slice(), LeaveOutWitness) {
|
||||
NotUseful => span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern"),
|
||||
Useful => (),
|
||||
@ -293,7 +311,17 @@ fn const_val_to_expr(value: &const_val) -> Gc<Expr> {
|
||||
}
|
||||
|
||||
pub struct StaticInliner<'a> {
|
||||
pub tcx: &'a ty::ctxt
|
||||
pub tcx: &'a ty::ctxt,
|
||||
pub failed: bool
|
||||
}
|
||||
|
||||
impl<'a> StaticInliner<'a> {
|
||||
pub fn new<'a>(tcx: &'a ty::ctxt) -> StaticInliner<'a> {
|
||||
StaticInliner {
|
||||
tcx: tcx,
|
||||
failed: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Folder for StaticInliner<'a> {
|
||||
@ -302,9 +330,17 @@ impl<'a> Folder for StaticInliner<'a> {
|
||||
PatIdent(..) | PatEnum(..) => {
|
||||
let def = self.tcx.def_map.borrow().find_copy(&pat.id);
|
||||
match def {
|
||||
Some(DefStatic(did, _)) => {
|
||||
let const_expr = lookup_const_by_id(self.tcx, did).unwrap();
|
||||
const_expr_to_pat(self.tcx, const_expr)
|
||||
Some(DefStatic(did, _)) => match lookup_const_by_id(self.tcx, did) {
|
||||
Some(const_expr) => box (GC) Pat {
|
||||
span: pat.span,
|
||||
..(*const_expr_to_pat(self.tcx, const_expr)).clone()
|
||||
},
|
||||
None => {
|
||||
self.failed = true;
|
||||
span_err!(self.tcx.sess, pat.span, E0158,
|
||||
"extern statics cannot be referenced in patterns");
|
||||
pat
|
||||
}
|
||||
},
|
||||
_ => noop_fold_pat(pat, self)
|
||||
}
|
||||
@ -813,7 +849,7 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &Local) {
|
||||
LocalFor => "`for` loop"
|
||||
};
|
||||
|
||||
let mut static_inliner = StaticInliner { tcx: cx.tcx };
|
||||
let mut static_inliner = StaticInliner::new(cx.tcx);
|
||||
match is_refutable(cx, static_inliner.fold_pat(loc.pat)) {
|
||||
Some(pat) => {
|
||||
span_err!(cx.tcx.sess, loc.pat.span, E0005,
|
||||
|
@ -1422,7 +1422,7 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
|
||||
bindings_map: create_bindings_map(bcx, *arm.pats.get(0), discr_expr, &*arm.body)
|
||||
}).collect();
|
||||
|
||||
let mut static_inliner = StaticInliner { tcx: scope_cx.tcx() };
|
||||
let mut static_inliner = StaticInliner::new(scope_cx.tcx());
|
||||
let mut matches = Vec::new();
|
||||
for arm_data in arm_datas.iter() {
|
||||
matches.extend(arm_data.arm.pats.iter().map(|&p| Match {
|
||||
|
@ -209,21 +209,6 @@ pub fn name_to_dummy_lifetime(name: Name) -> Lifetime {
|
||||
name: name }
|
||||
}
|
||||
|
||||
pub fn is_unguarded(a: &Arm) -> bool {
|
||||
match a.guard {
|
||||
None => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unguarded_pat(a: &Arm) -> Option<Vec<Gc<Pat>>> {
|
||||
if is_unguarded(a) {
|
||||
Some(/* FIXME (#2543) */ a.pats.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a "pretty" name for an `impl` from its type and trait.
|
||||
/// This is designed so that symbols of `impl`'d methods give some
|
||||
/// hint of where they came from, (previously they would all just be
|
||||
|
22
src/test/compile-fail/issue-16149.rs
Normal file
22
src/test/compile-fail/issue-16149.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
extern {
|
||||
static externalValue: int;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let boolValue = match 42 {
|
||||
externalValue => true,
|
||||
//~^ ERROR extern statics cannot be referenced in patterns
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user