]> git.lizzy.rs Git - rust.git/blob - src/librustc_const_eval/pattern.rs
Rollup merge of #42925 - tbu-:pr_document_file_open_errors, r=GuillaumeGomez
[rust.git] / src / librustc_const_eval / pattern.rs
1 // Copyright 2016 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 use eval;
12
13 use rustc::middle::const_val::{ConstEvalErr, ConstVal};
14 use rustc::mir::{Field, BorrowKind, Mutability};
15 use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
16 use rustc::ty::subst::{Substs, Kind};
17 use rustc::hir::{self, PatKind, RangeEnd};
18 use rustc::hir::def::{Def, CtorKind};
19 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
20
21 use rustc_data_structures::indexed_vec::Idx;
22
23 use std::fmt;
24 use syntax::ast;
25 use syntax::ptr::P;
26 use syntax_pos::Span;
27
28 #[derive(Clone, Debug)]
29 pub enum PatternError<'tcx> {
30     StaticInPattern(Span),
31     ConstEval(ConstEvalErr<'tcx>),
32 }
33
34 #[derive(Copy, Clone, Debug)]
35 pub enum BindingMode<'tcx> {
36     ByValue,
37     ByRef(Region<'tcx>, BorrowKind),
38 }
39
40 #[derive(Clone, Debug)]
41 pub struct FieldPattern<'tcx> {
42     pub field: Field,
43     pub pattern: Pattern<'tcx>,
44 }
45
46 #[derive(Clone, Debug)]
47 pub struct Pattern<'tcx> {
48     pub ty: Ty<'tcx>,
49     pub span: Span,
50     pub kind: Box<PatternKind<'tcx>>,
51 }
52
53 #[derive(Clone, Debug)]
54 pub enum PatternKind<'tcx> {
55     Wild,
56
57     /// x, ref x, x @ P, etc
58     Binding {
59         mutability: Mutability,
60         name: ast::Name,
61         mode: BindingMode<'tcx>,
62         var: ast::NodeId,
63         ty: Ty<'tcx>,
64         subpattern: Option<Pattern<'tcx>>,
65     },
66
67     /// Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
68     Variant {
69         adt_def: &'tcx AdtDef,
70         substs: &'tcx Substs<'tcx>,
71         variant_index: usize,
72         subpatterns: Vec<FieldPattern<'tcx>>,
73     },
74
75     /// (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
76     Leaf {
77         subpatterns: Vec<FieldPattern<'tcx>>,
78     },
79
80     /// box P, &P, &mut P, etc
81     Deref {
82         subpattern: Pattern<'tcx>,
83     },
84
85     Constant {
86         value: ConstVal<'tcx>,
87     },
88
89     Range {
90         lo: ConstVal<'tcx>,
91         hi: ConstVal<'tcx>,
92         end: RangeEnd,
93     },
94
95     /// matches against a slice, checking the length and extracting elements
96     Slice {
97         prefix: Vec<Pattern<'tcx>>,
98         slice: Option<Pattern<'tcx>>,
99         suffix: Vec<Pattern<'tcx>>,
100     },
101
102     /// fixed match against an array, irrefutable
103     Array {
104         prefix: Vec<Pattern<'tcx>>,
105         slice: Option<Pattern<'tcx>>,
106         suffix: Vec<Pattern<'tcx>>,
107     },
108 }
109
110 fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result {
111     match *value {
112         ConstVal::Float(ref x) => write!(f, "{}", x),
113         ConstVal::Integral(ref i) => write!(f, "{}", i),
114         ConstVal::Str(ref s) => write!(f, "{:?}", &s[..]),
115         ConstVal::ByteStr(ref b) => write!(f, "{:?}", &b[..]),
116         ConstVal::Bool(b) => write!(f, "{:?}", b),
117         ConstVal::Char(c) => write!(f, "{:?}", c),
118         ConstVal::Variant(_) |
119         ConstVal::Struct(_) |
120         ConstVal::Tuple(_) |
121         ConstVal::Function(..) |
122         ConstVal::Array(..) |
123         ConstVal::Repeat(..) => bug!("{:?} not printable in a pattern", value)
124     }
125 }
126
127 impl<'tcx> fmt::Display for Pattern<'tcx> {
128     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129         match *self.kind {
130             PatternKind::Wild => write!(f, "_"),
131             PatternKind::Binding { mutability, name, mode, ref subpattern, .. } => {
132                 let is_mut = match mode {
133                     BindingMode::ByValue => mutability == Mutability::Mut,
134                     BindingMode::ByRef(_, bk) => {
135                         write!(f, "ref ")?;
136                         bk == BorrowKind::Mut
137                     }
138                 };
139                 if is_mut {
140                     write!(f, "mut ")?;
141                 }
142                 write!(f, "{}", name)?;
143                 if let Some(ref subpattern) = *subpattern {
144                     write!(f, " @ {}", subpattern)?;
145                 }
146                 Ok(())
147             }
148             PatternKind::Variant { ref subpatterns, .. } |
149             PatternKind::Leaf { ref subpatterns } => {
150                 let variant = match *self.kind {
151                     PatternKind::Variant { adt_def, variant_index, .. } => {
152                         Some(&adt_def.variants[variant_index])
153                     }
154                     _ => if let ty::TyAdt(adt, _) = self.ty.sty {
155                         if adt.is_univariant() {
156                             Some(&adt.variants[0])
157                         } else {
158                             None
159                         }
160                     } else {
161                         None
162                     }
163                 };
164
165                 let mut first = true;
166                 let mut start_or_continue = || if first { first = false; "" } else { ", " };
167
168                 if let Some(variant) = variant {
169                     write!(f, "{}", variant.name)?;
170
171                     // Only for TyAdt we can have `S {...}`,
172                     // which we handle separately here.
173                     if variant.ctor_kind == CtorKind::Fictive {
174                         write!(f, " {{ ")?;
175
176                         let mut printed = 0;
177                         for p in subpatterns {
178                             if let PatternKind::Wild = *p.pattern.kind {
179                                 continue;
180                             }
181                             let name = variant.fields[p.field.index()].name;
182                             write!(f, "{}{}: {}", start_or_continue(), name, p.pattern)?;
183                             printed += 1;
184                         }
185
186                         if printed < variant.fields.len() {
187                             write!(f, "{}..", start_or_continue())?;
188                         }
189
190                         return write!(f, " }}");
191                     }
192                 }
193
194                 let num_fields = variant.map_or(subpatterns.len(), |v| v.fields.len());
195                 if num_fields != 0 || variant.is_none() {
196                     write!(f, "(")?;
197                     for i in 0..num_fields {
198                         write!(f, "{}", start_or_continue())?;
199
200                         // Common case: the field is where we expect it.
201                         if let Some(p) = subpatterns.get(i) {
202                             if p.field.index() == i {
203                                 write!(f, "{}", p.pattern)?;
204                                 continue;
205                             }
206                         }
207
208                         // Otherwise, we have to go looking for it.
209                         if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
210                             write!(f, "{}", p.pattern)?;
211                         } else {
212                             write!(f, "_")?;
213                         }
214                     }
215                     write!(f, ")")?;
216                 }
217
218                 Ok(())
219             }
220             PatternKind::Deref { ref subpattern } => {
221                 match self.ty.sty {
222                     ty::TyAdt(def, _) if def.is_box() => write!(f, "box ")?,
223                     ty::TyRef(_, mt) => {
224                         write!(f, "&")?;
225                         if mt.mutbl == hir::MutMutable {
226                             write!(f, "mut ")?;
227                         }
228                     }
229                     _ => bug!("{} is a bad Deref pattern type", self.ty)
230                 }
231                 write!(f, "{}", subpattern)
232             }
233             PatternKind::Constant { ref value } => {
234                 print_const_val(value, f)
235             }
236             PatternKind::Range { ref lo, ref hi, ref end } => {
237                 print_const_val(lo, f)?;
238                 match *end {
239                     RangeEnd::Included => write!(f, "...")?,
240                     RangeEnd::Excluded => write!(f, "..")?,
241                 }
242                 print_const_val(hi, f)
243             }
244             PatternKind::Slice { ref prefix, ref slice, ref suffix } |
245             PatternKind::Array { ref prefix, ref slice, ref suffix } => {
246                 let mut first = true;
247                 let mut start_or_continue = || if first { first = false; "" } else { ", " };
248                 write!(f, "[")?;
249                 for p in prefix {
250                     write!(f, "{}{}", start_or_continue(), p)?;
251                 }
252                 if let Some(ref slice) = *slice {
253                     write!(f, "{}", start_or_continue())?;
254                     match *slice.kind {
255                         PatternKind::Wild => {}
256                         _ => write!(f, "{}", slice)?
257                     }
258                     write!(f, "..")?;
259                 }
260                 for p in suffix {
261                     write!(f, "{}{}", start_or_continue(), p)?;
262                 }
263                 write!(f, "]")
264             }
265         }
266     }
267 }
268
269 pub struct PatternContext<'a, 'gcx: 'tcx, 'tcx: 'a> {
270     pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
271     pub tables: &'a ty::TypeckTables<'gcx>,
272     pub errors: Vec<PatternError<'tcx>>,
273 }
274
275 impl<'a, 'gcx, 'tcx> Pattern<'tcx> {
276     pub fn from_hir(tcx: TyCtxt<'a, 'gcx, 'tcx>,
277                     tables: &'a ty::TypeckTables<'gcx>,
278                     pat: &hir::Pat) -> Self {
279         let mut pcx = PatternContext::new(tcx, tables);
280         let result = pcx.lower_pattern(pat);
281         if !pcx.errors.is_empty() {
282             span_bug!(pat.span, "encountered errors lowering pattern: {:?}", pcx.errors)
283         }
284         debug!("Pattern::from_hir({:?}) = {:?}", pat, result);
285         result
286     }
287 }
288
289 impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
290     pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, tables: &'a ty::TypeckTables<'gcx>) -> Self {
291         PatternContext { tcx: tcx, tables: tables, errors: vec![] }
292     }
293
294     pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
295         let mut ty = self.tables.node_id_to_type(pat.id);
296
297         let kind = match pat.node {
298             PatKind::Wild => PatternKind::Wild,
299
300             PatKind::Lit(ref value) => self.lower_lit(value),
301
302             PatKind::Range(ref lo, ref hi, ref end) => {
303                 match (self.lower_lit(lo), self.lower_lit(hi)) {
304                     (PatternKind::Constant { value: lo },
305                      PatternKind::Constant { value: hi }) => {
306                         PatternKind::Range { lo: lo, hi: hi, end: end.clone() }
307                     }
308                     _ => PatternKind::Wild
309                 }
310             }
311
312             PatKind::Path(ref qpath) => {
313                 return self.lower_path(qpath, pat.id, pat.id, pat.span);
314             }
315
316             PatKind::Ref(ref subpattern, _) |
317             PatKind::Box(ref subpattern) => {
318                 PatternKind::Deref { subpattern: self.lower_pattern(subpattern) }
319             }
320
321             PatKind::Slice(ref prefix, ref slice, ref suffix) => {
322                 let ty = self.tables.node_id_to_type(pat.id);
323                 match ty.sty {
324                     ty::TyRef(_, mt) =>
325                         PatternKind::Deref {
326                             subpattern: Pattern {
327                                 ty: mt.ty,
328                                 span: pat.span,
329                                 kind: Box::new(self.slice_or_array_pattern(
330                                     pat.span, mt.ty, prefix, slice, suffix))
331                             },
332                         },
333
334                     ty::TySlice(..) |
335                     ty::TyArray(..) =>
336                         self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix),
337
338                     ref sty =>
339                         span_bug!(
340                             pat.span,
341                             "unexpanded type for vector pattern: {:?}",
342                             sty),
343                 }
344             }
345
346             PatKind::Tuple(ref subpatterns, ddpos) => {
347                 let ty = self.tables.node_id_to_type(pat.id);
348                 match ty.sty {
349                     ty::TyTuple(ref tys, _) => {
350                         let subpatterns =
351                             subpatterns.iter()
352                                        .enumerate_and_adjust(tys.len(), ddpos)
353                                        .map(|(i, subpattern)| FieldPattern {
354                                             field: Field::new(i),
355                                             pattern: self.lower_pattern(subpattern)
356                                        })
357                                        .collect();
358
359                         PatternKind::Leaf { subpatterns: subpatterns }
360                     }
361
362                     ref sty => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", sty),
363                 }
364             }
365
366             PatKind::Binding(bm, def_id, ref ident, ref sub) => {
367                 let id = self.tcx.hir.as_local_node_id(def_id).unwrap();
368                 let var_ty = self.tables.node_id_to_type(pat.id);
369                 let region = match var_ty.sty {
370                     ty::TyRef(r, _) => Some(r),
371                     _ => None,
372                 };
373                 let (mutability, mode) = match bm {
374                     hir::BindByValue(hir::MutMutable) =>
375                         (Mutability::Mut, BindingMode::ByValue),
376                     hir::BindByValue(hir::MutImmutable) =>
377                         (Mutability::Not, BindingMode::ByValue),
378                     hir::BindByRef(hir::MutMutable) =>
379                         (Mutability::Not, BindingMode::ByRef(region.unwrap(), BorrowKind::Mut)),
380                     hir::BindByRef(hir::MutImmutable) =>
381                         (Mutability::Not, BindingMode::ByRef(region.unwrap(), BorrowKind::Shared)),
382                 };
383
384                 // A ref x pattern is the same node used for x, and as such it has
385                 // x's type, which is &T, where we want T (the type being matched).
386                 if let hir::BindByRef(_) = bm {
387                     if let ty::TyRef(_, mt) = ty.sty {
388                         ty = mt.ty;
389                     } else {
390                         bug!("`ref {}` has wrong type {}", ident.node, ty);
391                     }
392                 }
393
394                 PatternKind::Binding {
395                     mutability: mutability,
396                     mode: mode,
397                     name: ident.node,
398                     var: id,
399                     ty: var_ty,
400                     subpattern: self.lower_opt_pattern(sub),
401                 }
402             }
403
404             PatKind::TupleStruct(ref qpath, ref subpatterns, ddpos) => {
405                 let def = self.tables.qpath_def(qpath, pat.id);
406                 let adt_def = match ty.sty {
407                     ty::TyAdt(adt_def, _) => adt_def,
408                     _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"),
409                 };
410                 let variant_def = adt_def.variant_of_def(def);
411
412                 let subpatterns =
413                         subpatterns.iter()
414                                    .enumerate_and_adjust(variant_def.fields.len(), ddpos)
415                                    .map(|(i, field)| FieldPattern {
416                                        field: Field::new(i),
417                                        pattern: self.lower_pattern(field),
418                                    })
419                                    .collect();
420                 self.lower_variant_or_leaf(def, ty, subpatterns)
421             }
422
423             PatKind::Struct(ref qpath, ref fields, _) => {
424                 let def = self.tables.qpath_def(qpath, pat.id);
425                 let adt_def = match ty.sty {
426                     ty::TyAdt(adt_def, _) => adt_def,
427                     _ => {
428                         span_bug!(
429                             pat.span,
430                             "struct pattern not applied to an ADT");
431                     }
432                 };
433                 let variant_def = adt_def.variant_of_def(def);
434
435                 let subpatterns =
436                     fields.iter()
437                           .map(|field| {
438                               let index = variant_def.index_of_field_named(field.node.name);
439                               let index = index.unwrap_or_else(|| {
440                                   span_bug!(
441                                       pat.span,
442                                       "no field with name {:?}",
443                                       field.node.name);
444                               });
445                               FieldPattern {
446                                   field: Field::new(index),
447                                   pattern: self.lower_pattern(&field.node.pat),
448                               }
449                           })
450                           .collect();
451
452                 self.lower_variant_or_leaf(def, ty, subpatterns)
453             }
454         };
455
456         Pattern {
457             span: pat.span,
458             ty: ty,
459             kind: Box::new(kind),
460         }
461     }
462
463     fn lower_patterns(&mut self, pats: &[P<hir::Pat>]) -> Vec<Pattern<'tcx>> {
464         pats.iter().map(|p| self.lower_pattern(p)).collect()
465     }
466
467     fn lower_opt_pattern(&mut self, pat: &Option<P<hir::Pat>>) -> Option<Pattern<'tcx>>
468     {
469         pat.as_ref().map(|p| self.lower_pattern(p))
470     }
471
472     fn flatten_nested_slice_patterns(
473         &mut self,
474         prefix: Vec<Pattern<'tcx>>,
475         slice: Option<Pattern<'tcx>>,
476         suffix: Vec<Pattern<'tcx>>)
477         -> (Vec<Pattern<'tcx>>, Option<Pattern<'tcx>>, Vec<Pattern<'tcx>>)
478     {
479         let orig_slice = match slice {
480             Some(orig_slice) => orig_slice,
481             None => return (prefix, slice, suffix)
482         };
483         let orig_prefix = prefix;
484         let orig_suffix = suffix;
485
486         // dance because of intentional borrow-checker stupidity.
487         let kind = *orig_slice.kind;
488         match kind {
489             PatternKind::Slice { prefix, slice, mut suffix } |
490             PatternKind::Array { prefix, slice, mut suffix } => {
491                 let mut orig_prefix = orig_prefix;
492
493                 orig_prefix.extend(prefix);
494                 suffix.extend(orig_suffix);
495
496                 (orig_prefix, slice, suffix)
497             }
498             _ => {
499                 (orig_prefix, Some(Pattern {
500                     kind: box kind, ..orig_slice
501                 }), orig_suffix)
502             }
503         }
504     }
505
506     fn slice_or_array_pattern(
507         &mut self,
508         span: Span,
509         ty: Ty<'tcx>,
510         prefix: &[P<hir::Pat>],
511         slice: &Option<P<hir::Pat>>,
512         suffix: &[P<hir::Pat>])
513         -> PatternKind<'tcx>
514     {
515         let prefix = self.lower_patterns(prefix);
516         let slice = self.lower_opt_pattern(slice);
517         let suffix = self.lower_patterns(suffix);
518         let (prefix, slice, suffix) =
519             self.flatten_nested_slice_patterns(prefix, slice, suffix);
520
521         match ty.sty {
522             ty::TySlice(..) => {
523                 // matching a slice or fixed-length array
524                 PatternKind::Slice { prefix: prefix, slice: slice, suffix: suffix }
525             }
526
527             ty::TyArray(_, len) => {
528                 // fixed-length array
529                 assert!(len >= prefix.len() + suffix.len());
530                 PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix }
531             }
532
533             _ => {
534                 span_bug!(span, "bad slice pattern type {:?}", ty);
535             }
536         }
537     }
538
539     fn lower_variant_or_leaf(
540         &mut self,
541         def: Def,
542         ty: Ty<'tcx>,
543         subpatterns: Vec<FieldPattern<'tcx>>)
544         -> PatternKind<'tcx>
545     {
546         match def {
547             Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
548                 let enum_id = self.tcx.parent_def_id(variant_id).unwrap();
549                 let adt_def = self.tcx.adt_def(enum_id);
550                 if adt_def.variants.len() > 1 {
551                     let substs = match ty.sty {
552                         ty::TyAdt(_, substs) |
553                         ty::TyFnDef(_, substs) => substs,
554                         _ => bug!("inappropriate type for def: {:?}", ty.sty),
555                     };
556                     PatternKind::Variant {
557                         adt_def: adt_def,
558                         substs: substs,
559                         variant_index: adt_def.variant_index_with_id(variant_id),
560                         subpatterns: subpatterns,
561                     }
562                 } else {
563                     PatternKind::Leaf { subpatterns: subpatterns }
564                 }
565             }
566
567             Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
568             Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => {
569                 PatternKind::Leaf { subpatterns: subpatterns }
570             }
571
572             _ => bug!()
573         }
574     }
575
576     fn lower_path(&mut self,
577                   qpath: &hir::QPath,
578                   id: ast::NodeId,
579                   pat_id: ast::NodeId,
580                   span: Span)
581                   -> Pattern<'tcx> {
582         let ty = self.tables.node_id_to_type(id);
583         let def = self.tables.qpath_def(qpath, id);
584         let kind = match def {
585             Def::Const(def_id) | Def::AssociatedConst(def_id) => {
586                 let tcx = self.tcx.global_tcx();
587                 let substs = self.tables.node_substs(id);
588                 match eval::lookup_const_by_id(tcx, def_id, substs) {
589                     Some((def_id, _substs)) => {
590                         // Enter the inlined constant's tables temporarily.
591                         let old_tables = self.tables;
592                         self.tables = tcx.typeck_tables_of(def_id);
593                         let body = if let Some(id) = tcx.hir.as_local_node_id(def_id) {
594                             tcx.hir.body(tcx.hir.body_owned_by(id))
595                         } else {
596                             tcx.sess.cstore.item_body(tcx, def_id)
597                         };
598                         let pat = self.lower_const_expr(&body.value, pat_id, span);
599                         self.tables = old_tables;
600                         return pat;
601                     }
602                     None => {
603                         self.errors.push(PatternError::StaticInPattern(span));
604                         PatternKind::Wild
605                     }
606                 }
607             }
608             _ => self.lower_variant_or_leaf(def, ty, vec![]),
609         };
610
611         Pattern {
612             span: span,
613             ty: ty,
614             kind: Box::new(kind),
615         }
616     }
617
618     fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'tcx> {
619         let const_cx = eval::ConstContext::with_tables(self.tcx.global_tcx(), self.tables);
620         match const_cx.eval(expr) {
621             Ok(value) => {
622                 if let ConstVal::Variant(def_id) = value {
623                     let ty = self.tables.expr_ty(expr);
624                     self.lower_variant_or_leaf(Def::Variant(def_id), ty, vec![])
625                 } else {
626                     PatternKind::Constant { value: value }
627                 }
628             }
629             Err(e) => {
630                 self.errors.push(PatternError::ConstEval(e));
631                 PatternKind::Wild
632             }
633         }
634     }
635
636     fn lower_const_expr(&mut self,
637                         expr: &hir::Expr,
638                         pat_id: ast::NodeId,
639                         span: Span)
640                         -> Pattern<'tcx> {
641         let pat_ty = self.tables.expr_ty(expr);
642         debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id);
643         match pat_ty.sty {
644             ty::TyFloat(_) => {
645                 self.tcx.sess.span_err(span, "floating point constants cannot be used in patterns");
646             }
647             ty::TyAdt(adt_def, _) if adt_def.is_union() => {
648                 // Matching on union fields is unsafe, we can't hide it in constants
649                 self.tcx.sess.span_err(span, "cannot use unions in constant patterns");
650             }
651             ty::TyAdt(adt_def, _) => {
652                 if !self.tcx.has_attr(adt_def.did, "structural_match") {
653                     let msg = format!("to use a constant of type `{}` in a pattern, \
654                                        `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
655                                       self.tcx.item_path_str(adt_def.did),
656                                       self.tcx.item_path_str(adt_def.did));
657                     self.tcx.sess.span_err(span, &msg);
658                 }
659             }
660             _ => { }
661         }
662         let kind = match expr.node {
663             hir::ExprTup(ref exprs) => {
664                 PatternKind::Leaf {
665                     subpatterns: exprs.iter().enumerate().map(|(i, expr)| {
666                         FieldPattern {
667                             field: Field::new(i),
668                             pattern: self.lower_const_expr(expr, pat_id, span)
669                         }
670                     }).collect()
671                 }
672             }
673
674             hir::ExprCall(ref callee, ref args) => {
675                 let qpath = match callee.node {
676                     hir::ExprPath(ref qpath) => qpath,
677                     _ => bug!()
678                 };
679                 let ty = self.tables.node_id_to_type(callee.id);
680                 let def = self.tables.qpath_def(qpath, callee.id);
681                 match def {
682                     Def::Fn(..) | Def::Method(..) => self.lower_lit(expr),
683                     _ => {
684                         let subpatterns = args.iter().enumerate().map(|(i, expr)| {
685                             FieldPattern {
686                                 field: Field::new(i),
687                                 pattern: self.lower_const_expr(expr, pat_id, span)
688                             }
689                         }).collect();
690                         self.lower_variant_or_leaf(def, ty, subpatterns)
691                     }
692                 }
693             }
694
695             hir::ExprStruct(ref qpath, ref fields, None) => {
696                 let def = self.tables.qpath_def(qpath, expr.id);
697                 let adt_def = match pat_ty.sty {
698                     ty::TyAdt(adt_def, _) => adt_def,
699                     _ => {
700                         span_bug!(
701                             expr.span,
702                             "struct expr without ADT type");
703                     }
704                 };
705                 let variant_def = adt_def.variant_of_def(def);
706
707                 let subpatterns =
708                     fields.iter()
709                           .map(|field| {
710                               let index = variant_def.index_of_field_named(field.name.node);
711                               let index = index.unwrap_or_else(|| {
712                                   span_bug!(
713                                       expr.span,
714                                       "no field with name {:?}",
715                                       field.name);
716                               });
717                               FieldPattern {
718                                   field: Field::new(index),
719                                   pattern: self.lower_const_expr(&field.expr, pat_id, span),
720                               }
721                           })
722                           .collect();
723
724                 self.lower_variant_or_leaf(def, pat_ty, subpatterns)
725             }
726
727             hir::ExprArray(ref exprs) => {
728                 let pats = exprs.iter()
729                                 .map(|expr| self.lower_const_expr(expr, pat_id, span))
730                                 .collect();
731                 PatternKind::Array {
732                     prefix: pats,
733                     slice: None,
734                     suffix: vec![]
735                 }
736             }
737
738             hir::ExprPath(ref qpath) => {
739                 return self.lower_path(qpath, expr.id, pat_id, span);
740             }
741
742             _ => self.lower_lit(expr)
743         };
744
745         Pattern {
746             span: span,
747             ty: pat_ty,
748             kind: Box::new(kind),
749         }
750     }
751 }
752
753 pub trait PatternFoldable<'tcx> : Sized {
754     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
755         self.super_fold_with(folder)
756     }
757
758     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self;
759 }
760
761 pub trait PatternFolder<'tcx> : Sized {
762     fn fold_pattern(&mut self, pattern: &Pattern<'tcx>) -> Pattern<'tcx> {
763         pattern.super_fold_with(self)
764     }
765
766     fn fold_pattern_kind(&mut self, kind: &PatternKind<'tcx>) -> PatternKind<'tcx> {
767         kind.super_fold_with(self)
768     }
769 }
770
771
772 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Box<T> {
773     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
774         let content: T = (**self).fold_with(folder);
775         box content
776     }
777 }
778
779 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Vec<T> {
780     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
781         self.iter().map(|t| t.fold_with(folder)).collect()
782     }
783 }
784
785 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option<T> {
786     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self{
787         self.as_ref().map(|t| t.fold_with(folder))
788     }
789 }
790
791 macro_rules! CloneImpls {
792     (<$lt_tcx:tt> $($ty:ty),+) => {
793         $(
794             impl<$lt_tcx> PatternFoldable<$lt_tcx> for $ty {
795                 fn super_fold_with<F: PatternFolder<$lt_tcx>>(&self, _: &mut F) -> Self {
796                     Clone::clone(self)
797                 }
798             }
799         )+
800     }
801 }
802
803 CloneImpls!{ <'tcx>
804     Span, Field, Mutability, ast::Name, ast::NodeId, usize, ConstVal<'tcx>, Region<'tcx>,
805     Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
806     &'tcx Substs<'tcx>, &'tcx Kind<'tcx>
807 }
808
809 impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> {
810     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
811         FieldPattern {
812             field: self.field.fold_with(folder),
813             pattern: self.pattern.fold_with(folder)
814         }
815     }
816 }
817
818 impl<'tcx> PatternFoldable<'tcx> for Pattern<'tcx> {
819     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
820         folder.fold_pattern(self)
821     }
822
823     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
824         Pattern {
825             ty: self.ty.fold_with(folder),
826             span: self.span.fold_with(folder),
827             kind: self.kind.fold_with(folder)
828         }
829     }
830 }
831
832 impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
833     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
834         folder.fold_pattern_kind(self)
835     }
836
837     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
838         match *self {
839             PatternKind::Wild => PatternKind::Wild,
840             PatternKind::Binding {
841                 mutability,
842                 name,
843                 mode,
844                 var,
845                 ty,
846                 ref subpattern,
847             } => PatternKind::Binding {
848                 mutability: mutability.fold_with(folder),
849                 name: name.fold_with(folder),
850                 mode: mode.fold_with(folder),
851                 var: var.fold_with(folder),
852                 ty: ty.fold_with(folder),
853                 subpattern: subpattern.fold_with(folder),
854             },
855             PatternKind::Variant {
856                 adt_def,
857                 substs,
858                 variant_index,
859                 ref subpatterns,
860             } => PatternKind::Variant {
861                 adt_def: adt_def.fold_with(folder),
862                 substs: substs.fold_with(folder),
863                 variant_index: variant_index.fold_with(folder),
864                 subpatterns: subpatterns.fold_with(folder)
865             },
866             PatternKind::Leaf {
867                 ref subpatterns,
868             } => PatternKind::Leaf {
869                 subpatterns: subpatterns.fold_with(folder),
870             },
871             PatternKind::Deref {
872                 ref subpattern,
873             } => PatternKind::Deref {
874                 subpattern: subpattern.fold_with(folder),
875             },
876             PatternKind::Constant {
877                 ref value
878             } => PatternKind::Constant {
879                 value: value.fold_with(folder)
880             },
881             PatternKind::Range {
882                 ref lo,
883                 ref hi,
884                 ref end,
885             } => PatternKind::Range {
886                 lo: lo.fold_with(folder),
887                 hi: hi.fold_with(folder),
888                 end: end.clone(),
889             },
890             PatternKind::Slice {
891                 ref prefix,
892                 ref slice,
893                 ref suffix,
894             } => PatternKind::Slice {
895                 prefix: prefix.fold_with(folder),
896                 slice: slice.fold_with(folder),
897                 suffix: suffix.fold_with(folder)
898             },
899             PatternKind::Array {
900                 ref prefix,
901                 ref slice,
902                 ref suffix
903             } => PatternKind::Array {
904                 prefix: prefix.fold_with(folder),
905                 slice: slice.fold_with(folder),
906                 suffix: suffix.fold_with(folder)
907             },
908         }
909     }
910 }