]> git.lizzy.rs Git - rust.git/blob - src/librustc/hir/lowering.rs
Rollup merge of #35591 - GuillaumeGomez:generics_span, r=jntrmr
[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;
45 use hir::map::definitions::DefPathData;
46 use hir::def_id::{DefIndex, DefId};
47 use hir::def::{Def, PathResolution};
48 use session::Session;
49
50 use std::collections::BTreeMap;
51 use std::iter;
52 use syntax::ast::*;
53 use syntax::errors;
54 use syntax::ptr::P;
55 use syntax::codemap::{respan, Spanned};
56 use syntax::parse::token;
57 use syntax::std_inject;
58 use syntax::visit::{self, Visitor};
59 use syntax_pos::Span;
60
61 pub struct LoweringContext<'a> {
62     crate_root: Option<&'static str>,
63     // Use to assign ids to hir nodes that do not directly correspond to an ast node
64     sess: Option<&'a Session>,
65     // As we walk the AST we must keep track of the current 'parent' def id (in
66     // the form of a DefIndex) so that if we create a new node which introduces
67     // a definition, then we can properly create the def id.
68     parent_def: Option<DefIndex>,
69     resolver: &'a mut Resolver,
70 }
71
72 pub trait Resolver {
73     // Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc.
74     fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def;
75
76     // Obtain the resolution for a node id
77     fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution>;
78
79     // Record the resolution of a path or binding generated by the lowerer when expanding.
80     fn record_resolution(&mut self, id: NodeId, def: Def);
81
82     // We must keep the set of definitions up to date as we add nodes that weren't in the AST.
83     // This should only return `None` during testing.
84     fn definitions(&mut self) -> Option<&mut Definitions>;
85 }
86
87 pub struct DummyResolver;
88 impl Resolver for DummyResolver {
89     fn resolve_generated_global_path(&mut self, _path: &hir::Path, _is_value: bool) -> Def {
90         Def::Err
91     }
92     fn get_resolution(&mut self, _id: NodeId) -> Option<PathResolution> {
93         None
94     }
95     fn record_resolution(&mut self, _id: NodeId, _def: Def) {}
96     fn definitions(&mut self) -> Option<&mut Definitions> {
97         None
98     }
99 }
100
101 pub fn lower_crate(sess: &Session,
102                    krate: &Crate,
103                    resolver: &mut Resolver)
104                    -> hir::Crate {
105     // We're constructing the HIR here; we don't care what we will
106     // read, since we haven't even constructed the *input* to
107     // incr. comp. yet.
108     let _ignore = sess.dep_graph.in_ignore();
109
110     LoweringContext {
111         crate_root: if std_inject::no_core(krate) {
112             None
113         } else if std_inject::no_std(krate) {
114             Some("core")
115         } else {
116             Some("std")
117         },
118         sess: Some(sess),
119         parent_def: None,
120         resolver: resolver,
121     }.lower_crate(krate)
122 }
123
124 impl<'a> LoweringContext<'a> {
125     pub fn testing_context(resolver: &'a mut Resolver) -> Self {
126         LoweringContext {
127             crate_root: None,
128             sess: None,
129             parent_def: None,
130             resolver: resolver,
131         }
132     }
133
134     fn lower_crate(&mut self, c: &Crate) -> hir::Crate {
135         struct ItemLowerer<'lcx, 'interner: 'lcx> {
136             items: BTreeMap<NodeId, hir::Item>,
137             lctx: &'lcx mut LoweringContext<'interner>,
138         }
139
140         impl<'lcx, 'interner> Visitor for ItemLowerer<'lcx, 'interner> {
141             fn visit_item(&mut self, item: &Item) {
142                 self.items.insert(item.id, self.lctx.lower_item(item));
143                 visit::walk_item(self, item);
144             }
145         }
146
147         let items = {
148             let mut item_lowerer = ItemLowerer { items: BTreeMap::new(), lctx: self };
149             visit::walk_crate(&mut item_lowerer, c);
150             item_lowerer.items
151         };
152
153         hir::Crate {
154             module: self.lower_mod(&c.module),
155             attrs: self.lower_attrs(&c.attrs),
156             config: c.config.clone().into(),
157             span: c.span,
158             exported_macros: c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect(),
159             items: items,
160         }
161     }
162
163     fn next_id(&self) -> NodeId {
164         self.sess.map(Session::next_node_id).unwrap_or(0)
165     }
166
167     fn diagnostic(&self) -> &errors::Handler {
168         self.sess.map(Session::diagnostic)
169                  .unwrap_or_else(|| panic!("this lowerer cannot emit diagnostics"))
170     }
171
172     fn str_to_ident(&self, s: &'static str) -> Name {
173         token::gensym(s)
174     }
175
176     fn with_parent_def<T, F>(&mut self, parent_id: NodeId, f: F) -> T
177         where F: FnOnce(&mut LoweringContext) -> T
178     {
179         let old_def = self.parent_def;
180         self.parent_def = match self.resolver.definitions() {
181             Some(defs) => Some(defs.opt_def_index(parent_id).unwrap()),
182             None => old_def,
183         };
184
185         let result = f(self);
186
187         self.parent_def = old_def;
188         result
189     }
190
191     fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
192         o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
193     }
194
195     fn lower_attrs(&mut self, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
196         attrs.clone().into()
197     }
198
199     fn lower_view_path(&mut self, view_path: &ViewPath) -> P<hir::ViewPath> {
200         P(Spanned {
201             node: match view_path.node {
202                 ViewPathSimple(ident, ref path) => {
203                     hir::ViewPathSimple(ident.name, self.lower_path(path))
204                 }
205                 ViewPathGlob(ref path) => {
206                     hir::ViewPathGlob(self.lower_path(path))
207                 }
208                 ViewPathList(ref path, ref path_list_idents) => {
209                     hir::ViewPathList(self.lower_path(path),
210                                       path_list_idents.iter()
211                                                       .map(|item| self.lower_path_list_item(item))
212                                                       .collect())
213                 }
214             },
215             span: view_path.span,
216         })
217     }
218
219     fn lower_path_list_item(&mut self, path_list_ident: &PathListItem) -> hir::PathListItem {
220         Spanned {
221             node: match path_list_ident.node {
222                 PathListItemKind::Ident { id, name, rename } => hir::PathListIdent {
223                     id: id,
224                     name: name.name,
225                     rename: rename.map(|x| x.name),
226                 },
227                 PathListItemKind::Mod { id, rename } => hir::PathListMod {
228                     id: id,
229                     rename: rename.map(|x| x.name),
230                 },
231             },
232             span: path_list_ident.span,
233         }
234     }
235
236     fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {
237         hir::Arm {
238             attrs: self.lower_attrs(&arm.attrs),
239             pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(),
240             guard: arm.guard.as_ref().map(|ref x| self.lower_expr(x)),
241             body: self.lower_expr(&arm.body),
242         }
243     }
244
245     fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding {
246         hir::TypeBinding {
247             id: b.id,
248             name: b.ident.name,
249             ty: self.lower_ty(&b.ty),
250             span: b.span,
251         }
252     }
253
254     fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
255         use syntax::ast::TyKind::*;
256         P(hir::Ty {
257             id: t.id,
258             node: match t.node {
259                 Infer | ImplicitSelf => hir::TyInfer,
260                 Vec(ref ty) => hir::TyVec(self.lower_ty(ty)),
261                 Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
262                 Rptr(ref region, ref mt) => {
263                     hir::TyRptr(self.lower_opt_lifetime(region), self.lower_mt(mt))
264                 }
265                 BareFn(ref f) => {
266                     hir::TyBareFn(P(hir::BareFnTy {
267                         lifetimes: self.lower_lifetime_defs(&f.lifetimes),
268                         unsafety: self.lower_unsafety(f.unsafety),
269                         abi: f.abi,
270                         decl: self.lower_fn_decl(&f.decl),
271                     }))
272                 }
273                 Never => hir::TyNever,
274                 Tup(ref tys) => hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty)).collect()),
275                 Paren(ref ty) => {
276                     return self.lower_ty(ty);
277                 }
278                 Path(ref qself, ref path) => {
279                     let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
280                         hir::QSelf {
281                             ty: self.lower_ty(ty),
282                             position: position,
283                         }
284                     });
285                     hir::TyPath(qself, self.lower_path(path))
286                 }
287                 ObjectSum(ref ty, ref bounds) => {
288                     hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds))
289                 }
290                 FixedLengthVec(ref ty, ref e) => {
291                     hir::TyFixedLengthVec(self.lower_ty(ty), self.lower_expr(e))
292                 }
293                 Typeof(ref expr) => {
294                     hir::TyTypeof(self.lower_expr(expr))
295                 }
296                 PolyTraitRef(ref bounds) => {
297                     hir::TyPolyTraitRef(self.lower_bounds(bounds))
298                 }
299                 ImplTrait(ref bounds) => {
300                     hir::TyImplTrait(self.lower_bounds(bounds))
301                 }
302                 Mac(_) => panic!("TyMac should have been expanded by now."),
303             },
304             span: t.span,
305         })
306     }
307
308     fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod {
309         hir::ForeignMod {
310             abi: fm.abi,
311             items: fm.items.iter().map(|x| self.lower_foreign_item(x)).collect(),
312         }
313     }
314
315     fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
316         Spanned {
317             node: hir::Variant_ {
318                 name: v.node.name.name,
319                 attrs: self.lower_attrs(&v.node.attrs),
320                 data: self.lower_variant_data(&v.node.data),
321                 disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_expr(e)),
322             },
323             span: v.span,
324         }
325     }
326
327     fn lower_path(&mut self, p: &Path) -> hir::Path {
328         hir::Path {
329             global: p.global,
330             segments: p.segments
331                        .iter()
332                        .map(|&PathSegment { identifier, ref parameters }| {
333                            hir::PathSegment {
334                                name: identifier.name,
335                                parameters: self.lower_path_parameters(parameters),
336                            }
337                        })
338                        .collect(),
339             span: p.span,
340         }
341     }
342
343     fn lower_path_parameters(&mut self, path_parameters: &PathParameters) -> hir::PathParameters {
344         match *path_parameters {
345             PathParameters::AngleBracketed(ref data) =>
346                 hir::AngleBracketedParameters(self.lower_angle_bracketed_parameter_data(data)),
347             PathParameters::Parenthesized(ref data) =>
348                 hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)),
349         }
350     }
351
352     fn lower_angle_bracketed_parameter_data(&mut self,
353                                             data: &AngleBracketedParameterData)
354                                             -> hir::AngleBracketedParameterData {
355         let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data;
356         hir::AngleBracketedParameterData {
357             lifetimes: self.lower_lifetimes(lifetimes),
358             types: types.iter().map(|ty| self.lower_ty(ty)).collect(),
359             bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(),
360         }
361     }
362
363     fn lower_parenthesized_parameter_data(&mut self,
364                                           data: &ParenthesizedParameterData)
365                                           -> hir::ParenthesizedParameterData {
366         let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
367         hir::ParenthesizedParameterData {
368             inputs: inputs.iter().map(|ty| self.lower_ty(ty)).collect(),
369             output: output.as_ref().map(|ty| self.lower_ty(ty)),
370             span: span,
371         }
372     }
373
374     fn lower_local(&mut self, l: &Local) -> P<hir::Local> {
375         P(hir::Local {
376             id: l.id,
377             ty: l.ty.as_ref().map(|t| self.lower_ty(t)),
378             pat: self.lower_pat(&l.pat),
379             init: l.init.as_ref().map(|e| self.lower_expr(e)),
380             span: l.span,
381             attrs: l.attrs.clone(),
382         })
383     }
384
385     fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
386         match m {
387             Mutability::Mutable => hir::MutMutable,
388             Mutability::Immutable => hir::MutImmutable,
389         }
390     }
391
392     fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
393         hir::Arg {
394             id: arg.id,
395             pat: self.lower_pat(&arg.pat),
396             ty: self.lower_ty(&arg.ty),
397         }
398     }
399
400     fn lower_fn_decl(&mut self, decl: &FnDecl) -> P<hir::FnDecl> {
401         P(hir::FnDecl {
402             inputs: decl.inputs.iter().map(|x| self.lower_arg(x)).collect(),
403             output: match decl.output {
404                 FunctionRetTy::Ty(ref ty) => hir::Return(self.lower_ty(ty)),
405                 FunctionRetTy::Default(span) => hir::DefaultReturn(span),
406             },
407             variadic: decl.variadic,
408         })
409     }
410
411     fn lower_ty_param_bound(&mut self, tpb: &TyParamBound) -> hir::TyParamBound {
412         match *tpb {
413             TraitTyParamBound(ref ty, modifier) => {
414                 hir::TraitTyParamBound(self.lower_poly_trait_ref(ty),
415                                        self.lower_trait_bound_modifier(modifier))
416             }
417             RegionTyParamBound(ref lifetime) => {
418                 hir::RegionTyParamBound(self.lower_lifetime(lifetime))
419             }
420         }
421     }
422
423     fn lower_ty_param(&mut self, tp: &TyParam) -> hir::TyParam {
424         hir::TyParam {
425             id: tp.id,
426             name: tp.ident.name,
427             bounds: self.lower_bounds(&tp.bounds),
428             default: tp.default.as_ref().map(|x| self.lower_ty(x)),
429             span: tp.span,
430         }
431     }
432
433     fn lower_ty_params(&mut self, tps: &P<[TyParam]>) -> hir::HirVec<hir::TyParam> {
434         tps.iter().map(|tp| self.lower_ty_param(tp)).collect()
435     }
436
437     fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
438         hir::Lifetime {
439             id: l.id,
440             name: l.name,
441             span: l.span,
442         }
443     }
444
445     fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef {
446         hir::LifetimeDef {
447             lifetime: self.lower_lifetime(&l.lifetime),
448             bounds: self.lower_lifetimes(&l.bounds),
449         }
450     }
451
452     fn lower_lifetimes(&mut self, lts: &Vec<Lifetime>) -> hir::HirVec<hir::Lifetime> {
453         lts.iter().map(|l| self.lower_lifetime(l)).collect()
454     }
455
456     fn lower_lifetime_defs(&mut self, lts: &Vec<LifetimeDef>) -> hir::HirVec<hir::LifetimeDef> {
457         lts.iter().map(|l| self.lower_lifetime_def(l)).collect()
458     }
459
460     fn lower_opt_lifetime(&mut self, o_lt: &Option<Lifetime>) -> Option<hir::Lifetime> {
461         o_lt.as_ref().map(|lt| self.lower_lifetime(lt))
462     }
463
464     fn lower_generics(&mut self, g: &Generics) -> hir::Generics {
465         hir::Generics {
466             ty_params: self.lower_ty_params(&g.ty_params),
467             lifetimes: self.lower_lifetime_defs(&g.lifetimes),
468             where_clause: self.lower_where_clause(&g.where_clause),
469             span: g.span,
470         }
471     }
472
473     fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause {
474         hir::WhereClause {
475             id: wc.id,
476             predicates: wc.predicates
477                           .iter()
478                           .map(|predicate| self.lower_where_predicate(predicate))
479                           .collect(),
480         }
481     }
482
483     fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate {
484         match *pred {
485             WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_lifetimes,
486                                                                 ref bounded_ty,
487                                                                 ref bounds,
488                                                                 span}) => {
489                 hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
490                     bound_lifetimes: self.lower_lifetime_defs(bound_lifetimes),
491                     bounded_ty: self.lower_ty(bounded_ty),
492                     bounds: bounds.iter().map(|x| self.lower_ty_param_bound(x)).collect(),
493                     span: span,
494                 })
495             }
496             WherePredicate::RegionPredicate(WhereRegionPredicate{ ref lifetime,
497                                                                   ref bounds,
498                                                                   span}) => {
499                 hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
500                     span: span,
501                     lifetime: self.lower_lifetime(lifetime),
502                     bounds: bounds.iter().map(|bound| self.lower_lifetime(bound)).collect(),
503                 })
504             }
505             WherePredicate::EqPredicate(WhereEqPredicate{ id,
506                                                           ref path,
507                                                           ref ty,
508                                                           span}) => {
509                 hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
510                     id: id,
511                     path: self.lower_path(path),
512                     ty: self.lower_ty(ty),
513                     span: span,
514                 })
515             }
516         }
517     }
518
519     fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
520         match *vdata {
521             VariantData::Struct(ref fields, id) => {
522                 hir::VariantData::Struct(fields.iter()
523                                                .enumerate()
524                                                .map(|f| self.lower_struct_field(f))
525                                                .collect(),
526                                          id)
527             }
528             VariantData::Tuple(ref fields, id) => {
529                 hir::VariantData::Tuple(fields.iter()
530                                               .enumerate()
531                                               .map(|f| self.lower_struct_field(f))
532                                               .collect(),
533                                         id)
534             }
535             VariantData::Unit(id) => hir::VariantData::Unit(id),
536         }
537     }
538
539     fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
540         hir::TraitRef {
541             path: self.lower_path(&p.path),
542             ref_id: p.ref_id,
543         }
544     }
545
546     fn lower_poly_trait_ref(&mut self, p: &PolyTraitRef) -> hir::PolyTraitRef {
547         hir::PolyTraitRef {
548             bound_lifetimes: self.lower_lifetime_defs(&p.bound_lifetimes),
549             trait_ref: self.lower_trait_ref(&p.trait_ref),
550             span: p.span,
551         }
552     }
553
554     fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField {
555         hir::StructField {
556             span: f.span,
557             id: f.id,
558             name: f.ident.map(|ident| ident.name).unwrap_or(token::intern(&index.to_string())),
559             vis: self.lower_visibility(&f.vis),
560             ty: self.lower_ty(&f.ty),
561             attrs: self.lower_attrs(&f.attrs),
562         }
563     }
564
565     fn lower_field(&mut self, f: &Field) -> hir::Field {
566         hir::Field {
567             name: respan(f.ident.span, f.ident.node.name),
568             expr: self.lower_expr(&f.expr),
569             span: f.span,
570         }
571     }
572
573     fn lower_mt(&mut self, mt: &MutTy) -> hir::MutTy {
574         hir::MutTy {
575             ty: self.lower_ty(&mt.ty),
576             mutbl: self.lower_mutability(mt.mutbl),
577         }
578     }
579
580     fn lower_bounds(&mut self, bounds: &TyParamBounds) -> hir::TyParamBounds {
581         bounds.iter().map(|bound| self.lower_ty_param_bound(bound)).collect()
582     }
583
584     fn lower_block(&mut self, b: &Block) -> P<hir::Block> {
585         let mut stmts = Vec::new();
586         let mut expr = None;
587
588         if let Some((last, rest)) = b.stmts.split_last() {
589             stmts = rest.iter().map(|s| self.lower_stmt(s)).collect::<Vec<_>>();
590             let last = self.lower_stmt(last);
591             if let hir::StmtExpr(e, _) = last.node {
592                 expr = Some(e);
593             } else {
594                 stmts.push(last);
595             }
596         }
597
598         P(hir::Block {
599             id: b.id,
600             stmts: stmts.into(),
601             expr: expr,
602             rules: self.lower_block_check_mode(&b.rules),
603             span: b.span,
604         })
605     }
606
607     fn lower_item_kind(&mut self, i: &ItemKind) -> hir::Item_ {
608         match *i {
609             ItemKind::ExternCrate(string) => hir::ItemExternCrate(string),
610             ItemKind::Use(ref view_path) => {
611                 hir::ItemUse(self.lower_view_path(view_path))
612             }
613             ItemKind::Static(ref t, m, ref e) => {
614                 hir::ItemStatic(self.lower_ty(t),
615                                 self.lower_mutability(m),
616                                 self.lower_expr(e))
617             }
618             ItemKind::Const(ref t, ref e) => {
619                 hir::ItemConst(self.lower_ty(t), self.lower_expr(e))
620             }
621             ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
622                 hir::ItemFn(self.lower_fn_decl(decl),
623                             self.lower_unsafety(unsafety),
624                             self.lower_constness(constness),
625                             abi,
626                             self.lower_generics(generics),
627                             self.lower_block(body))
628             }
629             ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
630             ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
631             ItemKind::Ty(ref t, ref generics) => {
632                 hir::ItemTy(self.lower_ty(t), self.lower_generics(generics))
633             }
634             ItemKind::Enum(ref enum_definition, ref generics) => {
635                 hir::ItemEnum(hir::EnumDef {
636                                   variants: enum_definition.variants
637                                                            .iter()
638                                                            .map(|x| self.lower_variant(x))
639                                                            .collect(),
640                               },
641                               self.lower_generics(generics))
642             }
643             ItemKind::Struct(ref struct_def, ref generics) => {
644                 let struct_def = self.lower_variant_data(struct_def);
645                 hir::ItemStruct(struct_def, self.lower_generics(generics))
646             }
647             ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
648                 hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
649                                      self.lower_trait_ref(trait_ref))
650             }
651             ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
652                 let new_impl_items = impl_items.iter()
653                                                .map(|item| self.lower_impl_item(item))
654                                                .collect();
655                 let ifce = ifce.as_ref().map(|trait_ref| self.lower_trait_ref(trait_ref));
656                 hir::ItemImpl(self.lower_unsafety(unsafety),
657                               self.lower_impl_polarity(polarity),
658                               self.lower_generics(generics),
659                               ifce,
660                               self.lower_ty(ty),
661                               new_impl_items)
662             }
663             ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => {
664                 let bounds = self.lower_bounds(bounds);
665                 let items = items.iter().map(|item| self.lower_trait_item(item)).collect();
666                 hir::ItemTrait(self.lower_unsafety(unsafety),
667                                self.lower_generics(generics),
668                                bounds,
669                                items)
670             }
671             ItemKind::Mac(_) => panic!("Shouldn't still be around"),
672         }
673     }
674
675     fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
676         self.with_parent_def(i.id, |this| {
677             hir::TraitItem {
678                 id: i.id,
679                 name: i.ident.name,
680                 attrs: this.lower_attrs(&i.attrs),
681                 node: match i.node {
682                     TraitItemKind::Const(ref ty, ref default) => {
683                         hir::ConstTraitItem(this.lower_ty(ty),
684                                             default.as_ref().map(|x| this.lower_expr(x)))
685                     }
686                     TraitItemKind::Method(ref sig, ref body) => {
687                         hir::MethodTraitItem(this.lower_method_sig(sig),
688                                              body.as_ref().map(|x| this.lower_block(x)))
689                     }
690                     TraitItemKind::Type(ref bounds, ref default) => {
691                         hir::TypeTraitItem(this.lower_bounds(bounds),
692                                            default.as_ref().map(|x| this.lower_ty(x)))
693                     }
694                     TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"),
695                 },
696                 span: i.span,
697             }
698         })
699     }
700
701     fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
702         self.with_parent_def(i.id, |this| {
703             hir::ImplItem {
704                 id: i.id,
705                 name: i.ident.name,
706                 attrs: this.lower_attrs(&i.attrs),
707                 vis: this.lower_visibility(&i.vis),
708                 defaultness: this.lower_defaultness(i.defaultness),
709                 node: match i.node {
710                     ImplItemKind::Const(ref ty, ref expr) => {
711                         hir::ImplItemKind::Const(this.lower_ty(ty), this.lower_expr(expr))
712                     }
713                     ImplItemKind::Method(ref sig, ref body) => {
714                         hir::ImplItemKind::Method(this.lower_method_sig(sig),
715                                                   this.lower_block(body))
716                     }
717                     ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)),
718                     ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
719                 },
720                 span: i.span,
721             }
722         })
723     }
724
725     fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
726         hir::Mod {
727             inner: m.inner,
728             item_ids: m.items.iter().map(|x| self.lower_item_id(x)).collect(),
729         }
730     }
731
732     fn lower_macro_def(&mut self, m: &MacroDef) -> hir::MacroDef {
733         hir::MacroDef {
734             name: m.ident.name,
735             attrs: self.lower_attrs(&m.attrs),
736             id: m.id,
737             span: m.span,
738             imported_from: m.imported_from.map(|x| x.name),
739             export: m.export,
740             use_locally: m.use_locally,
741             allow_internal_unstable: m.allow_internal_unstable,
742             body: m.body.clone().into(),
743         }
744     }
745
746     fn lower_item_id(&mut self, i: &Item) -> hir::ItemId {
747         hir::ItemId { id: i.id }
748     }
749
750     pub fn lower_item(&mut self, i: &Item) -> hir::Item {
751         let node = self.with_parent_def(i.id, |this| {
752             this.lower_item_kind(&i.node)
753         });
754
755         hir::Item {
756             id: i.id,
757             name: i.ident.name,
758             attrs: self.lower_attrs(&i.attrs),
759             node: node,
760             vis: self.lower_visibility(&i.vis),
761             span: i.span,
762         }
763     }
764
765     fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
766         self.with_parent_def(i.id, |this| {
767             hir::ForeignItem {
768                 id: i.id,
769                 name: i.ident.name,
770                 attrs: this.lower_attrs(&i.attrs),
771                 node: match i.node {
772                     ForeignItemKind::Fn(ref fdec, ref generics) => {
773                         hir::ForeignItemFn(this.lower_fn_decl(fdec), this.lower_generics(generics))
774                     }
775                     ForeignItemKind::Static(ref t, m) => {
776                         hir::ForeignItemStatic(this.lower_ty(t), m)
777                     }
778                 },
779                 vis: this.lower_visibility(&i.vis),
780                 span: i.span,
781             }
782         })
783     }
784
785     fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig {
786         let hir_sig = hir::MethodSig {
787             generics: self.lower_generics(&sig.generics),
788             abi: sig.abi,
789             unsafety: self.lower_unsafety(sig.unsafety),
790             constness: self.lower_constness(sig.constness),
791             decl: self.lower_fn_decl(&sig.decl),
792         };
793         // Check for `self: _` and `self: &_`
794         if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) {
795             match hir_sig.decl.get_self().map(|eself| eself.node) {
796                 Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => {
797                     self.diagnostic().span_err(sig.decl.inputs[0].ty.span,
798                         "the type placeholder `_` is not allowed within types on item signatures");
799                 }
800                 _ => {}
801             }
802         }
803         hir_sig
804     }
805
806     fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
807         match u {
808             Unsafety::Unsafe => hir::Unsafety::Unsafe,
809             Unsafety::Normal => hir::Unsafety::Normal,
810         }
811     }
812
813     fn lower_constness(&mut self, c: Constness) -> hir::Constness {
814         match c {
815             Constness::Const => hir::Constness::Const,
816             Constness::NotConst => hir::Constness::NotConst,
817         }
818     }
819
820     fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
821         match u {
822             UnOp::Deref => hir::UnDeref,
823             UnOp::Not => hir::UnNot,
824             UnOp::Neg => hir::UnNeg,
825         }
826     }
827
828     fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
829         Spanned {
830             node: match b.node {
831                 BinOpKind::Add => hir::BiAdd,
832                 BinOpKind::Sub => hir::BiSub,
833                 BinOpKind::Mul => hir::BiMul,
834                 BinOpKind::Div => hir::BiDiv,
835                 BinOpKind::Rem => hir::BiRem,
836                 BinOpKind::And => hir::BiAnd,
837                 BinOpKind::Or => hir::BiOr,
838                 BinOpKind::BitXor => hir::BiBitXor,
839                 BinOpKind::BitAnd => hir::BiBitAnd,
840                 BinOpKind::BitOr => hir::BiBitOr,
841                 BinOpKind::Shl => hir::BiShl,
842                 BinOpKind::Shr => hir::BiShr,
843                 BinOpKind::Eq => hir::BiEq,
844                 BinOpKind::Lt => hir::BiLt,
845                 BinOpKind::Le => hir::BiLe,
846                 BinOpKind::Ne => hir::BiNe,
847                 BinOpKind::Ge => hir::BiGe,
848                 BinOpKind::Gt => hir::BiGt,
849             },
850             span: b.span,
851         }
852     }
853
854     fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
855         P(hir::Pat {
856             id: p.id,
857             node: match p.node {
858                 PatKind::Wild => hir::PatKind::Wild,
859                 PatKind::Ident(ref binding_mode, pth1, ref sub) => {
860                     self.with_parent_def(p.id, |this| {
861                         match this.resolver.get_resolution(p.id).map(|d| d.base_def) {
862                             // `None` can occur in body-less function signatures
863                             None | Some(Def::Local(..)) => {
864                                 hir::PatKind::Binding(this.lower_binding_mode(binding_mode),
865                                                       respan(pth1.span, pth1.node.name),
866                                                       sub.as_ref().map(|x| this.lower_pat(x)))
867                             }
868                             _ => hir::PatKind::Path(None, hir::Path::from_name(pth1.span,
869                                                                                pth1.node.name))
870                         }
871                     })
872                 }
873                 PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)),
874                 PatKind::TupleStruct(ref pth, ref pats, ddpos) => {
875                     hir::PatKind::TupleStruct(self.lower_path(pth),
876                                               pats.iter().map(|x| self.lower_pat(x)).collect(),
877                                               ddpos)
878                 }
879                 PatKind::Path(ref opt_qself, ref path) => {
880                     let opt_qself = opt_qself.as_ref().map(|qself| {
881                         hir::QSelf { ty: self.lower_ty(&qself.ty), position: qself.position }
882                     });
883                     hir::PatKind::Path(opt_qself, self.lower_path(path))
884                 }
885                 PatKind::Struct(ref pth, ref fields, etc) => {
886                     let pth = self.lower_path(pth);
887                     let fs = fields.iter()
888                                    .map(|f| {
889                                        Spanned {
890                                            span: f.span,
891                                            node: hir::FieldPat {
892                                                name: f.node.ident.name,
893                                                pat: self.lower_pat(&f.node.pat),
894                                                is_shorthand: f.node.is_shorthand,
895                                            },
896                                        }
897                                    })
898                                    .collect();
899                     hir::PatKind::Struct(pth, fs, etc)
900                 }
901                 PatKind::Tuple(ref elts, ddpos) => {
902                     hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
903                 }
904                 PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
905                 PatKind::Ref(ref inner, mutbl) => {
906                     hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl))
907                 }
908                 PatKind::Range(ref e1, ref e2) => {
909                     hir::PatKind::Range(self.lower_expr(e1), self.lower_expr(e2))
910                 }
911                 PatKind::Vec(ref before, ref slice, ref after) => {
912                     hir::PatKind::Vec(before.iter().map(|x| self.lower_pat(x)).collect(),
913                                 slice.as_ref().map(|x| self.lower_pat(x)),
914                                 after.iter().map(|x| self.lower_pat(x)).collect())
915                 }
916                 PatKind::Mac(_) => panic!("Shouldn't exist here"),
917             },
918             span: p.span,
919         })
920     }
921
922     fn lower_expr(&mut self, e: &Expr) -> P<hir::Expr> {
923         P(hir::Expr {
924             id: e.id,
925             node: match e.node {
926                 // Issue #22181:
927                 // Eventually a desugaring for `box EXPR`
928                 // (similar to the desugaring above for `in PLACE BLOCK`)
929                 // should go here, desugaring
930                 //
931                 // to:
932                 //
933                 // let mut place = BoxPlace::make_place();
934                 // let raw_place = Place::pointer(&mut place);
935                 // let value = $value;
936                 // unsafe {
937                 //     ::std::ptr::write(raw_place, value);
938                 //     Boxed::finalize(place)
939                 // }
940                 //
941                 // But for now there are type-inference issues doing that.
942                 ExprKind::Box(ref e) => {
943                     hir::ExprBox(self.lower_expr(e))
944                 }
945
946                 // Desugar ExprBox: `in (PLACE) EXPR`
947                 ExprKind::InPlace(ref placer, ref value_expr) => {
948                     // to:
949                     //
950                     // let p = PLACE;
951                     // let mut place = Placer::make_place(p);
952                     // let raw_place = Place::pointer(&mut place);
953                     // push_unsafe!({
954                     //     std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
955                     //     InPlace::finalize(place)
956                     // })
957                     let placer_expr = self.lower_expr(placer);
958                     let value_expr = self.lower_expr(value_expr);
959
960                     let placer_ident = self.str_to_ident("placer");
961                     let place_ident = self.str_to_ident("place");
962                     let p_ptr_ident = self.str_to_ident("p_ptr");
963
964                     let make_place = ["ops", "Placer", "make_place"];
965                     let place_pointer = ["ops", "Place", "pointer"];
966                     let move_val_init = ["intrinsics", "move_val_init"];
967                     let inplace_finalize = ["ops", "InPlace", "finalize"];
968
969                     let make_call = |this: &mut LoweringContext, p, args| {
970                         let path = this.std_path(e.span, p);
971                         let path = this.expr_path(path, ThinVec::new());
972                         this.expr_call(e.span, path, args)
973                     };
974
975                     let mk_stmt_let = |this: &mut LoweringContext, bind, expr| {
976                         this.stmt_let(e.span, false, bind, expr)
977                     };
978
979                     let mk_stmt_let_mut = |this: &mut LoweringContext, bind, expr| {
980                         this.stmt_let(e.span, true, bind, expr)
981                     };
982
983                     // let placer = <placer_expr> ;
984                     let (s1, placer_binding) = {
985                         let placer_expr = self.signal_block_expr(hir_vec![],
986                                                                  placer_expr,
987                                                                  e.span,
988                                                                  hir::PopUnstableBlock,
989                                                                  ThinVec::new());
990                         mk_stmt_let(self, placer_ident, placer_expr)
991                     };
992
993                     // let mut place = Placer::make_place(placer);
994                     let (s2, place_binding) = {
995                         let placer = self.expr_ident(e.span, placer_ident, placer_binding);
996                         let call = make_call(self, &make_place, hir_vec![placer]);
997                         mk_stmt_let_mut(self, place_ident, call)
998                     };
999
1000                     // let p_ptr = Place::pointer(&mut place);
1001                     let (s3, p_ptr_binding) = {
1002                         let agent = self.expr_ident(e.span, place_ident, place_binding);
1003                         let args = hir_vec![self.expr_mut_addr_of(e.span, agent)];
1004                         let call = make_call(self, &place_pointer, args);
1005                         mk_stmt_let(self, p_ptr_ident, call)
1006                     };
1007
1008                     // pop_unsafe!(EXPR));
1009                     let pop_unsafe_expr = {
1010                         let value_expr = self.signal_block_expr(hir_vec![],
1011                                                                 value_expr,
1012                                                                 e.span,
1013                                                                 hir::PopUnstableBlock,
1014                                                                 ThinVec::new());
1015                         self.signal_block_expr(hir_vec![],
1016                                                value_expr,
1017                                                e.span,
1018                                                hir::PopUnsafeBlock(hir::CompilerGenerated),
1019                                                ThinVec::new())
1020                     };
1021
1022                     // push_unsafe!({
1023                     //     std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
1024                     //     InPlace::finalize(place)
1025                     // })
1026                     let expr = {
1027                         let ptr = self.expr_ident(e.span, p_ptr_ident, p_ptr_binding);
1028                         let call_move_val_init =
1029                             hir::StmtSemi(
1030                                 make_call(self, &move_val_init, hir_vec![ptr, pop_unsafe_expr]),
1031                                 self.next_id());
1032                         let call_move_val_init = respan(e.span, call_move_val_init);
1033
1034                         let place = self.expr_ident(e.span, place_ident, place_binding);
1035                         let call = make_call(self, &inplace_finalize, hir_vec![place]);
1036                         self.signal_block_expr(hir_vec![call_move_val_init],
1037                                                call,
1038                                                e.span,
1039                                                hir::PushUnsafeBlock(hir::CompilerGenerated),
1040                                                ThinVec::new())
1041                     };
1042
1043                     return self.signal_block_expr(hir_vec![s1, s2, s3],
1044                                                   expr,
1045                                                   e.span,
1046                                                   hir::PushUnstableBlock,
1047                                                   e.attrs.clone());
1048                 }
1049
1050                 ExprKind::Vec(ref exprs) => {
1051                     hir::ExprVec(exprs.iter().map(|x| self.lower_expr(x)).collect())
1052                 }
1053                 ExprKind::Repeat(ref expr, ref count) => {
1054                     let expr = self.lower_expr(expr);
1055                     let count = self.lower_expr(count);
1056                     hir::ExprRepeat(expr, count)
1057                 }
1058                 ExprKind::Tup(ref elts) => {
1059                     hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect())
1060                 }
1061                 ExprKind::Call(ref f, ref args) => {
1062                     let f = self.lower_expr(f);
1063                     hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
1064                 }
1065                 ExprKind::MethodCall(i, ref tps, ref args) => {
1066                     let tps = tps.iter().map(|x| self.lower_ty(x)).collect();
1067                     let args = args.iter().map(|x| self.lower_expr(x)).collect();
1068                     hir::ExprMethodCall(respan(i.span, i.node.name), tps, args)
1069                 }
1070                 ExprKind::Binary(binop, ref lhs, ref rhs) => {
1071                     let binop = self.lower_binop(binop);
1072                     let lhs = self.lower_expr(lhs);
1073                     let rhs = self.lower_expr(rhs);
1074                     hir::ExprBinary(binop, lhs, rhs)
1075                 }
1076                 ExprKind::Unary(op, ref ohs) => {
1077                     let op = self.lower_unop(op);
1078                     let ohs = self.lower_expr(ohs);
1079                     hir::ExprUnary(op, ohs)
1080                 }
1081                 ExprKind::Lit(ref l) => hir::ExprLit(P((**l).clone())),
1082                 ExprKind::Cast(ref expr, ref ty) => {
1083                     let expr = self.lower_expr(expr);
1084                     hir::ExprCast(expr, self.lower_ty(ty))
1085                 }
1086                 ExprKind::Type(ref expr, ref ty) => {
1087                     let expr = self.lower_expr(expr);
1088                     hir::ExprType(expr, self.lower_ty(ty))
1089                 }
1090                 ExprKind::AddrOf(m, ref ohs) => {
1091                     let m = self.lower_mutability(m);
1092                     let ohs = self.lower_expr(ohs);
1093                     hir::ExprAddrOf(m, ohs)
1094                 }
1095                 // More complicated than you might expect because the else branch
1096                 // might be `if let`.
1097                 ExprKind::If(ref cond, ref blk, ref else_opt) => {
1098                     let else_opt = else_opt.as_ref().map(|els| {
1099                         match els.node {
1100                             ExprKind::IfLet(..) => {
1101                                 // wrap the if-let expr in a block
1102                                 let span = els.span;
1103                                 let els = self.lower_expr(els);
1104                                 let id = self.next_id();
1105                                 let blk = P(hir::Block {
1106                                     stmts: hir_vec![],
1107                                     expr: Some(els),
1108                                     id: id,
1109                                     rules: hir::DefaultBlock,
1110                                     span: span,
1111                                 });
1112                                 self.expr_block(blk, ThinVec::new())
1113                             }
1114                             _ => self.lower_expr(els),
1115                         }
1116                     });
1117
1118                     hir::ExprIf(self.lower_expr(cond), self.lower_block(blk), else_opt)
1119                 }
1120                 ExprKind::While(ref cond, ref body, opt_ident) => {
1121                     hir::ExprWhile(self.lower_expr(cond), self.lower_block(body),
1122                                    self.lower_opt_sp_ident(opt_ident))
1123                 }
1124                 ExprKind::Loop(ref body, opt_ident) => {
1125                     hir::ExprLoop(self.lower_block(body), self.lower_opt_sp_ident(opt_ident))
1126                 }
1127                 ExprKind::Match(ref expr, ref arms) => {
1128                     hir::ExprMatch(self.lower_expr(expr),
1129                                    arms.iter().map(|x| self.lower_arm(x)).collect(),
1130                                    hir::MatchSource::Normal)
1131                 }
1132                 ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => {
1133                     self.with_parent_def(e.id, |this| {
1134                         hir::ExprClosure(this.lower_capture_clause(capture_clause),
1135                                          this.lower_fn_decl(decl),
1136                                          this.lower_block(body),
1137                                          fn_decl_span)
1138                     })
1139                 }
1140                 ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk)),
1141                 ExprKind::Assign(ref el, ref er) => {
1142                     hir::ExprAssign(self.lower_expr(el), self.lower_expr(er))
1143                 }
1144                 ExprKind::AssignOp(op, ref el, ref er) => {
1145                     hir::ExprAssignOp(self.lower_binop(op),
1146                                       self.lower_expr(el),
1147                                       self.lower_expr(er))
1148                 }
1149                 ExprKind::Field(ref el, ident) => {
1150                     hir::ExprField(self.lower_expr(el), respan(ident.span, ident.node.name))
1151                 }
1152                 ExprKind::TupField(ref el, ident) => {
1153                     hir::ExprTupField(self.lower_expr(el), ident)
1154                 }
1155                 ExprKind::Index(ref el, ref er) => {
1156                     hir::ExprIndex(self.lower_expr(el), self.lower_expr(er))
1157                 }
1158                 ExprKind::Range(ref e1, ref e2, lims) => {
1159                     fn make_struct(this: &mut LoweringContext,
1160                                    ast_expr: &Expr,
1161                                    path: &[&str],
1162                                    fields: &[(&str, &P<Expr>)]) -> P<hir::Expr> {
1163                         let struct_path = this.std_path(ast_expr.span,
1164                                                         &iter::once(&"ops").chain(path)
1165                                                                            .map(|s| *s)
1166                                                                            .collect::<Vec<_>>());
1167
1168                         let hir_expr = if fields.len() == 0 {
1169                             this.expr_path(struct_path, ast_expr.attrs.clone())
1170                         } else {
1171                             let fields = fields.into_iter().map(|&(s, e)| {
1172                                 let expr = this.lower_expr(&e);
1173                                 let signal_block = this.signal_block_expr(hir_vec![],
1174                                                                           expr,
1175                                                                           e.span,
1176                                                                           hir::PopUnstableBlock,
1177                                                                           ThinVec::new());
1178                                 this.field(token::intern(s), signal_block, ast_expr.span)
1179                             }).collect();
1180                             let attrs = ast_expr.attrs.clone();
1181
1182                             this.expr_struct(ast_expr.span, struct_path, fields, None, attrs)
1183                         };
1184
1185                         this.signal_block_expr(hir_vec![],
1186                                                hir_expr,
1187                                                ast_expr.span,
1188                                                hir::PushUnstableBlock,
1189                                                ThinVec::new())
1190                     }
1191
1192                     use syntax::ast::RangeLimits::*;
1193
1194                     return match (e1, e2, lims) {
1195                         (&None,         &None,         HalfOpen) =>
1196                             make_struct(self, e, &["RangeFull"], &[]),
1197
1198                         (&Some(ref e1), &None,         HalfOpen) =>
1199                             make_struct(self, e, &["RangeFrom"],
1200                                                  &[("start", e1)]),
1201
1202                         (&None,         &Some(ref e2), HalfOpen) =>
1203                             make_struct(self, e, &["RangeTo"],
1204                                                  &[("end", e2)]),
1205
1206                         (&Some(ref e1), &Some(ref e2), HalfOpen) =>
1207                             make_struct(self, e, &["Range"],
1208                                                  &[("start", e1), ("end", e2)]),
1209
1210                         (&None,         &Some(ref e2), Closed)   =>
1211                             make_struct(self, e, &["RangeToInclusive"],
1212                                                  &[("end", e2)]),
1213
1214                         (&Some(ref e1), &Some(ref e2), Closed)   =>
1215                             make_struct(self, e, &["RangeInclusive", "NonEmpty"],
1216                                                  &[("start", e1), ("end", e2)]),
1217
1218                         _ => panic!(self.diagnostic()
1219                                         .span_fatal(e.span, "inclusive range with no end")),
1220                     };
1221                 }
1222                 ExprKind::Path(ref qself, ref path) => {
1223                     let hir_qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
1224                         hir::QSelf {
1225                             ty: self.lower_ty(ty),
1226                             position: position,
1227                         }
1228                     });
1229                     hir::ExprPath(hir_qself, self.lower_path(path))
1230                 }
1231                 ExprKind::Break(opt_ident) => hir::ExprBreak(self.lower_opt_sp_ident(opt_ident)),
1232                 ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)),
1233                 ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| self.lower_expr(x))),
1234                 ExprKind::InlineAsm(InlineAsm {
1235                         ref inputs,
1236                         ref outputs,
1237                         ref asm,
1238                         asm_str_style,
1239                         ref clobbers,
1240                         volatile,
1241                         alignstack,
1242                         dialect,
1243                         expn_id,
1244                     }) => hir::ExprInlineAsm(hir::InlineAsm {
1245                     inputs: inputs.iter().map(|&(ref c, _)| c.clone()).collect(),
1246                     outputs: outputs.iter()
1247                                     .map(|out| {
1248                                         hir::InlineAsmOutput {
1249                                             constraint: out.constraint.clone(),
1250                                             is_rw: out.is_rw,
1251                                             is_indirect: out.is_indirect,
1252                                         }
1253                                     })
1254                                     .collect(),
1255                     asm: asm.clone(),
1256                     asm_str_style: asm_str_style,
1257                     clobbers: clobbers.clone().into(),
1258                     volatile: volatile,
1259                     alignstack: alignstack,
1260                     dialect: dialect,
1261                     expn_id: expn_id,
1262                 }, outputs.iter().map(|out| self.lower_expr(&out.expr)).collect(),
1263                    inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect()),
1264                 ExprKind::Struct(ref path, ref fields, ref maybe_expr) => {
1265                     hir::ExprStruct(self.lower_path(path),
1266                                     fields.iter().map(|x| self.lower_field(x)).collect(),
1267                                     maybe_expr.as_ref().map(|x| self.lower_expr(x)))
1268                 }
1269                 ExprKind::Paren(ref ex) => {
1270                     return self.lower_expr(ex).map(|mut ex| {
1271                         // include parens in span, but only if it is a super-span.
1272                         if e.span.contains(ex.span) {
1273                             ex.span = e.span;
1274                         }
1275                         // merge attributes into the inner expression.
1276                         let mut attrs = e.attrs.clone();
1277                         attrs.extend::<Vec<_>>(ex.attrs.into());
1278                         ex.attrs = attrs;
1279                         ex
1280                     });
1281                 }
1282
1283                 // Desugar ExprIfLet
1284                 // From: `if let <pat> = <sub_expr> <body> [<else_opt>]`
1285                 ExprKind::IfLet(ref pat, ref sub_expr, ref body, ref else_opt) => {
1286                     // to:
1287                     //
1288                     //   match <sub_expr> {
1289                     //     <pat> => <body>,
1290                     //     [_ if <else_opt_if_cond> => <else_opt_if_body>,]
1291                     //     _ => [<else_opt> | ()]
1292                     //   }
1293
1294                     // `<pat> => <body>`
1295                     let pat_arm = {
1296                         let body = self.lower_block(body);
1297                         let body_expr = self.expr_block(body, ThinVec::new());
1298                         let pat = self.lower_pat(pat);
1299                         self.arm(hir_vec![pat], body_expr)
1300                     };
1301
1302                     // `[_ if <else_opt_if_cond> => <else_opt_if_body>,]`
1303                     let mut else_opt = else_opt.as_ref().map(|e| self.lower_expr(e));
1304                     let else_if_arms = {
1305                         let mut arms = vec![];
1306                         loop {
1307                             let else_opt_continue = else_opt.and_then(|els| {
1308                                 els.and_then(|els| {
1309                                     match els.node {
1310                                         // else if
1311                                         hir::ExprIf(cond, then, else_opt) => {
1312                                             let pat_under = self.pat_wild(e.span);
1313                                             arms.push(hir::Arm {
1314                                                 attrs: hir_vec![],
1315                                                 pats: hir_vec![pat_under],
1316                                                 guard: Some(cond),
1317                                                 body: self.expr_block(then, ThinVec::new()),
1318                                             });
1319                                             else_opt.map(|else_opt| (else_opt, true))
1320                                         }
1321                                         _ => Some((P(els), false)),
1322                                     }
1323                                 })
1324                             });
1325                             match else_opt_continue {
1326                                 Some((e, true)) => {
1327                                     else_opt = Some(e);
1328                                 }
1329                                 Some((e, false)) => {
1330                                     else_opt = Some(e);
1331                                     break;
1332                                 }
1333                                 None => {
1334                                     else_opt = None;
1335                                     break;
1336                                 }
1337                             }
1338                         }
1339                         arms
1340                     };
1341
1342                     let contains_else_clause = else_opt.is_some();
1343
1344                     // `_ => [<else_opt> | ()]`
1345                     let else_arm = {
1346                         let pat_under = self.pat_wild(e.span);
1347                         let else_expr =
1348                             else_opt.unwrap_or_else(|| self.expr_tuple(e.span, hir_vec![]));
1349                         self.arm(hir_vec![pat_under], else_expr)
1350                     };
1351
1352                     let mut arms = Vec::with_capacity(else_if_arms.len() + 2);
1353                     arms.push(pat_arm);
1354                     arms.extend(else_if_arms);
1355                     arms.push(else_arm);
1356
1357                     let sub_expr = self.lower_expr(sub_expr);
1358                     // add attributes to the outer returned expr node
1359                     return self.expr(e.span,
1360                                      hir::ExprMatch(sub_expr,
1361                                                     arms.into(),
1362                                                     hir::MatchSource::IfLetDesugar {
1363                                                         contains_else_clause: contains_else_clause,
1364                                                     }),
1365                                      e.attrs.clone());
1366                 }
1367
1368                 // Desugar ExprWhileLet
1369                 // From: `[opt_ident]: while let <pat> = <sub_expr> <body>`
1370                 ExprKind::WhileLet(ref pat, ref sub_expr, ref body, opt_ident) => {
1371                     // to:
1372                     //
1373                     //   [opt_ident]: loop {
1374                     //     match <sub_expr> {
1375                     //       <pat> => <body>,
1376                     //       _ => break
1377                     //     }
1378                     //   }
1379
1380                     // `<pat> => <body>`
1381                     let pat_arm = {
1382                         let body = self.lower_block(body);
1383                         let body_expr = self.expr_block(body, ThinVec::new());
1384                         let pat = self.lower_pat(pat);
1385                         self.arm(hir_vec![pat], body_expr)
1386                     };
1387
1388                     // `_ => break`
1389                     let break_arm = {
1390                         let pat_under = self.pat_wild(e.span);
1391                         let break_expr = self.expr_break(e.span, ThinVec::new());
1392                         self.arm(hir_vec![pat_under], break_expr)
1393                     };
1394
1395                     // `match <sub_expr> { ... }`
1396                     let arms = hir_vec![pat_arm, break_arm];
1397                     let sub_expr = self.lower_expr(sub_expr);
1398                     let match_expr = self.expr(e.span,
1399                                                hir::ExprMatch(sub_expr,
1400                                                               arms,
1401                                                               hir::MatchSource::WhileLetDesugar),
1402                                                ThinVec::new());
1403
1404                     // `[opt_ident]: loop { ... }`
1405                     let loop_block = self.block_expr(match_expr);
1406                     let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident));
1407                     // add attributes to the outer returned expr node
1408                     let attrs = e.attrs.clone();
1409                     return P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs });
1410                 }
1411
1412                 // Desugar ExprForLoop
1413                 // From: `[opt_ident]: for <pat> in <head> <body>`
1414                 ExprKind::ForLoop(ref pat, ref head, ref body, opt_ident) => {
1415                     // to:
1416                     //
1417                     //   {
1418                     //     let result = match ::std::iter::IntoIterator::into_iter(<head>) {
1419                     //       mut iter => {
1420                     //         [opt_ident]: loop {
1421                     //           match ::std::iter::Iterator::next(&mut iter) {
1422                     //             ::std::option::Option::Some(<pat>) => <body>,
1423                     //             ::std::option::Option::None => break
1424                     //           }
1425                     //         }
1426                     //       }
1427                     //     };
1428                     //     result
1429                     //   }
1430
1431                     // expand <head>
1432                     let head = self.lower_expr(head);
1433
1434                     let iter = self.str_to_ident("iter");
1435
1436                     // `::std::option::Option::Some(<pat>) => <body>`
1437                     let pat_arm = {
1438                         let body_block = self.lower_block(body);
1439                         let body_span = body_block.span;
1440                         let body_expr = P(hir::Expr {
1441                             id: self.next_id(),
1442                             node: hir::ExprBlock(body_block),
1443                             span: body_span,
1444                             attrs: ThinVec::new(),
1445                         });
1446                         let pat = self.lower_pat(pat);
1447                         let some_pat = self.pat_some(e.span, pat);
1448
1449                         self.arm(hir_vec![some_pat], body_expr)
1450                     };
1451
1452                     // `::std::option::Option::None => break`
1453                     let break_arm = {
1454                         let break_expr = self.expr_break(e.span, ThinVec::new());
1455                         let pat = self.pat_none(e.span);
1456                         self.arm(hir_vec![pat], break_expr)
1457                     };
1458
1459                     // `mut iter`
1460                     let iter_pat = self.pat_ident_binding_mode(e.span, iter,
1461                                                                hir::BindByValue(hir::MutMutable));
1462
1463                     // `match ::std::iter::Iterator::next(&mut iter) { ... }`
1464                     let match_expr = {
1465                         let next_path = self.std_path(e.span, &["iter", "Iterator", "next"]);
1466                         let iter = self.expr_ident(e.span, iter, iter_pat.id);
1467                         let ref_mut_iter = self.expr_mut_addr_of(e.span, iter);
1468                         let next_path = self.expr_path(next_path, ThinVec::new());
1469                         let next_expr = self.expr_call(e.span, next_path, hir_vec![ref_mut_iter]);
1470                         let arms = hir_vec![pat_arm, break_arm];
1471
1472                         self.expr(e.span,
1473                                   hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar),
1474                                   ThinVec::new())
1475                     };
1476
1477                     // `[opt_ident]: loop { ... }`
1478                     let loop_block = self.block_expr(match_expr);
1479                     let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident));
1480                     let loop_expr = P(hir::Expr {
1481                         id: e.id,
1482                         node: loop_expr,
1483                         span: e.span,
1484                         attrs: ThinVec::new(),
1485                     });
1486
1487                     // `mut iter => { ... }`
1488                     let iter_arm = self.arm(hir_vec![iter_pat], loop_expr);
1489
1490                     // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
1491                     let into_iter_expr = {
1492                         let into_iter_path = self.std_path(e.span,
1493                                                            &["iter", "IntoIterator", "into_iter"]);
1494
1495                         let into_iter = self.expr_path(into_iter_path, ThinVec::new());
1496                         self.expr_call(e.span, into_iter, hir_vec![head])
1497                     };
1498
1499                     let match_expr = self.expr_match(e.span,
1500                                                      into_iter_expr,
1501                                                      hir_vec![iter_arm],
1502                                                      hir::MatchSource::ForLoopDesugar);
1503
1504                     // `{ let _result = ...; _result }`
1505                     // underscore prevents an unused_variables lint if the head diverges
1506                     let result_ident = self.str_to_ident("_result");
1507                     let (let_stmt, let_stmt_binding) =
1508                         self.stmt_let(e.span, false, result_ident, match_expr);
1509
1510                     let result = self.expr_ident(e.span, result_ident, let_stmt_binding);
1511                     let block = self.block_all(e.span, hir_vec![let_stmt], Some(result));
1512                     // add the attributes to the outer returned expr node
1513                     return self.expr_block(block, e.attrs.clone());
1514                 }
1515
1516                 // Desugar ExprKind::Try
1517                 // From: `<expr>?`
1518                 ExprKind::Try(ref sub_expr) => {
1519                     // to:
1520                     //
1521                     // {
1522                     //     match { Carrier::translate( { <expr> } ) } {
1523                     //         Ok(val) => val,
1524                     //         Err(err) => { return Carrier::from_error(From::from(err)); }
1525                     //     }
1526                     // }
1527
1528                     // { Carrier::translate( { <expr> } ) }
1529                     let discr = {
1530                         // expand <expr>
1531                         let sub_expr = self.lower_expr(sub_expr);
1532                         let sub_expr = self.signal_block_expr(hir_vec![],
1533                                                               sub_expr,
1534                                                               e.span,
1535                                                               hir::PopUnstableBlock,
1536                                                               ThinVec::new());
1537
1538                         let path = self.std_path(e.span, &["ops", "Carrier", "translate"]);
1539                         let path = self.expr_path(path, ThinVec::new());
1540                         let call = self.expr_call(e.span, path, hir_vec![sub_expr]);
1541
1542                         self.signal_block_expr(hir_vec![],
1543                                                call,
1544                                                e.span,
1545                                                hir::PushUnstableBlock,
1546                                                ThinVec::new())
1547                     };
1548
1549                     // Ok(val) => val
1550                     let ok_arm = {
1551                         let val_ident = self.str_to_ident("val");
1552                         let val_pat = self.pat_ident(e.span, val_ident);
1553                         let val_expr = self.expr_ident(e.span, val_ident, val_pat.id);
1554                         let ok_pat = self.pat_ok(e.span, val_pat);
1555
1556                         self.arm(hir_vec![ok_pat], val_expr)
1557                     };
1558
1559                     // Err(err) => { return Carrier::from_error(From::from(err)); }
1560                     let err_arm = {
1561                         let err_ident = self.str_to_ident("err");
1562                         let err_local = self.pat_ident(e.span, err_ident);
1563                         let from_expr = {
1564                             let path = self.std_path(e.span, &["convert", "From", "from"]);
1565                             let from = self.expr_path(path, ThinVec::new());
1566                             let err_expr = self.expr_ident(e.span, err_ident, err_local.id);
1567
1568                             self.expr_call(e.span, from, hir_vec![err_expr])
1569                         };
1570                         let from_err_expr = {
1571                             let path = self.std_path(e.span, &["ops", "Carrier", "from_error"]);
1572                             let from_err = self.expr_path(path, ThinVec::new());
1573                             self.expr_call(e.span, from_err, hir_vec![from_expr])
1574                         };
1575
1576                         let ret_expr = self.expr(e.span,
1577                                                  hir::Expr_::ExprRet(Some(from_err_expr)),
1578                                                                      ThinVec::new());
1579                         let ret_stmt = self.stmt_expr(ret_expr);
1580                         let block = self.signal_block_stmt(ret_stmt, e.span,
1581                                                            hir::PushUnstableBlock, ThinVec::new());
1582
1583                         let err_pat = self.pat_err(e.span, err_local);
1584                         self.arm(hir_vec![err_pat], block)
1585                     };
1586
1587                     return self.expr_match(e.span, discr, hir_vec![err_arm, ok_arm],
1588                                            hir::MatchSource::TryDesugar);
1589                 }
1590
1591                 ExprKind::Mac(_) => panic!("Shouldn't exist here"),
1592             },
1593             span: e.span,
1594             attrs: e.attrs.clone(),
1595         })
1596     }
1597
1598     fn lower_stmt(&mut self, s: &Stmt) -> hir::Stmt {
1599         match s.node {
1600             StmtKind::Local(ref l) => Spanned {
1601                 node: hir::StmtDecl(P(Spanned {
1602                     node: hir::DeclLocal(self.lower_local(l)),
1603                     span: s.span,
1604                 }), s.id),
1605                 span: s.span,
1606             },
1607             StmtKind::Item(ref it) => Spanned {
1608                 node: hir::StmtDecl(P(Spanned {
1609                     node: hir::DeclItem(self.lower_item_id(it)),
1610                     span: s.span,
1611                 }), s.id),
1612                 span: s.span,
1613             },
1614             StmtKind::Expr(ref e) => {
1615                 Spanned {
1616                     node: hir::StmtExpr(self.lower_expr(e), s.id),
1617                     span: s.span,
1618                 }
1619             }
1620             StmtKind::Semi(ref e) => {
1621                 Spanned {
1622                     node: hir::StmtSemi(self.lower_expr(e), s.id),
1623                     span: s.span,
1624                 }
1625             }
1626             StmtKind::Mac(..) => panic!("Shouldn't exist here"),
1627         }
1628     }
1629
1630     fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause {
1631         match c {
1632             CaptureBy::Value => hir::CaptureByValue,
1633             CaptureBy::Ref => hir::CaptureByRef,
1634         }
1635     }
1636
1637     fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility {
1638         match *v {
1639             Visibility::Public => hir::Public,
1640             Visibility::Crate(_) => hir::Visibility::Crate,
1641             Visibility::Restricted { ref path, id } =>
1642                 hir::Visibility::Restricted { path: P(self.lower_path(path)), id: id },
1643             Visibility::Inherited => hir::Inherited,
1644         }
1645     }
1646
1647     fn lower_defaultness(&mut self, d: Defaultness) -> hir::Defaultness {
1648         match d {
1649             Defaultness::Default => hir::Defaultness::Default,
1650             Defaultness::Final => hir::Defaultness::Final,
1651         }
1652     }
1653
1654     fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
1655         match *b {
1656             BlockCheckMode::Default => hir::DefaultBlock,
1657             BlockCheckMode::Unsafe(u) => hir::UnsafeBlock(self.lower_unsafe_source(u)),
1658         }
1659     }
1660
1661     fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingMode {
1662         match *b {
1663             BindingMode::ByRef(m) => hir::BindByRef(self.lower_mutability(m)),
1664             BindingMode::ByValue(m) => hir::BindByValue(self.lower_mutability(m)),
1665         }
1666     }
1667
1668     fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource {
1669         match u {
1670             CompilerGenerated => hir::CompilerGenerated,
1671             UserProvided => hir::UserProvided,
1672         }
1673     }
1674
1675     fn lower_impl_polarity(&mut self, i: ImplPolarity) -> hir::ImplPolarity {
1676         match i {
1677             ImplPolarity::Positive => hir::ImplPolarity::Positive,
1678             ImplPolarity::Negative => hir::ImplPolarity::Negative,
1679         }
1680     }
1681
1682     fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier {
1683         match f {
1684             TraitBoundModifier::None => hir::TraitBoundModifier::None,
1685             TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe,
1686         }
1687     }
1688
1689     // Helper methods for building HIR.
1690
1691     fn arm(&mut self, pats: hir::HirVec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
1692         hir::Arm {
1693             attrs: hir_vec![],
1694             pats: pats,
1695             guard: None,
1696             body: expr,
1697         }
1698     }
1699
1700     fn field(&mut self, name: Name, expr: P<hir::Expr>, span: Span) -> hir::Field {
1701         hir::Field {
1702             name: Spanned {
1703                 node: name,
1704                 span: span,
1705             },
1706             span: span,
1707             expr: expr,
1708         }
1709     }
1710
1711     fn expr_break(&mut self, span: Span, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
1712         self.expr(span, hir::ExprBreak(None), attrs)
1713     }
1714
1715     fn expr_call(&mut self, span: Span, e: P<hir::Expr>, args: hir::HirVec<P<hir::Expr>>)
1716                  -> P<hir::Expr> {
1717         self.expr(span, hir::ExprCall(e, args), ThinVec::new())
1718     }
1719
1720     fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> P<hir::Expr> {
1721         let expr_path = hir::ExprPath(None, self.path_ident(span, id));
1722         let expr = self.expr(span, expr_path, ThinVec::new());
1723
1724         let def = self.resolver.definitions().map(|defs| {
1725             Def::Local(defs.local_def_id(binding), binding)
1726         }).unwrap_or(Def::Err);
1727         self.resolver.record_resolution(expr.id, def);
1728
1729         expr
1730     }
1731
1732     fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> P<hir::Expr> {
1733         self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), ThinVec::new())
1734     }
1735
1736     fn expr_path(&mut self, path: hir::Path, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
1737         let def = self.resolver.resolve_generated_global_path(&path, true);
1738         let expr = self.expr(path.span, hir::ExprPath(None, path), attrs);
1739         self.resolver.record_resolution(expr.id, def);
1740         expr
1741     }
1742
1743     fn expr_match(&mut self,
1744                   span: Span,
1745                   arg: P<hir::Expr>,
1746                   arms: hir::HirVec<hir::Arm>,
1747                   source: hir::MatchSource)
1748                   -> P<hir::Expr> {
1749         self.expr(span, hir::ExprMatch(arg, arms, source), ThinVec::new())
1750     }
1751
1752     fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
1753         self.expr(b.span, hir::ExprBlock(b), attrs)
1754     }
1755
1756     fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<P<hir::Expr>>) -> P<hir::Expr> {
1757         self.expr(sp, hir::ExprTup(exprs), ThinVec::new())
1758     }
1759
1760     fn expr_struct(&mut self,
1761                    sp: Span,
1762                    path: hir::Path,
1763                    fields: hir::HirVec<hir::Field>,
1764                    e: Option<P<hir::Expr>>,
1765                    attrs: ThinVec<Attribute>) -> P<hir::Expr> {
1766         let def = self.resolver.resolve_generated_global_path(&path, false);
1767         let expr = self.expr(sp, hir::ExprStruct(path, fields, e), attrs);
1768         self.resolver.record_resolution(expr.id, def);
1769         expr
1770     }
1771
1772     fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
1773         P(hir::Expr {
1774             id: self.next_id(),
1775             node: node,
1776             span: span,
1777             attrs: attrs,
1778         })
1779     }
1780
1781     fn stmt_let(&mut self, sp: Span, mutbl: bool, ident: Name, ex: P<hir::Expr>)
1782                 -> (hir::Stmt, NodeId) {
1783         let pat = if mutbl {
1784             self.pat_ident_binding_mode(sp, ident, hir::BindByValue(hir::MutMutable))
1785         } else {
1786             self.pat_ident(sp, ident)
1787         };
1788         let pat_id = pat.id;
1789         let local = P(hir::Local {
1790             pat: pat,
1791             ty: None,
1792             init: Some(ex),
1793             id: self.next_id(),
1794             span: sp,
1795             attrs: ThinVec::new(),
1796         });
1797         let decl = respan(sp, hir::DeclLocal(local));
1798         (respan(sp, hir::StmtDecl(P(decl), self.next_id())), pat_id)
1799     }
1800
1801     // Turns `<expr>` into `<expr>;`, note that this produces a StmtSemi, not a
1802     // StmtExpr.
1803     fn stmt_expr(&self, expr: P<hir::Expr>) -> hir::Stmt {
1804         hir::Stmt {
1805             span: expr.span,
1806             node: hir::StmtSemi(expr, self.next_id()),
1807         }
1808     }
1809
1810     fn block_expr(&mut self, expr: P<hir::Expr>) -> P<hir::Block> {
1811         self.block_all(expr.span, hir::HirVec::new(), Some(expr))
1812     }
1813
1814     fn block_all(&mut self, span: Span, stmts: hir::HirVec<hir::Stmt>, expr: Option<P<hir::Expr>>)
1815                  -> P<hir::Block> {
1816         P(hir::Block {
1817             stmts: stmts,
1818             expr: expr,
1819             id: self.next_id(),
1820             rules: hir::DefaultBlock,
1821             span: span,
1822         })
1823     }
1824
1825     fn pat_ok(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
1826         let path = self.std_path(span, &["result", "Result", "Ok"]);
1827         self.pat_enum(span, path, hir_vec![pat])
1828     }
1829
1830     fn pat_err(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
1831         let path = self.std_path(span, &["result", "Result", "Err"]);
1832         self.pat_enum(span, path, hir_vec![pat])
1833     }
1834
1835     fn pat_some(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
1836         let path = self.std_path(span, &["option", "Option", "Some"]);
1837         self.pat_enum(span, path, hir_vec![pat])
1838     }
1839
1840     fn pat_none(&mut self, span: Span) -> P<hir::Pat> {
1841         let path = self.std_path(span, &["option", "Option", "None"]);
1842         self.pat_enum(span, path, hir_vec![])
1843     }
1844
1845     fn pat_enum(&mut self, span: Span, path: hir::Path, subpats: hir::HirVec<P<hir::Pat>>)
1846                 -> P<hir::Pat> {
1847         let def = self.resolver.resolve_generated_global_path(&path, true);
1848         let pt = if subpats.is_empty() {
1849             hir::PatKind::Path(None, path)
1850         } else {
1851             hir::PatKind::TupleStruct(path, subpats, None)
1852         };
1853         let pat = self.pat(span, pt);
1854         self.resolver.record_resolution(pat.id, def);
1855         pat
1856     }
1857
1858     fn pat_ident(&mut self, span: Span, name: Name) -> P<hir::Pat> {
1859         self.pat_ident_binding_mode(span, name, hir::BindByValue(hir::MutImmutable))
1860     }
1861
1862     fn pat_ident_binding_mode(&mut self, span: Span, name: Name, bm: hir::BindingMode)
1863                               -> P<hir::Pat> {
1864         let pat_ident = hir::PatKind::Binding(bm,
1865                                             Spanned {
1866                                                 span: span,
1867                                                 node: name,
1868                                             },
1869                                             None);
1870
1871         let pat = self.pat(span, pat_ident);
1872
1873         let parent_def = self.parent_def;
1874         let def = self.resolver.definitions().map(|defs| {
1875             let def_path_data = DefPathData::Binding(name.as_str());
1876             let def_index = defs.create_def_with_parent(parent_def, pat.id, def_path_data);
1877             Def::Local(DefId::local(def_index), pat.id)
1878         }).unwrap_or(Def::Err);
1879         self.resolver.record_resolution(pat.id, def);
1880
1881         pat
1882     }
1883
1884     fn pat_wild(&mut self, span: Span) -> P<hir::Pat> {
1885         self.pat(span, hir::PatKind::Wild)
1886     }
1887
1888     fn pat(&mut self, span: Span, pat: hir::PatKind) -> P<hir::Pat> {
1889         P(hir::Pat {
1890             id: self.next_id(),
1891             node: pat,
1892             span: span,
1893         })
1894     }
1895
1896     fn path_ident(&mut self, span: Span, id: Name) -> hir::Path {
1897         self.path(span, vec![id])
1898     }
1899
1900     fn path(&mut self, span: Span, strs: Vec<Name>) -> hir::Path {
1901         self.path_all(span, false, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new())
1902     }
1903
1904     fn path_global(&mut self, span: Span, strs: Vec<Name>) -> hir::Path {
1905         self.path_all(span, true, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new())
1906     }
1907
1908     fn path_all(&mut self,
1909                 sp: Span,
1910                 global: bool,
1911                 mut names: Vec<Name>,
1912                 lifetimes: hir::HirVec<hir::Lifetime>,
1913                 types: hir::HirVec<P<hir::Ty>>,
1914                 bindings: hir::HirVec<hir::TypeBinding>)
1915                 -> hir::Path {
1916         let last_identifier = names.pop().unwrap();
1917         let mut segments: Vec<hir::PathSegment> = names.into_iter().map(|name| {
1918             hir::PathSegment {
1919                 name: name,
1920                 parameters: hir::PathParameters::none(),
1921            }
1922         }).collect();
1923
1924         segments.push(hir::PathSegment {
1925             name: last_identifier,
1926             parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
1927                 lifetimes: lifetimes,
1928                 types: types,
1929                 bindings: bindings,
1930             }),
1931         });
1932         hir::Path {
1933             span: sp,
1934             global: global,
1935             segments: segments.into(),
1936         }
1937     }
1938
1939     fn std_path_components(&mut self, components: &[&str]) -> Vec<Name> {
1940         let mut v = Vec::new();
1941         if let Some(s) = self.crate_root {
1942             v.push(token::intern(s));
1943         }
1944         v.extend(components.iter().map(|s| token::intern(s)));
1945         return v;
1946     }
1947
1948     // Given suffix ["b","c","d"], returns path `::std::b::c::d` when
1949     // `fld.cx.use_std`, and `::core::b::c::d` otherwise.
1950     fn std_path(&mut self, span: Span, components: &[&str]) -> hir::Path {
1951         let idents = self.std_path_components(components);
1952         self.path_global(span, idents)
1953     }
1954
1955     fn signal_block_expr(&mut self,
1956                          stmts: hir::HirVec<hir::Stmt>,
1957                          expr: P<hir::Expr>,
1958                          span: Span,
1959                          rule: hir::BlockCheckMode,
1960                          attrs: ThinVec<Attribute>)
1961                          -> P<hir::Expr> {
1962         let id = self.next_id();
1963         let block = P(hir::Block {
1964             rules: rule,
1965             span: span,
1966             id: id,
1967             stmts: stmts,
1968             expr: Some(expr),
1969         });
1970         self.expr_block(block, attrs)
1971     }
1972
1973     fn signal_block_stmt(&mut self,
1974                          stmt: hir::Stmt,
1975                          span: Span,
1976                          rule: hir::BlockCheckMode,
1977                          attrs: ThinVec<Attribute>)
1978                          -> P<hir::Expr> {
1979         let id = self.next_id();
1980         let block = P(hir::Block {
1981             rules: rule,
1982             span: span,
1983             id: id,
1984             stmts: hir_vec![stmt],
1985             expr: None,
1986         });
1987         self.expr_block(block, attrs)
1988     }
1989 }