Skip to content

Commit c001b09

Browse files
committed
rustc_const_eval: build Pattern instead of hir::Pat for pretty-printing.
1 parent e227433 commit c001b09

File tree

3 files changed

+231
-105
lines changed

3 files changed

+231
-105
lines changed

src/librustc_const_eval/_match.rs

+62-83
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,12 @@ use rustc_data_structures::indexed_vec::Idx;
2323
use pattern::{FieldPattern, Pattern, PatternKind};
2424
use pattern::{PatternFoldable, PatternFolder};
2525

26-
use rustc::hir::def::Def;
2726
use rustc::hir::def_id::DefId;
2827
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
2928

30-
use rustc::hir;
31-
use rustc::hir::def::CtorKind;
32-
use rustc::hir::{Pat, PatKind};
29+
use rustc::mir::Field;
3330
use rustc::util::common::ErrorReported;
3431

35-
use syntax::ast::{self, DUMMY_NODE_ID};
36-
use syntax::codemap::Spanned;
37-
use syntax::ptr::P;
3832
use syntax_pos::{Span, DUMMY_SP};
3933

4034
use arena::TypedArena;
@@ -74,12 +68,6 @@ impl<'tcx> PatternFolder<'tcx> for LiteralExpander {
7468
}
7569
}
7670

77-
pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
78-
id: DUMMY_NODE_ID,
79-
node: PatKind::Wild,
80-
span: DUMMY_SP
81-
};
82-
8371
impl<'tcx> Pattern<'tcx> {
8472
fn is_wildcard(&self) -> bool {
8573
match *self.kind {
@@ -224,25 +212,34 @@ pub enum Constructor {
224212
}
225213

226214
impl<'tcx> Constructor {
227-
fn variant_for_adt(&self, adt: &'tcx ty::AdtDef) -> &'tcx ty::VariantDef {
215+
fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> usize {
228216
match self {
229-
&Variant(vid) => adt.variant_with_id(vid),
217+
&Variant(vid) => adt.variant_index_with_id(vid),
230218
&Single => {
231219
assert_eq!(adt.variants.len(), 1);
232-
&adt.variants[0]
220+
0
233221
}
234222
_ => bug!("bad constructor {:?} for adt {:?}", self, adt)
235223
}
236224
}
237225
}
238226

239-
#[derive(Clone, PartialEq)]
240-
pub enum Usefulness {
227+
#[derive(Clone)]
228+
pub enum Usefulness<'tcx> {
241229
Useful,
242-
UsefulWithWitness(Vec<Witness>),
230+
UsefulWithWitness(Vec<Witness<'tcx>>),
243231
NotUseful
244232
}
245233

234+
impl<'tcx> Usefulness<'tcx> {
235+
fn is_useful(&self) -> bool {
236+
match *self {
237+
NotUseful => false,
238+
_ => true
239+
}
240+
}
241+
}
242+
246243
#[derive(Copy, Clone)]
247244
pub enum WitnessPreference {
248245
ConstructWitness,
@@ -255,39 +252,25 @@ struct PatternContext<'tcx> {
255252
max_slice_length: usize,
256253
}
257254

258-
259-
fn const_val_to_expr(value: &ConstVal) -> P<hir::Expr> {
260-
let node = match value {
261-
&ConstVal::Bool(b) => ast::LitKind::Bool(b),
262-
_ => bug!()
263-
};
264-
P(hir::Expr {
265-
id: DUMMY_NODE_ID,
266-
node: hir::ExprLit(P(Spanned { node: node, span: DUMMY_SP })),
267-
span: DUMMY_SP,
268-
attrs: ast::ThinVec::new(),
269-
})
270-
}
271-
272255
/// A stack of patterns in reverse order of construction
273-
#[derive(Clone, PartialEq, Eq)]
274-
pub struct Witness(Vec<P<Pat>>);
256+
#[derive(Clone)]
257+
pub struct Witness<'tcx>(Vec<Pattern<'tcx>>);
275258

276-
impl Witness {
277-
pub fn single_pattern(&self) -> &Pat {
259+
impl<'tcx> Witness<'tcx> {
260+
pub fn single_pattern(&self) -> &Pattern<'tcx> {
278261
assert_eq!(self.0.len(), 1);
279262
&self.0[0]
280263
}
281264

282-
fn push_wild_constructor<'a, 'tcx>(
265+
fn push_wild_constructor<'a>(
283266
mut self,
284267
cx: &MatchCheckCtxt<'a, 'tcx>,
285268
ctor: &Constructor,
286269
ty: Ty<'tcx>)
287270
-> Self
288271
{
289272
let arity = constructor_arity(cx, ctor, ty);
290-
self.0.extend(repeat(DUMMY_WILD_PAT).take(arity).map(|p| P(p.clone())));
273+
self.0.extend(repeat(cx.wild_pattern).take(arity).cloned());
291274
self.apply_constructor(cx, ctor, ty)
292275
}
293276

@@ -305,7 +288,7 @@ impl Witness {
305288
///
306289
/// left_ty: struct X { a: (bool, &'static str), b: usize}
307290
/// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 }
308-
fn apply_constructor<'a, 'tcx>(
291+
fn apply_constructor<'a>(
309292
mut self,
310293
cx: &MatchCheckCtxt<'a,'tcx>,
311294
ctor: &Constructor,
@@ -318,60 +301,56 @@ impl Witness {
318301
let mut pats = self.0.drain(len-arity..).rev();
319302

320303
match ty.sty {
321-
ty::TyTuple(..) => PatKind::Tuple(pats.collect(), None),
322-
323-
ty::TyAdt(adt, _) => {
324-
let v = ctor.variant_for_adt(adt);
325-
let qpath = hir::QPath::Resolved(None, P(hir::Path {
326-
span: DUMMY_SP,
327-
def: Def::Err,
328-
segments: vec![hir::PathSegment::from_name(v.name)].into(),
329-
}));
330-
match v.ctor_kind {
331-
CtorKind::Fictive => {
332-
let field_pats: hir::HirVec<_> = v.fields.iter()
333-
.zip(pats)
334-
.filter(|&(_, ref pat)| pat.node != PatKind::Wild)
335-
.map(|(field, pat)| Spanned {
336-
span: DUMMY_SP,
337-
node: hir::FieldPat {
338-
name: field.name,
339-
pat: pat,
340-
is_shorthand: false,
341-
}
342-
}).collect();
343-
let has_more_fields = field_pats.len() < arity;
344-
PatKind::Struct(qpath, field_pats, has_more_fields)
304+
ty::TyAdt(..) |
305+
ty::TyTuple(..) => {
306+
let pats = pats.enumerate().map(|(i, p)| {
307+
FieldPattern {
308+
field: Field::new(i),
309+
pattern: p
345310
}
346-
CtorKind::Fn => {
347-
PatKind::TupleStruct(qpath, pats.collect(), None)
311+
}).collect();
312+
313+
if let ty::TyAdt(adt, _) = ty.sty {
314+
if adt.variants.len() > 1 {
315+
PatternKind::Variant {
316+
adt_def: adt,
317+
variant_index: ctor.variant_index_for_adt(adt),
318+
subpatterns: pats
319+
}
320+
} else {
321+
PatternKind::Leaf { subpatterns: pats }
348322
}
349-
CtorKind::Const => PatKind::Path(qpath)
323+
} else {
324+
PatternKind::Leaf { subpatterns: pats }
350325
}
351326
}
352327

353-
ty::TyRef(_, ty::TypeAndMut { mutbl, .. }) => {
354-
PatKind::Ref(pats.nth(0).unwrap(), mutbl)
328+
ty::TyRef(..) => {
329+
PatternKind::Deref { subpattern: pats.nth(0).unwrap() }
355330
}
356331

357332
ty::TySlice(_) | ty::TyArray(..) => {
358-
PatKind::Slice(pats.collect(), None, hir::HirVec::new())
333+
PatternKind::Slice {
334+
prefix: pats.collect(),
335+
slice: None,
336+
suffix: vec![]
337+
}
359338
}
360339

361340
_ => {
362341
match *ctor {
363-
ConstantValue(ref v) => PatKind::Lit(const_val_to_expr(v)),
364-
_ => PatKind::Wild,
342+
ConstantValue(ref v) => PatternKind::Constant { value: v.clone() },
343+
_ => PatternKind::Wild,
365344
}
366345
}
367346
}
368347
};
369348

370-
self.0.push(P(hir::Pat {
371-
id: DUMMY_NODE_ID,
372-
node: pat,
373-
span: DUMMY_SP
374-
}));
349+
self.0.push(Pattern {
350+
ty: ty,
351+
span: DUMMY_SP,
352+
kind: Box::new(pat),
353+
});
375354

376355
self
377356
}
@@ -528,13 +507,13 @@ pub fn is_useful<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
528507
matrix: &Matrix<'a, 'tcx>,
529508
v: &[&'a Pattern<'tcx>],
530509
witness: WitnessPreference)
531-
-> Usefulness {
510+
-> Usefulness<'tcx> {
532511
let &Matrix(ref rows) = matrix;
533512
debug!("is_useful({:?}, {:?})", matrix, v);
534513
if rows.is_empty() {
535514
return match witness {
536515
ConstructWitness => UsefulWithWitness(vec![Witness(
537-
repeat(DUMMY_WILD_PAT).take(v.len()).map(|p| P(p.clone())).collect()
516+
repeat(cx.wild_pattern).take(v.len()).cloned().collect()
538517
)]),
539518
LeaveOutWitness => Useful
540519
};
@@ -559,15 +538,15 @@ pub fn is_useful<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
559538
debug!("is_useful - expanding constructors: {:?}", constructors);
560539
constructors.into_iter().map(|c|
561540
is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
562-
).find(|result| result != &NotUseful).unwrap_or(NotUseful)
541+
).find(|result| result.is_useful()).unwrap_or(NotUseful)
563542
} else {
564543
debug!("is_useful - expanding wildcard");
565544
let constructors = missing_constructors(cx, matrix, pcx);
566545
debug!("is_useful - missing_constructors = {:?}", constructors);
567546
if constructors.is_empty() {
568547
all_constructors(cx, pcx).into_iter().map(|c| {
569548
is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
570-
}).find(|result| result != &NotUseful).unwrap_or(NotUseful)
549+
}).find(|result| result.is_useful()).unwrap_or(NotUseful)
571550
} else {
572551
let matrix = rows.iter().filter_map(|r| {
573552
if r[0].is_wildcard() {
@@ -597,7 +576,7 @@ fn is_useful_specialized<'a, 'tcx>(
597576
v: &[&'a Pattern<'tcx>],
598577
ctor: Constructor,
599578
lty: Ty<'tcx>,
600-
witness: WitnessPreference) -> Usefulness
579+
witness: WitnessPreference) -> Usefulness<'tcx>
601580
{
602581
let arity = constructor_arity(cx, &ctor, lty);
603582
let matrix = Matrix(m.iter().flat_map(|r| {
@@ -672,7 +651,7 @@ fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize
672651
},
673652
ty::TyRef(..) => 1,
674653
ty::TyAdt(adt, _) => {
675-
ctor.variant_for_adt(adt).fields.len()
654+
adt.variants[ctor.variant_index_for_adt(adt)].fields.len()
676655
}
677656
_ => 0
678657
}

src/librustc_const_eval/check_match.rs

+15-21
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@
99
// except according to those terms.
1010

1111
use _match::{MatchCheckCtxt, Matrix, expand_pattern, is_useful};
12-
use _match::{DUMMY_WILD_PAT};
1312
use _match::Usefulness::*;
1413
use _match::WitnessPreference::*;
1514

16-
use pattern::{Pattern, PatternContext, PatternError};
15+
use pattern::{Pattern, PatternContext, PatternError, PatternKind};
1716

1817
use eval::report_const_eval_err;
1918

@@ -230,9 +229,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
230229
Useful => bug!()
231230
};
232231

233-
let pattern_string = hir::print::to_string(&self.tcx.map, |s| {
234-
s.print_pat(witness[0].single_pattern())
235-
});
232+
let pattern_string = witness[0].single_pattern().to_string();
236233
let mut diag = struct_span_err!(
237234
self.tcx.sess, pat.span, E0005,
238235
"refutable pattern in {}: `{}` not covered",
@@ -369,23 +366,21 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
369366
match is_useful(cx, matrix, &[cx.wild_pattern], ConstructWitness) {
370367
UsefulWithWitness(pats) => {
371368
let witnesses = if pats.is_empty() {
372-
vec![DUMMY_WILD_PAT]
369+
vec![cx.wild_pattern]
373370
} else {
374371
pats.iter().map(|w| w.single_pattern()).collect()
375372
};
376373
match source {
377374
hir::MatchSource::ForLoopDesugar => {
378375
// `witnesses[0]` has the form `Some(<head>)`, peel off the `Some`
379-
let witness = match witnesses[0].node {
380-
PatKind::TupleStruct(_, ref pats, _) => match &pats[..] {
381-
&[ref pat] => &**pat,
376+
let witness = match *witnesses[0].kind {
377+
PatternKind::Variant { ref subpatterns, .. } => match &subpatterns[..] {
378+
&[ref pat] => &pat.pattern,
382379
_ => bug!(),
383380
},
384381
_ => bug!(),
385382
};
386-
let pattern_string = hir::print::to_string(&cx.tcx.map, |s| {
387-
s.print_pat(witness)
388-
});
383+
let pattern_string = witness.to_string();
389384
struct_span_err!(cx.tcx.sess, sp, E0297,
390385
"refutable pattern in `for` loop binding: \
391386
`{}` not covered",
@@ -394,24 +389,23 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
394389
.emit();
395390
},
396391
_ => {
397-
let pattern_strings: Vec<_> = witnesses.iter().map(|w| {
398-
hir::print::to_string(&cx.tcx.map, |s| s.print_pat(w))
399-
}).collect();
400392
const LIMIT: usize = 3;
401-
let joined_patterns = match pattern_strings.len() {
393+
let joined_patterns = match witnesses.len() {
402394
0 => bug!(),
403-
1 => format!("`{}`", pattern_strings[0]),
395+
1 => format!("`{}`", witnesses[0]),
404396
2...LIMIT => {
405-
let (tail, head) = pattern_strings.split_last().unwrap();
406-
format!("`{}`", head.join("`, `") + "` and `" + tail)
397+
let (tail, head) = witnesses.split_last().unwrap();
398+
let head: Vec<_> = head.iter().map(|w| w.to_string()).collect();
399+
format!("`{}` and `{}`", head.join("`, `"), tail)
407400
},
408401
_ => {
409-
let (head, tail) = pattern_strings.split_at(LIMIT);
402+
let (head, tail) = witnesses.split_at(LIMIT);
403+
let head: Vec<_> = head.iter().map(|w| w.to_string()).collect();
410404
format!("`{}` and {} more", head.join("`, `"), tail.len())
411405
}
412406
};
413407

414-
let label_text = match pattern_strings.len(){
408+
let label_text = match witnesses.len() {
415409
1 => format!("pattern {} not covered", joined_patterns),
416410
_ => format!("patterns {} not covered", joined_patterns)
417411
};

0 commit comments

Comments
 (0)