lowering.rs 102.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

N
Nick Cameron 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// Lowers the AST to the HIR.
//
// Since the AST and HIR are fairly similar, this is mostly a simple procedure,
// much like a fold. Where lowering involves a bit more work things get more
// interesting and there are some invariants you should know about. These mostly
// concern spans and ids.
//
// Spans are assigned to AST nodes during parsing and then are modified during
// expansion to indicate the origin of a node and the process it went through
// being expanded. Ids are assigned to AST nodes just before lowering.
//
// For the simpler lowering steps, ids and spans should be preserved. Unlike
// expansion we do not preserve the process of lowering in the spans, so spans
// should not be modified here. When creating a new node (as opposed to
// 'folding' an existing one), then you create a new id using `next_id()`.
//
// You must ensure that ids are unique. That means that you should only use the
N
Nick Cameron 已提交
28
// id from an AST node in a single HIR node (you can assume that AST node ids
N
Nick Cameron 已提交
29
// are unique). Every new node must have a unique id. Avoid cloning HIR nodes.
N
Nick Cameron 已提交
30
// If you do, you must then set the new node's id to a fresh one.
N
Nick Cameron 已提交
31 32 33 34 35 36 37 38 39 40 41
//
// Spans are used for error messages and for tools to map semantics back to
// source code. It is therefore not as important with spans as ids to be strict
// about use (you can't break the compiler by screwing up a span). Obviously, a
// HIR node can only have a single span. But multiple nodes can have the same
// span and spans don't need to be kept in order, etc. Where code is preserved
// by lowering, it should have the same span as in the AST. Where HIR nodes are
// new it is probably best to give a span for the whole AST node being lowered.
// All nodes should have real spans, don't use dummy spans. Tools are likely to
// get confused if the spans from leaf AST nodes occur in multiple places
// in the HIR, especially for multiple identifiers.
42 43

use hir;
44
use hir::map::{Definitions, DefKey};
N
Nick Cameron 已提交
45
use hir::map::definitions::DefPathData;
46
use hir::def_id::{DefIndex, DefId};
47
use hir::def::{Def, PathResolution};
48
use session::Session;
49
use util::nodemap::{DefIdMap, NodeMap, FxHashMap};
50

51
use std::collections::BTreeMap;
52
use std::iter;
53

54
use syntax::attr;
55
use syntax::ast::*;
56
use syntax::errors;
57
use syntax::ptr::P;
58
use syntax::codemap::{self, respan, Spanned};
59
use syntax::std_inject;
60
use syntax::symbol::{Symbol, keywords};
61
use syntax::util::small_vector::SmallVector;
62
use syntax::visit::{self, Visitor};
63
use syntax_pos::Span;
64

N
Nick Cameron 已提交
65
pub struct LoweringContext<'a> {
66
    crate_root: Option<&'static str>,
67
    // Use to assign ids to hir nodes that do not directly correspond to an ast node
68
    sess: &'a Session,
N
Nick Cameron 已提交
69 70 71
    // As we walk the AST we must keep track of the current 'parent' def id (in
    // the form of a DefIndex) so that if we create a new node which introduces
    // a definition, then we can properly create the def id.
72 73
    parent_def: Option<DefIndex>,
    resolver: &'a mut Resolver,
74 75 76 77

    /// The items being lowered are collected here.
    items: BTreeMap<NodeId, hir::Item>,

78
    trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>,
79
    impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
80
    bodies: FxHashMap<hir::BodyId, hir::Body>,
81 82

    type_def_lifetime_params: DefIdMap<usize>,
83 84 85
}

pub trait Resolver {
86
    // Resolve a hir path generated by the lowerer when expanding `for`, `if let`, etc.
J
Jeffrey Seyfried 已提交
87
    fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool);
88

89 90 91
    // Obtain the resolution for a node id
    fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution>;

92
    // We must keep the set of definitions up to date as we add nodes that weren't in the AST.
93
    // This should only return `None` during testing.
94
    fn definitions(&mut self) -> &mut Definitions;
N
Nick Cameron 已提交
95 96
}

97 98 99
pub fn lower_crate(sess: &Session,
                   krate: &Crate,
                   resolver: &mut Resolver)
J
Jeffrey Seyfried 已提交
100
                   -> hir::Crate {
101 102 103 104 105
    // We're constructing the HIR here; we don't care what we will
    // read, since we haven't even constructed the *input* to
    // incr. comp. yet.
    let _ignore = sess.dep_graph.in_ignore();

J
Jeffrey Seyfried 已提交
106
    LoweringContext {
107
        crate_root: std_inject::injected_crate_name(krate),
108
        sess: sess,
J
Jeffrey Seyfried 已提交
109 110
        parent_def: None,
        resolver: resolver,
111
        items: BTreeMap::new(),
112
        trait_items: BTreeMap::new(),
113
        impl_items: BTreeMap::new(),
114
        bodies: FxHashMap(),
115
        type_def_lifetime_params: DefIdMap(),
J
Jeffrey Seyfried 已提交
116 117
    }.lower_crate(krate)
}
118

119 120 121 122 123 124 125 126
#[derive(Copy, Clone, PartialEq, Eq)]
enum ParamMode {
    /// Any path in a type context.
    Explicit,
    /// The `module::Type` in `module::Type::method` in an expression.
    Optional
}

J
Jeffrey Seyfried 已提交
127
impl<'a> LoweringContext<'a> {
128
    fn lower_crate(mut self, c: &Crate) -> hir::Crate {
129 130 131 132 133 134 135 136
        /// Full-crate AST visitor that inserts into a fresh
        /// `LoweringContext` any information that may be
        /// needed from arbitrary locations in the crate.
        /// E.g. The number of lifetime generic parameters
        /// declared for every type and trait definition.
        struct MiscCollector<'lcx, 'interner: 'lcx> {
            lctx: &'lcx mut LoweringContext<'interner>,
        }
137

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
        impl<'lcx, 'interner> Visitor<'lcx> for MiscCollector<'lcx, 'interner> {
            fn visit_item(&mut self, item: &'lcx Item) {
                match item.node {
                    ItemKind::Struct(_, ref generics) |
                    ItemKind::Union(_, ref generics) |
                    ItemKind::Enum(_, ref generics) |
                    ItemKind::Ty(_, ref generics) |
                    ItemKind::Trait(_, ref generics, ..) => {
                        let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
                        let count = generics.lifetimes.len();
                        self.lctx.type_def_lifetime_params.insert(def_id, count);
                    }
                    _ => {}
                }
                visit::walk_item(self, item);
            }
154 155
        }

156 157 158 159
        struct ItemLowerer<'lcx, 'interner: 'lcx> {
            lctx: &'lcx mut LoweringContext<'interner>,
        }

160 161
        impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> {
            fn visit_item(&mut self, item: &'lcx Item) {
162 163
                let hir_item = self.lctx.lower_item(item);
                self.lctx.items.insert(item.id, hir_item);
164 165
                visit::walk_item(self, item);
            }
166

167 168 169 170 171 172 173
            fn visit_trait_item(&mut self, item: &'lcx TraitItem) {
                let id = hir::TraitItemId { node_id: item.id };
                let hir_item = self.lctx.lower_trait_item(item);
                self.lctx.trait_items.insert(id, hir_item);
                visit::walk_trait_item(self, item);
            }

174
            fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
175
                let id = hir::ImplItemId { node_id: item.id };
176 177
                let hir_item = self.lctx.lower_impl_item(item);
                self.lctx.impl_items.insert(id, hir_item);
178 179
                visit::walk_impl_item(self, item);
            }
180 181
        }

182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
        visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c);
        visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c);

        let module = self.lower_mod(&c.module);
        let attrs = self.lower_attrs(&c.attrs);
        let exported_macros = c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect();

        hir::Crate {
            module: module,
            attrs: attrs,
            span: c.span,
            exported_macros: exported_macros,
            items: self.items,
            trait_items: self.trait_items,
            impl_items: self.impl_items,
            bodies: self.bodies,
        }
199
    }
200

201 202
    fn record_body(&mut self, value: hir::Expr, decl: Option<&FnDecl>)
                   -> hir::BodyId {
203
        let body = hir::Body {
204 205 206
            arguments: decl.map_or(hir_vec![], |decl| {
                decl.inputs.iter().map(|x| self.lower_arg(x)).collect()
            }),
207 208 209 210
            value: value
        };
        let id = body.id();
        self.bodies.insert(id, body);
211
        id
212 213
    }

214
    fn next_id(&self) -> NodeId {
215
        self.sess.next_node_id()
216 217
    }

218 219 220 221 222 223 224 225 226
    fn expect_full_def(&mut self, id: NodeId) -> Def {
        self.resolver.get_resolution(id).map_or(Def::Err, |pr| {
            if pr.depth != 0 {
                bug!("path not fully resolved: {:?}", pr);
            }
            pr.base_def
        })
    }

227
    fn diagnostic(&self) -> &errors::Handler {
228
        self.sess.diagnostic()
229
    }
N
Nick Cameron 已提交
230

V
Vadim Petrochenkov 已提交
231
    fn str_to_ident(&self, s: &'static str) -> Name {
232
        Symbol::gensym(s)
N
Nick Cameron 已提交
233
    }
234

235 236 237 238 239 240 241 242 243 244 245 246
    fn allow_internal_unstable(&self, reason: &'static str, mut span: Span) -> Span {
        span.expn_id = self.sess.codemap().record_expansion(codemap::ExpnInfo {
            call_site: span,
            callee: codemap::NameAndSpan {
                format: codemap::CompilerDesugaring(Symbol::intern(reason)),
                span: Some(span),
                allow_internal_unstable: true,
            },
        });
        span
    }

247 248 249 250
    fn with_parent_def<T, F>(&mut self, parent_id: NodeId, f: F) -> T
        where F: FnOnce(&mut LoweringContext) -> T
    {
        let old_def = self.parent_def;
251 252 253
        self.parent_def = {
            let defs = self.resolver.definitions();
            Some(defs.opt_def_index(parent_id).unwrap())
254
        };
255

256
        let result = f(self);
N
Nick Cameron 已提交
257

258
        self.parent_def = old_def;
N
Nick Cameron 已提交
259 260
        result
    }
261

262 263 264 265 266 267 268 269
    fn def_key(&mut self, id: DefId) -> DefKey {
        if id.is_local() {
            self.resolver.definitions().def_key(id.index)
        } else {
            self.sess.cstore.def_key(id)
        }
    }

270
    fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
271
        o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
272 273
    }

274 275 276 277 278 279 280 281 282 283 284 285 286
    fn lower_label(&mut self, id: NodeId, label: Option<Spanned<Ident>>) -> Option<hir::Label> {
        label.map(|sp_ident| {
            hir::Label {
                span: sp_ident.span,
                name: sp_ident.node.name,
                loop_id: match self.expect_full_def(id) {
                    Def::Label(loop_id) => loop_id,
                    _ => DUMMY_NODE_ID
                }
            }
        })
    }

287 288 289
    fn lower_attrs(&mut self, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
        attrs.clone().into()
    }
290

291 292 293 294
    fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {
        hir::Arm {
            attrs: self.lower_attrs(&arm.attrs),
            pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(),
295 296
            guard: arm.guard.as_ref().map(|ref x| P(self.lower_expr(x))),
            body: P(self.lower_expr(&arm.body)),
297
        }
298 299
    }

300 301 302 303 304 305 306
    fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding {
        hir::TypeBinding {
            id: b.id,
            name: b.ident.name,
            ty: self.lower_ty(&b.ty),
            span: b.span,
        }
307 308
    }

309 310 311 312
    fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
        P(hir::Ty {
            id: t.id,
            node: match t.node {
313
                TyKind::Infer => hir::TyInfer,
314 315 316
                TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)),
                TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
                TyKind::Rptr(ref region, ref mt) => {
317
                    let span = Span { hi: t.span.lo, ..t.span };
318 319
                    let lifetime = match *region {
                        Some(ref lt) => self.lower_lifetime(lt),
320
                        None => self.elided_lifetime(span)
321 322
                    };
                    hir::TyRptr(lifetime, self.lower_mt(mt))
323
                }
324
                TyKind::BareFn(ref f) => {
325 326 327 328 329 330 331
                    hir::TyBareFn(P(hir::BareFnTy {
                        lifetimes: self.lower_lifetime_defs(&f.lifetimes),
                        unsafety: self.lower_unsafety(f.unsafety),
                        abi: f.abi,
                        decl: self.lower_fn_decl(&f.decl),
                    }))
                }
332
                TyKind::Never => hir::TyNever,
J
Jonas Schievink 已提交
333 334 335
                TyKind::Tup(ref tys) => {
                    hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty)).collect())
                }
336
                TyKind::Paren(ref ty) => {
337 338
                    return self.lower_ty(ty);
                }
339
                TyKind::Path(ref qself, ref path) => {
340 341
                    let qpath = self.lower_qpath(t.id, qself, path, ParamMode::Explicit);
                    return self.ty_path(t.id, t.span, qpath);
342
                }
343 344 345 346 347 348 349 350 351 352
                TyKind::ImplicitSelf => {
                    hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
                        def: self.expect_full_def(t.id),
                        segments: hir_vec![hir::PathSegment {
                            name: keywords::SelfType.name(),
                            parameters: hir::PathParameters::none()
                        }],
                        span: t.span,
                    })))
                }
353 354 355
                TyKind::Array(ref ty, ref length) => {
                    let length = self.lower_expr(length);
                    hir::TyArray(self.lower_ty(ty),
356
                                 self.record_body(length, None))
357
                }
358
                TyKind::Typeof(ref expr) => {
359
                    let expr = self.lower_expr(expr);
360
                    hir::TyTypeof(self.record_body(expr, None))
361
                }
362
                TyKind::TraitObject(ref bounds) => {
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
                    let mut lifetime_bound = None;
                    let bounds = bounds.iter().filter_map(|bound| {
                        match *bound {
                            TraitTyParamBound(ref ty, TraitBoundModifier::None) => {
                                Some(self.lower_poly_trait_ref(ty))
                            }
                            TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
                            RegionTyParamBound(ref lifetime) => {
                                lifetime_bound = Some(self.lower_lifetime(lifetime));
                                None
                            }
                        }
                    }).collect();
                    let lifetime_bound = lifetime_bound.unwrap_or_else(|| {
                        self.elided_lifetime(t.span)
                    });
                    hir::TyTraitObject(bounds, lifetime_bound)
380
                }
381
                TyKind::ImplTrait(ref bounds) => {
382
                    hir::TyImplTrait(self.lower_bounds(bounds))
383
                }
384
                TyKind::Mac(_) => panic!("TyMac should have been expanded by now."),
385 386 387
            },
            span: t.span,
        })
388
    }
389

390 391 392 393 394
    fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod {
        hir::ForeignMod {
            abi: fm.abi,
            items: fm.items.iter().map(|x| self.lower_foreign_item(x)).collect(),
        }
395
    }
396

397 398 399 400 401 402
    fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
        Spanned {
            node: hir::Variant_ {
                name: v.node.name.name,
                attrs: self.lower_attrs(&v.node.attrs),
                data: self.lower_variant_data(&v.node.data),
403 404
                disr_expr: v.node.disr_expr.as_ref().map(|e| {
                    let e = self.lower_expr(e);
405
                    self.record_body(e, None)
406
                }),
407 408 409
            },
            span: v.span,
        }
410 411
    }

412 413 414 415 416 417 418 419 420 421 422 423 424 425
    fn lower_qpath(&mut self,
                   id: NodeId,
                   qself: &Option<QSelf>,
                   p: &Path,
                   param_mode: ParamMode)
                   -> hir::QPath {
        let qself_position = qself.as_ref().map(|q| q.position);
        let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty));

        let resolution = self.resolver.get_resolution(id)
                                      .unwrap_or(PathResolution::new(Def::Err));

        let proj_start = p.segments.len() - resolution.depth;
        let path = P(hir::Path {
426
            def: resolution.base_def,
427 428 429
            segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
                let param_mode = match (qself_position, param_mode) {
                    (Some(j), ParamMode::Optional) if i < j => {
430 431 432 433 434 435 436
                        // This segment is part of the trait path in a
                        // qualified path - one of `a`, `b` or `Trait`
                        // in `<X as a::b::Trait>::T::U::method`.
                        ParamMode::Explicit
                    }
                    _ => param_mode
                };
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470

                // Figure out if this is a type/trait segment,
                // which may need lifetime elision performed.
                let parent_def_id = |this: &mut Self, def_id: DefId| {
                    DefId {
                        krate: def_id.krate,
                        index: this.def_key(def_id).parent.expect("missing parent")
                    }
                };
                let type_def_id = match resolution.base_def {
                    Def::AssociatedTy(def_id) if i + 2 == proj_start => {
                        Some(parent_def_id(self, def_id))
                    }
                    Def::Variant(def_id) if i + 1 == proj_start => {
                        Some(parent_def_id(self, def_id))
                    }
                    Def::Struct(def_id) |
                    Def::Union(def_id) |
                    Def::Enum(def_id) |
                    Def::TyAlias(def_id) |
                    Def::Trait(def_id) if i + 1 == proj_start => Some(def_id),
                    _ => None
                };

                let num_lifetimes = type_def_id.map_or(0, |def_id| {
                    if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
                        return n;
                    }
                    assert!(!def_id.is_local());
                    let (n, _) = self.sess.cstore.item_generics_own_param_counts(def_id);
                    self.type_def_lifetime_params.insert(def_id, n);
                    n
                });
                self.lower_path_segment(p.span, segment, param_mode, num_lifetimes)
471
            }).collect(),
472
            span: p.span,
473 474 475 476 477 478
        });

        // Simple case, either no projections, or only fully-qualified.
        // E.g. `std::mem::size_of` or `<I as Iterator>::Item`.
        if resolution.depth == 0 {
            return hir::QPath::Resolved(qself, path);
479
        }
480 481 482 483 484 485 486 487 488 489

        // Create the innermost type that we're projecting from.
        let mut ty = if path.segments.is_empty() {
            // If the base path is empty that means there exists a
            // syntactical `Self`, e.g. `&i32` in `<&i32>::clone`.
            qself.expect("missing QSelf for <T>::...")
        } else {
            // Otherwise, the base path is an implicit `Self` type path,
            // e.g. `Vec` in `Vec::new` or `<I as Iterator>::Item` in
            // `<I as Iterator>::Item::default`.
490 491
            let new_id = self.next_id();
            self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path))
492 493 494 495 496 497 498 499 500 501 502 503 504
        };

        // Anything after the base path are associated "extensions",
        // out of which all but the last one are associated types,
        // e.g. for `std::vec::Vec::<T>::IntoIter::Item::clone`:
        // * base path is `std::vec::Vec<T>`
        // * "extensions" are `IntoIter`, `Item` and `clone`
        // * type nodes are:
        //   1. `std::vec::Vec<T>` (created above)
        //   2. `<std::vec::Vec<T>>::IntoIter`
        //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
        // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
        for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
505
            let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0));
506 507 508 509 510 511 512 513
            let qpath = hir::QPath::TypeRelative(ty, segment);

            // It's finished, return the extension of the right node type.
            if i == p.segments.len() - 1 {
                return qpath;
            }

            // Wrap the associated extension in another type node.
514 515
            let new_id = self.next_id();
            ty = self.ty_path(new_id, p.span, qpath);
516 517 518 519 520
        }

        // Should've returned in the for loop above.
        span_bug!(p.span, "lower_qpath: no final extension segment in {}..{}",
                  proj_start, p.segments.len())
521 522
    }

523
    fn lower_path_extra(&mut self,
524
                        id: NodeId,
525 526
                        p: &Path,
                        name: Option<Name>,
527 528
                        param_mode: ParamMode,
                        defaults_to_global: bool)
529
                        -> hir::Path {
530 531 532 533 534
        let mut segments = p.segments.iter();
        if defaults_to_global && p.is_global() {
            segments.next();
        }

535
        hir::Path {
536
            def: self.expect_full_def(id),
537
            segments: segments.map(|segment| {
538
                self.lower_path_segment(p.span, segment, param_mode, 0)
539 540 541 542 543 544
            }).chain(name.map(|name| {
                hir::PathSegment {
                    name: name,
                    parameters: hir::PathParameters::none()
                }
            })).collect(),
545 546 547 548
            span: p.span,
        }
    }

549
    fn lower_path(&mut self,
550
                  id: NodeId,
551
                  p: &Path,
552 553
                  param_mode: ParamMode,
                  defaults_to_global: bool)
554
                  -> hir::Path {
555
        self.lower_path_extra(id, p, None, param_mode, defaults_to_global)
556 557
    }

558
    fn lower_path_segment(&mut self,
559
                          path_span: Span,
560
                          segment: &PathSegment,
561 562
                          param_mode: ParamMode,
                          expected_lifetimes: usize)
563
                          -> hir::PathSegment {
564
        let mut parameters = if let Some(ref parameters) = segment.parameters {
J
Jeffrey Seyfried 已提交
565 566 567 568 569 570 571 572
            match **parameters {
                PathParameters::AngleBracketed(ref data) => {
                    let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
                    hir::AngleBracketedParameters(data)
                }
                PathParameters::Parenthesized(ref data) => {
                    hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data))
                }
573
            }
J
Jeffrey Seyfried 已提交
574 575 576
        } else {
            let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode);
            hir::AngleBracketedParameters(data)
577 578
        };

579 580 581 582 583 584 585 586
        if let hir::AngleBracketedParameters(ref mut data) = parameters {
            if data.lifetimes.is_empty() {
                data.lifetimes = (0..expected_lifetimes).map(|_| {
                    self.elided_lifetime(path_span)
                }).collect();
            }
        }

587 588 589
        hir::PathSegment {
            name: segment.identifier.name,
            parameters: parameters,
590 591 592
        }
    }

593
    fn lower_angle_bracketed_parameter_data(&mut self,
594 595
                                            data: &AngleBracketedParameterData,
                                            param_mode: ParamMode)
596 597 598 599 600
                                            -> hir::AngleBracketedParameterData {
        let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data;
        hir::AngleBracketedParameterData {
            lifetimes: self.lower_lifetimes(lifetimes),
            types: types.iter().map(|ty| self.lower_ty(ty)).collect(),
601
            infer_types: types.is_empty() && param_mode == ParamMode::Optional,
602 603
            bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(),
        }
604 605
    }

606 607 608 609 610 611 612 613 614
    fn lower_parenthesized_parameter_data(&mut self,
                                          data: &ParenthesizedParameterData)
                                          -> hir::ParenthesizedParameterData {
        let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
        hir::ParenthesizedParameterData {
            inputs: inputs.iter().map(|ty| self.lower_ty(ty)).collect(),
            output: output.as_ref().map(|ty| self.lower_ty(ty)),
            span: span,
        }
N
Nick Cameron 已提交
615
    }
616

617 618 619 620 621
    fn lower_local(&mut self, l: &Local) -> P<hir::Local> {
        P(hir::Local {
            id: l.id,
            ty: l.ty.as_ref().map(|t| self.lower_ty(t)),
            pat: self.lower_pat(&l.pat),
622
            init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
623 624 625
            span: l.span,
            attrs: l.attrs.clone(),
        })
N
Nick Cameron 已提交
626
    }
627

628 629 630 631 632
    fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
        match m {
            Mutability::Mutable => hir::MutMutable,
            Mutability::Immutable => hir::MutImmutable,
        }
633 634
    }

635 636 637 638 639
    fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
        hir::Arg {
            id: arg.id,
            pat: self.lower_pat(&arg.pat),
        }
N
Nick Cameron 已提交
640
    }
641

642 643 644 645 646 647 648 649 650 651 652 653
    fn lower_fn_args_to_names(&mut self, decl: &FnDecl)
                              -> hir::HirVec<Spanned<Name>> {
        decl.inputs.iter().map(|arg| {
            match arg.pat.node {
                PatKind::Ident(_, ident, None) => {
                    respan(ident.span, ident.node.name)
                }
                _ => respan(arg.pat.span, keywords::Invalid.name()),
            }
        }).collect()
    }

654 655
    fn lower_fn_decl(&mut self, decl: &FnDecl) -> P<hir::FnDecl> {
        P(hir::FnDecl {
656
            inputs: decl.inputs.iter().map(|arg| self.lower_ty(&arg.ty)).collect(),
657 658 659 660 661 662 663
            output: match decl.output {
                FunctionRetTy::Ty(ref ty) => hir::Return(self.lower_ty(ty)),
                FunctionRetTy::Default(span) => hir::DefaultReturn(span),
            },
            variadic: decl.variadic,
        })
    }
664

665 666 667 668 669 670 671 672 673 674 675
    fn lower_ty_param_bound(&mut self, tpb: &TyParamBound) -> hir::TyParamBound {
        match *tpb {
            TraitTyParamBound(ref ty, modifier) => {
                hir::TraitTyParamBound(self.lower_poly_trait_ref(ty),
                                       self.lower_trait_bound_modifier(modifier))
            }
            RegionTyParamBound(ref lifetime) => {
                hir::RegionTyParamBound(self.lower_lifetime(lifetime))
            }
        }
    }
676

677
    fn lower_ty_param(&mut self, tp: &TyParam, add_bounds: &[TyParamBound]) -> hir::TyParam {
678 679 680 681 682
        let mut name = tp.ident.name;

        // Don't expose `Self` (recovered "keyword used as ident" parse error).
        // `rustc::ty` expects `Self` to be only used for a trait's `Self`.
        // Instead, use gensym("Self") to create a distinct name that looks the same.
683 684
        if name == keywords::SelfType.name() {
            name = Symbol::gensym("Self");
685 686
        }

687 688 689 690 691
        let mut bounds = self.lower_bounds(&tp.bounds);
        if !add_bounds.is_empty() {
            bounds = bounds.into_iter().chain(self.lower_bounds(add_bounds).into_iter()).collect();
        }

692 693
        hir::TyParam {
            id: tp.id,
694
            name: name,
695
            bounds: bounds,
696 697
            default: tp.default.as_ref().map(|x| self.lower_ty(x)),
            span: tp.span,
698
            pure_wrt_drop: tp.attrs.iter().any(|attr| attr.check_name("may_dangle")),
699
        }
700 701
    }

702
    fn lower_ty_params(&mut self, tps: &Vec<TyParam>, add_bounds: &NodeMap<Vec<TyParamBound>>)
703 704 705 706
                       -> hir::HirVec<hir::TyParam> {
        tps.iter().map(|tp| {
            self.lower_ty_param(tp, add_bounds.get(&tp.id).map_or(&[][..], |x| &x))
        }).collect()
707 708
    }

709 710 711 712 713
    fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
        hir::Lifetime {
            id: l.id,
            name: l.name,
            span: l.span,
714 715 716
        }
    }

717 718 719 720
    fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef {
        hir::LifetimeDef {
            lifetime: self.lower_lifetime(&l.lifetime),
            bounds: self.lower_lifetimes(&l.bounds),
721
            pure_wrt_drop: l.attrs.iter().any(|attr| attr.check_name("may_dangle")),
722
        }
723
    }
724

725 726
    fn lower_lifetimes(&mut self, lts: &Vec<Lifetime>) -> hir::HirVec<hir::Lifetime> {
        lts.iter().map(|l| self.lower_lifetime(l)).collect()
N
Nick Cameron 已提交
727
    }
728

729 730
    fn lower_lifetime_defs(&mut self, lts: &Vec<LifetimeDef>) -> hir::HirVec<hir::LifetimeDef> {
        lts.iter().map(|l| self.lower_lifetime_def(l)).collect()
731 732
    }

733
    fn lower_generics(&mut self, g: &Generics) -> hir::Generics {
734 735 736 737 738 739 740 741 742 743 744 745 746 747
        // Collect `?Trait` bounds in where clause and move them to parameter definitions.
        let mut add_bounds = NodeMap();
        for pred in &g.where_clause.predicates {
            if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
                'next_bound: for bound in &bound_pred.bounds {
                    if let TraitTyParamBound(_, TraitBoundModifier::Maybe) = *bound {
                        let report_error = |this: &mut Self| {
                            this.diagnostic().span_err(bound_pred.bounded_ty.span,
                                                       "`?Trait` bounds are only permitted at the \
                                                        point where a type parameter is declared");
                        };
                        // Check if the where clause type is a plain type parameter.
                        match bound_pred.bounded_ty.node {
                            TyKind::Path(None, ref path)
748 749
                                    if path.segments.len() == 1 &&
                                       bound_pred.bound_lifetimes.is_empty() => {
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
                                if let Some(Def::TyParam(def_id)) =
                                        self.resolver.get_resolution(bound_pred.bounded_ty.id)
                                                     .map(|d| d.base_def) {
                                    if let Some(node_id) =
                                            self.resolver.definitions().as_local_node_id(def_id) {
                                        for ty_param in &g.ty_params {
                                            if node_id == ty_param.id {
                                                add_bounds.entry(ty_param.id).or_insert(Vec::new())
                                                                            .push(bound.clone());
                                                continue 'next_bound;
                                            }
                                        }
                                    }
                                }
                                report_error(self)
                            }
                            _ => report_error(self)
                        }
                    }
                }
            }
        }

773
        hir::Generics {
774
            ty_params: self.lower_ty_params(&g.ty_params, &add_bounds),
775 776
            lifetimes: self.lower_lifetime_defs(&g.lifetimes),
            where_clause: self.lower_where_clause(&g.where_clause),
777
            span: g.span,
778
        }
779
    }
780

781 782 783 784 785 786 787 788
    fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause {
        hir::WhereClause {
            id: wc.id,
            predicates: wc.predicates
                          .iter()
                          .map(|predicate| self.lower_where_predicate(predicate))
                          .collect(),
        }
N
Nick Cameron 已提交
789
    }
790

791 792 793 794 795 796 797 798 799
    fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate {
        match *pred {
            WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_lifetimes,
                                                                ref bounded_ty,
                                                                ref bounds,
                                                                span}) => {
                hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
                    bound_lifetimes: self.lower_lifetime_defs(bound_lifetimes),
                    bounded_ty: self.lower_ty(bounded_ty),
800 801 802 803 804
                    bounds: bounds.iter().filter_map(|bound| match *bound {
                        // Ignore `?Trait` bounds, they were copied into type parameters already.
                        TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
                        _ => Some(self.lower_ty_param_bound(bound))
                    }).collect(),
805 806 807 808 809 810 811 812 813 814 815 816 817
                    span: span,
                })
            }
            WherePredicate::RegionPredicate(WhereRegionPredicate{ ref lifetime,
                                                                  ref bounds,
                                                                  span}) => {
                hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
                    span: span,
                    lifetime: self.lower_lifetime(lifetime),
                    bounds: bounds.iter().map(|bound| self.lower_lifetime(bound)).collect(),
                })
            }
            WherePredicate::EqPredicate(WhereEqPredicate{ id,
818 819
                                                          ref lhs_ty,
                                                          ref rhs_ty,
820 821 822
                                                          span}) => {
                hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
                    id: id,
823 824
                    lhs_ty: self.lower_ty(lhs_ty),
                    rhs_ty: self.lower_ty(rhs_ty),
825 826 827
                    span: span,
                })
            }
828
        }
829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847
    }

    fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
        match *vdata {
            VariantData::Struct(ref fields, id) => {
                hir::VariantData::Struct(fields.iter()
                                               .enumerate()
                                               .map(|f| self.lower_struct_field(f))
                                               .collect(),
                                         id)
            }
            VariantData::Tuple(ref fields, id) => {
                hir::VariantData::Tuple(fields.iter()
                                              .enumerate()
                                              .map(|f| self.lower_struct_field(f))
                                              .collect(),
                                        id)
            }
            VariantData::Unit(id) => hir::VariantData::Unit(id),
848
        }
849 850 851
    }

    fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
852 853 854 855
        let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit) {
            hir::QPath::Resolved(None, path) => path.and_then(|path| path),
            qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath)
        };
856
        hir::TraitRef {
857
            path: path,
858
            ref_id: p.ref_id,
859
        }
860 861 862 863 864 865 866
    }

    fn lower_poly_trait_ref(&mut self, p: &PolyTraitRef) -> hir::PolyTraitRef {
        hir::PolyTraitRef {
            bound_lifetimes: self.lower_lifetime_defs(&p.bound_lifetimes),
            trait_ref: self.lower_trait_ref(&p.trait_ref),
            span: p.span,
867
        }
868 869 870 871 872 873
    }

    fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField {
        hir::StructField {
            span: f.span,
            id: f.id,
874
            name: f.ident.map(|ident| ident.name).unwrap_or(Symbol::intern(&index.to_string())),
875 876 877
            vis: self.lower_visibility(&f.vis),
            ty: self.lower_ty(&f.ty),
            attrs: self.lower_attrs(&f.attrs),
878 879 880
        }
    }

881 882 883
    fn lower_field(&mut self, f: &Field) -> hir::Field {
        hir::Field {
            name: respan(f.ident.span, f.ident.node.name),
884
            expr: P(self.lower_expr(&f.expr)),
885
            span: f.span,
886
            is_shorthand: f.is_shorthand,
N
Nick Cameron 已提交
887
        }
888
    }
889

890 891 892 893
    fn lower_mt(&mut self, mt: &MutTy) -> hir::MutTy {
        hir::MutTy {
            ty: self.lower_ty(&mt.ty),
            mutbl: self.lower_mutability(mt.mutbl),
N
Nick Cameron 已提交
894
        }
895
    }
896

897
    fn lower_bounds(&mut self, bounds: &[TyParamBound]) -> hir::TyParamBounds {
898
        bounds.iter().map(|bound| self.lower_ty_param_bound(bound)).collect()
899 900
    }

901
    fn lower_block(&mut self, b: &Block) -> P<hir::Block> {
902 903
        let mut expr = None;

904 905
        let mut stmts = b.stmts.iter().flat_map(|s| self.lower_stmt(s)).collect::<Vec<_>>();
        if let Some(last) = stmts.pop() {
906 907 908 909 910 911 912
            if let hir::StmtExpr(e, _) = last.node {
                expr = Some(e);
            } else {
                stmts.push(last);
            }
        }

913 914
        P(hir::Block {
            id: b.id,
915 916
            stmts: stmts.into(),
            expr: expr,
917 918 919 920
            rules: self.lower_block_check_mode(&b.rules),
            span: b.span,
        })
    }
921

922
    fn lower_item_kind(&mut self,
923
                       id: NodeId,
924 925 926 927 928
                       name: &mut Name,
                       attrs: &hir::HirVec<Attribute>,
                       vis: &mut hir::Visibility,
                       i: &ItemKind)
                       -> hir::Item_ {
929 930 931
        match *i {
            ItemKind::ExternCrate(string) => hir::ItemExternCrate(string),
            ItemKind::Use(ref view_path) => {
932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948
                let path = match view_path.node {
                    ViewPathSimple(_, ref path) => path,
                    ViewPathGlob(ref path) => path,
                    ViewPathList(ref path, ref path_list_idents) => {
                        for &Spanned { node: ref import, span } in path_list_idents {
                            // `use a::{self as x, b as y};` lowers to
                            // `use a as x; use a::b as y;`
                            let mut ident = import.name;
                            let suffix = if ident.name == keywords::SelfValue.name() {
                                if let Some(last) = path.segments.last() {
                                    ident = last.identifier;
                                }
                                None
                            } else {
                                Some(ident.name)
                            };

949
                            let mut path = self.lower_path_extra(import.id, path, suffix,
950
                                                                 ParamMode::Explicit, true);
951 952 953 954 955 956 957 958 959 960 961 962 963
                            path.span = span;
                            self.items.insert(import.id, hir::Item {
                                id: import.id,
                                name: import.rename.unwrap_or(ident).name,
                                attrs: attrs.clone(),
                                node: hir::ItemUse(P(path), hir::UseKind::Single),
                                vis: vis.clone(),
                                span: span,
                            });
                        }
                        path
                    }
                };
964
                let path = P(self.lower_path(id, path, ParamMode::Explicit, true));
965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981
                let kind = match view_path.node {
                    ViewPathSimple(ident, _) => {
                        *name = ident.name;
                        hir::UseKind::Single
                    }
                    ViewPathGlob(_) => {
                        hir::UseKind::Glob
                    }
                    ViewPathList(..) => {
                        // Privatize the degenerate import base, used only to check
                        // the stability of `use a::{};`, to avoid it showing up as
                        // a reexport by accident when `pub`, e.g. in documentation.
                        *vis = hir::Inherited;
                        hir::UseKind::ListStem
                    }
                };
                hir::ItemUse(path, kind)
982 983
            }
            ItemKind::Static(ref t, m, ref e) => {
984
                let value = self.lower_expr(e);
985 986
                hir::ItemStatic(self.lower_ty(t),
                                self.lower_mutability(m),
987
                                self.record_body(value, None))
988 989
            }
            ItemKind::Const(ref t, ref e) => {
990 991
                let value = self.lower_expr(e);
                hir::ItemConst(self.lower_ty(t),
992
                               self.record_body(value, None))
993 994
            }
            ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
995
                let body = self.lower_block(body);
996
                let body = self.expr_block(body, ThinVec::new());
997
                let body_id = self.record_body(body, Some(decl));
998 999 1000 1001 1002
                hir::ItemFn(self.lower_fn_decl(decl),
                            self.lower_unsafety(unsafety),
                            self.lower_constness(constness),
                            abi,
                            self.lower_generics(generics),
1003
                            body_id)
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
            }
            ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
            ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
            ItemKind::Ty(ref t, ref generics) => {
                hir::ItemTy(self.lower_ty(t), self.lower_generics(generics))
            }
            ItemKind::Enum(ref enum_definition, ref generics) => {
                hir::ItemEnum(hir::EnumDef {
                                  variants: enum_definition.variants
                                                           .iter()
                                                           .map(|x| self.lower_variant(x))
                                                           .collect(),
                              },
                              self.lower_generics(generics))
            }
            ItemKind::Struct(ref struct_def, ref generics) => {
                let struct_def = self.lower_variant_data(struct_def);
                hir::ItemStruct(struct_def, self.lower_generics(generics))
            }
1023 1024 1025 1026
            ItemKind::Union(ref vdata, ref generics) => {
                let vdata = self.lower_variant_data(vdata);
                hir::ItemUnion(vdata, self.lower_generics(generics))
            }
1027 1028 1029 1030 1031 1032
            ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
                hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
                                     self.lower_trait_ref(trait_ref))
            }
            ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
                let new_impl_items = impl_items.iter()
1033
                                               .map(|item| self.lower_impl_item_ref(item))
1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
                                               .collect();
                let ifce = ifce.as_ref().map(|trait_ref| self.lower_trait_ref(trait_ref));
                hir::ItemImpl(self.lower_unsafety(unsafety),
                              self.lower_impl_polarity(polarity),
                              self.lower_generics(generics),
                              ifce,
                              self.lower_ty(ty),
                              new_impl_items)
            }
            ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => {
                let bounds = self.lower_bounds(bounds);
1045
                let items = items.iter().map(|item| self.lower_trait_item_ref(item)).collect();
1046 1047 1048 1049 1050 1051 1052
                hir::ItemTrait(self.lower_unsafety(unsafety),
                               self.lower_generics(generics),
                               bounds,
                               items)
            }
            ItemKind::Mac(_) => panic!("Shouldn't still be around"),
        }
N
Nick Cameron 已提交
1053
    }
1054

1055 1056 1057 1058 1059 1060 1061 1062
    fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
        self.with_parent_def(i.id, |this| {
            hir::TraitItem {
                id: i.id,
                name: i.ident.name,
                attrs: this.lower_attrs(&i.attrs),
                node: match i.node {
                    TraitItemKind::Const(ref ty, ref default) => {
1063
                        hir::TraitItemKind::Const(this.lower_ty(ty),
1064 1065
                                                  default.as_ref().map(|x| {
                            let value = this.lower_expr(x);
1066
                            this.record_body(value, None)
1067
                        }))
1068
                    }
1069 1070
                    TraitItemKind::Method(ref sig, None) => {
                        let names = this.lower_fn_args_to_names(&sig.decl);
1071
                        hir::TraitItemKind::Method(this.lower_method_sig(sig),
1072 1073 1074 1075 1076 1077 1078 1079
                                                   hir::TraitMethod::Required(names))
                    }
                    TraitItemKind::Method(ref sig, Some(ref body)) => {
                        let body = this.lower_block(body);
                        let expr = this.expr_block(body, ThinVec::new());
                        let body_id = this.record_body(expr, Some(&sig.decl));
                        hir::TraitItemKind::Method(this.lower_method_sig(sig),
                                                   hir::TraitMethod::Provided(body_id))
1080 1081
                    }
                    TraitItemKind::Type(ref bounds, ref default) => {
1082 1083
                        hir::TraitItemKind::Type(this.lower_bounds(bounds),
                                                 default.as_ref().map(|x| this.lower_ty(x)))
1084
                    }
1085
                    TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"),
1086 1087 1088 1089
                },
                span: i.span,
            }
        })
1090 1091
    }

1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
    fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef {
        let (kind, has_default) = match i.node {
            TraitItemKind::Const(_, ref default) => {
                (hir::AssociatedItemKind::Const, default.is_some())
            }
            TraitItemKind::Type(_, ref default) => {
                (hir::AssociatedItemKind::Type, default.is_some())
            }
            TraitItemKind::Method(ref sig, ref default) => {
                (hir::AssociatedItemKind::Method {
                    has_self: sig.decl.has_self(),
                 }, default.is_some())
            }
            TraitItemKind::Macro(..) => unimplemented!(),
        };
        hir::TraitItemRef {
            id: hir::TraitItemId { node_id: i.id },
            name: i.ident.name,
            span: i.span,
            defaultness: self.lower_defaultness(Defaultness::Default, has_default),
            kind: kind,
        }
    }

1116 1117 1118 1119 1120 1121 1122
    fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
        self.with_parent_def(i.id, |this| {
            hir::ImplItem {
                id: i.id,
                name: i.ident.name,
                attrs: this.lower_attrs(&i.attrs),
                vis: this.lower_visibility(&i.vis),
1123
                defaultness: this.lower_defaultness(i.defaultness, true /* [1] */),
1124 1125
                node: match i.node {
                    ImplItemKind::Const(ref ty, ref expr) => {
1126
                        let value = this.lower_expr(expr);
1127
                        let body_id = this.record_body(value, None);
1128
                        hir::ImplItemKind::Const(this.lower_ty(ty), body_id)
1129 1130
                    }
                    ImplItemKind::Method(ref sig, ref body) => {
1131
                        let body = this.lower_block(body);
1132
                        let expr = this.expr_block(body, ThinVec::new());
1133
                        let body_id = this.record_body(expr, Some(&sig.decl));
1134
                        hir::ImplItemKind::Method(this.lower_method_sig(sig), body_id)
1135 1136 1137 1138 1139 1140 1141
                    }
                    ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)),
                    ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
                },
                span: i.span,
            }
        })
1142 1143

        // [1] since `default impl` is not yet implemented, this is always true in impls
1144 1145
    }

1146 1147 1148 1149 1150 1151
    fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
        hir::ImplItemRef {
            id: hir::ImplItemId { node_id: i.id },
            name: i.ident.name,
            span: i.span,
            vis: self.lower_visibility(&i.vis),
1152
            defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
1153 1154 1155 1156
            kind: match i.node {
                ImplItemKind::Const(..) => hir::AssociatedItemKind::Const,
                ImplItemKind::Type(..) => hir::AssociatedItemKind::Type,
                ImplItemKind::Method(ref sig, _) => hir::AssociatedItemKind::Method {
1157
                    has_self: sig.decl.has_self(),
1158 1159 1160 1161
                },
                ImplItemKind::Macro(..) => unimplemented!(),
            },
        }
1162 1163

        // [1] since `default impl` is not yet implemented, this is always true in impls
1164 1165
    }

1166 1167 1168
    fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
        hir::Mod {
            inner: m.inner,
1169
            item_ids: m.items.iter().flat_map(|x| self.lower_item_id(x)).collect(),
1170 1171
        }
    }
1172

1173 1174 1175 1176 1177 1178 1179 1180 1181
    fn lower_macro_def(&mut self, m: &MacroDef) -> hir::MacroDef {
        hir::MacroDef {
            name: m.ident.name,
            attrs: self.lower_attrs(&m.attrs),
            id: m.id,
            span: m.span,
            body: m.body.clone().into(),
        }
    }
1182

1183 1184 1185 1186 1187 1188 1189 1190
    fn lower_item_id(&mut self, i: &Item) -> SmallVector<hir::ItemId> {
        if let ItemKind::Use(ref view_path) = i.node {
            if let ViewPathList(_, ref imports) = view_path.node {
                return iter::once(i.id).chain(imports.iter().map(|import| import.node.id))
                    .map(|id| hir::ItemId { id: id }).collect();
            }
        }
        SmallVector::one(hir::ItemId { id: i.id })
1191 1192
    }

1193
    pub fn lower_item(&mut self, i: &Item) -> hir::Item {
1194 1195 1196
        let mut name = i.ident.name;
        let attrs = self.lower_attrs(&i.attrs);
        let mut vis = self.lower_visibility(&i.vis);
1197
        let node = self.with_parent_def(i.id, |this| {
1198
            this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node)
1199 1200 1201
        });

        hir::Item {
N
Nick Cameron 已提交
1202
            id: i.id,
1203 1204
            name: name,
            attrs: attrs,
1205
            node: node,
1206
            vis: vis,
N
Nick Cameron 已提交
1207 1208
            span: i.span,
        }
1209
    }
1210

1211 1212 1213 1214 1215 1216 1217 1218
    fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
        self.with_parent_def(i.id, |this| {
            hir::ForeignItem {
                id: i.id,
                name: i.ident.name,
                attrs: this.lower_attrs(&i.attrs),
                node: match i.node {
                    ForeignItemKind::Fn(ref fdec, ref generics) => {
1219 1220 1221
                        hir::ForeignItemFn(this.lower_fn_decl(fdec),
                                           this.lower_fn_args_to_names(fdec),
                                           this.lower_generics(generics))
1222 1223 1224 1225 1226 1227 1228 1229 1230
                    }
                    ForeignItemKind::Static(ref t, m) => {
                        hir::ForeignItemStatic(this.lower_ty(t), m)
                    }
                },
                vis: this.lower_visibility(&i.vis),
                span: i.span,
            }
        })
1231 1232
    }

1233
    fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig {
1234
        hir::MethodSig {
1235 1236 1237 1238 1239 1240
            generics: self.lower_generics(&sig.generics),
            abi: sig.abi,
            unsafety: self.lower_unsafety(sig.unsafety),
            constness: self.lower_constness(sig.constness),
            decl: self.lower_fn_decl(&sig.decl),
        }
1241 1242
    }

1243 1244 1245 1246 1247
    fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
        match u {
            Unsafety::Unsafe => hir::Unsafety::Unsafe,
            Unsafety::Normal => hir::Unsafety::Normal,
        }
1248 1249
    }

1250 1251
    fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
        match c.node {
1252 1253 1254
            Constness::Const => hir::Constness::Const,
            Constness::NotConst => hir::Constness::NotConst,
        }
1255 1256
    }

1257 1258 1259 1260 1261 1262
    fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
        match u {
            UnOp::Deref => hir::UnDeref,
            UnOp::Not => hir::UnNot,
            UnOp::Neg => hir::UnNeg,
        }
1263 1264
    }

1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289
    fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
        Spanned {
            node: match b.node {
                BinOpKind::Add => hir::BiAdd,
                BinOpKind::Sub => hir::BiSub,
                BinOpKind::Mul => hir::BiMul,
                BinOpKind::Div => hir::BiDiv,
                BinOpKind::Rem => hir::BiRem,
                BinOpKind::And => hir::BiAnd,
                BinOpKind::Or => hir::BiOr,
                BinOpKind::BitXor => hir::BiBitXor,
                BinOpKind::BitAnd => hir::BiBitAnd,
                BinOpKind::BitOr => hir::BiBitOr,
                BinOpKind::Shl => hir::BiShl,
                BinOpKind::Shr => hir::BiShr,
                BinOpKind::Eq => hir::BiEq,
                BinOpKind::Lt => hir::BiLt,
                BinOpKind::Le => hir::BiLe,
                BinOpKind::Ne => hir::BiNe,
                BinOpKind::Ge => hir::BiGe,
                BinOpKind::Gt => hir::BiGt,
            },
            span: b.span,
        }
    }
1290

1291 1292 1293 1294 1295 1296 1297
    fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
        P(hir::Pat {
            id: p.id,
            node: match p.node {
                PatKind::Wild => hir::PatKind::Wild,
                PatKind::Ident(ref binding_mode, pth1, ref sub) => {
                    self.with_parent_def(p.id, |this| {
1298
                        match this.resolver.get_resolution(p.id).map(|d| d.base_def) {
1299
                            // `None` can occur in body-less function signatures
1300 1301 1302 1303
                            def @ None | def @ Some(Def::Local(_)) => {
                                let def_id = def.map(|d| d.def_id()).unwrap_or_else(|| {
                                    this.resolver.definitions().local_def_id(p.id)
                                });
1304
                                hir::PatKind::Binding(this.lower_binding_mode(binding_mode),
1305
                                                      def_id,
1306
                                                      respan(pth1.span, pth1.node.name),
1307 1308
                                                      sub.as_ref().map(|x| this.lower_pat(x)))
                            }
1309 1310 1311 1312 1313 1314 1315 1316
                            Some(def) => {
                                hir::PatKind::Path(hir::QPath::Resolved(None, P(hir::Path {
                                    span: pth1.span,
                                    def: def,
                                    segments: hir_vec![
                                        hir::PathSegment::from_name(pth1.node.name)
                                    ],
                                })))
1317
                            }
1318
                        }
1319 1320
                    })
                }
1321
                PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
1322
                PatKind::TupleStruct(ref path, ref pats, ddpos) => {
1323 1324
                    let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);
                    hir::PatKind::TupleStruct(qpath,
1325 1326
                                              pats.iter().map(|x| self.lower_pat(x)).collect(),
                                              ddpos)
1327
                }
1328
                PatKind::Path(ref qself, ref path) => {
1329
                    hir::PatKind::Path(self.lower_qpath(p.id, qself, path, ParamMode::Optional))
1330
                }
1331 1332 1333
                PatKind::Struct(ref path, ref fields, etc) => {
                    let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);

1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345
                    let fs = fields.iter()
                                   .map(|f| {
                                       Spanned {
                                           span: f.span,
                                           node: hir::FieldPat {
                                               name: f.node.ident.name,
                                               pat: self.lower_pat(&f.node.pat),
                                               is_shorthand: f.node.is_shorthand,
                                           },
                                       }
                                   })
                                   .collect();
1346
                    hir::PatKind::Struct(qpath, fs, etc)
1347
                }
1348 1349
                PatKind::Tuple(ref elts, ddpos) => {
                    hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
1350 1351 1352 1353 1354
                }
                PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
                PatKind::Ref(ref inner, mutbl) => {
                    hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl))
                }
1355 1356 1357 1358
                PatKind::Range(ref e1, ref e2, ref end) => {
                    hir::PatKind::Range(P(self.lower_expr(e1)),
                                        P(self.lower_expr(e2)),
                                        self.lower_range_end(end))
1359
                }
1360
                PatKind::Slice(ref before, ref slice, ref after) => {
1361
                    hir::PatKind::Slice(before.iter().map(|x| self.lower_pat(x)).collect(),
1362 1363 1364 1365 1366 1367 1368 1369
                                slice.as_ref().map(|x| self.lower_pat(x)),
                                after.iter().map(|x| self.lower_pat(x)).collect())
                }
                PatKind::Mac(_) => panic!("Shouldn't exist here"),
            },
            span: p.span,
        })
    }
N
Nick Cameron 已提交
1370

1371 1372 1373 1374 1375 1376 1377
    fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
        match *e {
            RangeEnd::Included => hir::RangeEnd::Included,
            RangeEnd::Excluded => hir::RangeEnd::Excluded,
        }
    }

1378 1379
    fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
        hir::Expr {
1380 1381 1382 1383 1384 1385 1386
            id: e.id,
            node: match e.node {
                // Issue #22181:
                // Eventually a desugaring for `box EXPR`
                // (similar to the desugaring above for `in PLACE BLOCK`)
                // should go here, desugaring
                //
N
Nick Cameron 已提交
1387 1388
                // to:
                //
1389
                // let mut place = BoxPlace::make_place();
N
Nick Cameron 已提交
1390
                // let raw_place = Place::pointer(&mut place);
1391 1392 1393 1394 1395 1396 1397 1398
                // let value = $value;
                // unsafe {
                //     ::std::ptr::write(raw_place, value);
                //     Boxed::finalize(place)
                // }
                //
                // But for now there are type-inference issues doing that.
                ExprKind::Box(ref e) => {
1399
                    hir::ExprBox(P(self.lower_expr(e)))
1400
                }
N
Nick Cameron 已提交
1401

1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412
                // Desugar ExprBox: `in (PLACE) EXPR`
                ExprKind::InPlace(ref placer, ref value_expr) => {
                    // to:
                    //
                    // let p = PLACE;
                    // let mut place = Placer::make_place(p);
                    // let raw_place = Place::pointer(&mut place);
                    // push_unsafe!({
                    //     std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
                    //     InPlace::finalize(place)
                    // })
1413 1414
                    let placer_expr = P(self.lower_expr(placer));
                    let value_expr = P(self.lower_expr(value_expr));
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424

                    let placer_ident = self.str_to_ident("placer");
                    let place_ident = self.str_to_ident("place");
                    let p_ptr_ident = self.str_to_ident("p_ptr");

                    let make_place = ["ops", "Placer", "make_place"];
                    let place_pointer = ["ops", "Place", "pointer"];
                    let move_val_init = ["intrinsics", "move_val_init"];
                    let inplace_finalize = ["ops", "InPlace", "finalize"];

1425
                    let unstable_span = self.allow_internal_unstable("<-", e.span);
1426
                    let make_call = |this: &mut LoweringContext, p, args| {
1427
                        let path = P(this.expr_std_path(unstable_span, p, ThinVec::new()));
1428
                        P(this.expr_call(e.span, path, args))
1429
                    };
N
Nick Cameron 已提交
1430

1431
                    let mk_stmt_let = |this: &mut LoweringContext, bind, expr| {
1432
                        this.stmt_let(e.span, false, bind, expr)
1433 1434
                    };

1435
                    let mk_stmt_let_mut = |this: &mut LoweringContext, bind, expr| {
1436
                        this.stmt_let(e.span, true, bind, expr)
1437
                    };
1438

1439 1440 1441 1442
                    // let placer = <placer_expr> ;
                    let (s1, placer_binding) = {
                        mk_stmt_let(self, placer_ident, placer_expr)
                    };
1443

1444 1445
                    // let mut place = Placer::make_place(placer);
                    let (s2, place_binding) = {
1446
                        let placer = self.expr_ident(e.span, placer_ident, placer_binding);
1447 1448 1449
                        let call = make_call(self, &make_place, hir_vec![placer]);
                        mk_stmt_let_mut(self, place_ident, call)
                    };
1450

1451 1452
                    // let p_ptr = Place::pointer(&mut place);
                    let (s3, p_ptr_binding) = {
1453
                        let agent = P(self.expr_ident(e.span, place_ident, place_binding));
1454
                        let args = hir_vec![self.expr_mut_addr_of(e.span, agent)];
1455 1456 1457
                        let call = make_call(self, &place_pointer, args);
                        mk_stmt_let(self, p_ptr_ident, call)
                    };
1458

1459 1460
                    // pop_unsafe!(EXPR));
                    let pop_unsafe_expr = {
1461 1462 1463
                        self.signal_block_expr(hir_vec![],
                                               value_expr,
                                               e.span,
1464 1465
                                               hir::PopUnsafeBlock(hir::CompilerGenerated),
                                               ThinVec::new())
1466
                    };
1467

1468 1469 1470 1471 1472
                    // push_unsafe!({
                    //     std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
                    //     InPlace::finalize(place)
                    // })
                    let expr = {
1473
                        let ptr = self.expr_ident(e.span, p_ptr_ident, p_ptr_binding);
1474 1475 1476 1477 1478 1479
                        let call_move_val_init =
                            hir::StmtSemi(
                                make_call(self, &move_val_init, hir_vec![ptr, pop_unsafe_expr]),
                                self.next_id());
                        let call_move_val_init = respan(e.span, call_move_val_init);

1480
                        let place = self.expr_ident(e.span, place_ident, place_binding);
1481
                        let call = make_call(self, &inplace_finalize, hir_vec![place]);
1482 1483 1484 1485 1486
                        P(self.signal_block_expr(hir_vec![call_move_val_init],
                                                 call,
                                                 e.span,
                                                 hir::PushUnsafeBlock(hir::CompilerGenerated),
                                                 ThinVec::new()))
1487
                    };
1488

1489 1490 1491
                    let block = self.block_all(e.span, hir_vec![s1, s2, s3], Some(expr));
                    // add the attributes to the outer returned expr node
                    return self.expr_block(P(block), e.attrs.clone());
1492
                }
1493

1494
                ExprKind::Array(ref exprs) => {
1495
                    hir::ExprArray(exprs.iter().map(|x| self.lower_expr(x)).collect())
1496 1497
                }
                ExprKind::Repeat(ref expr, ref count) => {
1498
                    let expr = P(self.lower_expr(expr));
1499
                    let count = self.lower_expr(count);
1500
                    hir::ExprRepeat(expr, self.record_body(count, None))
1501 1502 1503 1504 1505
                }
                ExprKind::Tup(ref elts) => {
                    hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect())
                }
                ExprKind::Call(ref f, ref args) => {
1506
                    let f = P(self.lower_expr(f));
1507 1508 1509 1510 1511 1512 1513 1514 1515
                    hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
                }
                ExprKind::MethodCall(i, ref tps, ref args) => {
                    let tps = tps.iter().map(|x| self.lower_ty(x)).collect();
                    let args = args.iter().map(|x| self.lower_expr(x)).collect();
                    hir::ExprMethodCall(respan(i.span, i.node.name), tps, args)
                }
                ExprKind::Binary(binop, ref lhs, ref rhs) => {
                    let binop = self.lower_binop(binop);
1516 1517
                    let lhs = P(self.lower_expr(lhs));
                    let rhs = P(self.lower_expr(rhs));
1518 1519 1520 1521
                    hir::ExprBinary(binop, lhs, rhs)
                }
                ExprKind::Unary(op, ref ohs) => {
                    let op = self.lower_unop(op);
1522
                    let ohs = P(self.lower_expr(ohs));
1523 1524 1525 1526
                    hir::ExprUnary(op, ohs)
                }
                ExprKind::Lit(ref l) => hir::ExprLit(P((**l).clone())),
                ExprKind::Cast(ref expr, ref ty) => {
1527
                    let expr = P(self.lower_expr(expr));
1528 1529 1530
                    hir::ExprCast(expr, self.lower_ty(ty))
                }
                ExprKind::Type(ref expr, ref ty) => {
1531
                    let expr = P(self.lower_expr(expr));
1532 1533 1534 1535
                    hir::ExprType(expr, self.lower_ty(ty))
                }
                ExprKind::AddrOf(m, ref ohs) => {
                    let m = self.lower_mutability(m);
1536
                    let ohs = P(self.lower_expr(ohs));
1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
                    hir::ExprAddrOf(m, ohs)
                }
                // More complicated than you might expect because the else branch
                // might be `if let`.
                ExprKind::If(ref cond, ref blk, ref else_opt) => {
                    let else_opt = else_opt.as_ref().map(|els| {
                        match els.node {
                            ExprKind::IfLet(..) => {
                                // wrap the if-let expr in a block
                                let span = els.span;
1547
                                let els = P(self.lower_expr(els));
1548 1549 1550 1551 1552 1553 1554 1555
                                let id = self.next_id();
                                let blk = P(hir::Block {
                                    stmts: hir_vec![],
                                    expr: Some(els),
                                    id: id,
                                    rules: hir::DefaultBlock,
                                    span: span,
                                });
1556
                                P(self.expr_block(blk, ThinVec::new()))
1557
                            }
1558
                            _ => P(self.lower_expr(els)),
1559 1560
                        }
                    });
1561

1562
                    hir::ExprIf(P(self.lower_expr(cond)), self.lower_block(blk), else_opt)
1563 1564
                }
                ExprKind::While(ref cond, ref body, opt_ident) => {
1565
                    hir::ExprWhile(P(self.lower_expr(cond)), self.lower_block(body),
1566
                                   self.lower_opt_sp_ident(opt_ident))
1567 1568
                }
                ExprKind::Loop(ref body, opt_ident) => {
1569 1570 1571
                    hir::ExprLoop(self.lower_block(body),
                                  self.lower_opt_sp_ident(opt_ident),
                                  hir::LoopSource::Loop)
1572 1573
                }
                ExprKind::Match(ref expr, ref arms) => {
1574
                    hir::ExprMatch(P(self.lower_expr(expr)),
1575 1576 1577 1578 1579
                                   arms.iter().map(|x| self.lower_arm(x)).collect(),
                                   hir::MatchSource::Normal)
                }
                ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => {
                    self.with_parent_def(e.id, |this| {
1580
                        let expr = this.lower_expr(body);
1581 1582
                        hir::ExprClosure(this.lower_capture_clause(capture_clause),
                                         this.lower_fn_decl(decl),
1583
                                         this.record_body(expr, Some(decl)),
1584 1585 1586 1587 1588
                                         fn_decl_span)
                    })
                }
                ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk)),
                ExprKind::Assign(ref el, ref er) => {
1589
                    hir::ExprAssign(P(self.lower_expr(el)), P(self.lower_expr(er)))
1590 1591 1592
                }
                ExprKind::AssignOp(op, ref el, ref er) => {
                    hir::ExprAssignOp(self.lower_binop(op),
1593 1594
                                      P(self.lower_expr(el)),
                                      P(self.lower_expr(er)))
1595 1596
                }
                ExprKind::Field(ref el, ident) => {
1597
                    hir::ExprField(P(self.lower_expr(el)), respan(ident.span, ident.node.name))
1598 1599
                }
                ExprKind::TupField(ref el, ident) => {
1600
                    hir::ExprTupField(P(self.lower_expr(el)), ident)
1601 1602
                }
                ExprKind::Index(ref el, ref er) => {
1603
                    hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er)))
1604 1605 1606 1607 1608
                }
                ExprKind::Range(ref e1, ref e2, lims) => {
                    fn make_struct(this: &mut LoweringContext,
                                   ast_expr: &Expr,
                                   path: &[&str],
1609
                                   fields: &[(&str, &P<Expr>)]) -> hir::Expr {
1610 1611
                        let struct_path = &iter::once(&"ops").chain(path).map(|s| *s)
                                                             .collect::<Vec<_>>();
1612
                        let unstable_span = this.allow_internal_unstable("...", ast_expr.span);
1613

1614 1615
                        if fields.len() == 0 {
                            this.expr_std_path(unstable_span, struct_path,
1616
                                               ast_expr.attrs.clone())
1617 1618
                        } else {
                            let fields = fields.into_iter().map(|&(s, e)| {
1619
                                let expr = P(this.lower_expr(&e));
1620 1621
                                let unstable_span = this.allow_internal_unstable("...", e.span);
                                this.field(Symbol::intern(s), expr, unstable_span)
1622 1623 1624
                            }).collect();
                            let attrs = ast_expr.attrs.clone();

1625 1626
                            this.expr_std_struct(unstable_span, struct_path, fields, None, attrs)
                        }
N
Nick Cameron 已提交
1627
                    }
1628 1629 1630 1631 1632

                    use syntax::ast::RangeLimits::*;

                    return match (e1, e2, lims) {
                        (&None,         &None,         HalfOpen) =>
1633
                            make_struct(self, e, &["RangeFull"], &[]),
1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654

                        (&Some(ref e1), &None,         HalfOpen) =>
                            make_struct(self, e, &["RangeFrom"],
                                                 &[("start", e1)]),

                        (&None,         &Some(ref e2), HalfOpen) =>
                            make_struct(self, e, &["RangeTo"],
                                                 &[("end", e2)]),

                        (&Some(ref e1), &Some(ref e2), HalfOpen) =>
                            make_struct(self, e, &["Range"],
                                                 &[("start", e1), ("end", e2)]),

                        (&None,         &Some(ref e2), Closed)   =>
                            make_struct(self, e, &["RangeToInclusive"],
                                                 &[("end", e2)]),

                        (&Some(ref e1), &Some(ref e2), Closed)   =>
                            make_struct(self, e, &["RangeInclusive", "NonEmpty"],
                                                 &[("start", e1), ("end", e2)]),

1655
                        _ => panic!(self.diagnostic()
1656 1657 1658 1659
                                        .span_fatal(e.span, "inclusive range with no end")),
                    };
                }
                ExprKind::Path(ref qself, ref path) => {
1660
                    hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional))
1661
                }
1662
                ExprKind::Break(opt_ident, ref opt_expr) => {
1663
                    hir::ExprBreak(self.lower_label(e.id, opt_ident),
1664 1665
                                   opt_expr.as_ref().map(|x| P(self.lower_expr(x))))
                }
1666
                ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_label(e.id, opt_ident)),
1667
                ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| P(self.lower_expr(x)))),
J
Jeffrey Seyfried 已提交
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691
                ExprKind::InlineAsm(ref asm) => {
                    let hir_asm = hir::InlineAsm {
                        inputs: asm.inputs.iter().map(|&(ref c, _)| c.clone()).collect(),
                        outputs: asm.outputs.iter().map(|out| {
                            hir::InlineAsmOutput {
                                constraint: out.constraint.clone(),
                                is_rw: out.is_rw,
                                is_indirect: out.is_indirect,
                            }
                        }).collect(),
                        asm: asm.asm.clone(),
                        asm_str_style: asm.asm_str_style,
                        clobbers: asm.clobbers.clone().into(),
                        volatile: asm.volatile,
                        alignstack: asm.alignstack,
                        dialect: asm.dialect,
                        expn_id: asm.expn_id,
                    };
                    let outputs =
                        asm.outputs.iter().map(|out| self.lower_expr(&out.expr)).collect();
                    let inputs =
                        asm.inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect();
                    hir::ExprInlineAsm(P(hir_asm), outputs, inputs)
                }
1692
                ExprKind::Struct(ref path, ref fields, ref maybe_expr) => {
1693
                    hir::ExprStruct(self.lower_qpath(e.id, &None, path, ParamMode::Optional),
1694
                                    fields.iter().map(|x| self.lower_field(x)).collect(),
1695
                                    maybe_expr.as_ref().map(|x| P(self.lower_expr(x))))
1696 1697
                }
                ExprKind::Paren(ref ex) => {
1698 1699 1700 1701 1702 1703 1704 1705 1706 1707
                    let mut ex = self.lower_expr(ex);
                    // include parens in span, but only if it is a super-span.
                    if e.span.contains(ex.span) {
                        ex.span = e.span;
                    }
                    // merge attributes into the inner expression.
                    let mut attrs = e.attrs.clone();
                    attrs.extend::<Vec<_>>(ex.attrs.into());
                    ex.attrs = attrs;
                    return ex;
1708
                }
N
Nick Cameron 已提交
1709

1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723
                // Desugar ExprIfLet
                // From: `if let <pat> = <sub_expr> <body> [<else_opt>]`
                ExprKind::IfLet(ref pat, ref sub_expr, ref body, ref else_opt) => {
                    // to:
                    //
                    //   match <sub_expr> {
                    //     <pat> => <body>,
                    //     [_ if <else_opt_if_cond> => <else_opt_if_body>,]
                    //     _ => [<else_opt> | ()]
                    //   }

                    // `<pat> => <body>`
                    let pat_arm = {
                        let body = self.lower_block(body);
1724
                        let body_expr = P(self.expr_block(body, ThinVec::new()));
1725 1726
                        let pat = self.lower_pat(pat);
                        self.arm(hir_vec![pat], body_expr)
1727 1728 1729
                    };

                    // `[_ if <else_opt_if_cond> => <else_opt_if_body>,]`
1730
                    let mut else_opt = else_opt.as_ref().map(|e| P(self.lower_expr(e)));
1731 1732 1733 1734 1735 1736 1737 1738
                    let else_if_arms = {
                        let mut arms = vec![];
                        loop {
                            let else_opt_continue = else_opt.and_then(|els| {
                                els.and_then(|els| {
                                    match els.node {
                                        // else if
                                        hir::ExprIf(cond, then, else_opt) => {
1739
                                            let pat_under = self.pat_wild(e.span);
1740 1741 1742 1743
                                            arms.push(hir::Arm {
                                                attrs: hir_vec![],
                                                pats: hir_vec![pat_under],
                                                guard: Some(cond),
1744
                                                body: P(self.expr_block(then, ThinVec::new())),
1745 1746 1747 1748
                                            });
                                            else_opt.map(|else_opt| (else_opt, true))
                                        }
                                        _ => Some((P(els), false)),
N
Nick Cameron 已提交
1749
                                    }
1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762
                                })
                            });
                            match else_opt_continue {
                                Some((e, true)) => {
                                    else_opt = Some(e);
                                }
                                Some((e, false)) => {
                                    else_opt = Some(e);
                                    break;
                                }
                                None => {
                                    else_opt = None;
                                    break;
N
Nick Cameron 已提交
1763 1764 1765
                                }
                            }
                        }
1766 1767
                        arms
                    };
N
Nick Cameron 已提交
1768

1769
                    let contains_else_clause = else_opt.is_some();
N
Nick Cameron 已提交
1770

1771 1772
                    // `_ => [<else_opt> | ()]`
                    let else_arm = {
1773
                        let pat_under = self.pat_wild(e.span);
1774
                        let else_expr =
1775
                            else_opt.unwrap_or_else(|| self.expr_tuple(e.span, hir_vec![]));
1776
                        self.arm(hir_vec![pat_under], else_expr)
1777
                    };
1778

1779 1780 1781 1782 1783
                    let mut arms = Vec::with_capacity(else_if_arms.len() + 2);
                    arms.push(pat_arm);
                    arms.extend(else_if_arms);
                    arms.push(else_arm);

1784
                    let sub_expr = P(self.lower_expr(sub_expr));
1785
                    // add attributes to the outer returned expr node
1786 1787 1788 1789 1790 1791 1792
                    return self.expr(e.span,
                                     hir::ExprMatch(sub_expr,
                                                    arms.into(),
                                                    hir::MatchSource::IfLetDesugar {
                                                        contains_else_clause: contains_else_clause,
                                                    }),
                                     e.attrs.clone());
1793
                }
1794

1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809
                // Desugar ExprWhileLet
                // From: `[opt_ident]: while let <pat> = <sub_expr> <body>`
                ExprKind::WhileLet(ref pat, ref sub_expr, ref body, opt_ident) => {
                    // to:
                    //
                    //   [opt_ident]: loop {
                    //     match <sub_expr> {
                    //       <pat> => <body>,
                    //       _ => break
                    //     }
                    //   }

                    // `<pat> => <body>`
                    let pat_arm = {
                        let body = self.lower_block(body);
1810
                        let body_expr = P(self.expr_block(body, ThinVec::new()));
1811 1812
                        let pat = self.lower_pat(pat);
                        self.arm(hir_vec![pat], body_expr)
1813
                    };
1814

1815 1816
                    // `_ => break`
                    let break_arm = {
1817
                        let pat_under = self.pat_wild(e.span);
1818
                        let break_expr = self.expr_break(e.span, ThinVec::new());
1819
                        self.arm(hir_vec![pat_under], break_expr)
1820
                    };
J
Jeffrey Seyfried 已提交
1821

1822 1823
                    // `match <sub_expr> { ... }`
                    let arms = hir_vec![pat_arm, break_arm];
1824
                    let sub_expr = P(self.lower_expr(sub_expr));
1825 1826 1827 1828
                    let match_expr = self.expr(e.span,
                                               hir::ExprMatch(sub_expr,
                                                              arms,
                                                              hir::MatchSource::WhileLetDesugar),
1829
                                               ThinVec::new());
1830 1831

                    // `[opt_ident]: loop { ... }`
1832
                    let loop_block = P(self.block_expr(P(match_expr)));
1833 1834
                    let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident),
                                                  hir::LoopSource::WhileLet);
1835 1836
                    // add attributes to the outer returned expr node
                    let attrs = e.attrs.clone();
1837
                    return hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs };
1838
                }
1839

1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866
                // Desugar ExprForLoop
                // From: `[opt_ident]: for <pat> in <head> <body>`
                ExprKind::ForLoop(ref pat, ref head, ref body, opt_ident) => {
                    // to:
                    //
                    //   {
                    //     let result = match ::std::iter::IntoIterator::into_iter(<head>) {
                    //       mut iter => {
                    //         [opt_ident]: loop {
                    //           match ::std::iter::Iterator::next(&mut iter) {
                    //             ::std::option::Option::Some(<pat>) => <body>,
                    //             ::std::option::Option::None => break
                    //           }
                    //         }
                    //       }
                    //     };
                    //     result
                    //   }

                    // expand <head>
                    let head = self.lower_expr(head);

                    let iter = self.str_to_ident("iter");

                    // `::std::option::Option::Some(<pat>) => <body>`
                    let pat_arm = {
                        let body_block = self.lower_block(body);
1867
                        let body_expr = P(self.expr_block(body_block, ThinVec::new()));
1868
                        let pat = self.lower_pat(pat);
1869
                        let some_pat = self.pat_some(e.span, pat);
J
Jeffrey Seyfried 已提交
1870

1871
                        self.arm(hir_vec![some_pat], body_expr)
1872
                    };
J
Jeffrey Seyfried 已提交
1873

1874 1875
                    // `::std::option::Option::None => break`
                    let break_arm = {
1876
                        let break_expr = self.expr_break(e.span, ThinVec::new());
1877 1878
                        let pat = self.pat_none(e.span);
                        self.arm(hir_vec![pat], break_expr)
1879
                    };
J
Jeffrey Seyfried 已提交
1880

1881
                    // `mut iter`
1882 1883
                    let iter_pat = self.pat_ident_binding_mode(e.span, iter,
                                                               hir::BindByValue(hir::MutMutable));
1884 1885 1886

                    // `match ::std::iter::Iterator::next(&mut iter) { ... }`
                    let match_expr = {
1887
                        let iter = P(self.expr_ident(e.span, iter, iter_pat.id));
1888
                        let ref_mut_iter = self.expr_mut_addr_of(e.span, iter);
1889
                        let next_path = &["iter", "Iterator", "next"];
1890
                        let next_path = P(self.expr_std_path(e.span, next_path, ThinVec::new()));
1891 1892
                        let next_expr = P(self.expr_call(e.span, next_path,
                                          hir_vec![ref_mut_iter]));
1893 1894
                        let arms = hir_vec![pat_arm, break_arm];

1895 1896 1897 1898
                        P(self.expr(e.span,
                                    hir::ExprMatch(next_expr, arms,
                                                   hir::MatchSource::ForLoopDesugar),
                                    ThinVec::new()))
1899
                    };
1900

1901
                    // `[opt_ident]: loop { ... }`
1902
                    let loop_block = P(self.block_expr(match_expr));
1903 1904
                    let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident),
                                                  hir::LoopSource::ForLoop);
1905 1906 1907 1908 1909 1910
                    let loop_expr = P(hir::Expr {
                        id: e.id,
                        node: loop_expr,
                        span: e.span,
                        attrs: ThinVec::new(),
                    });
1911

1912
                    // `mut iter => { ... }`
1913
                    let iter_arm = self.arm(hir_vec![iter_pat], loop_expr);
1914

1915 1916
                    // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
                    let into_iter_expr = {
1917
                        let into_iter_path = &["iter", "IntoIterator", "into_iter"];
1918 1919
                        let into_iter = P(self.expr_std_path(e.span, into_iter_path,
                                                             ThinVec::new()));
1920
                        P(self.expr_call(e.span, into_iter, hir_vec![head]))
J
Jeffrey Seyfried 已提交
1921
                    };
1922

1923 1924 1925 1926
                    let match_expr = P(self.expr_match(e.span,
                                                       into_iter_expr,
                                                       hir_vec![iter_arm],
                                                       hir::MatchSource::ForLoopDesugar));
1927 1928 1929 1930 1931

                    // `{ let _result = ...; _result }`
                    // underscore prevents an unused_variables lint if the head diverges
                    let result_ident = self.str_to_ident("_result");
                    let (let_stmt, let_stmt_binding) =
1932
                        self.stmt_let(e.span, false, result_ident, match_expr);
1933

1934 1935
                    let result = P(self.expr_ident(e.span, result_ident, let_stmt_binding));
                    let block = P(self.block_all(e.span, hir_vec![let_stmt], Some(result)));
1936
                    // add the attributes to the outer returned expr node
1937
                    return self.expr_block(block, e.attrs.clone());
1938 1939 1940 1941 1942 1943 1944
                }

                // Desugar ExprKind::Try
                // From: `<expr>?`
                ExprKind::Try(ref sub_expr) => {
                    // to:
                    //
1945
                    // match Carrier::translate(<expr>) {
A
Andrew Cann 已提交
1946 1947 1948
                    //     Ok(val) => #[allow(unreachable_code)] val,
                    //     Err(err) => #[allow(unreachable_code)]
                    //                 return Carrier::from_error(From::from(err)),
1949
                    // }
1950
                    let unstable_span = self.allow_internal_unstable("?", e.span);
1951

1952
                    // Carrier::translate(<expr>)
1953 1954
                    let discr = {
                        // expand <expr>
1955
                        let sub_expr = self.lower_expr(sub_expr);
1956

1957
                        let path = &["ops", "Carrier", "translate"];
1958 1959
                        let path = P(self.expr_std_path(unstable_span, path, ThinVec::new()));
                        P(self.expr_call(e.span, path, hir_vec![sub_expr]))
1960
                    };
1961

1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976
                    // #[allow(unreachable_code)]
                    let attr = {
                        // allow(unreachable_code)
                        let allow = {
                            let allow_ident = self.str_to_ident("allow");
                            let uc_ident = self.str_to_ident("unreachable_code");
                            let uc_meta_item = attr::mk_spanned_word_item(e.span, uc_ident);
                            let uc_nested = NestedMetaItemKind::MetaItem(uc_meta_item);
                            let uc_spanned = respan(e.span, uc_nested);
                            attr::mk_spanned_list_item(e.span, allow_ident, vec![uc_spanned])
                        };
                        attr::mk_spanned_attr_outer(e.span, attr::mk_attr_id(), allow)
                    };
                    let attrs = vec![attr];

A
Andrew Cann 已提交
1977
                    // Ok(val) => #[allow(unreachable_code)] val,
1978 1979
                    let ok_arm = {
                        let val_ident = self.str_to_ident("val");
1980
                        let val_pat = self.pat_ident(e.span, val_ident);
A
Andrew Cann 已提交
1981 1982 1983
                        let val_expr = P(self.expr_ident_with_attrs(e.span,
                                                                    val_ident,
                                                                    val_pat.id,
A
Andrew Cann 已提交
1984
                                                                    ThinVec::from(attrs.clone())));
1985
                        let ok_pat = self.pat_ok(e.span, val_pat);
1986

1987
                        self.arm(hir_vec![ok_pat], val_expr)
J
Jorge Aparicio 已提交
1988 1989
                    };

A
Andrew Cann 已提交
1990 1991
                    // Err(err) => #[allow(unreachable_code)]
                    //             return Carrier::from_error(From::from(err)),
1992 1993
                    let err_arm = {
                        let err_ident = self.str_to_ident("err");
1994
                        let err_local = self.pat_ident(e.span, err_ident);
1995
                        let from_expr = {
1996
                            let path = &["convert", "From", "from"];
1997
                            let from = P(self.expr_std_path(e.span, path, ThinVec::new()));
1998
                            let err_expr = self.expr_ident(e.span, err_ident, err_local.id);
1999

2000
                            self.expr_call(e.span, from, hir_vec![err_expr])
2001
                        };
2002
                        let from_err_expr = {
2003
                            let path = &["ops", "Carrier", "from_error"];
2004 2005
                            let from_err = P(self.expr_std_path(unstable_span, path,
                                                                ThinVec::new()));
2006
                            P(self.expr_call(e.span, from_err, hir_vec![from_expr]))
2007
                        };
2008

2009 2010
                        let ret_expr = P(self.expr(e.span,
                                                   hir::Expr_::ExprRet(Some(from_err_expr)),
A
Andrew Cann 已提交
2011
                                                                       ThinVec::from(attrs)));
2012 2013

                        let err_pat = self.pat_err(e.span, err_local);
2014
                        self.arm(hir_vec![err_pat], ret_expr)
2015
                    };
J
Jeffrey Seyfried 已提交
2016

2017
                    return self.expr_match(e.span, discr, hir_vec![err_arm, ok_arm],
2018
                                           hir::MatchSource::TryDesugar);
2019
                }
J
Jorge Aparicio 已提交
2020

2021 2022 2023 2024
                ExprKind::Mac(_) => panic!("Shouldn't exist here"),
            },
            span: e.span,
            attrs: e.attrs.clone(),
2025
        }
2026
    }
2027

2028 2029
    fn lower_stmt(&mut self, s: &Stmt) -> SmallVector<hir::Stmt> {
        SmallVector::one(match s.node {
J
Jeffrey Seyfried 已提交
2030 2031 2032
            StmtKind::Local(ref l) => Spanned {
                node: hir::StmtDecl(P(Spanned {
                    node: hir::DeclLocal(self.lower_local(l)),
2033
                    span: s.span,
J
Jeffrey Seyfried 已提交
2034 2035 2036
                }), s.id),
                span: s.span,
            },
2037 2038 2039 2040 2041 2042 2043 2044
            StmtKind::Item(ref it) => {
                // Can only use the ID once.
                let mut id = Some(s.id);
                return self.lower_item_id(it).into_iter().map(|item_id| Spanned {
                    node: hir::StmtDecl(P(Spanned {
                        node: hir::DeclItem(item_id),
                        span: s.span,
                    }), id.take().unwrap_or_else(|| self.next_id())),
J
Jeffrey Seyfried 已提交
2045
                    span: s.span,
2046 2047
                }).collect();
            }
J
Jeffrey Seyfried 已提交
2048
            StmtKind::Expr(ref e) => {
2049
                Spanned {
2050
                    node: hir::StmtExpr(P(self.lower_expr(e)), s.id),
2051 2052
                    span: s.span,
                }
2053
            }
J
Jeffrey Seyfried 已提交
2054
            StmtKind::Semi(ref e) => {
2055
                Spanned {
2056
                    node: hir::StmtSemi(P(self.lower_expr(e)), s.id),
2057 2058
                    span: s.span,
                }
2059
            }
2060
            StmtKind::Mac(..) => panic!("Shouldn't exist here"),
2061
        })
2062 2063
    }

2064 2065 2066 2067 2068
    fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause {
        match c {
            CaptureBy::Value => hir::CaptureByValue,
            CaptureBy::Ref => hir::CaptureByRef,
        }
2069 2070
    }

2071 2072 2073 2074
    fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility {
        match *v {
            Visibility::Public => hir::Public,
            Visibility::Crate(_) => hir::Visibility::Crate,
2075 2076
            Visibility::Restricted { ref path, id } => {
                hir::Visibility::Restricted {
2077
                    path: P(self.lower_path(id, path, ParamMode::Explicit, true)),
2078 2079 2080
                    id: id
                }
            }
2081 2082
            Visibility::Inherited => hir::Inherited,
        }
2083 2084
    }

2085
    fn lower_defaultness(&mut self, d: Defaultness, has_value: bool) -> hir::Defaultness {
2086
        match d {
2087 2088 2089 2090 2091
            Defaultness::Default => hir::Defaultness::Default { has_value: has_value },
            Defaultness::Final => {
                assert!(has_value);
                hir::Defaultness::Final
            }
2092
        }
2093 2094
    }

2095 2096 2097 2098 2099
    fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
        match *b {
            BlockCheckMode::Default => hir::DefaultBlock,
            BlockCheckMode::Unsafe(u) => hir::UnsafeBlock(self.lower_unsafe_source(u)),
        }
2100 2101
    }

2102 2103 2104 2105 2106
    fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingMode {
        match *b {
            BindingMode::ByRef(m) => hir::BindByRef(self.lower_mutability(m)),
            BindingMode::ByValue(m) => hir::BindByValue(self.lower_mutability(m)),
        }
2107 2108
    }

2109 2110 2111 2112 2113
    fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource {
        match u {
            CompilerGenerated => hir::CompilerGenerated,
            UserProvided => hir::UserProvided,
        }
2114 2115
    }

2116 2117 2118 2119 2120
    fn lower_impl_polarity(&mut self, i: ImplPolarity) -> hir::ImplPolarity {
        match i {
            ImplPolarity::Positive => hir::ImplPolarity::Positive,
            ImplPolarity::Negative => hir::ImplPolarity::Negative,
        }
2121 2122
    }

2123 2124 2125 2126 2127
    fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier {
        match f {
            TraitBoundModifier::None => hir::TraitBoundModifier::None,
            TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe,
        }
2128
    }
2129

2130
    // Helper methods for building HIR.
2131

2132 2133 2134 2135 2136 2137 2138
    fn arm(&mut self, pats: hir::HirVec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
        hir::Arm {
            attrs: hir_vec![],
            pats: pats,
            guard: None,
            body: expr,
        }
2139 2140
    }

2141 2142 2143 2144 2145 2146
    fn field(&mut self, name: Name, expr: P<hir::Expr>, span: Span) -> hir::Field {
        hir::Field {
            name: Spanned {
                node: name,
                span: span,
            },
2147
            span: span,
2148
            expr: expr,
2149
            is_shorthand: false,
2150
        }
2151 2152
    }

2153
    fn expr_break(&mut self, span: Span, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
2154
        P(self.expr(span, hir::ExprBreak(None, None), attrs))
2155
    }
2156

2157 2158
    fn expr_call(&mut self, span: Span, e: P<hir::Expr>, args: hir::HirVec<hir::Expr>)
                 -> hir::Expr {
2159
        self.expr(span, hir::ExprCall(e, args), ThinVec::new())
2160
    }
2161

2162
    fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> hir::Expr {
2163 2164 2165 2166 2167 2168 2169
        self.expr_ident_with_attrs(span, id, binding, ThinVec::new())
    }

    fn expr_ident_with_attrs(&mut self, span: Span,
                                        id: Name,
                                        binding: NodeId,
                                        attrs: ThinVec<Attribute>) -> hir::Expr {
2170 2171
        let def = {
            let defs = self.resolver.definitions();
2172
            Def::Local(defs.local_def_id(binding))
2173
        };
2174 2175 2176 2177 2178 2179

        let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(hir::Path {
            span: span,
            def: def,
            segments: hir_vec![hir::PathSegment::from_name(id)],
        })));
2180

2181
        self.expr(span, expr_path, attrs)
2182
    }
2183

2184
    fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> hir::Expr {
2185
        self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), ThinVec::new())
2186
    }
2187

2188 2189 2190 2191
    fn expr_std_path(&mut self,
                     span: Span,
                     components: &[&str],
                     attrs: ThinVec<Attribute>)
2192
                     -> hir::Expr {
2193
        let path = self.std_path(span, components, true);
2194
        self.expr(span, hir::ExprPath(hir::QPath::Resolved(None, P(path))), attrs)
2195
    }
2196

2197 2198 2199 2200
    fn expr_match(&mut self,
                  span: Span,
                  arg: P<hir::Expr>,
                  arms: hir::HirVec<hir::Arm>,
2201
                  source: hir::MatchSource)
2202
                  -> hir::Expr {
2203
        self.expr(span, hir::ExprMatch(arg, arms, source), ThinVec::new())
2204
    }
2205

2206
    fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinVec<Attribute>) -> hir::Expr {
2207 2208
        self.expr(b.span, hir::ExprBlock(b), attrs)
    }
2209

2210 2211
    fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<hir::Expr>) -> P<hir::Expr> {
        P(self.expr(sp, hir::ExprTup(exprs), ThinVec::new()))
2212
    }
N
Nick Cameron 已提交
2213

2214 2215 2216 2217 2218
    fn expr_std_struct(&mut self,
                       span: Span,
                       components: &[&str],
                       fields: hir::HirVec<hir::Field>,
                       e: Option<P<hir::Expr>>,
2219
                       attrs: ThinVec<Attribute>) -> hir::Expr {
2220
        let path = self.std_path(span, components, false);
2221
        let qpath = hir::QPath::Resolved(None, P(path));
2222
        self.expr(span, hir::ExprStruct(qpath, fields, e), attrs)
2223
    }
2224

2225 2226
    fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> hir::Expr {
        hir::Expr {
2227 2228 2229 2230
            id: self.next_id(),
            node: node,
            span: span,
            attrs: attrs,
2231
        }
2232
    }
2233

2234
    fn stmt_let(&mut self, sp: Span, mutbl: bool, ident: Name, ex: P<hir::Expr>)
2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247
                -> (hir::Stmt, NodeId) {
        let pat = if mutbl {
            self.pat_ident_binding_mode(sp, ident, hir::BindByValue(hir::MutMutable))
        } else {
            self.pat_ident(sp, ident)
        };
        let pat_id = pat.id;
        let local = P(hir::Local {
            pat: pat,
            ty: None,
            init: Some(ex),
            id: self.next_id(),
            span: sp,
2248
            attrs: ThinVec::new(),
2249 2250 2251 2252
        });
        let decl = respan(sp, hir::DeclLocal(local));
        (respan(sp, hir::StmtDecl(P(decl), self.next_id())), pat_id)
    }
2253

2254
    fn block_expr(&mut self, expr: P<hir::Expr>) -> hir::Block {
2255 2256
        self.block_all(expr.span, hir::HirVec::new(), Some(expr))
    }
2257

2258
    fn block_all(&mut self, span: Span, stmts: hir::HirVec<hir::Stmt>, expr: Option<P<hir::Expr>>)
2259 2260
                 -> hir::Block {
        hir::Block {
2261 2262 2263 2264 2265
            stmts: stmts,
            expr: expr,
            id: self.next_id(),
            rules: hir::DefaultBlock,
            span: span,
2266
        }
2267
    }
2268

2269
    fn pat_ok(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
2270
        self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat])
2271
    }
2272

2273
    fn pat_err(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
2274
        self.pat_std_enum(span, &["result", "Result", "Err"], hir_vec![pat])
2275
    }
J
Jorge Aparicio 已提交
2276

2277
    fn pat_some(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
2278
        self.pat_std_enum(span, &["option", "Option", "Some"], hir_vec![pat])
2279
    }
J
Jorge Aparicio 已提交
2280

2281
    fn pat_none(&mut self, span: Span) -> P<hir::Pat> {
2282
        self.pat_std_enum(span, &["option", "Option", "None"], hir_vec![])
2283
    }
2284

2285 2286 2287 2288 2289 2290
    fn pat_std_enum(&mut self,
                    span: Span,
                    components: &[&str],
                    subpats: hir::HirVec<P<hir::Pat>>)
                    -> P<hir::Pat> {
        let path = self.std_path(span, components, true);
2291
        let qpath = hir::QPath::Resolved(None, P(path));
2292
        let pt = if subpats.is_empty() {
2293
            hir::PatKind::Path(qpath)
2294
        } else {
2295
            hir::PatKind::TupleStruct(qpath, subpats, None)
2296
        };
2297
        self.pat(span, pt)
2298
    }
2299

V
Vadim Petrochenkov 已提交
2300 2301
    fn pat_ident(&mut self, span: Span, name: Name) -> P<hir::Pat> {
        self.pat_ident_binding_mode(span, name, hir::BindByValue(hir::MutImmutable))
2302
    }
2303

V
Vadim Petrochenkov 已提交
2304
    fn pat_ident_binding_mode(&mut self, span: Span, name: Name, bm: hir::BindingMode)
2305
                              -> P<hir::Pat> {
2306
        let id = self.next_id();
2307
        let parent_def = self.parent_def;
2308
        let def_id = {
2309
            let defs = self.resolver.definitions();
2310
            let def_path_data = DefPathData::Binding(name.as_str());
2311 2312
            let def_index = defs.create_def_with_parent(parent_def, id, def_path_data);
            DefId::local(def_index)
2313
        };
N
Nick Cameron 已提交
2314

2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325
        P(hir::Pat {
            id: id,
            node: hir::PatKind::Binding(bm,
                                        def_id,
                                        Spanned {
                                            span: span,
                                            node: name,
                                        },
                                        None),
            span: span,
        })
2326
    }
2327

2328 2329 2330
    fn pat_wild(&mut self, span: Span) -> P<hir::Pat> {
        self.pat(span, hir::PatKind::Wild)
    }
2331

2332 2333 2334 2335 2336 2337 2338
    fn pat(&mut self, span: Span, pat: hir::PatKind) -> P<hir::Pat> {
        P(hir::Pat {
            id: self.next_id(),
            node: pat,
            span: span,
        })
    }
2339

2340 2341 2342 2343 2344 2345 2346
    /// Given suffix ["b","c","d"], returns path `::std::b::c::d` when
    /// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
    /// The path is also resolved according to `is_value`.
    fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path {
        let mut path = hir::Path {
            span: span,
            def: Def::Err,
2347 2348 2349
            segments: iter::once(keywords::CrateRoot.name()).chain({
                self.crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
            }).map(hir::PathSegment::from_name).collect(),
2350
        };
2351

J
Jeffrey Seyfried 已提交
2352
        self.resolver.resolve_hir_path(&mut path, is_value);
2353
        path
2354 2355 2356 2357 2358 2359 2360
    }

    fn signal_block_expr(&mut self,
                         stmts: hir::HirVec<hir::Stmt>,
                         expr: P<hir::Expr>,
                         span: Span,
                         rule: hir::BlockCheckMode,
2361
                         attrs: ThinVec<Attribute>)
2362
                         -> hir::Expr {
2363 2364 2365 2366 2367 2368 2369 2370 2371 2372
        let id = self.next_id();
        let block = P(hir::Block {
            rules: rule,
            span: span,
            id: id,
            stmts: stmts,
            expr: Some(expr),
        });
        self.expr_block(block, attrs)
    }
2373

2374 2375 2376 2377 2378 2379
    fn ty_path(&mut self, id: NodeId, span: Span, qpath: hir::QPath) -> P<hir::Ty> {
        let mut id = id;
        let node = match qpath {
            hir::QPath::Resolved(None, path) => {
                // Turn trait object paths into `TyTraitObject` instead.
                if let Def::Trait(_) = path.def {
2380
                    let principal = hir::PolyTraitRef {
2381 2382 2383 2384 2385 2386
                        bound_lifetimes: hir_vec![],
                        trait_ref: hir::TraitRef {
                            path: path.and_then(|path| path),
                            ref_id: id,
                        },
                        span,
2387
                    };
2388 2389 2390 2391 2392

                    // The original ID is taken by the `PolyTraitRef`,
                    // so the `Ty` itself needs a different one.
                    id = self.next_id();

2393
                    hir::TyTraitObject(hir_vec![principal], self.elided_lifetime(span))
2394 2395 2396 2397 2398 2399 2400
                } else {
                    hir::TyPath(hir::QPath::Resolved(None, path))
                }
            }
            _ => hir::TyPath(qpath)
        };
        P(hir::Ty { id, node, span })
2401
    }
2402 2403 2404 2405 2406 2407 2408 2409

    fn elided_lifetime(&mut self, span: Span) -> hir::Lifetime {
        hir::Lifetime {
            id: self.next_id(),
            span: span,
            name: keywords::Invalid.name()
        }
    }
2410
}