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