]> git.lizzy.rs Git - rust.git/blob - src/librustc_const_eval/pattern.rs
Do not show `::constructor` on tuple struct diagnostics
[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::lint;
14 use rustc::middle::const_val::{ConstEvalErr, ConstVal};
15 use rustc::mir::{Field, BorrowKind, Mutability};
16 use rustc::ty::{self, TyCtxt, AdtDef, Ty, TypeVariants, Region};
17 use rustc::ty::subst::{Substs, Kind};
18 use rustc::hir::{self, PatKind, RangeEnd};
19 use rustc::hir::def::{Def, CtorKind};
20 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
21
22 use rustc_data_structures::indexed_vec::Idx;
23
24 use std::fmt;
25 use syntax::ast;
26 use syntax::ptr::P;
27 use syntax_pos::Span;
28
29 #[derive(Clone, Debug)]
30 pub enum PatternError<'tcx> {
31     StaticInPattern(Span),
32     ConstEval(ConstEvalErr<'tcx>),
33 }
34
35 #[derive(Copy, Clone, Debug)]
36 pub enum BindingMode<'tcx> {
37     ByValue,
38     ByRef(&'tcx Region, BorrowKind),
39 }
40
41 #[derive(Clone, Debug)]
42 pub struct FieldPattern<'tcx> {
43     pub field: Field,
44     pub pattern: Pattern<'tcx>,
45 }
46
47 #[derive(Clone, Debug)]
48 pub struct Pattern<'tcx> {
49     pub ty: Ty<'tcx>,
50     pub span: Span,
51     pub kind: Box<PatternKind<'tcx>>,
52 }
53
54 #[derive(Clone, Debug)]
55 pub enum PatternKind<'tcx> {
56     Wild,
57
58     /// x, ref x, x @ P, etc
59     Binding {
60         mutability: Mutability,
61         name: ast::Name,
62         mode: BindingMode<'tcx>,
63         var: ast::NodeId,
64         ty: Ty<'tcx>,
65         subpattern: Option<Pattern<'tcx>>,
66     },
67
68     /// Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
69     Variant {
70         adt_def: &'tcx AdtDef,
71         substs: &'tcx Substs<'tcx>,
72         variant_index: usize,
73         subpatterns: Vec<FieldPattern<'tcx>>,
74     },
75
76     /// (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
77     Leaf {
78         subpatterns: Vec<FieldPattern<'tcx>>,
79     },
80
81     /// box P, &P, &mut P, etc
82     Deref {
83         subpattern: Pattern<'tcx>,
84     },
85
86     Constant {
87         value: ConstVal<'tcx>,
88     },
89
90     Range {
91         lo: ConstVal<'tcx>,
92         hi: ConstVal<'tcx>,
93         end: RangeEnd,
94     },
95
96     /// matches against a slice, checking the length and extracting elements
97     Slice {
98         prefix: Vec<Pattern<'tcx>>,
99         slice: Option<Pattern<'tcx>>,
100         suffix: Vec<Pattern<'tcx>>,
101     },
102
103     /// fixed match against an array, irrefutable
104     Array {
105         prefix: Vec<Pattern<'tcx>>,
106         slice: Option<Pattern<'tcx>>,
107         suffix: Vec<Pattern<'tcx>>,
108     },
109 }
110
111 fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result {
112     match *value {
113         ConstVal::Float(ref x) => write!(f, "{}", x),
114         ConstVal::Integral(ref i) => write!(f, "{}", i),
115         ConstVal::Str(ref s) => write!(f, "{:?}", &s[..]),
116         ConstVal::ByteStr(ref b) => write!(f, "{:?}", &b[..]),
117         ConstVal::Bool(b) => write!(f, "{:?}", b),
118         ConstVal::Char(c) => write!(f, "{:?}", c),
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.lookup_adt_def(enum_id);
550                 if adt_def.variants.len() > 1 {
551                     let substs = match ty.sty {
552                         TypeVariants::TyAdt(_, substs) => substs,
553                         TypeVariants::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_id_item_substs(id)
588                     .unwrap_or_else(|| tcx.intern_substs(&[]));
589                 match eval::lookup_const_by_id(tcx, def_id, substs) {
590                     Some((const_expr, const_tables)) => {
591                         // Enter the inlined constant's tables temporarily.
592                         let old_tables = self.tables;
593                         self.tables = const_tables;
594                         let pat = self.lower_const_expr(const_expr, pat_id, span);
595                         self.tables = old_tables;
596                         return pat;
597                     }
598                     None => {
599                         self.errors.push(PatternError::StaticInPattern(span));
600                         PatternKind::Wild
601                     }
602                 }
603             }
604             _ => self.lower_variant_or_leaf(def, ty, vec![]),
605         };
606
607         Pattern {
608             span: span,
609             ty: ty,
610             kind: Box::new(kind),
611         }
612     }
613
614     fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'tcx> {
615         let const_cx = eval::ConstContext::with_tables(self.tcx.global_tcx(), self.tables);
616         match const_cx.eval(expr) {
617             Ok(value) => {
618                 PatternKind::Constant { value: value }
619             }
620             Err(e) => {
621                 self.errors.push(PatternError::ConstEval(e));
622                 PatternKind::Wild
623             }
624         }
625     }
626
627     fn lower_const_expr(&mut self,
628                         expr: &hir::Expr,
629                         pat_id: ast::NodeId,
630                         span: Span)
631                         -> Pattern<'tcx> {
632         let pat_ty = self.tables.expr_ty(expr);
633         debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id);
634         match pat_ty.sty {
635             ty::TyFloat(_) => {
636                 self.tcx.sess.add_lint(
637                     lint::builtin::ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN,
638                     pat_id,
639                     span,
640                     format!("floating point constants cannot be used in patterns"));
641             }
642             ty::TyAdt(adt_def, _) if adt_def.is_union() => {
643                 // Matching on union fields is unsafe, we can't hide it in constants
644                 self.tcx.sess.span_err(span, "cannot use unions in constant patterns");
645             }
646             ty::TyAdt(adt_def, _) => {
647                 if !self.tcx.has_attr(adt_def.did, "structural_match") {
648                     self.tcx.sess.add_lint(
649                         lint::builtin::ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
650                         pat_id,
651                         span,
652                         format!("to use a constant of type `{}` \
653                                  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                 }
658             }
659             _ => { }
660         }
661         let kind = match expr.node {
662             hir::ExprTup(ref exprs) => {
663                 PatternKind::Leaf {
664                     subpatterns: exprs.iter().enumerate().map(|(i, expr)| {
665                         FieldPattern {
666                             field: Field::new(i),
667                             pattern: self.lower_const_expr(expr, pat_id, span)
668                         }
669                     }).collect()
670                 }
671             }
672
673             hir::ExprCall(ref callee, ref args) => {
674                 let qpath = match callee.node {
675                     hir::ExprPath(ref qpath) => qpath,
676                     _ => bug!()
677                 };
678                 let ty = self.tables.node_id_to_type(callee.id);
679                 let def = self.tables.qpath_def(qpath, callee.id);
680                 match def {
681                     Def::Fn(..) | Def::Method(..) => self.lower_lit(expr),
682                     _ => {
683                         let subpatterns = args.iter().enumerate().map(|(i, expr)| {
684                             FieldPattern {
685                                 field: Field::new(i),
686                                 pattern: self.lower_const_expr(expr, pat_id, span)
687                             }
688                         }).collect();
689                         self.lower_variant_or_leaf(def, ty, subpatterns)
690                     }
691                 }
692             }
693
694             hir::ExprStruct(ref qpath, ref fields, None) => {
695                 let def = self.tables.qpath_def(qpath, expr.id);
696                 let adt_def = match pat_ty.sty {
697                     ty::TyAdt(adt_def, _) => adt_def,
698                     _ => {
699                         span_bug!(
700                             expr.span,
701                             "struct expr without ADT type");
702                     }
703                 };
704                 let variant_def = adt_def.variant_of_def(def);
705
706                 let subpatterns =
707                     fields.iter()
708                           .map(|field| {
709                               let index = variant_def.index_of_field_named(field.name.node);
710                               let index = index.unwrap_or_else(|| {
711                                   span_bug!(
712                                       expr.span,
713                                       "no field with name {:?}",
714                                       field.name);
715                               });
716                               FieldPattern {
717                                   field: Field::new(index),
718                                   pattern: self.lower_const_expr(&field.expr, pat_id, span),
719                               }
720                           })
721                           .collect();
722
723                 self.lower_variant_or_leaf(def, pat_ty, subpatterns)
724             }
725
726             hir::ExprArray(ref exprs) => {
727                 let pats = exprs.iter()
728                                 .map(|expr| self.lower_const_expr(expr, pat_id, span))
729                                 .collect();
730                 PatternKind::Array {
731                     prefix: pats,
732                     slice: None,
733                     suffix: vec![]
734                 }
735             }
736
737             hir::ExprPath(ref qpath) => {
738                 return self.lower_path(qpath, expr.id, pat_id, span);
739             }
740
741             _ => self.lower_lit(expr)
742         };
743
744         Pattern {
745             span: span,
746             ty: pat_ty,
747             kind: Box::new(kind),
748         }
749     }
750 }
751
752 pub trait PatternFoldable<'tcx> : Sized {
753     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
754         self.super_fold_with(folder)
755     }
756
757     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self;
758 }
759
760 pub trait PatternFolder<'tcx> : Sized {
761     fn fold_pattern(&mut self, pattern: &Pattern<'tcx>) -> Pattern<'tcx> {
762         pattern.super_fold_with(self)
763     }
764
765     fn fold_pattern_kind(&mut self, kind: &PatternKind<'tcx>) -> PatternKind<'tcx> {
766         kind.super_fold_with(self)
767     }
768 }
769
770
771 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Box<T> {
772     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
773         let content: T = (**self).fold_with(folder);
774         box content
775     }
776 }
777
778 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Vec<T> {
779     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
780         self.iter().map(|t| t.fold_with(folder)).collect()
781     }
782 }
783
784 impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option<T> {
785     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self{
786         self.as_ref().map(|t| t.fold_with(folder))
787     }
788 }
789
790 macro_rules! CloneImpls {
791     (<$lt_tcx:tt> $($ty:ty),+) => {
792         $(
793             impl<$lt_tcx> PatternFoldable<$lt_tcx> for $ty {
794                 fn super_fold_with<F: PatternFolder<$lt_tcx>>(&self, _: &mut F) -> Self {
795                     Clone::clone(self)
796                 }
797             }
798         )+
799     }
800 }
801
802 CloneImpls!{ <'tcx>
803     Span, Field, Mutability, ast::Name, ast::NodeId, usize, ConstVal<'tcx>, Region,
804     Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
805     &'tcx Substs<'tcx>, &'tcx Kind<'tcx>
806 }
807
808 impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> {
809     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
810         FieldPattern {
811             field: self.field.fold_with(folder),
812             pattern: self.pattern.fold_with(folder)
813         }
814     }
815 }
816
817 impl<'tcx> PatternFoldable<'tcx> for Pattern<'tcx> {
818     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
819         folder.fold_pattern(self)
820     }
821
822     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
823         Pattern {
824             ty: self.ty.fold_with(folder),
825             span: self.span.fold_with(folder),
826             kind: self.kind.fold_with(folder)
827         }
828     }
829 }
830
831 impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
832     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
833         folder.fold_pattern_kind(self)
834     }
835
836     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
837         match *self {
838             PatternKind::Wild => PatternKind::Wild,
839             PatternKind::Binding {
840                 mutability,
841                 name,
842                 mode,
843                 var,
844                 ty,
845                 ref subpattern,
846             } => PatternKind::Binding {
847                 mutability: mutability.fold_with(folder),
848                 name: name.fold_with(folder),
849                 mode: mode.fold_with(folder),
850                 var: var.fold_with(folder),
851                 ty: ty.fold_with(folder),
852                 subpattern: subpattern.fold_with(folder),
853             },
854             PatternKind::Variant {
855                 adt_def,
856                 substs,
857                 variant_index,
858                 ref subpatterns,
859             } => PatternKind::Variant {
860                 adt_def: adt_def.fold_with(folder),
861                 substs: substs.fold_with(folder),
862                 variant_index: variant_index.fold_with(folder),
863                 subpatterns: subpatterns.fold_with(folder)
864             },
865             PatternKind::Leaf {
866                 ref subpatterns,
867             } => PatternKind::Leaf {
868                 subpatterns: subpatterns.fold_with(folder),
869             },
870             PatternKind::Deref {
871                 ref subpattern,
872             } => PatternKind::Deref {
873                 subpattern: subpattern.fold_with(folder),
874             },
875             PatternKind::Constant {
876                 ref value
877             } => PatternKind::Constant {
878                 value: value.fold_with(folder)
879             },
880             PatternKind::Range {
881                 ref lo,
882                 ref hi,
883                 ref end,
884             } => PatternKind::Range {
885                 lo: lo.fold_with(folder),
886                 hi: hi.fold_with(folder),
887                 end: end.clone(),
888             },
889             PatternKind::Slice {
890                 ref prefix,
891                 ref slice,
892                 ref suffix,
893             } => PatternKind::Slice {
894                 prefix: prefix.fold_with(folder),
895                 slice: slice.fold_with(folder),
896                 suffix: suffix.fold_with(folder)
897             },
898             PatternKind::Array {
899                 ref prefix,
900                 ref slice,
901                 ref suffix
902             } => PatternKind::Array {
903                 prefix: prefix.fold_with(folder),
904                 slice: slice.fold_with(folder),
905                 suffix: suffix.fold_with(folder)
906             },
907         }
908     }
909 }