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