Skip to content

Commit df61658

Browse files
committed
Auto merge of #38766 - eddyb:less-fake-hir, r=arielb1
Stop creating fake HIR pattern nodes. This replaces all the HIR patterns `rustc_const_eval` creates with the more appropriate HAIR equivalent. The only place left that creates HIR nodes is the "explicit lifetimes in function signature" suggestion, which only creates type nodes while rebuilding the signature, but that is only in case of an error. cc @arielb1
2 parents 07191e2 + c6e130e commit df61658

File tree

4 files changed

+411
-293
lines changed

4 files changed

+411
-293
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-28
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

@@ -117,13 +116,6 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
117116
fn report_inlining_errors(&self, patcx: PatternContext, pat_span: Span) {
118117
for error in patcx.errors {
119118
match error {
120-
PatternError::BadConstInPattern(span, def_id) => {
121-
self.tcx.sess.span_err(
122-
span,
123-
&format!("constants of the type `{}` \
124-
cannot be used in patterns",
125-
self.tcx.item_path_str(def_id)));
126-
}
127119
PatternError::StaticInPattern(span) => {
128120
span_err!(self.tcx.sess, span, E0158,
129121
"statics cannot be referenced in patterns");
@@ -230,9 +222,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
230222
Useful => bug!()
231223
};
232224

233-
let pattern_string = hir::print::to_string(&self.tcx.map, |s| {
234-
s.print_pat(witness[0].single_pattern())
235-
});
225+
let pattern_string = witness[0].single_pattern().to_string();
236226
let mut diag = struct_span_err!(
237227
self.tcx.sess, pat.span, E0005,
238228
"refutable pattern in {}: `{}` not covered",
@@ -369,23 +359,21 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
369359
match is_useful(cx, matrix, &[cx.wild_pattern], ConstructWitness) {
370360
UsefulWithWitness(pats) => {
371361
let witnesses = if pats.is_empty() {
372-
vec![DUMMY_WILD_PAT]
362+
vec![cx.wild_pattern]
373363
} else {
374364
pats.iter().map(|w| w.single_pattern()).collect()
375365
};
376366
match source {
377367
hir::MatchSource::ForLoopDesugar => {
378368
// `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,
369+
let witness = match *witnesses[0].kind {
370+
PatternKind::Variant { ref subpatterns, .. } => match &subpatterns[..] {
371+
&[ref pat] => &pat.pattern,
382372
_ => bug!(),
383373
},
384374
_ => bug!(),
385375
};
386-
let pattern_string = hir::print::to_string(&cx.tcx.map, |s| {
387-
s.print_pat(witness)
388-
});
376+
let pattern_string = witness.to_string();
389377
struct_span_err!(cx.tcx.sess, sp, E0297,
390378
"refutable pattern in `for` loop binding: \
391379
`{}` not covered",
@@ -394,24 +382,23 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
394382
.emit();
395383
},
396384
_ => {
397-
let pattern_strings: Vec<_> = witnesses.iter().map(|w| {
398-
hir::print::to_string(&cx.tcx.map, |s| s.print_pat(w))
399-
}).collect();
400385
const LIMIT: usize = 3;
401-
let joined_patterns = match pattern_strings.len() {
386+
let joined_patterns = match witnesses.len() {
402387
0 => bug!(),
403-
1 => format!("`{}`", pattern_strings[0]),
388+
1 => format!("`{}`", witnesses[0]),
404389
2...LIMIT => {
405-
let (tail, head) = pattern_strings.split_last().unwrap();
406-
format!("`{}`", head.join("`, `") + "` and `" + tail)
390+
let (tail, head) = witnesses.split_last().unwrap();
391+
let head: Vec<_> = head.iter().map(|w| w.to_string()).collect();
392+
format!("`{}` and `{}`", head.join("`, `"), tail)
407393
},
408394
_ => {
409-
let (head, tail) = pattern_strings.split_at(LIMIT);
395+
let (head, tail) = witnesses.split_at(LIMIT);
396+
let head: Vec<_> = head.iter().map(|w| w.to_string()).collect();
410397
format!("`{}` and {} more", head.join("`, `"), tail.len())
411398
}
412399
};
413400

414-
let label_text = match pattern_strings.len(){
401+
let label_text = match witnesses.len() {
415402
1 => format!("pattern {} not covered", joined_patterns),
416403
_ => format!("patterns {} not covered", joined_patterns)
417404
};

0 commit comments

Comments
 (0)