]> git.lizzy.rs Git - rust.git/blob - src/librustc/hir/lowering.rs
add inline attributes to stage 0 methods
[rust.git] / src / librustc / hir / lowering.rs
1 // Copyright 2015 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 // Lowers the AST to the HIR.
12 //
13 // Since the AST and HIR are fairly similar, this is mostly a simple procedure,
14 // much like a fold. Where lowering involves a bit more work things get more
15 // interesting and there are some invariants you should know about. These mostly
16 // concern spans and ids.
17 //
18 // Spans are assigned to AST nodes during parsing and then are modified during
19 // expansion to indicate the origin of a node and the process it went through
20 // being expanded. Ids are assigned to AST nodes just before lowering.
21 //
22 // For the simpler lowering steps, ids and spans should be preserved. Unlike
23 // expansion we do not preserve the process of lowering in the spans, so spans
24 // should not be modified here. When creating a new node (as opposed to
25 // 'folding' an existing one), then you create a new id using `next_id()`.
26 //
27 // You must ensure that ids are unique. That means that you should only use the
28 // id from an AST node in a single HIR node (you can assume that AST node ids
29 // are unique). Every new node must have a unique id. Avoid cloning HIR nodes.
30 // If you do, you must then set the new node's id to a fresh one.
31 //
32 // Spans are used for error messages and for tools to map semantics back to
33 // source code. It is therefore not as important with spans as ids to be strict
34 // about use (you can't break the compiler by screwing up a span). Obviously, a
35 // HIR node can only have a single span. But multiple nodes can have the same
36 // span and spans don't need to be kept in order, etc. Where code is preserved
37 // by lowering, it should have the same span as in the AST. Where HIR nodes are
38 // new it is probably best to give a span for the whole AST node being lowered.
39 // All nodes should have real spans, don't use dummy spans. Tools are likely to
40 // get confused if the spans from leaf AST nodes occur in multiple places
41 // in the HIR, especially for multiple identifiers.
42
43 use hir;
44 use hir::map::{Definitions, DefKey};
45 use hir::map::definitions::DefPathData;
46 use hir::def_id::{DefIndex, DefId};
47 use hir::def::{Def, PathResolution};
48 use session::Session;
49 use util::nodemap::{DefIdMap, NodeMap};
50
51 use std::collections::BTreeMap;
52 use std::iter;
53 use std::mem;
54
55 use syntax::attr;
56 use syntax::ast::*;
57 use syntax::errors;
58 use syntax::ptr::P;
59 use syntax::codemap::{self, respan, Spanned};
60 use syntax::std_inject;
61 use syntax::symbol::{Symbol, keywords};
62 use syntax::util::small_vector::SmallVector;
63 use syntax::visit::{self, Visitor};
64 use syntax_pos::Span;
65
66 pub struct LoweringContext<'a> {
67     crate_root: Option<&'static str>,
68     // Use to assign ids to hir nodes that do not directly correspond to an ast node
69     sess: &'a Session,
70     // As we walk the AST we must keep track of the current 'parent' def id (in
71     // the form of a DefIndex) so that if we create a new node which introduces
72     // a definition, then we can properly create the def id.
73     parent_def: Option<DefIndex>,
74     resolver: &'a mut Resolver,
75
76     /// The items being lowered are collected here.
77     items: BTreeMap<NodeId, hir::Item>,
78
79     trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>,
80     impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
81     bodies: BTreeMap<hir::BodyId, hir::Body>,
82     exported_macros: Vec<hir::MacroDef>,
83
84     trait_impls: BTreeMap<DefId, Vec<NodeId>>,
85     trait_default_impl: BTreeMap<DefId, NodeId>,
86
87     catch_scopes: Vec<NodeId>,
88     loop_scopes: Vec<NodeId>,
89     is_in_loop_condition: bool,
90
91     type_def_lifetime_params: DefIdMap<usize>,
92 }
93
94 pub trait Resolver {
95     // Resolve a hir path generated by the lowerer when expanding `for`, `if let`, etc.
96     fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool);
97
98     // Obtain the resolution for a node id
99     fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution>;
100
101     // We must keep the set of definitions up to date as we add nodes that weren't in the AST.
102     // This should only return `None` during testing.
103     fn definitions(&mut self) -> &mut Definitions;
104 }
105
106 pub fn lower_crate(sess: &Session,
107                    krate: &Crate,
108                    resolver: &mut Resolver)
109                    -> hir::Crate {
110     // We're constructing the HIR here; we don't care what we will
111     // read, since we haven't even constructed the *input* to
112     // incr. comp. yet.
113     let _ignore = sess.dep_graph.in_ignore();
114
115     LoweringContext {
116         crate_root: std_inject::injected_crate_name(krate),
117         sess: sess,
118         parent_def: None,
119         resolver: resolver,
120         items: BTreeMap::new(),
121         trait_items: BTreeMap::new(),
122         impl_items: BTreeMap::new(),
123         bodies: BTreeMap::new(),
124         trait_impls: BTreeMap::new(),
125         trait_default_impl: BTreeMap::new(),
126         exported_macros: Vec::new(),
127         catch_scopes: Vec::new(),
128         loop_scopes: Vec::new(),
129         is_in_loop_condition: false,
130         type_def_lifetime_params: DefIdMap(),
131     }.lower_crate(krate)
132 }
133
134 #[derive(Copy, Clone, PartialEq, Eq)]
135 enum ParamMode {
136     /// Any path in a type context.
137     Explicit,
138     /// The `module::Type` in `module::Type::method` in an expression.
139     Optional
140 }
141
142 impl<'a> LoweringContext<'a> {
143     fn lower_crate(mut self, c: &Crate) -> hir::Crate {
144         /// Full-crate AST visitor that inserts into a fresh
145         /// `LoweringContext` any information that may be
146         /// needed from arbitrary locations in the crate.
147         /// E.g. The number of lifetime generic parameters
148         /// declared for every type and trait definition.
149         struct MiscCollector<'lcx, 'interner: 'lcx> {
150             lctx: &'lcx mut LoweringContext<'interner>,
151         }
152
153         impl<'lcx, 'interner> Visitor<'lcx> for MiscCollector<'lcx, 'interner> {
154             fn visit_item(&mut self, item: &'lcx Item) {
155                 match item.node {
156                     ItemKind::Struct(_, ref generics) |
157                     ItemKind::Union(_, ref generics) |
158                     ItemKind::Enum(_, ref generics) |
159                     ItemKind::Ty(_, ref generics) |
160                     ItemKind::Trait(_, ref generics, ..) => {
161                         let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
162                         let count = generics.lifetimes.len();
163                         self.lctx.type_def_lifetime_params.insert(def_id, count);
164                     }
165                     _ => {}
166                 }
167                 visit::walk_item(self, item);
168             }
169         }
170
171         struct ItemLowerer<'lcx, 'interner: 'lcx> {
172             lctx: &'lcx mut LoweringContext<'interner>,
173         }
174
175         impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> {
176             fn visit_item(&mut self, item: &'lcx Item) {
177                 if let Some(hir_item) = self.lctx.lower_item(item) {
178                     self.lctx.items.insert(item.id, hir_item);
179                     visit::walk_item(self, item);
180                 }
181             }
182
183             fn visit_trait_item(&mut self, item: &'lcx TraitItem) {
184                 let id = hir::TraitItemId { node_id: item.id };
185                 let hir_item = self.lctx.lower_trait_item(item);
186                 self.lctx.trait_items.insert(id, hir_item);
187                 visit::walk_trait_item(self, item);
188             }
189
190             fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
191                 let id = hir::ImplItemId { node_id: item.id };
192                 let hir_item = self.lctx.lower_impl_item(item);
193                 self.lctx.impl_items.insert(id, hir_item);
194                 visit::walk_impl_item(self, item);
195             }
196         }
197
198         visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c);
199         visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c);
200
201         let module = self.lower_mod(&c.module);
202         let attrs = self.lower_attrs(&c.attrs);
203         let body_ids = body_ids(&self.bodies);
204
205         hir::Crate {
206             module: module,
207             attrs: attrs,
208             span: c.span,
209             exported_macros: hir::HirVec::from(self.exported_macros),
210             items: self.items,
211             trait_items: self.trait_items,
212             impl_items: self.impl_items,
213             bodies: self.bodies,
214             body_ids: body_ids,
215             trait_impls: self.trait_impls,
216             trait_default_impl: self.trait_default_impl,
217         }
218     }
219
220     fn record_body(&mut self, value: hir::Expr, decl: Option<&FnDecl>)
221                    -> hir::BodyId {
222         let body = hir::Body {
223             arguments: decl.map_or(hir_vec![], |decl| {
224                 decl.inputs.iter().map(|x| self.lower_arg(x)).collect()
225             }),
226             value: value
227         };
228         let id = body.id();
229         self.bodies.insert(id, body);
230         id
231     }
232
233     fn next_id(&self) -> NodeId {
234         self.sess.next_node_id()
235     }
236
237     fn expect_full_def(&mut self, id: NodeId) -> Def {
238         self.resolver.get_resolution(id).map_or(Def::Err, |pr| {
239             if pr.unresolved_segments() != 0 {
240                 bug!("path not fully resolved: {:?}", pr);
241             }
242             pr.base_def()
243         })
244     }
245
246     fn diagnostic(&self) -> &errors::Handler {
247         self.sess.diagnostic()
248     }
249
250     fn str_to_ident(&self, s: &'static str) -> Name {
251         Symbol::gensym(s)
252     }
253
254     fn allow_internal_unstable(&self, reason: &'static str, mut span: Span) -> Span {
255         span.expn_id = self.sess.codemap().record_expansion(codemap::ExpnInfo {
256             call_site: span,
257             callee: codemap::NameAndSpan {
258                 format: codemap::CompilerDesugaring(Symbol::intern(reason)),
259                 span: Some(span),
260                 allow_internal_unstable: true,
261             },
262         });
263         span
264     }
265
266     fn with_catch_scope<T, F>(&mut self, catch_id: NodeId, f: F) -> T
267         where F: FnOnce(&mut LoweringContext) -> T
268     {
269         let len = self.catch_scopes.len();
270         self.catch_scopes.push(catch_id);
271
272         let result = f(self);
273         assert_eq!(len + 1, self.catch_scopes.len(),
274             "catch scopes should be added and removed in stack order");
275
276         self.catch_scopes.pop().unwrap();
277
278         result
279     }
280
281     fn with_loop_scope<T, F>(&mut self, loop_id: NodeId, f: F) -> T
282         where F: FnOnce(&mut LoweringContext) -> T
283     {
284         // We're no longer in the base loop's condition; we're in another loop.
285         let was_in_loop_condition = self.is_in_loop_condition;
286         self.is_in_loop_condition = false;
287
288         let len = self.loop_scopes.len();
289         self.loop_scopes.push(loop_id);
290
291         let result = f(self);
292         assert_eq!(len + 1, self.loop_scopes.len(),
293             "Loop scopes should be added and removed in stack order");
294
295         self.loop_scopes.pop().unwrap();
296
297         self.is_in_loop_condition = was_in_loop_condition;
298
299         result
300     }
301
302     fn with_loop_condition_scope<T, F>(&mut self, f: F) -> T
303         where F: FnOnce(&mut LoweringContext) -> T
304     {
305         let was_in_loop_condition = self.is_in_loop_condition;
306         self.is_in_loop_condition = true;
307
308         let result = f(self);
309
310         self.is_in_loop_condition = was_in_loop_condition;
311
312         result
313     }
314
315     fn with_new_scopes<T, F>(&mut self, f: F) -> T
316         where F: FnOnce(&mut LoweringContext) -> T
317     {
318         let was_in_loop_condition = self.is_in_loop_condition;
319         self.is_in_loop_condition = false;
320
321         let catch_scopes = mem::replace(&mut self.catch_scopes, Vec::new());
322         let loop_scopes = mem::replace(&mut self.loop_scopes, Vec::new());
323         let result = f(self);
324         self.catch_scopes = catch_scopes;
325         self.loop_scopes = loop_scopes;
326
327         self.is_in_loop_condition = was_in_loop_condition;
328
329         result
330     }
331
332     fn with_parent_def<T, F>(&mut self, parent_id: NodeId, f: F) -> T
333         where F: FnOnce(&mut LoweringContext) -> T
334     {
335         let old_def = self.parent_def;
336         self.parent_def = {
337             let defs = self.resolver.definitions();
338             Some(defs.opt_def_index(parent_id).unwrap())
339         };
340
341         let result = f(self);
342
343         self.parent_def = old_def;
344         result
345     }
346
347     fn def_key(&mut self, id: DefId) -> DefKey {
348         if id.is_local() {
349             self.resolver.definitions().def_key(id.index)
350         } else {
351             self.sess.cstore.def_key(id)
352         }
353     }
354
355     fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
356         o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
357     }
358
359     fn lower_destination(&mut self, destination: Option<(NodeId, Spanned<Ident>)>)
360         -> hir::Destination
361     {
362         match destination {
363             Some((id, label_ident)) => hir::Destination {
364                 ident: Some(label_ident),
365                 loop_id: if let Def::Label(loop_id) = self.expect_full_def(id) {
366                     hir::LoopIdResult::Ok(loop_id)
367                 } else {
368                     hir::LoopIdResult::Err(hir::LoopIdError::UnresolvedLabel)
369                 }
370             },
371             None => hir::Destination {
372                 ident: None,
373                 loop_id: self.loop_scopes.last().map(|innermost_loop_id| Ok(*innermost_loop_id))
374                             .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)).into()
375             }
376         }
377     }
378
379     fn lower_attrs(&mut self, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
380         attrs.clone().into()
381     }
382
383     fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {
384         hir::Arm {
385             attrs: self.lower_attrs(&arm.attrs),
386             pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(),
387             guard: arm.guard.as_ref().map(|ref x| P(self.lower_expr(x))),
388             body: P(self.lower_expr(&arm.body)),
389         }
390     }
391
392     fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding {
393         hir::TypeBinding {
394             id: b.id,
395             name: b.ident.name,
396             ty: self.lower_ty(&b.ty),
397             span: b.span,
398         }
399     }
400
401     fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
402         P(hir::Ty {
403             id: t.id,
404             node: match t.node {
405                 TyKind::Infer => hir::TyInfer,
406                 TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)),
407                 TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
408                 TyKind::Rptr(ref region, ref mt) => {
409                     let span = Span { hi: t.span.lo, ..t.span };
410                     let lifetime = match *region {
411                         Some(ref lt) => self.lower_lifetime(lt),
412                         None => self.elided_lifetime(span)
413                     };
414                     hir::TyRptr(lifetime, self.lower_mt(mt))
415                 }
416                 TyKind::BareFn(ref f) => {
417                     hir::TyBareFn(P(hir::BareFnTy {
418                         lifetimes: self.lower_lifetime_defs(&f.lifetimes),
419                         unsafety: self.lower_unsafety(f.unsafety),
420                         abi: f.abi,
421                         decl: self.lower_fn_decl(&f.decl),
422                     }))
423                 }
424                 TyKind::Never => hir::TyNever,
425                 TyKind::Tup(ref tys) => {
426                     hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty)).collect())
427                 }
428                 TyKind::Paren(ref ty) => {
429                     return self.lower_ty(ty);
430                 }
431                 TyKind::Path(ref qself, ref path) => {
432                     let qpath = self.lower_qpath(t.id, qself, path, ParamMode::Explicit);
433                     return self.ty_path(t.id, t.span, qpath);
434                 }
435                 TyKind::ImplicitSelf => {
436                     hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
437                         def: self.expect_full_def(t.id),
438                         segments: hir_vec![hir::PathSegment {
439                             name: keywords::SelfType.name(),
440                             parameters: hir::PathParameters::none()
441                         }],
442                         span: t.span,
443                     })))
444                 }
445                 TyKind::Array(ref ty, ref length) => {
446                     let length = self.lower_expr(length);
447                     hir::TyArray(self.lower_ty(ty),
448                                  self.record_body(length, None))
449                 }
450                 TyKind::Typeof(ref expr) => {
451                     let expr = self.lower_expr(expr);
452                     hir::TyTypeof(self.record_body(expr, None))
453                 }
454                 TyKind::TraitObject(ref bounds) => {
455                     let mut lifetime_bound = None;
456                     let bounds = bounds.iter().filter_map(|bound| {
457                         match *bound {
458                             TraitTyParamBound(ref ty, TraitBoundModifier::None) => {
459                                 Some(self.lower_poly_trait_ref(ty))
460                             }
461                             TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
462                             RegionTyParamBound(ref lifetime) => {
463                                 lifetime_bound = Some(self.lower_lifetime(lifetime));
464                                 None
465                             }
466                         }
467                     }).collect();
468                     let lifetime_bound = lifetime_bound.unwrap_or_else(|| {
469                         self.elided_lifetime(t.span)
470                     });
471                     hir::TyTraitObject(bounds, lifetime_bound)
472                 }
473                 TyKind::ImplTrait(ref bounds) => {
474                     hir::TyImplTrait(self.lower_bounds(bounds))
475                 }
476                 TyKind::Mac(_) => panic!("TyMac should have been expanded by now."),
477             },
478             span: t.span,
479         })
480     }
481
482     fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod {
483         hir::ForeignMod {
484             abi: fm.abi,
485             items: fm.items.iter().map(|x| self.lower_foreign_item(x)).collect(),
486         }
487     }
488
489     fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
490         Spanned {
491             node: hir::Variant_ {
492                 name: v.node.name.name,
493                 attrs: self.lower_attrs(&v.node.attrs),
494                 data: self.lower_variant_data(&v.node.data),
495                 disr_expr: v.node.disr_expr.as_ref().map(|e| {
496                     let e = self.lower_expr(e);
497                     self.record_body(e, None)
498                 }),
499             },
500             span: v.span,
501         }
502     }
503
504     fn lower_qpath(&mut self,
505                    id: NodeId,
506                    qself: &Option<QSelf>,
507                    p: &Path,
508                    param_mode: ParamMode)
509                    -> hir::QPath {
510         let qself_position = qself.as_ref().map(|q| q.position);
511         let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty));
512
513         let resolution = self.resolver.get_resolution(id)
514                                       .unwrap_or(PathResolution::new(Def::Err));
515
516         let proj_start = p.segments.len() - resolution.unresolved_segments();
517         let path = P(hir::Path {
518             def: resolution.base_def(),
519             segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
520                 let param_mode = match (qself_position, param_mode) {
521                     (Some(j), ParamMode::Optional) if i < j => {
522                         // This segment is part of the trait path in a
523                         // qualified path - one of `a`, `b` or `Trait`
524                         // in `<X as a::b::Trait>::T::U::method`.
525                         ParamMode::Explicit
526                     }
527                     _ => param_mode
528                 };
529
530                 // Figure out if this is a type/trait segment,
531                 // which may need lifetime elision performed.
532                 let parent_def_id = |this: &mut Self, def_id: DefId| {
533                     DefId {
534                         krate: def_id.krate,
535                         index: this.def_key(def_id).parent.expect("missing parent")
536                     }
537                 };
538                 let type_def_id = match resolution.base_def() {
539                     Def::AssociatedTy(def_id) if i + 2 == proj_start => {
540                         Some(parent_def_id(self, def_id))
541                     }
542                     Def::Variant(def_id) if i + 1 == proj_start => {
543                         Some(parent_def_id(self, def_id))
544                     }
545                     Def::Struct(def_id) |
546                     Def::Union(def_id) |
547                     Def::Enum(def_id) |
548                     Def::TyAlias(def_id) |
549                     Def::Trait(def_id) if i + 1 == proj_start => Some(def_id),
550                     _ => None
551                 };
552
553                 let num_lifetimes = type_def_id.map_or(0, |def_id| {
554                     if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
555                         return n;
556                     }
557                     assert!(!def_id.is_local());
558                     let n = self.sess.cstore.item_generics_cloned(def_id).regions.len();
559                     self.type_def_lifetime_params.insert(def_id, n);
560                     n
561                 });
562                 self.lower_path_segment(p.span, segment, param_mode, num_lifetimes)
563             }).collect(),
564             span: p.span,
565         });
566
567         // Simple case, either no projections, or only fully-qualified.
568         // E.g. `std::mem::size_of` or `<I as Iterator>::Item`.
569         if resolution.unresolved_segments() == 0 {
570             return hir::QPath::Resolved(qself, path);
571         }
572
573         // Create the innermost type that we're projecting from.
574         let mut ty = if path.segments.is_empty() {
575             // If the base path is empty that means there exists a
576             // syntactical `Self`, e.g. `&i32` in `<&i32>::clone`.
577             qself.expect("missing QSelf for <T>::...")
578         } else {
579             // Otherwise, the base path is an implicit `Self` type path,
580             // e.g. `Vec` in `Vec::new` or `<I as Iterator>::Item` in
581             // `<I as Iterator>::Item::default`.
582             let new_id = self.next_id();
583             self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path))
584         };
585
586         // Anything after the base path are associated "extensions",
587         // out of which all but the last one are associated types,
588         // e.g. for `std::vec::Vec::<T>::IntoIter::Item::clone`:
589         // * base path is `std::vec::Vec<T>`
590         // * "extensions" are `IntoIter`, `Item` and `clone`
591         // * type nodes are:
592         //   1. `std::vec::Vec<T>` (created above)
593         //   2. `<std::vec::Vec<T>>::IntoIter`
594         //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
595         // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
596         for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
597             let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0));
598             let qpath = hir::QPath::TypeRelative(ty, segment);
599
600             // It's finished, return the extension of the right node type.
601             if i == p.segments.len() - 1 {
602                 return qpath;
603             }
604
605             // Wrap the associated extension in another type node.
606             let new_id = self.next_id();
607             ty = self.ty_path(new_id, p.span, qpath);
608         }
609
610         // Should've returned in the for loop above.
611         span_bug!(p.span, "lower_qpath: no final extension segment in {}..{}",
612                   proj_start, p.segments.len())
613     }
614
615     fn lower_path_extra(&mut self,
616                         id: NodeId,
617                         p: &Path,
618                         name: Option<Name>,
619                         param_mode: ParamMode,
620                         defaults_to_global: bool)
621                         -> hir::Path {
622         let mut segments = p.segments.iter();
623         if defaults_to_global && p.is_global() {
624             segments.next();
625         }
626
627         hir::Path {
628             def: self.expect_full_def(id),
629             segments: segments.map(|segment| {
630                 self.lower_path_segment(p.span, segment, param_mode, 0)
631             }).chain(name.map(|name| {
632                 hir::PathSegment {
633                     name: name,
634                     parameters: hir::PathParameters::none()
635                 }
636             })).collect(),
637             span: p.span,
638         }
639     }
640
641     fn lower_path(&mut self,
642                   id: NodeId,
643                   p: &Path,
644                   param_mode: ParamMode,
645                   defaults_to_global: bool)
646                   -> hir::Path {
647         self.lower_path_extra(id, p, None, param_mode, defaults_to_global)
648     }
649
650     fn lower_path_segment(&mut self,
651                           path_span: Span,
652                           segment: &PathSegment,
653                           param_mode: ParamMode,
654                           expected_lifetimes: usize)
655                           -> hir::PathSegment {
656         let mut parameters = if let Some(ref parameters) = segment.parameters {
657             match **parameters {
658                 PathParameters::AngleBracketed(ref data) => {
659                     let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
660                     hir::AngleBracketedParameters(data)
661                 }
662                 PathParameters::Parenthesized(ref data) => {
663                     hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data))
664                 }
665             }
666         } else {
667             let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode);
668             hir::AngleBracketedParameters(data)
669         };
670
671         if let hir::AngleBracketedParameters(ref mut data) = parameters {
672             if data.lifetimes.is_empty() {
673                 data.lifetimes = (0..expected_lifetimes).map(|_| {
674                     self.elided_lifetime(path_span)
675                 }).collect();
676             }
677         }
678
679         hir::PathSegment {
680             name: segment.identifier.name,
681             parameters: parameters,
682         }
683     }
684
685     fn lower_angle_bracketed_parameter_data(&mut self,
686                                             data: &AngleBracketedParameterData,
687                                             param_mode: ParamMode)
688                                             -> hir::AngleBracketedParameterData {
689         let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data;
690         hir::AngleBracketedParameterData {
691             lifetimes: self.lower_lifetimes(lifetimes),
692             types: types.iter().map(|ty| self.lower_ty(ty)).collect(),
693             infer_types: types.is_empty() && param_mode == ParamMode::Optional,
694             bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(),
695         }
696     }
697
698     fn lower_parenthesized_parameter_data(&mut self,
699                                           data: &ParenthesizedParameterData)
700                                           -> hir::ParenthesizedParameterData {
701         let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
702         hir::ParenthesizedParameterData {
703             inputs: inputs.iter().map(|ty| self.lower_ty(ty)).collect(),
704             output: output.as_ref().map(|ty| self.lower_ty(ty)),
705             span: span,
706         }
707     }
708
709     fn lower_local(&mut self, l: &Local) -> P<hir::Local> {
710         P(hir::Local {
711             id: l.id,
712             ty: l.ty.as_ref().map(|t| self.lower_ty(t)),
713             pat: self.lower_pat(&l.pat),
714             init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
715             span: l.span,
716             attrs: l.attrs.clone(),
717         })
718     }
719
720     fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
721         match m {
722             Mutability::Mutable => hir::MutMutable,
723             Mutability::Immutable => hir::MutImmutable,
724         }
725     }
726
727     fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
728         hir::Arg {
729             id: arg.id,
730             pat: self.lower_pat(&arg.pat),
731         }
732     }
733
734     fn lower_fn_args_to_names(&mut self, decl: &FnDecl)
735                               -> hir::HirVec<Spanned<Name>> {
736         decl.inputs.iter().map(|arg| {
737             match arg.pat.node {
738                 PatKind::Ident(_, ident, None) => {
739                     respan(ident.span, ident.node.name)
740                 }
741                 _ => respan(arg.pat.span, keywords::Invalid.name()),
742             }
743         }).collect()
744     }
745
746     fn lower_fn_decl(&mut self, decl: &FnDecl) -> P<hir::FnDecl> {
747         P(hir::FnDecl {
748             inputs: decl.inputs.iter().map(|arg| self.lower_ty(&arg.ty)).collect(),
749             output: match decl.output {
750                 FunctionRetTy::Ty(ref ty) => hir::Return(self.lower_ty(ty)),
751                 FunctionRetTy::Default(span) => hir::DefaultReturn(span),
752             },
753             variadic: decl.variadic,
754         })
755     }
756
757     fn lower_ty_param_bound(&mut self, tpb: &TyParamBound) -> hir::TyParamBound {
758         match *tpb {
759             TraitTyParamBound(ref ty, modifier) => {
760                 hir::TraitTyParamBound(self.lower_poly_trait_ref(ty),
761                                        self.lower_trait_bound_modifier(modifier))
762             }
763             RegionTyParamBound(ref lifetime) => {
764                 hir::RegionTyParamBound(self.lower_lifetime(lifetime))
765             }
766         }
767     }
768
769     fn lower_ty_param(&mut self, tp: &TyParam, add_bounds: &[TyParamBound]) -> hir::TyParam {
770         let mut name = tp.ident.name;
771
772         // Don't expose `Self` (recovered "keyword used as ident" parse error).
773         // `rustc::ty` expects `Self` to be only used for a trait's `Self`.
774         // Instead, use gensym("Self") to create a distinct name that looks the same.
775         if name == keywords::SelfType.name() {
776             name = Symbol::gensym("Self");
777         }
778
779         let mut bounds = self.lower_bounds(&tp.bounds);
780         if !add_bounds.is_empty() {
781             bounds = bounds.into_iter().chain(self.lower_bounds(add_bounds).into_iter()).collect();
782         }
783
784         hir::TyParam {
785             id: tp.id,
786             name: name,
787             bounds: bounds,
788             default: tp.default.as_ref().map(|x| self.lower_ty(x)),
789             span: tp.span,
790             pure_wrt_drop: tp.attrs.iter().any(|attr| attr.check_name("may_dangle")),
791         }
792     }
793
794     fn lower_ty_params(&mut self, tps: &Vec<TyParam>, add_bounds: &NodeMap<Vec<TyParamBound>>)
795                        -> hir::HirVec<hir::TyParam> {
796         tps.iter().map(|tp| {
797             self.lower_ty_param(tp, add_bounds.get(&tp.id).map_or(&[][..], |x| &x))
798         }).collect()
799     }
800
801     fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
802         hir::Lifetime {
803             id: l.id,
804             name: l.name,
805             span: l.span,
806         }
807     }
808
809     fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef {
810         hir::LifetimeDef {
811             lifetime: self.lower_lifetime(&l.lifetime),
812             bounds: self.lower_lifetimes(&l.bounds),
813             pure_wrt_drop: l.attrs.iter().any(|attr| attr.check_name("may_dangle")),
814         }
815     }
816
817     fn lower_lifetimes(&mut self, lts: &Vec<Lifetime>) -> hir::HirVec<hir::Lifetime> {
818         lts.iter().map(|l| self.lower_lifetime(l)).collect()
819     }
820
821     fn lower_lifetime_defs(&mut self, lts: &Vec<LifetimeDef>) -> hir::HirVec<hir::LifetimeDef> {
822         lts.iter().map(|l| self.lower_lifetime_def(l)).collect()
823     }
824
825     fn lower_generics(&mut self, g: &Generics) -> hir::Generics {
826         // Collect `?Trait` bounds in where clause and move them to parameter definitions.
827         let mut add_bounds = NodeMap();
828         for pred in &g.where_clause.predicates {
829             if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
830                 'next_bound: for bound in &bound_pred.bounds {
831                     if let TraitTyParamBound(_, TraitBoundModifier::Maybe) = *bound {
832                         let report_error = |this: &mut Self| {
833                             this.diagnostic().span_err(bound_pred.bounded_ty.span,
834                                                        "`?Trait` bounds are only permitted at the \
835                                                         point where a type parameter is declared");
836                         };
837                         // Check if the where clause type is a plain type parameter.
838                         match bound_pred.bounded_ty.node {
839                             TyKind::Path(None, ref path)
840                                     if path.segments.len() == 1 &&
841                                        bound_pred.bound_lifetimes.is_empty() => {
842                                 if let Some(Def::TyParam(def_id)) =
843                                         self.resolver.get_resolution(bound_pred.bounded_ty.id)
844                                                      .map(|d| d.base_def()) {
845                                     if let Some(node_id) =
846                                             self.resolver.definitions().as_local_node_id(def_id) {
847                                         for ty_param in &g.ty_params {
848                                             if node_id == ty_param.id {
849                                                 add_bounds.entry(ty_param.id).or_insert(Vec::new())
850                                                                             .push(bound.clone());
851                                                 continue 'next_bound;
852                                             }
853                                         }
854                                     }
855                                 }
856                                 report_error(self)
857                             }
858                             _ => report_error(self)
859                         }
860                     }
861                 }
862             }
863         }
864
865         hir::Generics {
866             ty_params: self.lower_ty_params(&g.ty_params, &add_bounds),
867             lifetimes: self.lower_lifetime_defs(&g.lifetimes),
868             where_clause: self.lower_where_clause(&g.where_clause),
869             span: g.span,
870         }
871     }
872
873     fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause {
874         hir::WhereClause {
875             id: wc.id,
876             predicates: wc.predicates
877                           .iter()
878                           .map(|predicate| self.lower_where_predicate(predicate))
879                           .collect(),
880         }
881     }
882
883     fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate {
884         match *pred {
885             WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_lifetimes,
886                                                                 ref bounded_ty,
887                                                                 ref bounds,
888                                                                 span}) => {
889                 hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
890                     bound_lifetimes: self.lower_lifetime_defs(bound_lifetimes),
891                     bounded_ty: self.lower_ty(bounded_ty),
892                     bounds: bounds.iter().filter_map(|bound| match *bound {
893                         // Ignore `?Trait` bounds, they were copied into type parameters already.
894                         TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
895                         _ => Some(self.lower_ty_param_bound(bound))
896                     }).collect(),
897                     span: span,
898                 })
899             }
900             WherePredicate::RegionPredicate(WhereRegionPredicate{ ref lifetime,
901                                                                   ref bounds,
902                                                                   span}) => {
903                 hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
904                     span: span,
905                     lifetime: self.lower_lifetime(lifetime),
906                     bounds: bounds.iter().map(|bound| self.lower_lifetime(bound)).collect(),
907                 })
908             }
909             WherePredicate::EqPredicate(WhereEqPredicate{ id,
910                                                           ref lhs_ty,
911                                                           ref rhs_ty,
912                                                           span}) => {
913                 hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
914                     id: id,
915                     lhs_ty: self.lower_ty(lhs_ty),
916                     rhs_ty: self.lower_ty(rhs_ty),
917                     span: span,
918                 })
919             }
920         }
921     }
922
923     fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
924         match *vdata {
925             VariantData::Struct(ref fields, id) => {
926                 hir::VariantData::Struct(fields.iter()
927                                                .enumerate()
928                                                .map(|f| self.lower_struct_field(f))
929                                                .collect(),
930                                          id)
931             }
932             VariantData::Tuple(ref fields, id) => {
933                 hir::VariantData::Tuple(fields.iter()
934                                               .enumerate()
935                                               .map(|f| self.lower_struct_field(f))
936                                               .collect(),
937                                         id)
938             }
939             VariantData::Unit(id) => hir::VariantData::Unit(id),
940         }
941     }
942
943     fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
944         let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit) {
945             hir::QPath::Resolved(None, path) => path.and_then(|path| path),
946             qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath)
947         };
948         hir::TraitRef {
949             path: path,
950             ref_id: p.ref_id,
951         }
952     }
953
954     fn lower_poly_trait_ref(&mut self, p: &PolyTraitRef) -> hir::PolyTraitRef {
955         hir::PolyTraitRef {
956             bound_lifetimes: self.lower_lifetime_defs(&p.bound_lifetimes),
957             trait_ref: self.lower_trait_ref(&p.trait_ref),
958             span: p.span,
959         }
960     }
961
962     fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField {
963         hir::StructField {
964             span: f.span,
965             id: f.id,
966             name: f.ident.map(|ident| ident.name).unwrap_or(Symbol::intern(&index.to_string())),
967             vis: self.lower_visibility(&f.vis),
968             ty: self.lower_ty(&f.ty),
969             attrs: self.lower_attrs(&f.attrs),
970         }
971     }
972
973     fn lower_field(&mut self, f: &Field) -> hir::Field {
974         hir::Field {
975             name: respan(f.ident.span, f.ident.node.name),
976             expr: P(self.lower_expr(&f.expr)),
977             span: f.span,
978             is_shorthand: f.is_shorthand,
979         }
980     }
981
982     fn lower_mt(&mut self, mt: &MutTy) -> hir::MutTy {
983         hir::MutTy {
984             ty: self.lower_ty(&mt.ty),
985             mutbl: self.lower_mutability(mt.mutbl),
986         }
987     }
988
989     fn lower_bounds(&mut self, bounds: &[TyParamBound]) -> hir::TyParamBounds {
990         bounds.iter().map(|bound| self.lower_ty_param_bound(bound)).collect()
991     }
992
993     fn lower_block(&mut self, b: &Block) -> P<hir::Block> {
994         let mut expr = None;
995
996         let mut stmts = b.stmts.iter().flat_map(|s| self.lower_stmt(s)).collect::<Vec<_>>();
997         if let Some(last) = stmts.pop() {
998             if let hir::StmtExpr(e, _) = last.node {
999                 expr = Some(e);
1000             } else {
1001                 stmts.push(last);
1002             }
1003         }
1004
1005         P(hir::Block {
1006             id: b.id,
1007             stmts: stmts.into(),
1008             expr: expr,
1009             rules: self.lower_block_check_mode(&b.rules),
1010             span: b.span,
1011         })
1012     }
1013
1014     fn lower_item_kind(&mut self,
1015                        id: NodeId,
1016                        name: &mut Name,
1017                        attrs: &hir::HirVec<Attribute>,
1018                        vis: &mut hir::Visibility,
1019                        i: &ItemKind)
1020                        -> hir::Item_ {
1021         match *i {
1022             ItemKind::ExternCrate(string) => hir::ItemExternCrate(string),
1023             ItemKind::Use(ref view_path) => {
1024                 let path = match view_path.node {
1025                     ViewPathSimple(_, ref path) => path,
1026                     ViewPathGlob(ref path) => path,
1027                     ViewPathList(ref path, ref path_list_idents) => {
1028                         for &Spanned { node: ref import, span } in path_list_idents {
1029                             // `use a::{self as x, b as y};` lowers to
1030                             // `use a as x; use a::b as y;`
1031                             let mut ident = import.name;
1032                             let suffix = if ident.name == keywords::SelfValue.name() {
1033                                 if let Some(last) = path.segments.last() {
1034                                     ident = last.identifier;
1035                                 }
1036                                 None
1037                             } else {
1038                                 Some(ident.name)
1039                             };
1040
1041                             let mut path = self.lower_path_extra(import.id, path, suffix,
1042                                                                  ParamMode::Explicit, true);
1043                             path.span = span;
1044                             self.items.insert(import.id, hir::Item {
1045                                 id: import.id,
1046                                 name: import.rename.unwrap_or(ident).name,
1047                                 attrs: attrs.clone(),
1048                                 node: hir::ItemUse(P(path), hir::UseKind::Single),
1049                                 vis: vis.clone(),
1050                                 span: span,
1051                             });
1052                         }
1053                         path
1054                     }
1055                 };
1056                 let path = P(self.lower_path(id, path, ParamMode::Explicit, true));
1057                 let kind = match view_path.node {
1058                     ViewPathSimple(ident, _) => {
1059                         *name = ident.name;
1060                         hir::UseKind::Single
1061                     }
1062                     ViewPathGlob(_) => {
1063                         hir::UseKind::Glob
1064                     }
1065                     ViewPathList(..) => {
1066                         // Privatize the degenerate import base, used only to check
1067                         // the stability of `use a::{};`, to avoid it showing up as
1068                         // a reexport by accident when `pub`, e.g. in documentation.
1069                         *vis = hir::Inherited;
1070                         hir::UseKind::ListStem
1071                     }
1072                 };
1073                 hir::ItemUse(path, kind)
1074             }
1075             ItemKind::Static(ref t, m, ref e) => {
1076                 let value = self.lower_expr(e);
1077                 hir::ItemStatic(self.lower_ty(t),
1078                                 self.lower_mutability(m),
1079                                 self.record_body(value, None))
1080             }
1081             ItemKind::Const(ref t, ref e) => {
1082                 let value = self.lower_expr(e);
1083                 hir::ItemConst(self.lower_ty(t),
1084                                self.record_body(value, None))
1085             }
1086             ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
1087                 self.with_new_scopes(|this| {
1088                     let body = this.lower_block(body);
1089                     let body = this.expr_block(body, ThinVec::new());
1090                     let body_id = this.record_body(body, Some(decl));
1091                     hir::ItemFn(this.lower_fn_decl(decl),
1092                                               this.lower_unsafety(unsafety),
1093                                               this.lower_constness(constness),
1094                                               abi,
1095                                               this.lower_generics(generics),
1096                                               body_id)
1097                 })
1098             }
1099             ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
1100             ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
1101             ItemKind::Ty(ref t, ref generics) => {
1102                 hir::ItemTy(self.lower_ty(t), self.lower_generics(generics))
1103             }
1104             ItemKind::Enum(ref enum_definition, ref generics) => {
1105                 hir::ItemEnum(hir::EnumDef {
1106                                   variants: enum_definition.variants
1107                                                            .iter()
1108                                                            .map(|x| self.lower_variant(x))
1109                                                            .collect(),
1110                               },
1111                               self.lower_generics(generics))
1112             }
1113             ItemKind::Struct(ref struct_def, ref generics) => {
1114                 let struct_def = self.lower_variant_data(struct_def);
1115                 hir::ItemStruct(struct_def, self.lower_generics(generics))
1116             }
1117             ItemKind::Union(ref vdata, ref generics) => {
1118                 let vdata = self.lower_variant_data(vdata);
1119                 hir::ItemUnion(vdata, self.lower_generics(generics))
1120             }
1121             ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
1122                 let trait_ref = self.lower_trait_ref(trait_ref);
1123
1124                 if let Def::Trait(def_id) = trait_ref.path.def {
1125                     self.trait_default_impl.insert(def_id, id);
1126                 }
1127
1128                 hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
1129                                      trait_ref)
1130             }
1131             ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
1132                 let new_impl_items = impl_items.iter()
1133                                                .map(|item| self.lower_impl_item_ref(item))
1134                                                .collect();
1135                 let ifce = ifce.as_ref().map(|trait_ref| self.lower_trait_ref(trait_ref));
1136
1137                 if let Some(ref trait_ref) = ifce {
1138                     if let Def::Trait(def_id) = trait_ref.path.def {
1139                         self.trait_impls.entry(def_id).or_insert(vec![]).push(id);
1140                     }
1141                 }
1142
1143                 hir::ItemImpl(self.lower_unsafety(unsafety),
1144                               self.lower_impl_polarity(polarity),
1145                               self.lower_generics(generics),
1146                               ifce,
1147                               self.lower_ty(ty),
1148                               new_impl_items)
1149             }
1150             ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => {
1151                 let bounds = self.lower_bounds(bounds);
1152                 let items = items.iter().map(|item| self.lower_trait_item_ref(item)).collect();
1153                 hir::ItemTrait(self.lower_unsafety(unsafety),
1154                                self.lower_generics(generics),
1155                                bounds,
1156                                items)
1157             }
1158             ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
1159         }
1160     }
1161
1162     fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
1163         self.with_parent_def(i.id, |this| {
1164             hir::TraitItem {
1165                 id: i.id,
1166                 name: i.ident.name,
1167                 attrs: this.lower_attrs(&i.attrs),
1168                 node: match i.node {
1169                     TraitItemKind::Const(ref ty, ref default) => {
1170                         hir::TraitItemKind::Const(this.lower_ty(ty),
1171                                                   default.as_ref().map(|x| {
1172                             let value = this.lower_expr(x);
1173                             this.record_body(value, None)
1174                         }))
1175                     }
1176                     TraitItemKind::Method(ref sig, None) => {
1177                         let names = this.lower_fn_args_to_names(&sig.decl);
1178                         hir::TraitItemKind::Method(this.lower_method_sig(sig),
1179                                                    hir::TraitMethod::Required(names))
1180                     }
1181                     TraitItemKind::Method(ref sig, Some(ref body)) => {
1182                         let body = this.lower_block(body);
1183                         let expr = this.expr_block(body, ThinVec::new());
1184                         let body_id = this.record_body(expr, Some(&sig.decl));
1185                         hir::TraitItemKind::Method(this.lower_method_sig(sig),
1186                                                    hir::TraitMethod::Provided(body_id))
1187                     }
1188                     TraitItemKind::Type(ref bounds, ref default) => {
1189                         hir::TraitItemKind::Type(this.lower_bounds(bounds),
1190                                                  default.as_ref().map(|x| this.lower_ty(x)))
1191                     }
1192                     TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"),
1193                 },
1194                 span: i.span,
1195             }
1196         })
1197     }
1198
1199     fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef {
1200         let (kind, has_default) = match i.node {
1201             TraitItemKind::Const(_, ref default) => {
1202                 (hir::AssociatedItemKind::Const, default.is_some())
1203             }
1204             TraitItemKind::Type(_, ref default) => {
1205                 (hir::AssociatedItemKind::Type, default.is_some())
1206             }
1207             TraitItemKind::Method(ref sig, ref default) => {
1208                 (hir::AssociatedItemKind::Method {
1209                     has_self: sig.decl.has_self(),
1210                  }, default.is_some())
1211             }
1212             TraitItemKind::Macro(..) => unimplemented!(),
1213         };
1214         hir::TraitItemRef {
1215             id: hir::TraitItemId { node_id: i.id },
1216             name: i.ident.name,
1217             span: i.span,
1218             defaultness: self.lower_defaultness(Defaultness::Default, has_default),
1219             kind: kind,
1220         }
1221     }
1222
1223     fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
1224         self.with_parent_def(i.id, |this| {
1225             hir::ImplItem {
1226                 id: i.id,
1227                 name: i.ident.name,
1228                 attrs: this.lower_attrs(&i.attrs),
1229                 vis: this.lower_visibility(&i.vis),
1230                 defaultness: this.lower_defaultness(i.defaultness, true /* [1] */),
1231                 node: match i.node {
1232                     ImplItemKind::Const(ref ty, ref expr) => {
1233                         let value = this.lower_expr(expr);
1234                         let body_id = this.record_body(value, None);
1235                         hir::ImplItemKind::Const(this.lower_ty(ty), body_id)
1236                     }
1237                     ImplItemKind::Method(ref sig, ref body) => {
1238                         let body = this.lower_block(body);
1239                         let expr = this.expr_block(body, ThinVec::new());
1240                         let body_id = this.record_body(expr, Some(&sig.decl));
1241                         hir::ImplItemKind::Method(this.lower_method_sig(sig), body_id)
1242                     }
1243                     ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)),
1244                     ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
1245                 },
1246                 span: i.span,
1247             }
1248         })
1249
1250         // [1] since `default impl` is not yet implemented, this is always true in impls
1251     }
1252
1253     fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
1254         hir::ImplItemRef {
1255             id: hir::ImplItemId { node_id: i.id },
1256             name: i.ident.name,
1257             span: i.span,
1258             vis: self.lower_visibility(&i.vis),
1259             defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
1260             kind: match i.node {
1261                 ImplItemKind::Const(..) => hir::AssociatedItemKind::Const,
1262                 ImplItemKind::Type(..) => hir::AssociatedItemKind::Type,
1263                 ImplItemKind::Method(ref sig, _) => hir::AssociatedItemKind::Method {
1264                     has_self: sig.decl.has_self(),
1265                 },
1266                 ImplItemKind::Macro(..) => unimplemented!(),
1267             },
1268         }
1269
1270         // [1] since `default impl` is not yet implemented, this is always true in impls
1271     }
1272
1273     fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
1274         hir::Mod {
1275             inner: m.inner,
1276             item_ids: m.items.iter().flat_map(|x| self.lower_item_id(x)).collect(),
1277         }
1278     }
1279
1280     fn lower_item_id(&mut self, i: &Item) -> SmallVector<hir::ItemId> {
1281         match i.node {
1282             ItemKind::Use(ref view_path) => {
1283                 if let ViewPathList(_, ref imports) = view_path.node {
1284                     return iter::once(i.id).chain(imports.iter().map(|import| import.node.id))
1285                         .map(|id| hir::ItemId { id: id }).collect();
1286                 }
1287             }
1288             ItemKind::MacroDef(..) => return SmallVector::new(),
1289             _ => {}
1290         }
1291         SmallVector::one(hir::ItemId { id: i.id })
1292     }
1293
1294     pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> {
1295         let mut name = i.ident.name;
1296         let attrs = self.lower_attrs(&i.attrs);
1297         let mut vis = self.lower_visibility(&i.vis);
1298         if let ItemKind::MacroDef(ref tts) = i.node {
1299             if i.attrs.iter().any(|attr| attr.name() == "macro_export") {
1300                 self.exported_macros.push(hir::MacroDef {
1301                     name: name, attrs: attrs, id: i.id, span: i.span, body: tts.clone().into(),
1302                 });
1303             }
1304             return None;
1305         }
1306
1307         let node = self.with_parent_def(i.id, |this| {
1308             this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node)
1309         });
1310
1311         Some(hir::Item {
1312             id: i.id,
1313             name: name,
1314             attrs: attrs,
1315             node: node,
1316             vis: vis,
1317             span: i.span,
1318         })
1319     }
1320
1321     fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
1322         self.with_parent_def(i.id, |this| {
1323             hir::ForeignItem {
1324                 id: i.id,
1325                 name: i.ident.name,
1326                 attrs: this.lower_attrs(&i.attrs),
1327                 node: match i.node {
1328                     ForeignItemKind::Fn(ref fdec, ref generics) => {
1329                         hir::ForeignItemFn(this.lower_fn_decl(fdec),
1330                                            this.lower_fn_args_to_names(fdec),
1331                                            this.lower_generics(generics))
1332                     }
1333                     ForeignItemKind::Static(ref t, m) => {
1334                         hir::ForeignItemStatic(this.lower_ty(t), m)
1335                     }
1336                 },
1337                 vis: this.lower_visibility(&i.vis),
1338                 span: i.span,
1339             }
1340         })
1341     }
1342
1343     fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig {
1344         hir::MethodSig {
1345             generics: self.lower_generics(&sig.generics),
1346             abi: sig.abi,
1347             unsafety: self.lower_unsafety(sig.unsafety),
1348             constness: self.lower_constness(sig.constness),
1349             decl: self.lower_fn_decl(&sig.decl),
1350         }
1351     }
1352
1353     fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
1354         match u {
1355             Unsafety::Unsafe => hir::Unsafety::Unsafe,
1356             Unsafety::Normal => hir::Unsafety::Normal,
1357         }
1358     }
1359
1360     fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
1361         match c.node {
1362             Constness::Const => hir::Constness::Const,
1363             Constness::NotConst => hir::Constness::NotConst,
1364         }
1365     }
1366
1367     fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
1368         match u {
1369             UnOp::Deref => hir::UnDeref,
1370             UnOp::Not => hir::UnNot,
1371             UnOp::Neg => hir::UnNeg,
1372         }
1373     }
1374
1375     fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
1376         Spanned {
1377             node: match b.node {
1378                 BinOpKind::Add => hir::BiAdd,
1379                 BinOpKind::Sub => hir::BiSub,
1380                 BinOpKind::Mul => hir::BiMul,
1381                 BinOpKind::Div => hir::BiDiv,
1382                 BinOpKind::Rem => hir::BiRem,
1383                 BinOpKind::And => hir::BiAnd,
1384                 BinOpKind::Or => hir::BiOr,
1385                 BinOpKind::BitXor => hir::BiBitXor,
1386                 BinOpKind::BitAnd => hir::BiBitAnd,
1387                 BinOpKind::BitOr => hir::BiBitOr,
1388                 BinOpKind::Shl => hir::BiShl,
1389                 BinOpKind::Shr => hir::BiShr,
1390                 BinOpKind::Eq => hir::BiEq,
1391                 BinOpKind::Lt => hir::BiLt,
1392                 BinOpKind::Le => hir::BiLe,
1393                 BinOpKind::Ne => hir::BiNe,
1394                 BinOpKind::Ge => hir::BiGe,
1395                 BinOpKind::Gt => hir::BiGt,
1396             },
1397             span: b.span,
1398         }
1399     }
1400
1401     fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
1402         P(hir::Pat {
1403             id: p.id,
1404             node: match p.node {
1405                 PatKind::Wild => hir::PatKind::Wild,
1406                 PatKind::Ident(ref binding_mode, pth1, ref sub) => {
1407                     self.with_parent_def(p.id, |this| {
1408                         match this.resolver.get_resolution(p.id).map(|d| d.base_def()) {
1409                             // `None` can occur in body-less function signatures
1410                             def @ None | def @ Some(Def::Local(_)) => {
1411                                 let def_id = def.map(|d| d.def_id()).unwrap_or_else(|| {
1412                                     this.resolver.definitions().local_def_id(p.id)
1413                                 });
1414                                 hir::PatKind::Binding(this.lower_binding_mode(binding_mode),
1415                                                       def_id,
1416                                                       respan(pth1.span, pth1.node.name),
1417                                                       sub.as_ref().map(|x| this.lower_pat(x)))
1418                             }
1419                             Some(def) => {
1420                                 hir::PatKind::Path(hir::QPath::Resolved(None, P(hir::Path {
1421                                     span: pth1.span,
1422                                     def: def,
1423                                     segments: hir_vec![
1424                                         hir::PathSegment::from_name(pth1.node.name)
1425                                     ],
1426                                 })))
1427                             }
1428                         }
1429                     })
1430                 }
1431                 PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
1432                 PatKind::TupleStruct(ref path, ref pats, ddpos) => {
1433                     let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);
1434                     hir::PatKind::TupleStruct(qpath,
1435                                               pats.iter().map(|x| self.lower_pat(x)).collect(),
1436                                               ddpos)
1437                 }
1438                 PatKind::Path(ref qself, ref path) => {
1439                     hir::PatKind::Path(self.lower_qpath(p.id, qself, path, ParamMode::Optional))
1440                 }
1441                 PatKind::Struct(ref path, ref fields, etc) => {
1442                     let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);
1443
1444                     let fs = fields.iter()
1445                                    .map(|f| {
1446                                        Spanned {
1447                                            span: f.span,
1448                                            node: hir::FieldPat {
1449                                                name: f.node.ident.name,
1450                                                pat: self.lower_pat(&f.node.pat),
1451                                                is_shorthand: f.node.is_shorthand,
1452                                            },
1453                                        }
1454                                    })
1455                                    .collect();
1456                     hir::PatKind::Struct(qpath, fs, etc)
1457                 }
1458                 PatKind::Tuple(ref elts, ddpos) => {
1459                     hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
1460                 }
1461                 PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
1462                 PatKind::Ref(ref inner, mutbl) => {
1463                     hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl))
1464                 }
1465                 PatKind::Range(ref e1, ref e2, ref end) => {
1466                     hir::PatKind::Range(P(self.lower_expr(e1)),
1467                                         P(self.lower_expr(e2)),
1468                                         self.lower_range_end(end))
1469                 }
1470                 PatKind::Slice(ref before, ref slice, ref after) => {
1471                     hir::PatKind::Slice(before.iter().map(|x| self.lower_pat(x)).collect(),
1472                                 slice.as_ref().map(|x| self.lower_pat(x)),
1473                                 after.iter().map(|x| self.lower_pat(x)).collect())
1474                 }
1475                 PatKind::Mac(_) => panic!("Shouldn't exist here"),
1476             },
1477             span: p.span,
1478         })
1479     }
1480
1481     fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
1482         match *e {
1483             RangeEnd::Included => hir::RangeEnd::Included,
1484             RangeEnd::Excluded => hir::RangeEnd::Excluded,
1485         }
1486     }
1487
1488     fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
1489         hir::Expr {
1490             id: e.id,
1491             node: match e.node {
1492                 // Issue #22181:
1493                 // Eventually a desugaring for `box EXPR`
1494                 // (similar to the desugaring above for `in PLACE BLOCK`)
1495                 // should go here, desugaring
1496                 //
1497                 // to:
1498                 //
1499                 // let mut place = BoxPlace::make_place();
1500                 // let raw_place = Place::pointer(&mut place);
1501                 // let value = $value;
1502                 // unsafe {
1503                 //     ::std::ptr::write(raw_place, value);
1504                 //     Boxed::finalize(place)
1505                 // }
1506                 //
1507                 // But for now there are type-inference issues doing that.
1508                 ExprKind::Box(ref e) => {
1509                     hir::ExprBox(P(self.lower_expr(e)))
1510                 }
1511
1512                 // Desugar ExprBox: `in (PLACE) EXPR`
1513                 ExprKind::InPlace(ref placer, ref value_expr) => {
1514                     // to:
1515                     //
1516                     // let p = PLACE;
1517                     // let mut place = Placer::make_place(p);
1518                     // let raw_place = Place::pointer(&mut place);
1519                     // push_unsafe!({
1520                     //     std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
1521                     //     InPlace::finalize(place)
1522                     // })
1523                     let placer_expr = P(self.lower_expr(placer));
1524                     let value_expr = P(self.lower_expr(value_expr));
1525
1526                     let placer_ident = self.str_to_ident("placer");
1527                     let place_ident = self.str_to_ident("place");
1528                     let p_ptr_ident = self.str_to_ident("p_ptr");
1529
1530                     let make_place = ["ops", "Placer", "make_place"];
1531                     let place_pointer = ["ops", "Place", "pointer"];
1532                     let move_val_init = ["intrinsics", "move_val_init"];
1533                     let inplace_finalize = ["ops", "InPlace", "finalize"];
1534
1535                     let unstable_span = self.allow_internal_unstable("<-", e.span);
1536                     let make_call = |this: &mut LoweringContext, p, args| {
1537                         let path = P(this.expr_std_path(unstable_span, p, ThinVec::new()));
1538                         P(this.expr_call(e.span, path, args))
1539                     };
1540
1541                     let mk_stmt_let = |this: &mut LoweringContext, bind, expr| {
1542                         this.stmt_let(e.span, false, bind, expr)
1543                     };
1544
1545                     let mk_stmt_let_mut = |this: &mut LoweringContext, bind, expr| {
1546                         this.stmt_let(e.span, true, bind, expr)
1547                     };
1548
1549                     // let placer = <placer_expr> ;
1550                     let (s1, placer_binding) = {
1551                         mk_stmt_let(self, placer_ident, placer_expr)
1552                     };
1553
1554                     // let mut place = Placer::make_place(placer);
1555                     let (s2, place_binding) = {
1556                         let placer = self.expr_ident(e.span, placer_ident, placer_binding);
1557                         let call = make_call(self, &make_place, hir_vec![placer]);
1558                         mk_stmt_let_mut(self, place_ident, call)
1559                     };
1560
1561                     // let p_ptr = Place::pointer(&mut place);
1562                     let (s3, p_ptr_binding) = {
1563                         let agent = P(self.expr_ident(e.span, place_ident, place_binding));
1564                         let args = hir_vec![self.expr_mut_addr_of(e.span, agent)];
1565                         let call = make_call(self, &place_pointer, args);
1566                         mk_stmt_let(self, p_ptr_ident, call)
1567                     };
1568
1569                     // pop_unsafe!(EXPR));
1570                     let pop_unsafe_expr = {
1571                         self.signal_block_expr(hir_vec![],
1572                                                value_expr,
1573                                                e.span,
1574                                                hir::PopUnsafeBlock(hir::CompilerGenerated),
1575                                                ThinVec::new())
1576                     };
1577
1578                     // push_unsafe!({
1579                     //     std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
1580                     //     InPlace::finalize(place)
1581                     // })
1582                     let expr = {
1583                         let ptr = self.expr_ident(e.span, p_ptr_ident, p_ptr_binding);
1584                         let call_move_val_init =
1585                             hir::StmtSemi(
1586                                 make_call(self, &move_val_init, hir_vec![ptr, pop_unsafe_expr]),
1587                                 self.next_id());
1588                         let call_move_val_init = respan(e.span, call_move_val_init);
1589
1590                         let place = self.expr_ident(e.span, place_ident, place_binding);
1591                         let call = make_call(self, &inplace_finalize, hir_vec![place]);
1592                         P(self.signal_block_expr(hir_vec![call_move_val_init],
1593                                                  call,
1594                                                  e.span,
1595                                                  hir::PushUnsafeBlock(hir::CompilerGenerated),
1596                                                  ThinVec::new()))
1597                     };
1598
1599                     let block = self.block_all(e.span, hir_vec![s1, s2, s3], Some(expr));
1600                     // add the attributes to the outer returned expr node
1601                     return self.expr_block(P(block), e.attrs.clone());
1602                 }
1603
1604                 ExprKind::Array(ref exprs) => {
1605                     hir::ExprArray(exprs.iter().map(|x| self.lower_expr(x)).collect())
1606                 }
1607                 ExprKind::Repeat(ref expr, ref count) => {
1608                     let expr = P(self.lower_expr(expr));
1609                     let count = self.lower_expr(count);
1610                     hir::ExprRepeat(expr, self.record_body(count, None))
1611                 }
1612                 ExprKind::Tup(ref elts) => {
1613                     hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect())
1614                 }
1615                 ExprKind::Call(ref f, ref args) => {
1616                     let f = P(self.lower_expr(f));
1617                     hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
1618                 }
1619                 ExprKind::MethodCall(i, ref tps, ref args) => {
1620                     let tps = tps.iter().map(|x| self.lower_ty(x)).collect();
1621                     let args = args.iter().map(|x| self.lower_expr(x)).collect();
1622                     hir::ExprMethodCall(respan(i.span, i.node.name), tps, args)
1623                 }
1624                 ExprKind::Binary(binop, ref lhs, ref rhs) => {
1625                     let binop = self.lower_binop(binop);
1626                     let lhs = P(self.lower_expr(lhs));
1627                     let rhs = P(self.lower_expr(rhs));
1628                     hir::ExprBinary(binop, lhs, rhs)
1629                 }
1630                 ExprKind::Unary(op, ref ohs) => {
1631                     let op = self.lower_unop(op);
1632                     let ohs = P(self.lower_expr(ohs));
1633                     hir::ExprUnary(op, ohs)
1634                 }
1635                 ExprKind::Lit(ref l) => hir::ExprLit(P((**l).clone())),
1636                 ExprKind::Cast(ref expr, ref ty) => {
1637                     let expr = P(self.lower_expr(expr));
1638                     hir::ExprCast(expr, self.lower_ty(ty))
1639                 }
1640                 ExprKind::Type(ref expr, ref ty) => {
1641                     let expr = P(self.lower_expr(expr));
1642                     hir::ExprType(expr, self.lower_ty(ty))
1643                 }
1644                 ExprKind::AddrOf(m, ref ohs) => {
1645                     let m = self.lower_mutability(m);
1646                     let ohs = P(self.lower_expr(ohs));
1647                     hir::ExprAddrOf(m, ohs)
1648                 }
1649                 // More complicated than you might expect because the else branch
1650                 // might be `if let`.
1651                 ExprKind::If(ref cond, ref blk, ref else_opt) => {
1652                     let else_opt = else_opt.as_ref().map(|els| {
1653                         match els.node {
1654                             ExprKind::IfLet(..) => {
1655                                 // wrap the if-let expr in a block
1656                                 let span = els.span;
1657                                 let els = P(self.lower_expr(els));
1658                                 let id = self.next_id();
1659                                 let blk = P(hir::Block {
1660                                     stmts: hir_vec![],
1661                                     expr: Some(els),
1662                                     id: id,
1663                                     rules: hir::DefaultBlock,
1664                                     span: span,
1665                                 });
1666                                 P(self.expr_block(blk, ThinVec::new()))
1667                             }
1668                             _ => P(self.lower_expr(els)),
1669                         }
1670                     });
1671
1672                     hir::ExprIf(P(self.lower_expr(cond)), self.lower_block(blk), else_opt)
1673                 }
1674                 ExprKind::While(ref cond, ref body, opt_ident) => {
1675                     self.with_loop_scope(e.id, |this|
1676                         hir::ExprWhile(
1677                             this.with_loop_condition_scope(|this| P(this.lower_expr(cond))),
1678                             this.lower_block(body),
1679                             this.lower_opt_sp_ident(opt_ident)))
1680                 }
1681                 ExprKind::Loop(ref body, opt_ident) => {
1682                     self.with_loop_scope(e.id, |this|
1683                         hir::ExprLoop(this.lower_block(body),
1684                                       this.lower_opt_sp_ident(opt_ident),
1685                                       hir::LoopSource::Loop))
1686                 }
1687                 ExprKind::Catch(ref body) => {
1688                     // FIXME(cramertj): Add catch to HIR
1689                     self.with_catch_scope(e.id, |this| hir::ExprBlock(this.lower_block(body)))
1690                 }
1691                 ExprKind::Match(ref expr, ref arms) => {
1692                     hir::ExprMatch(P(self.lower_expr(expr)),
1693                                    arms.iter().map(|x| self.lower_arm(x)).collect(),
1694                                    hir::MatchSource::Normal)
1695                 }
1696                 ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => {
1697                     self.with_new_scopes(|this| {
1698                         this.with_parent_def(e.id, |this| {
1699                             let expr = this.lower_expr(body);
1700                             hir::ExprClosure(this.lower_capture_clause(capture_clause),
1701                                              this.lower_fn_decl(decl),
1702                                              this.record_body(expr, Some(decl)),
1703                                              fn_decl_span)
1704                         })
1705                     })
1706                 }
1707                 ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk)),
1708                 ExprKind::Assign(ref el, ref er) => {
1709                     hir::ExprAssign(P(self.lower_expr(el)), P(self.lower_expr(er)))
1710                 }
1711                 ExprKind::AssignOp(op, ref el, ref er) => {
1712                     hir::ExprAssignOp(self.lower_binop(op),
1713                                       P(self.lower_expr(el)),
1714                                       P(self.lower_expr(er)))
1715                 }
1716                 ExprKind::Field(ref el, ident) => {
1717                     hir::ExprField(P(self.lower_expr(el)), respan(ident.span, ident.node.name))
1718                 }
1719                 ExprKind::TupField(ref el, ident) => {
1720                     hir::ExprTupField(P(self.lower_expr(el)), ident)
1721                 }
1722                 ExprKind::Index(ref el, ref er) => {
1723                     hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er)))
1724                 }
1725                 ExprKind::Range(ref e1, ref e2, lims) => {
1726                     fn make_struct(this: &mut LoweringContext,
1727                                    ast_expr: &Expr,
1728                                    path: &[&str],
1729                                    fields: &[(&str, &P<Expr>)]) -> hir::Expr {
1730                         let struct_path = &iter::once(&"ops").chain(path).map(|s| *s)
1731                                                              .collect::<Vec<_>>();
1732                         let unstable_span = this.allow_internal_unstable("...", ast_expr.span);
1733
1734                         if fields.len() == 0 {
1735                             this.expr_std_path(unstable_span, struct_path,
1736                                                ast_expr.attrs.clone())
1737                         } else {
1738                             let fields = fields.into_iter().map(|&(s, e)| {
1739                                 let expr = P(this.lower_expr(&e));
1740                                 let unstable_span = this.allow_internal_unstable("...", e.span);
1741                                 this.field(Symbol::intern(s), expr, unstable_span)
1742                             }).collect();
1743                             let attrs = ast_expr.attrs.clone();
1744
1745                             this.expr_std_struct(unstable_span, struct_path, fields, None, attrs)
1746                         }
1747                     }
1748
1749                     use syntax::ast::RangeLimits::*;
1750
1751                     return match (e1, e2, lims) {
1752                         (&None,         &None,         HalfOpen) =>
1753                             make_struct(self, e, &["RangeFull"], &[]),
1754
1755                         (&Some(ref e1), &None,         HalfOpen) =>
1756                             make_struct(self, e, &["RangeFrom"],
1757                                                  &[("start", e1)]),
1758
1759                         (&None,         &Some(ref e2), HalfOpen) =>
1760                             make_struct(self, e, &["RangeTo"],
1761                                                  &[("end", e2)]),
1762
1763                         (&Some(ref e1), &Some(ref e2), HalfOpen) =>
1764                             make_struct(self, e, &["Range"],
1765                                                  &[("start", e1), ("end", e2)]),
1766
1767                         (&None,         &Some(ref e2), Closed)   =>
1768                             make_struct(self, e, &["RangeToInclusive"],
1769                                                  &[("end", e2)]),
1770
1771                         (&Some(ref e1), &Some(ref e2), Closed)   =>
1772                             make_struct(self, e, &["RangeInclusive", "NonEmpty"],
1773                                                  &[("start", e1), ("end", e2)]),
1774
1775                         _ => panic!(self.diagnostic()
1776                                         .span_fatal(e.span, "inclusive range with no end")),
1777                     };
1778                 }
1779                 ExprKind::Path(ref qself, ref path) => {
1780                     hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional))
1781                 }
1782                 ExprKind::Break(opt_ident, ref opt_expr) => {
1783                     let label_result = if self.is_in_loop_condition && opt_ident.is_none() {
1784                         hir::Destination {
1785                             ident: opt_ident,
1786                             loop_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into(),
1787                         }
1788                     } else {
1789                         self.lower_destination(opt_ident.map(|ident| (e.id, ident)))
1790                     };
1791                     hir::ExprBreak(
1792                             label_result,
1793                             opt_expr.as_ref().map(|x| P(self.lower_expr(x))))
1794                 }
1795                 ExprKind::Continue(opt_ident) =>
1796                     hir::ExprAgain(
1797                         if self.is_in_loop_condition && opt_ident.is_none() {
1798                             hir::Destination {
1799                                 ident: opt_ident,
1800                                 loop_id: Err(
1801                                     hir::LoopIdError::UnlabeledCfInWhileCondition).into(),
1802                             }
1803                         } else {
1804                             self.lower_destination(opt_ident.map( |ident| (e.id, ident)))
1805                         }),
1806                 ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| P(self.lower_expr(x)))),
1807                 ExprKind::InlineAsm(ref asm) => {
1808                     let hir_asm = hir::InlineAsm {
1809                         inputs: asm.inputs.iter().map(|&(ref c, _)| c.clone()).collect(),
1810                         outputs: asm.outputs.iter().map(|out| {
1811                             hir::InlineAsmOutput {
1812                                 constraint: out.constraint.clone(),
1813                                 is_rw: out.is_rw,
1814                                 is_indirect: out.is_indirect,
1815                             }
1816                         }).collect(),
1817                         asm: asm.asm.clone(),
1818                         asm_str_style: asm.asm_str_style,
1819                         clobbers: asm.clobbers.clone().into(),
1820                         volatile: asm.volatile,
1821                         alignstack: asm.alignstack,
1822                         dialect: asm.dialect,
1823                         expn_id: asm.expn_id,
1824                     };
1825                     let outputs =
1826                         asm.outputs.iter().map(|out| self.lower_expr(&out.expr)).collect();
1827                     let inputs =
1828                         asm.inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect();
1829                     hir::ExprInlineAsm(P(hir_asm), outputs, inputs)
1830                 }
1831                 ExprKind::Struct(ref path, ref fields, ref maybe_expr) => {
1832                     hir::ExprStruct(self.lower_qpath(e.id, &None, path, ParamMode::Optional),
1833                                     fields.iter().map(|x| self.lower_field(x)).collect(),
1834                                     maybe_expr.as_ref().map(|x| P(self.lower_expr(x))))
1835                 }
1836                 ExprKind::Paren(ref ex) => {
1837                     let mut ex = self.lower_expr(ex);
1838                     // include parens in span, but only if it is a super-span.
1839                     if e.span.contains(ex.span) {
1840                         ex.span = e.span;
1841                     }
1842                     // merge attributes into the inner expression.
1843                     let mut attrs = e.attrs.clone();
1844                     attrs.extend::<Vec<_>>(ex.attrs.into());
1845                     ex.attrs = attrs;
1846                     return ex;
1847                 }
1848
1849                 // Desugar ExprIfLet
1850                 // From: `if let <pat> = <sub_expr> <body> [<else_opt>]`
1851                 ExprKind::IfLet(ref pat, ref sub_expr, ref body, ref else_opt) => {
1852                     // to:
1853                     //
1854                     //   match <sub_expr> {
1855                     //     <pat> => <body>,
1856                     //     [_ if <else_opt_if_cond> => <else_opt_if_body>,]
1857                     //     _ => [<else_opt> | ()]
1858                     //   }
1859
1860                     // `<pat> => <body>`
1861                     let pat_arm = {
1862                         let body = self.lower_block(body);
1863                         let body_expr = P(self.expr_block(body, ThinVec::new()));
1864                         let pat = self.lower_pat(pat);
1865                         self.arm(hir_vec![pat], body_expr)
1866                     };
1867
1868                     // `[_ if <else_opt_if_cond> => <else_opt_if_body>,]`
1869                     let mut else_opt = else_opt.as_ref().map(|e| P(self.lower_expr(e)));
1870                     let else_if_arms = {
1871                         let mut arms = vec![];
1872                         loop {
1873                             let else_opt_continue = else_opt.and_then(|els| {
1874                                 els.and_then(|els| {
1875                                     match els.node {
1876                                         // else if
1877                                         hir::ExprIf(cond, then, else_opt) => {
1878                                             let pat_under = self.pat_wild(e.span);
1879                                             arms.push(hir::Arm {
1880                                                 attrs: hir_vec![],
1881                                                 pats: hir_vec![pat_under],
1882                                                 guard: Some(cond),
1883                                                 body: P(self.expr_block(then, ThinVec::new())),
1884                                             });
1885                                             else_opt.map(|else_opt| (else_opt, true))
1886                                         }
1887                                         _ => Some((P(els), false)),
1888                                     }
1889                                 })
1890                             });
1891                             match else_opt_continue {
1892                                 Some((e, true)) => {
1893                                     else_opt = Some(e);
1894                                 }
1895                                 Some((e, false)) => {
1896                                     else_opt = Some(e);
1897                                     break;
1898                                 }
1899                                 None => {
1900                                     else_opt = None;
1901                                     break;
1902                                 }
1903                             }
1904                         }
1905                         arms
1906                     };
1907
1908                     let contains_else_clause = else_opt.is_some();
1909
1910                     // `_ => [<else_opt> | ()]`
1911                     let else_arm = {
1912                         let pat_under = self.pat_wild(e.span);
1913                         let else_expr =
1914                             else_opt.unwrap_or_else(|| self.expr_tuple(e.span, hir_vec![]));
1915                         self.arm(hir_vec![pat_under], else_expr)
1916                     };
1917
1918                     let mut arms = Vec::with_capacity(else_if_arms.len() + 2);
1919                     arms.push(pat_arm);
1920                     arms.extend(else_if_arms);
1921                     arms.push(else_arm);
1922
1923                     let sub_expr = P(self.lower_expr(sub_expr));
1924                     // add attributes to the outer returned expr node
1925                     return self.expr(e.span,
1926                                      hir::ExprMatch(sub_expr,
1927                                                     arms.into(),
1928                                                     hir::MatchSource::IfLetDesugar {
1929                                                         contains_else_clause: contains_else_clause,
1930                                                     }),
1931                                      e.attrs.clone());
1932                 }
1933
1934                 // Desugar ExprWhileLet
1935                 // From: `[opt_ident]: while let <pat> = <sub_expr> <body>`
1936                 ExprKind::WhileLet(ref pat, ref sub_expr, ref body, opt_ident) => {
1937                     // to:
1938                     //
1939                     //   [opt_ident]: loop {
1940                     //     match <sub_expr> {
1941                     //       <pat> => <body>,
1942                     //       _ => break
1943                     //     }
1944                     //   }
1945
1946                     // Note that the block AND the condition are evaluated in the loop scope.
1947                     // This is done to allow `break` from inside the condition of the loop.
1948                     let (body, break_expr, sub_expr) = self.with_loop_scope(e.id, |this| (
1949                         this.lower_block(body),
1950                         this.expr_break(e.span, ThinVec::new()),
1951                         this.with_loop_condition_scope(|this| P(this.lower_expr(sub_expr))),
1952                     ));
1953
1954                     // `<pat> => <body>`
1955                     let pat_arm = {
1956                         let body_expr = P(self.expr_block(body, ThinVec::new()));
1957                         let pat = self.lower_pat(pat);
1958                         self.arm(hir_vec![pat], body_expr)
1959                     };
1960
1961                     // `_ => break`
1962                     let break_arm = {
1963                         let pat_under = self.pat_wild(e.span);
1964                         self.arm(hir_vec![pat_under], break_expr)
1965                     };
1966
1967                     // `match <sub_expr> { ... }`
1968                     let arms = hir_vec![pat_arm, break_arm];
1969                     let match_expr = self.expr(e.span,
1970                                                hir::ExprMatch(sub_expr,
1971                                                               arms,
1972                                                               hir::MatchSource::WhileLetDesugar),
1973                                                ThinVec::new());
1974
1975                     // `[opt_ident]: loop { ... }`
1976                     let loop_block = P(self.block_expr(P(match_expr)));
1977                     let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident),
1978                                                   hir::LoopSource::WhileLet);
1979                     // add attributes to the outer returned expr node
1980                     let attrs = e.attrs.clone();
1981                     return hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs };
1982                 }
1983
1984                 // Desugar ExprForLoop
1985                 // From: `[opt_ident]: for <pat> in <head> <body>`
1986                 ExprKind::ForLoop(ref pat, ref head, ref body, opt_ident) => {
1987                     // to:
1988                     //
1989                     //   {
1990                     //     let result = match ::std::iter::IntoIterator::into_iter(<head>) {
1991                     //       mut iter => {
1992                     //         [opt_ident]: loop {
1993                     //           match ::std::iter::Iterator::next(&mut iter) {
1994                     //             ::std::option::Option::Some(<pat>) => <body>,
1995                     //             ::std::option::Option::None => break
1996                     //           }
1997                     //         }
1998                     //       }
1999                     //     };
2000                     //     result
2001                     //   }
2002
2003                     // expand <head>
2004                     let head = self.lower_expr(head);
2005
2006                     let iter = self.str_to_ident("iter");
2007
2008                     // `::std::option::Option::Some(<pat>) => <body>`
2009                     let pat_arm = {
2010                         let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body));
2011                         let body_expr = P(self.expr_block(body_block, ThinVec::new()));
2012                         let pat = self.lower_pat(pat);
2013                         let some_pat = self.pat_some(e.span, pat);
2014
2015                         self.arm(hir_vec![some_pat], body_expr)
2016                     };
2017
2018                     // `::std::option::Option::None => break`
2019                     let break_arm = {
2020                         let break_expr = self.with_loop_scope(e.id, |this|
2021                             this.expr_break(e.span, ThinVec::new()));
2022                         let pat = self.pat_none(e.span);
2023                         self.arm(hir_vec![pat], break_expr)
2024                     };
2025
2026                     // `mut iter`
2027                     let iter_pat = self.pat_ident_binding_mode(e.span, iter,
2028                                                                hir::BindByValue(hir::MutMutable));
2029
2030                     // `match ::std::iter::Iterator::next(&mut iter) { ... }`
2031                     let match_expr = {
2032                         let iter = P(self.expr_ident(e.span, iter, iter_pat.id));
2033                         let ref_mut_iter = self.expr_mut_addr_of(e.span, iter);
2034                         let next_path = &["iter", "Iterator", "next"];
2035                         let next_path = P(self.expr_std_path(e.span, next_path, ThinVec::new()));
2036                         let next_expr = P(self.expr_call(e.span, next_path,
2037                                           hir_vec![ref_mut_iter]));
2038                         let arms = hir_vec![pat_arm, break_arm];
2039
2040                         P(self.expr(e.span,
2041                                     hir::ExprMatch(next_expr, arms,
2042                                                    hir::MatchSource::ForLoopDesugar),
2043                                     ThinVec::new()))
2044                     };
2045
2046                     // `[opt_ident]: loop { ... }`
2047                     let loop_block = P(self.block_expr(match_expr));
2048                     let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident),
2049                                                   hir::LoopSource::ForLoop);
2050                     let loop_expr = P(hir::Expr {
2051                         id: e.id,
2052                         node: loop_expr,
2053                         span: e.span,
2054                         attrs: ThinVec::new(),
2055                     });
2056
2057                     // `mut iter => { ... }`
2058                     let iter_arm = self.arm(hir_vec![iter_pat], loop_expr);
2059
2060                     // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
2061                     let into_iter_expr = {
2062                         let into_iter_path = &["iter", "IntoIterator", "into_iter"];
2063                         let into_iter = P(self.expr_std_path(e.span, into_iter_path,
2064                                                              ThinVec::new()));
2065                         P(self.expr_call(e.span, into_iter, hir_vec![head]))
2066                     };
2067
2068                     let match_expr = P(self.expr_match(e.span,
2069                                                        into_iter_expr,
2070                                                        hir_vec![iter_arm],
2071                                                        hir::MatchSource::ForLoopDesugar));
2072
2073                     // `{ let _result = ...; _result }`
2074                     // underscore prevents an unused_variables lint if the head diverges
2075                     let result_ident = self.str_to_ident("_result");
2076                     let (let_stmt, let_stmt_binding) =
2077                         self.stmt_let(e.span, false, result_ident, match_expr);
2078
2079                     let result = P(self.expr_ident(e.span, result_ident, let_stmt_binding));
2080                     let block = P(self.block_all(e.span, hir_vec![let_stmt], Some(result)));
2081                     // add the attributes to the outer returned expr node
2082                     return self.expr_block(block, e.attrs.clone());
2083                 }
2084
2085                 // Desugar ExprKind::Try
2086                 // From: `<expr>?`
2087                 ExprKind::Try(ref sub_expr) => {
2088                     // to:
2089                     //
2090                     // match Carrier::translate(<expr>) {
2091                     //     Ok(val) => #[allow(unreachable_code)] val,
2092                     //     Err(err) => #[allow(unreachable_code)]
2093                     //                 return Carrier::from_error(From::from(err)),
2094                     // }
2095
2096                     // FIXME(cramertj): implement breaking to catch
2097                     if !self.catch_scopes.is_empty() {
2098                         bug!("`?` in catch scopes is unimplemented")
2099                     }
2100
2101                     let unstable_span = self.allow_internal_unstable("?", e.span);
2102
2103                     // Carrier::translate(<expr>)
2104                     let discr = {
2105                         // expand <expr>
2106                         let sub_expr = self.lower_expr(sub_expr);
2107
2108                         let path = &["ops", "Carrier", "translate"];
2109                         let path = P(self.expr_std_path(unstable_span, path, ThinVec::new()));
2110                         P(self.expr_call(e.span, path, hir_vec![sub_expr]))
2111                     };
2112
2113                     // #[allow(unreachable_code)]
2114                     let attr = {
2115                         // allow(unreachable_code)
2116                         let allow = {
2117                             let allow_ident = self.str_to_ident("allow");
2118                             let uc_ident = self.str_to_ident("unreachable_code");
2119                             let uc_meta_item = attr::mk_spanned_word_item(e.span, uc_ident);
2120                             let uc_nested = NestedMetaItemKind::MetaItem(uc_meta_item);
2121                             let uc_spanned = respan(e.span, uc_nested);
2122                             attr::mk_spanned_list_item(e.span, allow_ident, vec![uc_spanned])
2123                         };
2124                         attr::mk_spanned_attr_outer(e.span, attr::mk_attr_id(), allow)
2125                     };
2126                     let attrs = vec![attr];
2127
2128                     // Ok(val) => #[allow(unreachable_code)] val,
2129                     let ok_arm = {
2130                         let val_ident = self.str_to_ident("val");
2131                         let val_pat = self.pat_ident(e.span, val_ident);
2132                         let val_expr = P(self.expr_ident_with_attrs(e.span,
2133                                                                     val_ident,
2134                                                                     val_pat.id,
2135                                                                     ThinVec::from(attrs.clone())));
2136                         let ok_pat = self.pat_ok(e.span, val_pat);
2137
2138                         self.arm(hir_vec![ok_pat], val_expr)
2139                     };
2140
2141                     // Err(err) => #[allow(unreachable_code)]
2142                     //             return Carrier::from_error(From::from(err)),
2143                     let err_arm = {
2144                         let err_ident = self.str_to_ident("err");
2145                         let err_local = self.pat_ident(e.span, err_ident);
2146                         let from_expr = {
2147                             let path = &["convert", "From", "from"];
2148                             let from = P(self.expr_std_path(e.span, path, ThinVec::new()));
2149                             let err_expr = self.expr_ident(e.span, err_ident, err_local.id);
2150
2151                             self.expr_call(e.span, from, hir_vec![err_expr])
2152                         };
2153                         let from_err_expr = {
2154                             let path = &["ops", "Carrier", "from_error"];
2155                             let from_err = P(self.expr_std_path(unstable_span, path,
2156                                                                 ThinVec::new()));
2157                             P(self.expr_call(e.span, from_err, hir_vec![from_expr]))
2158                         };
2159
2160                         let ret_expr = P(self.expr(e.span,
2161                                                    hir::Expr_::ExprRet(Some(from_err_expr)),
2162                                                                        ThinVec::from(attrs)));
2163
2164                         let err_pat = self.pat_err(e.span, err_local);
2165                         self.arm(hir_vec![err_pat], ret_expr)
2166                     };
2167
2168                     return self.expr_match(e.span, discr, hir_vec![err_arm, ok_arm],
2169                                            hir::MatchSource::TryDesugar);
2170                 }
2171
2172                 ExprKind::Mac(_) => panic!("Shouldn't exist here"),
2173             },
2174             span: e.span,
2175             attrs: e.attrs.clone(),
2176         }
2177     }
2178
2179     fn lower_stmt(&mut self, s: &Stmt) -> SmallVector<hir::Stmt> {
2180         SmallVector::one(match s.node {
2181             StmtKind::Local(ref l) => Spanned {
2182                 node: hir::StmtDecl(P(Spanned {
2183                     node: hir::DeclLocal(self.lower_local(l)),
2184                     span: s.span,
2185                 }), s.id),
2186                 span: s.span,
2187             },
2188             StmtKind::Item(ref it) => {
2189                 // Can only use the ID once.
2190                 let mut id = Some(s.id);
2191                 return self.lower_item_id(it).into_iter().map(|item_id| Spanned {
2192                     node: hir::StmtDecl(P(Spanned {
2193                         node: hir::DeclItem(item_id),
2194                         span: s.span,
2195                     }), id.take().unwrap_or_else(|| self.next_id())),
2196                     span: s.span,
2197                 }).collect();
2198             }
2199             StmtKind::Expr(ref e) => {
2200                 Spanned {
2201                     node: hir::StmtExpr(P(self.lower_expr(e)), s.id),
2202                     span: s.span,
2203                 }
2204             }
2205             StmtKind::Semi(ref e) => {
2206                 Spanned {
2207                     node: hir::StmtSemi(P(self.lower_expr(e)), s.id),
2208                     span: s.span,
2209                 }
2210             }
2211             StmtKind::Mac(..) => panic!("Shouldn't exist here"),
2212         })
2213     }
2214
2215     fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause {
2216         match c {
2217             CaptureBy::Value => hir::CaptureByValue,
2218             CaptureBy::Ref => hir::CaptureByRef,
2219         }
2220     }
2221
2222     fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility {
2223         match *v {
2224             Visibility::Public => hir::Public,
2225             Visibility::Crate(_) => hir::Visibility::Crate,
2226             Visibility::Restricted { ref path, id } => {
2227                 hir::Visibility::Restricted {
2228                     path: P(self.lower_path(id, path, ParamMode::Explicit, true)),
2229                     id: id
2230                 }
2231             }
2232             Visibility::Inherited => hir::Inherited,
2233         }
2234     }
2235
2236     fn lower_defaultness(&mut self, d: Defaultness, has_value: bool) -> hir::Defaultness {
2237         match d {
2238             Defaultness::Default => hir::Defaultness::Default { has_value: has_value },
2239             Defaultness::Final => {
2240                 assert!(has_value);
2241                 hir::Defaultness::Final
2242             }
2243         }
2244     }
2245
2246     fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
2247         match *b {
2248             BlockCheckMode::Default => hir::DefaultBlock,
2249             BlockCheckMode::Unsafe(u) => hir::UnsafeBlock(self.lower_unsafe_source(u)),
2250         }
2251     }
2252
2253     fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingMode {
2254         match *b {
2255             BindingMode::ByRef(m) => hir::BindByRef(self.lower_mutability(m)),
2256             BindingMode::ByValue(m) => hir::BindByValue(self.lower_mutability(m)),
2257         }
2258     }
2259
2260     fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource {
2261         match u {
2262             CompilerGenerated => hir::CompilerGenerated,
2263             UserProvided => hir::UserProvided,
2264         }
2265     }
2266
2267     fn lower_impl_polarity(&mut self, i: ImplPolarity) -> hir::ImplPolarity {
2268         match i {
2269             ImplPolarity::Positive => hir::ImplPolarity::Positive,
2270             ImplPolarity::Negative => hir::ImplPolarity::Negative,
2271         }
2272     }
2273
2274     fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier {
2275         match f {
2276             TraitBoundModifier::None => hir::TraitBoundModifier::None,
2277             TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe,
2278         }
2279     }
2280
2281     // Helper methods for building HIR.
2282
2283     fn arm(&mut self, pats: hir::HirVec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
2284         hir::Arm {
2285             attrs: hir_vec![],
2286             pats: pats,
2287             guard: None,
2288             body: expr,
2289         }
2290     }
2291
2292     fn field(&mut self, name: Name, expr: P<hir::Expr>, span: Span) -> hir::Field {
2293         hir::Field {
2294             name: Spanned {
2295                 node: name,
2296                 span: span,
2297             },
2298             span: span,
2299             expr: expr,
2300             is_shorthand: false,
2301         }
2302     }
2303
2304     fn expr_break(&mut self, span: Span, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
2305         let expr_break = hir::ExprBreak(self.lower_destination(None), None);
2306         P(self.expr(span, expr_break, attrs))
2307     }
2308
2309     fn expr_call(&mut self, span: Span, e: P<hir::Expr>, args: hir::HirVec<hir::Expr>)
2310                  -> hir::Expr {
2311         self.expr(span, hir::ExprCall(e, args), ThinVec::new())
2312     }
2313
2314     fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> hir::Expr {
2315         self.expr_ident_with_attrs(span, id, binding, ThinVec::new())
2316     }
2317
2318     fn expr_ident_with_attrs(&mut self, span: Span,
2319                                         id: Name,
2320                                         binding: NodeId,
2321                                         attrs: ThinVec<Attribute>) -> hir::Expr {
2322         let def = {
2323             let defs = self.resolver.definitions();
2324             Def::Local(defs.local_def_id(binding))
2325         };
2326
2327         let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(hir::Path {
2328             span: span,
2329             def: def,
2330             segments: hir_vec![hir::PathSegment::from_name(id)],
2331         })));
2332
2333         self.expr(span, expr_path, attrs)
2334     }
2335
2336     fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> hir::Expr {
2337         self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), ThinVec::new())
2338     }
2339
2340     fn expr_std_path(&mut self,
2341                      span: Span,
2342                      components: &[&str],
2343                      attrs: ThinVec<Attribute>)
2344                      -> hir::Expr {
2345         let path = self.std_path(span, components, true);
2346         self.expr(span, hir::ExprPath(hir::QPath::Resolved(None, P(path))), attrs)
2347     }
2348
2349     fn expr_match(&mut self,
2350                   span: Span,
2351                   arg: P<hir::Expr>,
2352                   arms: hir::HirVec<hir::Arm>,
2353                   source: hir::MatchSource)
2354                   -> hir::Expr {
2355         self.expr(span, hir::ExprMatch(arg, arms, source), ThinVec::new())
2356     }
2357
2358     fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinVec<Attribute>) -> hir::Expr {
2359         self.expr(b.span, hir::ExprBlock(b), attrs)
2360     }
2361
2362     fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<hir::Expr>) -> P<hir::Expr> {
2363         P(self.expr(sp, hir::ExprTup(exprs), ThinVec::new()))
2364     }
2365
2366     fn expr_std_struct(&mut self,
2367                        span: Span,
2368                        components: &[&str],
2369                        fields: hir::HirVec<hir::Field>,
2370                        e: Option<P<hir::Expr>>,
2371                        attrs: ThinVec<Attribute>) -> hir::Expr {
2372         let path = self.std_path(span, components, false);
2373         let qpath = hir::QPath::Resolved(None, P(path));
2374         self.expr(span, hir::ExprStruct(qpath, fields, e), attrs)
2375     }
2376
2377     fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> hir::Expr {
2378         hir::Expr {
2379             id: self.next_id(),
2380             node: node,
2381             span: span,
2382             attrs: attrs,
2383         }
2384     }
2385
2386     fn stmt_let(&mut self, sp: Span, mutbl: bool, ident: Name, ex: P<hir::Expr>)
2387                 -> (hir::Stmt, NodeId) {
2388         let pat = if mutbl {
2389             self.pat_ident_binding_mode(sp, ident, hir::BindByValue(hir::MutMutable))
2390         } else {
2391             self.pat_ident(sp, ident)
2392         };
2393         let pat_id = pat.id;
2394         let local = P(hir::Local {
2395             pat: pat,
2396             ty: None,
2397             init: Some(ex),
2398             id: self.next_id(),
2399             span: sp,
2400             attrs: ThinVec::new(),
2401         });
2402         let decl = respan(sp, hir::DeclLocal(local));
2403         (respan(sp, hir::StmtDecl(P(decl), self.next_id())), pat_id)
2404     }
2405
2406     fn block_expr(&mut self, expr: P<hir::Expr>) -> hir::Block {
2407         self.block_all(expr.span, hir::HirVec::new(), Some(expr))
2408     }
2409
2410     fn block_all(&mut self, span: Span, stmts: hir::HirVec<hir::Stmt>, expr: Option<P<hir::Expr>>)
2411                  -> hir::Block {
2412         hir::Block {
2413             stmts: stmts,
2414             expr: expr,
2415             id: self.next_id(),
2416             rules: hir::DefaultBlock,
2417             span: span,
2418         }
2419     }
2420
2421     fn pat_ok(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
2422         self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat])
2423     }
2424
2425     fn pat_err(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
2426         self.pat_std_enum(span, &["result", "Result", "Err"], hir_vec![pat])
2427     }
2428
2429     fn pat_some(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
2430         self.pat_std_enum(span, &["option", "Option", "Some"], hir_vec![pat])
2431     }
2432
2433     fn pat_none(&mut self, span: Span) -> P<hir::Pat> {
2434         self.pat_std_enum(span, &["option", "Option", "None"], hir_vec![])
2435     }
2436
2437     fn pat_std_enum(&mut self,
2438                     span: Span,
2439                     components: &[&str],
2440                     subpats: hir::HirVec<P<hir::Pat>>)
2441                     -> P<hir::Pat> {
2442         let path = self.std_path(span, components, true);
2443         let qpath = hir::QPath::Resolved(None, P(path));
2444         let pt = if subpats.is_empty() {
2445             hir::PatKind::Path(qpath)
2446         } else {
2447             hir::PatKind::TupleStruct(qpath, subpats, None)
2448         };
2449         self.pat(span, pt)
2450     }
2451
2452     fn pat_ident(&mut self, span: Span, name: Name) -> P<hir::Pat> {
2453         self.pat_ident_binding_mode(span, name, hir::BindByValue(hir::MutImmutable))
2454     }
2455
2456     fn pat_ident_binding_mode(&mut self, span: Span, name: Name, bm: hir::BindingMode)
2457                               -> P<hir::Pat> {
2458         let id = self.next_id();
2459         let parent_def = self.parent_def;
2460         let def_id = {
2461             let defs = self.resolver.definitions();
2462             let def_path_data = DefPathData::Binding(name.as_str());
2463             let def_index = defs.create_def_with_parent(parent_def, id, def_path_data);
2464             DefId::local(def_index)
2465         };
2466
2467         P(hir::Pat {
2468             id: id,
2469             node: hir::PatKind::Binding(bm,
2470                                         def_id,
2471                                         Spanned {
2472                                             span: span,
2473                                             node: name,
2474                                         },
2475                                         None),
2476             span: span,
2477         })
2478     }
2479
2480     fn pat_wild(&mut self, span: Span) -> P<hir::Pat> {
2481         self.pat(span, hir::PatKind::Wild)
2482     }
2483
2484     fn pat(&mut self, span: Span, pat: hir::PatKind) -> P<hir::Pat> {
2485         P(hir::Pat {
2486             id: self.next_id(),
2487             node: pat,
2488             span: span,
2489         })
2490     }
2491
2492     /// Given suffix ["b","c","d"], returns path `::std::b::c::d` when
2493     /// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
2494     /// The path is also resolved according to `is_value`.
2495     fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path {
2496         let mut path = hir::Path {
2497             span: span,
2498             def: Def::Err,
2499             segments: iter::once(keywords::CrateRoot.name()).chain({
2500                 self.crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
2501             }).map(hir::PathSegment::from_name).collect(),
2502         };
2503
2504         self.resolver.resolve_hir_path(&mut path, is_value);
2505         path
2506     }
2507
2508     fn signal_block_expr(&mut self,
2509                          stmts: hir::HirVec<hir::Stmt>,
2510                          expr: P<hir::Expr>,
2511                          span: Span,
2512                          rule: hir::BlockCheckMode,
2513                          attrs: ThinVec<Attribute>)
2514                          -> hir::Expr {
2515         let id = self.next_id();
2516         let block = P(hir::Block {
2517             rules: rule,
2518             span: span,
2519             id: id,
2520             stmts: stmts,
2521             expr: Some(expr),
2522         });
2523         self.expr_block(block, attrs)
2524     }
2525
2526     fn ty_path(&mut self, id: NodeId, span: Span, qpath: hir::QPath) -> P<hir::Ty> {
2527         let mut id = id;
2528         let node = match qpath {
2529             hir::QPath::Resolved(None, path) => {
2530                 // Turn trait object paths into `TyTraitObject` instead.
2531                 if let Def::Trait(_) = path.def {
2532                     let principal = hir::PolyTraitRef {
2533                         bound_lifetimes: hir_vec![],
2534                         trait_ref: hir::TraitRef {
2535                             path: path.and_then(|path| path),
2536                             ref_id: id,
2537                         },
2538                         span,
2539                     };
2540
2541                     // The original ID is taken by the `PolyTraitRef`,
2542                     // so the `Ty` itself needs a different one.
2543                     id = self.next_id();
2544
2545                     hir::TyTraitObject(hir_vec![principal], self.elided_lifetime(span))
2546                 } else {
2547                     hir::TyPath(hir::QPath::Resolved(None, path))
2548                 }
2549             }
2550             _ => hir::TyPath(qpath)
2551         };
2552         P(hir::Ty { id, node, span })
2553     }
2554
2555     fn elided_lifetime(&mut self, span: Span) -> hir::Lifetime {
2556         hir::Lifetime {
2557             id: self.next_id(),
2558             span: span,
2559             name: keywords::Invalid.name()
2560         }
2561     }
2562 }
2563
2564 fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {
2565     // Sorting by span ensures that we get things in order within a
2566     // file, and also puts the files in a sensible order.
2567     let mut body_ids: Vec<_> = bodies.keys().cloned().collect();
2568     body_ids.sort_by_key(|b| bodies[b].value.span);
2569     body_ids
2570 }