Skip to content

Commit 76fb7d9

Browse files
committed
remove StaticInliner and NaN checking
NaN checking was a lint for a deprecated feature. It can go away.
1 parent 37418b8 commit 76fb7d9

File tree

8 files changed

+184
-274
lines changed

8 files changed

+184
-274
lines changed

src/librustc_const_eval/_match.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,10 @@ use std::cmp::Ordering;
4040
use std::fmt;
4141
use std::iter::{FromIterator, IntoIterator, repeat};
4242

43-
pub fn lower_pat<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: &Pat)
44-
-> &'a Pattern<'tcx>
43+
pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pattern<'tcx>)
44+
-> &'a Pattern<'tcx>
4545
{
46-
cx.pattern_arena.alloc(
47-
LiteralExpander.fold_pattern(&Pattern::from_hir(cx.tcx, pat))
48-
)
46+
cx.pattern_arena.alloc(LiteralExpander.fold_pattern(&pat))
4947
}
5048

5149
struct LiteralExpander;

src/librustc_const_eval/check_match.rs

+61-153
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,19 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use _match::{MatchCheckCtxt, Matrix, lower_pat, is_useful};
11+
use _match::{MatchCheckCtxt, Matrix, expand_pattern, is_useful};
1212
use _match::{DUMMY_WILD_PAT};
1313
use _match::Usefulness::*;
1414
use _match::WitnessPreference::*;
1515

16+
use pattern::{Pattern, PatternContext, PatternError};
17+
1618
use eval::report_const_eval_err;
17-
use eval::{eval_const_expr_partial, const_expr_to_pat, lookup_const_by_id};
18-
use eval::EvalHint::ExprTypeChecked;
1919

2020
use rustc::dep_graph::DepNode;
2121

2222
use rustc::hir::pat_util::{pat_bindings, pat_contains_bindings};
2323

24-
use rustc::middle::const_val::ConstVal;
2524
use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
2625
use rustc::middle::expr_use_visitor::{LoanCause, MutateMode};
2726
use rustc::middle::expr_use_visitor as euv;
@@ -39,9 +38,7 @@ use rustc::hir::{self, Pat, PatKind};
3938
use rustc_back::slice;
4039

4140
use syntax::ast;
42-
use syntax::codemap::Spanned;
4341
use syntax::ptr::P;
44-
use syntax::util::move_map::MoveMap;
4542
use syntax_pos::Span;
4643

4744
struct OuterVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> }
@@ -80,9 +77,6 @@ impl<'a, 'v, 'tcx> Visitor<'v> for OuterVisitor<'a, 'tcx> {
8077
}
8178
}
8279

83-
impl<'a, 'tcx> OuterVisitor<'a, 'tcx> {
84-
}
85-
8680
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
8781
tcx.visit_all_items_in_krate(DepNode::MatchCheck, &mut OuterVisitor { tcx: tcx });
8882
tcx.sess.abort_if_errors();
@@ -112,8 +106,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MatchVisitor<'a, 'tcx> {
112106
fn visit_local(&mut self, loc: &hir::Local) {
113107
intravisit::walk_local(self, loc);
114108

115-
let pat = StaticInliner::new(self.tcx).fold_pat(loc.pat.clone());
116-
self.check_irrefutable(&pat, false);
109+
self.check_irrefutable(&loc.pat, false);
117110

118111
// Check legality of move bindings and `@` patterns.
119112
self.check_patterns(false, slice::ref_slice(&loc.pat));
@@ -138,6 +131,27 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
138131
}
139132
}
140133

134+
fn report_inlining_errors(&self, patcx: PatternContext, pat_span: Span) {
135+
for error in patcx.errors {
136+
match error {
137+
PatternError::BadConstInPattern(span, def_id) => {
138+
self.tcx.sess.span_err(
139+
span,
140+
&format!("constants of the type `{}` \
141+
cannot be used in patterns",
142+
self.tcx.item_path_str(def_id)));
143+
}
144+
PatternError::StaticInPattern(span) => {
145+
span_err!(self.tcx.sess, span, E0158,
146+
"statics cannot be referenced in patterns");
147+
}
148+
PatternError::ConstEval(err) => {
149+
report_const_eval_err(self.tcx, &err, pat_span, "pattern").emit();
150+
}
151+
}
152+
}
153+
}
154+
141155
fn check_match(
142156
&self,
143157
scrut: &hir::Expr,
@@ -154,32 +168,36 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
154168
if let Some(ref guard) = arm.guard {
155169
check_for_mutation_in_guard(self, &guard);
156170
}
157-
}
158-
159-
let mut static_inliner = StaticInliner::new(self.tcx);
160-
let inlined_arms = arms.iter().map(|arm| {
161-
(arm.pats.iter().map(|pat| {
162-
static_inliner.fold_pat((*pat).clone())
163-
}).collect(), arm.guard.as_ref().map(|e| &**e))
164-
}).collect::<Vec<(Vec<P<Pat>>, Option<&hir::Expr>)>>();
165171

166-
// Bail out early if inlining failed.
167-
if static_inliner.failed {
168-
return;
172+
// Third, perform some lints.
173+
for pat in &arm.pats {
174+
check_for_bindings_named_the_same_as_variants(self, pat);
175+
}
169176
}
170177

171-
for pat in inlined_arms.iter().flat_map(|&(ref pats, _)| pats) {
172-
// Fourth, check if there are any references to NaN that we should warn about.
173-
check_for_static_nan(self, &pat);
178+
MatchCheckCtxt::create_and_enter(self.tcx, |ref cx| {
179+
let mut have_errors = false;
180+
181+
let inlined_arms : Vec<(Vec<_>, _)> = arms.iter().map(|arm| (
182+
arm.pats.iter().map(|pat| {
183+
let mut patcx = PatternContext::new(self.tcx);
184+
let pattern = expand_pattern(cx, patcx.lower_pattern(&pat));
185+
if !patcx.errors.is_empty() {
186+
self.report_inlining_errors(patcx, pat.span);
187+
have_errors = true;
188+
}
189+
(pattern, &**pat)
190+
}).collect(),
191+
arm.guard.as_ref().map(|e| &**e)
192+
)).collect();
174193

175-
// Fifth, check if for any of the patterns that match an enumerated type
176-
// are bindings with the same name as one of the variants of said type.
177-
check_for_bindings_named_the_same_as_variants(self, &pat);
178-
}
194+
// Bail out early if inlining failed.
195+
if have_errors {
196+
return;
197+
}
179198

180-
MatchCheckCtxt::create_and_enter(self.tcx, |ref cx| {
181199
// Fourth, check for unreachable arms.
182-
check_arms(cx, &inlined_arms[..], source);
200+
check_arms(cx, &inlined_arms, source);
183201

184202
// Finally, check if the whole match expression is exhaustive.
185203
// Check for empty enum, because is_useful only works on inhabited types.
@@ -204,7 +222,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
204222
.iter()
205223
.filter(|&&(_, guard)| guard.is_none())
206224
.flat_map(|arm| &arm.0)
207-
.map(|pat| vec![lower_pat(cx, &pat)])
225+
.map(|pat| vec![pat.0])
208226
.collect();
209227
check_exhaustive(cx, scrut.span, &matrix, source);
210228
})
@@ -218,8 +236,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
218236
};
219237

220238
MatchCheckCtxt::create_and_enter(self.tcx, |ref cx| {
239+
let mut patcx = PatternContext::new(self.tcx);
221240
let pats : Matrix = vec![vec![
222-
lower_pat(cx, pat)
241+
expand_pattern(cx, patcx.lower_pattern(pat))
223242
]].into_iter().collect();
224243

225244
let witness = match is_useful(cx, &pats, &[cx.wild_pattern], ConstructWitness) {
@@ -269,27 +288,6 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) {
269288
});
270289
}
271290

272-
// Check that we do not match against a static NaN (#6804)
273-
fn check_for_static_nan(cx: &MatchVisitor, pat: &Pat) {
274-
pat.walk(|p| {
275-
if let PatKind::Lit(ref expr) = p.node {
276-
match eval_const_expr_partial(cx.tcx, &expr, ExprTypeChecked, None) {
277-
Ok(ConstVal::Float(f)) if f.is_nan() => {
278-
span_warn!(cx.tcx.sess, p.span, E0003,
279-
"unmatchable NaN in pattern, \
280-
use the is_nan method in a guard instead");
281-
}
282-
Ok(_) => {}
283-
284-
Err(err) => {
285-
report_const_eval_err(cx.tcx, &err, p.span, "pattern").emit();
286-
}
287-
}
288-
}
289-
true
290-
});
291-
}
292-
293291
/// Checks for common cases of "catchall" patterns that may not be intended as such.
294292
fn pat_is_catchall(dm: &DefMap, pat: &Pat) -> bool {
295293
match pat.node {
@@ -304,15 +302,16 @@ fn pat_is_catchall(dm: &DefMap, pat: &Pat) -> bool {
304302
}
305303

306304
// Check for unreachable patterns
307-
fn check_arms(cx: &MatchCheckCtxt,
308-
arms: &[(Vec<P<Pat>>, Option<&hir::Expr>)],
309-
source: hir::MatchSource) {
305+
fn check_arms<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
306+
arms: &[(Vec<(&Pattern<'tcx>, &'a hir::Pat)>, Option<&hir::Expr>)],
307+
source: hir::MatchSource)
308+
{
310309
let mut seen = Matrix::empty();
311310
let mut catchall = None;
312311
let mut printed_if_let_err = false;
313312
for &(ref pats, guard) in arms {
314-
for pat in pats {
315-
let v = vec![lower_pat(cx, &pat)];
313+
for &(pat, hir_pat) in pats {
314+
let v = vec![pat];
316315

317316
match is_useful(cx, &seen, &v[..], LeaveOutWitness) {
318317
NotUseful => {
@@ -325,7 +324,7 @@ fn check_arms(cx: &MatchCheckCtxt,
325324
// find the first arm pattern so we can use its span
326325
let &(ref first_arm_pats, _) = &arms[0];
327326
let first_pat = &first_arm_pats[0];
328-
let span = first_pat.span;
327+
let span = first_pat.0.span;
329328
struct_span_err!(cx.tcx.sess, span, E0162,
330329
"irrefutable if-let pattern")
331330
.span_label(span, &format!("irrefutable pattern"))
@@ -338,7 +337,7 @@ fn check_arms(cx: &MatchCheckCtxt,
338337
// find the first arm pattern so we can use its span
339338
let &(ref first_arm_pats, _) = &arms[0];
340339
let first_pat = &first_arm_pats[0];
341-
let span = first_pat.span;
340+
let span = first_pat.0.span;
342341
struct_span_err!(cx.tcx.sess, span, E0165,
343342
"irrefutable while-let pattern")
344343
.span_label(span, &format!("irrefutable pattern"))
@@ -374,7 +373,7 @@ fn check_arms(cx: &MatchCheckCtxt,
374373
}
375374
if guard.is_none() {
376375
seen.push(v);
377-
if catchall.is_none() && pat_is_catchall(&cx.tcx.def_map.borrow(), pat) {
376+
if catchall.is_none() && pat_is_catchall(&cx.tcx.def_map.borrow(), hir_pat) {
378377
catchall = Some(pat.span);
379378
}
380379
}
@@ -448,97 +447,6 @@ fn check_exhaustive<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
448447
}
449448
}
450449

451-
452-
struct StaticInliner<'a, 'tcx: 'a> {
453-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
454-
failed: bool
455-
}
456-
457-
impl<'a, 'tcx> StaticInliner<'a, 'tcx> {
458-
pub fn new<'b>(tcx: TyCtxt<'b, 'tcx, 'tcx>) -> StaticInliner<'b, 'tcx> {
459-
StaticInliner {
460-
tcx: tcx,
461-
failed: false
462-
}
463-
}
464-
}
465-
466-
impl<'a, 'tcx> StaticInliner<'a, 'tcx> {
467-
fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
468-
match pat.node {
469-
PatKind::Path(..) => {
470-
match self.tcx.expect_def(pat.id) {
471-
Def::AssociatedConst(did) | Def::Const(did) => {
472-
let substs = Some(self.tcx.node_id_item_substs(pat.id).substs);
473-
if let Some((const_expr, _)) = lookup_const_by_id(self.tcx, did, substs) {
474-
match const_expr_to_pat(self.tcx, const_expr, pat.id, pat.span) {
475-
Ok(new_pat) => return new_pat,
476-
Err(def_id) => {
477-
self.failed = true;
478-
self.tcx.sess.span_err(
479-
pat.span,
480-
&format!("constants of the type `{}` \
481-
cannot be used in patterns",
482-
self.tcx.item_path_str(def_id)));
483-
}
484-
}
485-
} else {
486-
self.failed = true;
487-
span_err!(self.tcx.sess, pat.span, E0158,
488-
"statics cannot be referenced in patterns");
489-
}
490-
}
491-
_ => {}
492-
}
493-
}
494-
_ => {}
495-
}
496-
497-
pat.map(|Pat { id, node, span }| {
498-
let node = match node {
499-
PatKind::Binding(binding_mode, pth1, sub) => {
500-
PatKind::Binding(binding_mode, pth1, sub.map(|x| self.fold_pat(x)))
501-
}
502-
PatKind::TupleStruct(pth, pats, ddpos) => {
503-
PatKind::TupleStruct(pth, pats.move_map(|x| self.fold_pat(x)), ddpos)
504-
}
505-
PatKind::Struct(pth, fields, etc) => {
506-
let fs = fields.move_map(|f| {
507-
Spanned {
508-
span: f.span,
509-
node: hir::FieldPat {
510-
name: f.node.name,
511-
pat: self.fold_pat(f.node.pat),
512-
is_shorthand: f.node.is_shorthand,
513-
},
514-
}
515-
});
516-
PatKind::Struct(pth, fs, etc)
517-
}
518-
PatKind::Tuple(elts, ddpos) => {
519-
PatKind::Tuple(elts.move_map(|x| self.fold_pat(x)), ddpos)
520-
}
521-
PatKind::Box(inner) => PatKind::Box(self.fold_pat(inner)),
522-
PatKind::Ref(inner, mutbl) => PatKind::Ref(self.fold_pat(inner), mutbl),
523-
PatKind::Slice(before, slice, after) => {
524-
PatKind::Slice(before.move_map(|x| self.fold_pat(x)),
525-
slice.map(|x| self.fold_pat(x)),
526-
after.move_map(|x| self.fold_pat(x)))
527-
}
528-
PatKind::Wild |
529-
PatKind::Lit(_) |
530-
PatKind::Range(..) |
531-
PatKind::Path(..) => node
532-
};
533-
Pat {
534-
id: id,
535-
node: node,
536-
span: span
537-
}
538-
})
539-
}
540-
}
541-
542450
// Legality of move bindings checking
543451
fn check_legality_of_move_bindings(cx: &MatchVisitor,
544452
has_guard: bool,

src/librustc_const_eval/diagnostics.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ fn foo(x: Option<String>) {
7171
"##,*/
7272

7373

74-
E0003: r##"
74+
/*E0003: r##"
7575
Not-a-Number (NaN) values cannot be compared for equality and hence can never
7676
match the input to a match expression. So, the following will not compile:
7777
@@ -100,7 +100,7 @@ match number {
100100
}
101101
```
102102
"##,
103-
103+
*/
104104

105105
E0004: r##"
106106
This error indicates that the compiler cannot guarantee a matching pattern for

0 commit comments

Comments
 (0)