1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 // Lowers the AST to the HIR.
13 // Since the AST and HIR are fairly similar, this is mostly a simple procedure,
14 // much like a fold. Where lowering involves a bit more work things get more
15 // interesting and there are some invariants you should know about. These mostly
16 // concern spans and ids.
18 // Spans are assigned to AST nodes during parsing and then are modified during
19 // expansion to indicate the origin of a node and the process it went through
20 // being expanded. Ids are assigned to AST nodes just before lowering.
22 // For the simpler lowering steps, ids and spans should be preserved. Unlike
23 // expansion we do not preserve the process of lowering in the spans, so spans
24 // should not be modified here. When creating a new node (as opposed to
25 // 'folding' an existing one), then you create a new id using `next_id()`.
27 // You must ensure that ids are unique. That means that you should only use the
28 // id from an AST node in a single HIR node (you can assume that AST node ids
29 // are unique). Every new node must have a unique id. Avoid cloning HIR nodes.
30 // If you do, you must then set the new node's id to a fresh one.
32 // Spans are used for error messages and for tools to map semantics back to
33 // source code. It is therefore not as important with spans as ids to be strict
34 // about use (you can't break the compiler by screwing up a span). Obviously, a
35 // HIR node can only have a single span. But multiple nodes can have the same
36 // span and spans don't need to be kept in order, etc. Where code is preserved
37 // by lowering, it should have the same span as in the AST. Where HIR nodes are
38 // new it is probably best to give a span for the whole AST node being lowered.
39 // All nodes should have real spans, don't use dummy spans. Tools are likely to
40 // get confused if the spans from leaf AST nodes occur in multiple places
41 // in the HIR, especially for multiple identifiers.
44 use hir::map::Definitions;
45 use hir::map::definitions::DefPathData;
46 use hir::def_id::{DefIndex, DefId};
47 use hir::def::{Def, PathResolution};
50 use std::collections::BTreeMap;
55 use syntax::codemap::{respan, Spanned};
56 use syntax::std_inject;
57 use syntax::symbol::{Symbol, keywords};
58 use syntax::util::small_vector::SmallVector;
59 use syntax::visit::{self, Visitor};
62 pub struct LoweringContext<'a> {
63 crate_root: Option<&'static str>,
64 // Use to assign ids to hir nodes that do not directly correspond to an ast node
66 // As we walk the AST we must keep track of the current 'parent' def id (in
67 // the form of a DefIndex) so that if we create a new node which introduces
68 // a definition, then we can properly create the def id.
69 parent_def: Option<DefIndex>,
70 resolver: &'a mut Resolver,
72 /// The items being lowered are collected here.
73 items: BTreeMap<NodeId, hir::Item>,
75 impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
79 // Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc.
80 fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def;
82 // Obtain the resolution for a node id
83 fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution>;
85 // Record the resolution of a path or binding generated by the lowerer when expanding.
86 fn record_resolution(&mut self, id: NodeId, def: Def);
88 // We must keep the set of definitions up to date as we add nodes that weren't in the AST.
89 // This should only return `None` during testing.
90 fn definitions(&mut self) -> &mut Definitions;
93 pub fn lower_crate(sess: &Session,
95 resolver: &mut Resolver)
97 // We're constructing the HIR here; we don't care what we will
98 // read, since we haven't even constructed the *input* to
100 let _ignore = sess.dep_graph.in_ignore();
103 crate_root: std_inject::injected_crate_name(krate),
107 items: BTreeMap::new(),
108 impl_items: BTreeMap::new(),
112 #[derive(Copy, Clone, PartialEq, Eq)]
114 /// Any path in a type context.
116 /// The `module::Type` in `module::Type::method` in an expression.
120 impl<'a> LoweringContext<'a> {
121 fn lower_crate(mut self, c: &Crate) -> hir::Crate {
122 struct ItemLowerer<'lcx, 'interner: 'lcx> {
123 lctx: &'lcx mut LoweringContext<'interner>,
126 impl<'lcx, 'interner> Visitor for ItemLowerer<'lcx, 'interner> {
127 fn visit_item(&mut self, item: &Item) {
128 let hir_item = self.lctx.lower_item(item);
129 self.lctx.items.insert(item.id, hir_item);
130 visit::walk_item(self, item);
133 fn visit_impl_item(&mut self, item: &ImplItem) {
134 let id = self.lctx.lower_impl_item_ref(item).id;
135 let hir_item = self.lctx.lower_impl_item(item);
136 self.lctx.impl_items.insert(id, hir_item);
137 visit::walk_impl_item(self, item);
141 visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c);
144 module: self.lower_mod(&c.module),
145 attrs: self.lower_attrs(&c.attrs),
147 exported_macros: c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect(),
149 impl_items: self.impl_items,
153 fn next_id(&self) -> NodeId {
154 self.sess.next_node_id()
157 fn diagnostic(&self) -> &errors::Handler {
158 self.sess.diagnostic()
161 fn str_to_ident(&self, s: &'static str) -> Name {
165 fn with_parent_def<T, F>(&mut self, parent_id: NodeId, f: F) -> T
166 where F: FnOnce(&mut LoweringContext) -> T
168 let old_def = self.parent_def;
170 let defs = self.resolver.definitions();
171 Some(defs.opt_def_index(parent_id).unwrap())
174 let result = f(self);
176 self.parent_def = old_def;
180 fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
181 o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
184 fn lower_attrs(&mut self, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
188 fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {
190 attrs: self.lower_attrs(&arm.attrs),
191 pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(),
192 guard: arm.guard.as_ref().map(|ref x| P(self.lower_expr(x))),
193 body: P(self.lower_expr(&arm.body)),
197 fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding {
201 ty: self.lower_ty(&b.ty),
206 fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
210 TyKind::Infer | TyKind::ImplicitSelf => hir::TyInfer,
211 TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)),
212 TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
213 TyKind::Rptr(ref region, ref mt) => {
214 hir::TyRptr(self.lower_opt_lifetime(region), self.lower_mt(mt))
216 TyKind::BareFn(ref f) => {
217 hir::TyBareFn(P(hir::BareFnTy {
218 lifetimes: self.lower_lifetime_defs(&f.lifetimes),
219 unsafety: self.lower_unsafety(f.unsafety),
221 decl: self.lower_fn_decl(&f.decl),
224 TyKind::Never => hir::TyNever,
225 TyKind::Tup(ref tys) => {
226 hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty)).collect())
228 TyKind::Paren(ref ty) => {
229 return self.lower_ty(ty);
231 TyKind::Path(ref qself, ref path) => {
232 hir::TyPath(self.lower_qpath(t.id, qself, path, ParamMode::Explicit))
234 TyKind::ObjectSum(ref ty, ref bounds) => {
235 hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds))
237 TyKind::Array(ref ty, ref e) => {
238 hir::TyArray(self.lower_ty(ty), P(self.lower_expr(e)))
240 TyKind::Typeof(ref expr) => {
241 hir::TyTypeof(P(self.lower_expr(expr)))
243 TyKind::PolyTraitRef(ref bounds) => {
244 hir::TyPolyTraitRef(self.lower_bounds(bounds))
246 TyKind::ImplTrait(ref bounds) => {
247 hir::TyImplTrait(self.lower_bounds(bounds))
249 TyKind::Mac(_) => panic!("TyMac should have been expanded by now."),
255 fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod {
258 items: fm.items.iter().map(|x| self.lower_foreign_item(x)).collect(),
262 fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
264 node: hir::Variant_ {
265 name: v.node.name.name,
266 attrs: self.lower_attrs(&v.node.attrs),
267 data: self.lower_variant_data(&v.node.data),
268 disr_expr: v.node.disr_expr.as_ref().map(|e| P(self.lower_expr(e))),
274 fn lower_qpath(&mut self,
276 qself: &Option<QSelf>,
278 param_mode: ParamMode)
280 let qself_position = qself.as_ref().map(|q| q.position);
281 let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty));
283 let resolution = self.resolver.get_resolution(id)
284 .unwrap_or(PathResolution::new(Def::Err));
286 let proj_start = p.segments.len() - resolution.depth;
287 let path = P(hir::Path {
289 segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
290 let param_mode = match (qself_position, param_mode) {
291 (Some(j), ParamMode::Optional) if i < j => {
292 // This segment is part of the trait path in a
293 // qualified path - one of `a`, `b` or `Trait`
294 // in `<X as a::b::Trait>::T::U::method`.
299 self.lower_path_segment(segment, param_mode)
304 // Simple case, either no projections, or only fully-qualified.
305 // E.g. `std::mem::size_of` or `<I as Iterator>::Item`.
306 if resolution.depth == 0 {
307 return hir::QPath::Resolved(qself, path);
310 // Create the innermost type that we're projecting from.
311 let mut ty = if path.segments.is_empty() {
312 // If the base path is empty that means there exists a
313 // syntactical `Self`, e.g. `&i32` in `<&i32>::clone`.
314 qself.expect("missing QSelf for <T>::...")
316 // Otherwise, the base path is an implicit `Self` type path,
317 // e.g. `Vec` in `Vec::new` or `<I as Iterator>::Item` in
318 // `<I as Iterator>::Item::default`.
319 let ty = self.ty(p.span, hir::TyPath(hir::QPath::Resolved(qself, path)));
321 // Associate that innermost path type with the base Def.
322 self.resolver.record_resolution(ty.id, resolution.base_def);
327 // Anything after the base path are associated "extensions",
328 // out of which all but the last one are associated types,
329 // e.g. for `std::vec::Vec::<T>::IntoIter::Item::clone`:
330 // * base path is `std::vec::Vec<T>`
331 // * "extensions" are `IntoIter`, `Item` and `clone`
333 // 1. `std::vec::Vec<T>` (created above)
334 // 2. `<std::vec::Vec<T>>::IntoIter`
335 // 3. `<<std::vec::Vec<T>>::IntoIter>::Item`
336 // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
337 for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
338 let segment = P(self.lower_path_segment(segment, param_mode));
339 let qpath = hir::QPath::TypeRelative(ty, segment);
341 // It's finished, return the extension of the right node type.
342 if i == p.segments.len() - 1 {
346 // Wrap the associated extension in another type node.
347 ty = self.ty(p.span, hir::TyPath(qpath));
350 // Should've returned in the for loop above.
351 span_bug!(p.span, "lower_qpath: no final extension segment in {}..{}",
352 proj_start, p.segments.len())
355 fn lower_path_extra(&mut self,
358 param_mode: ParamMode)
362 segments: p.segments.iter().map(|segment| {
363 self.lower_path_segment(segment, param_mode)
364 }).chain(name.map(|name| {
367 parameters: hir::PathParameters::none()
374 fn lower_path(&mut self,
376 param_mode: ParamMode)
378 self.lower_path_extra(p, None, param_mode)
381 fn lower_path_segment(&mut self,
382 segment: &PathSegment,
383 param_mode: ParamMode)
384 -> hir::PathSegment {
385 let parameters = match segment.parameters {
386 PathParameters::AngleBracketed(ref data) => {
387 let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
388 hir::AngleBracketedParameters(data)
390 PathParameters::Parenthesized(ref data) =>
391 hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)),
395 name: segment.identifier.name,
396 parameters: parameters,
400 fn lower_angle_bracketed_parameter_data(&mut self,
401 data: &AngleBracketedParameterData,
402 param_mode: ParamMode)
403 -> hir::AngleBracketedParameterData {
404 let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data;
405 hir::AngleBracketedParameterData {
406 lifetimes: self.lower_lifetimes(lifetimes),
407 types: types.iter().map(|ty| self.lower_ty(ty)).collect(),
408 infer_types: types.is_empty() && param_mode == ParamMode::Optional,
409 bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(),
413 fn lower_parenthesized_parameter_data(&mut self,
414 data: &ParenthesizedParameterData)
415 -> hir::ParenthesizedParameterData {
416 let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
417 hir::ParenthesizedParameterData {
418 inputs: inputs.iter().map(|ty| self.lower_ty(ty)).collect(),
419 output: output.as_ref().map(|ty| self.lower_ty(ty)),
424 fn lower_local(&mut self, l: &Local) -> P<hir::Local> {
427 ty: l.ty.as_ref().map(|t| self.lower_ty(t)),
428 pat: self.lower_pat(&l.pat),
429 init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
431 attrs: l.attrs.clone(),
435 fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
437 Mutability::Mutable => hir::MutMutable,
438 Mutability::Immutable => hir::MutImmutable,
442 fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
445 pat: self.lower_pat(&arg.pat),
446 ty: self.lower_ty(&arg.ty),
450 fn lower_fn_decl(&mut self, decl: &FnDecl) -> P<hir::FnDecl> {
452 inputs: decl.inputs.iter().map(|x| self.lower_arg(x)).collect(),
453 output: match decl.output {
454 FunctionRetTy::Ty(ref ty) => hir::Return(self.lower_ty(ty)),
455 FunctionRetTy::Default(span) => hir::DefaultReturn(span),
457 variadic: decl.variadic,
461 fn lower_ty_param_bound(&mut self, tpb: &TyParamBound) -> hir::TyParamBound {
463 TraitTyParamBound(ref ty, modifier) => {
464 hir::TraitTyParamBound(self.lower_poly_trait_ref(ty),
465 self.lower_trait_bound_modifier(modifier))
467 RegionTyParamBound(ref lifetime) => {
468 hir::RegionTyParamBound(self.lower_lifetime(lifetime))
473 fn lower_ty_param(&mut self, tp: &TyParam) -> hir::TyParam {
474 let mut name = tp.ident.name;
476 // Don't expose `Self` (recovered "keyword used as ident" parse error).
477 // `rustc::ty` expects `Self` to be only used for a trait's `Self`.
478 // Instead, use gensym("Self") to create a distinct name that looks the same.
479 if name == keywords::SelfType.name() {
480 name = Symbol::gensym("Self");
486 bounds: self.lower_bounds(&tp.bounds),
487 default: tp.default.as_ref().map(|x| self.lower_ty(x)),
489 pure_wrt_drop: tp.attrs.iter().any(|attr| attr.check_name("may_dangle")),
493 fn lower_ty_params(&mut self, tps: &P<[TyParam]>) -> hir::HirVec<hir::TyParam> {
494 tps.iter().map(|tp| self.lower_ty_param(tp)).collect()
497 fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
505 fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef {
507 lifetime: self.lower_lifetime(&l.lifetime),
508 bounds: self.lower_lifetimes(&l.bounds),
509 pure_wrt_drop: l.attrs.iter().any(|attr| attr.check_name("may_dangle")),
513 fn lower_lifetimes(&mut self, lts: &Vec<Lifetime>) -> hir::HirVec<hir::Lifetime> {
514 lts.iter().map(|l| self.lower_lifetime(l)).collect()
517 fn lower_lifetime_defs(&mut self, lts: &Vec<LifetimeDef>) -> hir::HirVec<hir::LifetimeDef> {
518 lts.iter().map(|l| self.lower_lifetime_def(l)).collect()
521 fn lower_opt_lifetime(&mut self, o_lt: &Option<Lifetime>) -> Option<hir::Lifetime> {
522 o_lt.as_ref().map(|lt| self.lower_lifetime(lt))
525 fn lower_generics(&mut self, g: &Generics) -> hir::Generics {
527 ty_params: self.lower_ty_params(&g.ty_params),
528 lifetimes: self.lower_lifetime_defs(&g.lifetimes),
529 where_clause: self.lower_where_clause(&g.where_clause),
534 fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause {
537 predicates: wc.predicates
539 .map(|predicate| self.lower_where_predicate(predicate))
544 fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate {
546 WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_lifetimes,
550 hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
551 bound_lifetimes: self.lower_lifetime_defs(bound_lifetimes),
552 bounded_ty: self.lower_ty(bounded_ty),
553 bounds: bounds.iter().map(|x| self.lower_ty_param_bound(x)).collect(),
557 WherePredicate::RegionPredicate(WhereRegionPredicate{ ref lifetime,
560 hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
562 lifetime: self.lower_lifetime(lifetime),
563 bounds: bounds.iter().map(|bound| self.lower_lifetime(bound)).collect(),
566 WherePredicate::EqPredicate(WhereEqPredicate{ id,
570 hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
572 path: self.lower_path(path, ParamMode::Explicit),
573 ty: self.lower_ty(ty),
580 fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
582 VariantData::Struct(ref fields, id) => {
583 hir::VariantData::Struct(fields.iter()
585 .map(|f| self.lower_struct_field(f))
589 VariantData::Tuple(ref fields, id) => {
590 hir::VariantData::Tuple(fields.iter()
592 .map(|f| self.lower_struct_field(f))
596 VariantData::Unit(id) => hir::VariantData::Unit(id),
600 fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
602 path: self.lower_path(&p.path, ParamMode::Explicit),
607 fn lower_poly_trait_ref(&mut self, p: &PolyTraitRef) -> hir::PolyTraitRef {
609 bound_lifetimes: self.lower_lifetime_defs(&p.bound_lifetimes),
610 trait_ref: self.lower_trait_ref(&p.trait_ref),
615 fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField {
619 name: f.ident.map(|ident| ident.name).unwrap_or(Symbol::intern(&index.to_string())),
620 vis: self.lower_visibility(&f.vis),
621 ty: self.lower_ty(&f.ty),
622 attrs: self.lower_attrs(&f.attrs),
626 fn lower_field(&mut self, f: &Field) -> hir::Field {
628 name: respan(f.ident.span, f.ident.node.name),
629 expr: P(self.lower_expr(&f.expr)),
631 is_shorthand: f.is_shorthand,
635 fn lower_mt(&mut self, mt: &MutTy) -> hir::MutTy {
637 ty: self.lower_ty(&mt.ty),
638 mutbl: self.lower_mutability(mt.mutbl),
642 fn lower_bounds(&mut self, bounds: &TyParamBounds) -> hir::TyParamBounds {
643 bounds.iter().map(|bound| self.lower_ty_param_bound(bound)).collect()
646 fn lower_block(&mut self, b: &Block) -> P<hir::Block> {
649 let mut stmts = b.stmts.iter().flat_map(|s| self.lower_stmt(s)).collect::<Vec<_>>();
650 if let Some(last) = stmts.pop() {
651 if let hir::StmtExpr(e, _) = last.node {
662 rules: self.lower_block_check_mode(&b.rules),
667 fn lower_item_kind(&mut self,
669 attrs: &hir::HirVec<Attribute>,
670 vis: &mut hir::Visibility,
674 ItemKind::ExternCrate(string) => hir::ItemExternCrate(string),
675 ItemKind::Use(ref view_path) => {
676 let path = match view_path.node {
677 ViewPathSimple(_, ref path) => path,
678 ViewPathGlob(ref path) => path,
679 ViewPathList(ref path, ref path_list_idents) => {
680 for &Spanned { node: ref import, span } in path_list_idents {
681 // `use a::{self as x, b as y};` lowers to
682 // `use a as x; use a::b as y;`
683 let mut ident = import.name;
684 let suffix = if ident.name == keywords::SelfValue.name() {
685 if let Some(last) = path.segments.last() {
686 ident = last.identifier;
693 let mut path = self.lower_path_extra(path, suffix,
694 ParamMode::Explicit);
696 self.items.insert(import.id, hir::Item {
698 name: import.rename.unwrap_or(ident).name,
699 attrs: attrs.clone(),
700 node: hir::ItemUse(P(path), hir::UseKind::Single),
708 let path = P(self.lower_path(path, ParamMode::Explicit));
709 let kind = match view_path.node {
710 ViewPathSimple(ident, _) => {
717 ViewPathList(..) => {
718 // Privatize the degenerate import base, used only to check
719 // the stability of `use a::{};`, to avoid it showing up as
720 // a reexport by accident when `pub`, e.g. in documentation.
721 *vis = hir::Inherited;
722 hir::UseKind::ListStem
725 hir::ItemUse(path, kind)
727 ItemKind::Static(ref t, m, ref e) => {
728 hir::ItemStatic(self.lower_ty(t),
729 self.lower_mutability(m),
730 P(self.lower_expr(e)))
732 ItemKind::Const(ref t, ref e) => {
733 hir::ItemConst(self.lower_ty(t), P(self.lower_expr(e)))
735 ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
736 let body = self.lower_block(body);
737 hir::ItemFn(self.lower_fn_decl(decl),
738 self.lower_unsafety(unsafety),
739 self.lower_constness(constness),
741 self.lower_generics(generics),
742 P(self.expr_block(body, ThinVec::new())))
744 ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
745 ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
746 ItemKind::Ty(ref t, ref generics) => {
747 hir::ItemTy(self.lower_ty(t), self.lower_generics(generics))
749 ItemKind::Enum(ref enum_definition, ref generics) => {
750 hir::ItemEnum(hir::EnumDef {
751 variants: enum_definition.variants
753 .map(|x| self.lower_variant(x))
756 self.lower_generics(generics))
758 ItemKind::Struct(ref struct_def, ref generics) => {
759 let struct_def = self.lower_variant_data(struct_def);
760 hir::ItemStruct(struct_def, self.lower_generics(generics))
762 ItemKind::Union(ref vdata, ref generics) => {
763 let vdata = self.lower_variant_data(vdata);
764 hir::ItemUnion(vdata, self.lower_generics(generics))
766 ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
767 hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
768 self.lower_trait_ref(trait_ref))
770 ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
771 let new_impl_items = impl_items.iter()
772 .map(|item| self.lower_impl_item_ref(item))
774 let ifce = ifce.as_ref().map(|trait_ref| self.lower_trait_ref(trait_ref));
775 hir::ItemImpl(self.lower_unsafety(unsafety),
776 self.lower_impl_polarity(polarity),
777 self.lower_generics(generics),
782 ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => {
783 let bounds = self.lower_bounds(bounds);
784 let items = items.iter().map(|item| self.lower_trait_item(item)).collect();
785 hir::ItemTrait(self.lower_unsafety(unsafety),
786 self.lower_generics(generics),
790 ItemKind::Mac(_) => panic!("Shouldn't still be around"),
794 fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
795 self.with_parent_def(i.id, |this| {
799 attrs: this.lower_attrs(&i.attrs),
801 TraitItemKind::Const(ref ty, ref default) => {
802 hir::ConstTraitItem(this.lower_ty(ty),
803 default.as_ref().map(|x| P(this.lower_expr(x))))
805 TraitItemKind::Method(ref sig, ref body) => {
806 hir::MethodTraitItem(this.lower_method_sig(sig),
807 body.as_ref().map(|x| {
808 let body = this.lower_block(x);
809 P(this.expr_block(body, ThinVec::new()))
812 TraitItemKind::Type(ref bounds, ref default) => {
813 hir::TypeTraitItem(this.lower_bounds(bounds),
814 default.as_ref().map(|x| this.lower_ty(x)))
816 TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"),
823 fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
824 self.with_parent_def(i.id, |this| {
828 attrs: this.lower_attrs(&i.attrs),
829 vis: this.lower_visibility(&i.vis),
830 defaultness: this.lower_defaultness(i.defaultness, true /* [1] */),
832 ImplItemKind::Const(ref ty, ref expr) => {
833 hir::ImplItemKind::Const(this.lower_ty(ty), P(this.lower_expr(expr)))
835 ImplItemKind::Method(ref sig, ref body) => {
836 let body = this.lower_block(body);
837 hir::ImplItemKind::Method(this.lower_method_sig(sig),
838 P(this.expr_block(body, ThinVec::new())))
840 ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)),
841 ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
847 // [1] since `default impl` is not yet implemented, this is always true in impls
850 fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
852 id: hir::ImplItemId { node_id: i.id },
855 vis: self.lower_visibility(&i.vis),
856 defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
858 ImplItemKind::Const(..) => hir::AssociatedItemKind::Const,
859 ImplItemKind::Type(..) => hir::AssociatedItemKind::Type,
860 ImplItemKind::Method(ref sig, _) => hir::AssociatedItemKind::Method {
861 has_self: sig.decl.get_self().is_some(),
863 ImplItemKind::Macro(..) => unimplemented!(),
867 // [1] since `default impl` is not yet implemented, this is always true in impls
870 fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
873 item_ids: m.items.iter().flat_map(|x| self.lower_item_id(x)).collect(),
877 fn lower_macro_def(&mut self, m: &MacroDef) -> hir::MacroDef {
880 attrs: self.lower_attrs(&m.attrs),
883 imported_from: m.imported_from.map(|x| x.name),
884 allow_internal_unstable: m.allow_internal_unstable,
885 body: m.body.clone().into(),
889 fn lower_item_id(&mut self, i: &Item) -> SmallVector<hir::ItemId> {
890 if let ItemKind::Use(ref view_path) = i.node {
891 if let ViewPathList(_, ref imports) = view_path.node {
892 return iter::once(i.id).chain(imports.iter().map(|import| import.node.id))
893 .map(|id| hir::ItemId { id: id }).collect();
896 SmallVector::one(hir::ItemId { id: i.id })
899 pub fn lower_item(&mut self, i: &Item) -> hir::Item {
900 let mut name = i.ident.name;
901 let attrs = self.lower_attrs(&i.attrs);
902 let mut vis = self.lower_visibility(&i.vis);
903 let node = self.with_parent_def(i.id, |this| {
904 this.lower_item_kind(&mut name, &attrs, &mut vis, &i.node)
917 fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
918 self.with_parent_def(i.id, |this| {
922 attrs: this.lower_attrs(&i.attrs),
924 ForeignItemKind::Fn(ref fdec, ref generics) => {
925 hir::ForeignItemFn(this.lower_fn_decl(fdec), this.lower_generics(generics))
927 ForeignItemKind::Static(ref t, m) => {
928 hir::ForeignItemStatic(this.lower_ty(t), m)
931 vis: this.lower_visibility(&i.vis),
937 fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig {
938 let hir_sig = hir::MethodSig {
939 generics: self.lower_generics(&sig.generics),
941 unsafety: self.lower_unsafety(sig.unsafety),
942 constness: self.lower_constness(sig.constness),
943 decl: self.lower_fn_decl(&sig.decl),
945 // Check for `self: _` and `self: &_`
946 if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) {
947 match hir_sig.decl.get_self().map(|eself| eself.node) {
948 Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => {
949 self.diagnostic().span_err(sig.decl.inputs[0].ty.span,
950 "the type placeholder `_` is not allowed within types on item signatures");
958 fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
960 Unsafety::Unsafe => hir::Unsafety::Unsafe,
961 Unsafety::Normal => hir::Unsafety::Normal,
965 fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
967 Constness::Const => hir::Constness::Const,
968 Constness::NotConst => hir::Constness::NotConst,
972 fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
974 UnOp::Deref => hir::UnDeref,
975 UnOp::Not => hir::UnNot,
976 UnOp::Neg => hir::UnNeg,
980 fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
983 BinOpKind::Add => hir::BiAdd,
984 BinOpKind::Sub => hir::BiSub,
985 BinOpKind::Mul => hir::BiMul,
986 BinOpKind::Div => hir::BiDiv,
987 BinOpKind::Rem => hir::BiRem,
988 BinOpKind::And => hir::BiAnd,
989 BinOpKind::Or => hir::BiOr,
990 BinOpKind::BitXor => hir::BiBitXor,
991 BinOpKind::BitAnd => hir::BiBitAnd,
992 BinOpKind::BitOr => hir::BiBitOr,
993 BinOpKind::Shl => hir::BiShl,
994 BinOpKind::Shr => hir::BiShr,
995 BinOpKind::Eq => hir::BiEq,
996 BinOpKind::Lt => hir::BiLt,
997 BinOpKind::Le => hir::BiLe,
998 BinOpKind::Ne => hir::BiNe,
999 BinOpKind::Ge => hir::BiGe,
1000 BinOpKind::Gt => hir::BiGt,
1006 fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
1009 node: match p.node {
1010 PatKind::Wild => hir::PatKind::Wild,
1011 PatKind::Ident(ref binding_mode, pth1, ref sub) => {
1012 self.with_parent_def(p.id, |this| {
1013 match this.resolver.get_resolution(p.id).map(|d| d.base_def) {
1014 // `None` can occur in body-less function signatures
1015 None | Some(Def::Local(..)) => {
1016 hir::PatKind::Binding(this.lower_binding_mode(binding_mode),
1017 respan(pth1.span, pth1.node.name),
1018 sub.as_ref().map(|x| this.lower_pat(x)))
1021 let path = hir::Path::from_name(pth1.span, pth1.node.name);
1022 hir::PatKind::Path(hir::QPath::Resolved(None, P(path)))
1027 PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
1028 PatKind::TupleStruct(ref path, ref pats, ddpos) => {
1029 let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);
1030 hir::PatKind::TupleStruct(qpath,
1031 pats.iter().map(|x| self.lower_pat(x)).collect(),
1034 PatKind::Path(ref qself, ref path) => {
1035 hir::PatKind::Path(self.lower_qpath(p.id, qself, path, ParamMode::Optional))
1037 PatKind::Struct(ref path, ref fields, etc) => {
1038 let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);
1040 let fs = fields.iter()
1044 node: hir::FieldPat {
1045 name: f.node.ident.name,
1046 pat: self.lower_pat(&f.node.pat),
1047 is_shorthand: f.node.is_shorthand,
1052 hir::PatKind::Struct(qpath, fs, etc)
1054 PatKind::Tuple(ref elts, ddpos) => {
1055 hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
1057 PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
1058 PatKind::Ref(ref inner, mutbl) => {
1059 hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl))
1061 PatKind::Range(ref e1, ref e2) => {
1062 hir::PatKind::Range(P(self.lower_expr(e1)), P(self.lower_expr(e2)))
1064 PatKind::Slice(ref before, ref slice, ref after) => {
1065 hir::PatKind::Slice(before.iter().map(|x| self.lower_pat(x)).collect(),
1066 slice.as_ref().map(|x| self.lower_pat(x)),
1067 after.iter().map(|x| self.lower_pat(x)).collect())
1069 PatKind::Mac(_) => panic!("Shouldn't exist here"),
1075 fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
1078 node: match e.node {
1080 // Eventually a desugaring for `box EXPR`
1081 // (similar to the desugaring above for `in PLACE BLOCK`)
1082 // should go here, desugaring
1086 // let mut place = BoxPlace::make_place();
1087 // let raw_place = Place::pointer(&mut place);
1088 // let value = $value;
1090 // ::std::ptr::write(raw_place, value);
1091 // Boxed::finalize(place)
1094 // But for now there are type-inference issues doing that.
1095 ExprKind::Box(ref e) => {
1096 hir::ExprBox(P(self.lower_expr(e)))
1099 // Desugar ExprBox: `in (PLACE) EXPR`
1100 ExprKind::InPlace(ref placer, ref value_expr) => {
1104 // let mut place = Placer::make_place(p);
1105 // let raw_place = Place::pointer(&mut place);
1107 // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
1108 // InPlace::finalize(place)
1110 let placer_expr = P(self.lower_expr(placer));
1111 let value_expr = P(self.lower_expr(value_expr));
1113 let placer_ident = self.str_to_ident("placer");
1114 let place_ident = self.str_to_ident("place");
1115 let p_ptr_ident = self.str_to_ident("p_ptr");
1117 let make_place = ["ops", "Placer", "make_place"];
1118 let place_pointer = ["ops", "Place", "pointer"];
1119 let move_val_init = ["intrinsics", "move_val_init"];
1120 let inplace_finalize = ["ops", "InPlace", "finalize"];
1122 let make_call = |this: &mut LoweringContext, p, args| {
1123 let path = this.std_path(e.span, p);
1124 let path = this.expr_path(path, ThinVec::new());
1125 P(this.expr_call(e.span, path, args))
1128 let mk_stmt_let = |this: &mut LoweringContext, bind, expr| {
1129 this.stmt_let(e.span, false, bind, expr)
1132 let mk_stmt_let_mut = |this: &mut LoweringContext, bind, expr| {
1133 this.stmt_let(e.span, true, bind, expr)
1136 // let placer = <placer_expr> ;
1137 let (s1, placer_binding) = {
1138 let placer_expr = P(self.signal_block_expr(hir_vec![],
1141 hir::PopUnstableBlock,
1143 mk_stmt_let(self, placer_ident, placer_expr)
1146 // let mut place = Placer::make_place(placer);
1147 let (s2, place_binding) = {
1148 let placer = self.expr_ident(e.span, placer_ident, placer_binding);
1149 let call = make_call(self, &make_place, hir_vec![placer]);
1150 mk_stmt_let_mut(self, place_ident, call)
1153 // let p_ptr = Place::pointer(&mut place);
1154 let (s3, p_ptr_binding) = {
1155 let agent = P(self.expr_ident(e.span, place_ident, place_binding));
1156 let args = hir_vec![self.expr_mut_addr_of(e.span, agent)];
1157 let call = make_call(self, &place_pointer, args);
1158 mk_stmt_let(self, p_ptr_ident, call)
1161 // pop_unsafe!(EXPR));
1162 let pop_unsafe_expr = {
1163 let value_expr = P(self.signal_block_expr(hir_vec![],
1166 hir::PopUnstableBlock,
1168 self.signal_block_expr(hir_vec![],
1171 hir::PopUnsafeBlock(hir::CompilerGenerated),
1176 // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
1177 // InPlace::finalize(place)
1180 let ptr = self.expr_ident(e.span, p_ptr_ident, p_ptr_binding);
1181 let call_move_val_init =
1183 make_call(self, &move_val_init, hir_vec![ptr, pop_unsafe_expr]),
1185 let call_move_val_init = respan(e.span, call_move_val_init);
1187 let place = self.expr_ident(e.span, place_ident, place_binding);
1188 let call = make_call(self, &inplace_finalize, hir_vec![place]);
1189 P(self.signal_block_expr(hir_vec![call_move_val_init],
1192 hir::PushUnsafeBlock(hir::CompilerGenerated),
1196 return self.signal_block_expr(hir_vec![s1, s2, s3],
1199 hir::PushUnstableBlock,
1203 ExprKind::Vec(ref exprs) => {
1204 hir::ExprArray(exprs.iter().map(|x| self.lower_expr(x)).collect())
1206 ExprKind::Repeat(ref expr, ref count) => {
1207 let expr = P(self.lower_expr(expr));
1208 let count = P(self.lower_expr(count));
1209 hir::ExprRepeat(expr, count)
1211 ExprKind::Tup(ref elts) => {
1212 hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect())
1214 ExprKind::Call(ref f, ref args) => {
1215 let f = P(self.lower_expr(f));
1216 hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
1218 ExprKind::MethodCall(i, ref tps, ref args) => {
1219 let tps = tps.iter().map(|x| self.lower_ty(x)).collect();
1220 let args = args.iter().map(|x| self.lower_expr(x)).collect();
1221 hir::ExprMethodCall(respan(i.span, i.node.name), tps, args)
1223 ExprKind::Binary(binop, ref lhs, ref rhs) => {
1224 let binop = self.lower_binop(binop);
1225 let lhs = P(self.lower_expr(lhs));
1226 let rhs = P(self.lower_expr(rhs));
1227 hir::ExprBinary(binop, lhs, rhs)
1229 ExprKind::Unary(op, ref ohs) => {
1230 let op = self.lower_unop(op);
1231 let ohs = P(self.lower_expr(ohs));
1232 hir::ExprUnary(op, ohs)
1234 ExprKind::Lit(ref l) => hir::ExprLit(P((**l).clone())),
1235 ExprKind::Cast(ref expr, ref ty) => {
1236 let expr = P(self.lower_expr(expr));
1237 hir::ExprCast(expr, self.lower_ty(ty))
1239 ExprKind::Type(ref expr, ref ty) => {
1240 let expr = P(self.lower_expr(expr));
1241 hir::ExprType(expr, self.lower_ty(ty))
1243 ExprKind::AddrOf(m, ref ohs) => {
1244 let m = self.lower_mutability(m);
1245 let ohs = P(self.lower_expr(ohs));
1246 hir::ExprAddrOf(m, ohs)
1248 // More complicated than you might expect because the else branch
1249 // might be `if let`.
1250 ExprKind::If(ref cond, ref blk, ref else_opt) => {
1251 let else_opt = else_opt.as_ref().map(|els| {
1253 ExprKind::IfLet(..) => {
1254 // wrap the if-let expr in a block
1255 let span = els.span;
1256 let els = P(self.lower_expr(els));
1257 let id = self.next_id();
1258 let blk = P(hir::Block {
1262 rules: hir::DefaultBlock,
1265 P(self.expr_block(blk, ThinVec::new()))
1267 _ => P(self.lower_expr(els)),
1271 hir::ExprIf(P(self.lower_expr(cond)), self.lower_block(blk), else_opt)
1273 ExprKind::While(ref cond, ref body, opt_ident) => {
1274 hir::ExprWhile(P(self.lower_expr(cond)), self.lower_block(body),
1275 self.lower_opt_sp_ident(opt_ident))
1277 ExprKind::Loop(ref body, opt_ident) => {
1278 hir::ExprLoop(self.lower_block(body),
1279 self.lower_opt_sp_ident(opt_ident),
1280 hir::LoopSource::Loop)
1282 ExprKind::Match(ref expr, ref arms) => {
1283 hir::ExprMatch(P(self.lower_expr(expr)),
1284 arms.iter().map(|x| self.lower_arm(x)).collect(),
1285 hir::MatchSource::Normal)
1287 ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => {
1288 self.with_parent_def(e.id, |this| {
1289 hir::ExprClosure(this.lower_capture_clause(capture_clause),
1290 this.lower_fn_decl(decl),
1291 P(this.lower_expr(body)),
1295 ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk)),
1296 ExprKind::Assign(ref el, ref er) => {
1297 hir::ExprAssign(P(self.lower_expr(el)), P(self.lower_expr(er)))
1299 ExprKind::AssignOp(op, ref el, ref er) => {
1300 hir::ExprAssignOp(self.lower_binop(op),
1301 P(self.lower_expr(el)),
1302 P(self.lower_expr(er)))
1304 ExprKind::Field(ref el, ident) => {
1305 hir::ExprField(P(self.lower_expr(el)), respan(ident.span, ident.node.name))
1307 ExprKind::TupField(ref el, ident) => {
1308 hir::ExprTupField(P(self.lower_expr(el)), ident)
1310 ExprKind::Index(ref el, ref er) => {
1311 hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er)))
1313 ExprKind::Range(ref e1, ref e2, lims) => {
1314 fn make_struct(this: &mut LoweringContext,
1317 fields: &[(&str, &P<Expr>)]) -> hir::Expr {
1318 let struct_path = this.std_path(ast_expr.span,
1319 &iter::once(&"ops").chain(path)
1321 .collect::<Vec<_>>());
1323 let hir_expr = if fields.len() == 0 {
1324 this.expr_path(struct_path, ast_expr.attrs.clone())
1326 let fields = fields.into_iter().map(|&(s, e)| {
1327 let expr = P(this.lower_expr(&e));
1328 let signal_block = P(this.signal_block_expr(hir_vec![],
1331 hir::PopUnstableBlock,
1333 this.field(Symbol::intern(s), signal_block, ast_expr.span)
1335 let attrs = ast_expr.attrs.clone();
1337 this.expr_struct(ast_expr.span, struct_path, fields, None, attrs)
1340 this.signal_block_expr(hir_vec![],
1343 hir::PushUnstableBlock,
1347 use syntax::ast::RangeLimits::*;
1349 return match (e1, e2, lims) {
1350 (&None, &None, HalfOpen) =>
1351 make_struct(self, e, &["RangeFull"], &[]),
1353 (&Some(ref e1), &None, HalfOpen) =>
1354 make_struct(self, e, &["RangeFrom"],
1357 (&None, &Some(ref e2), HalfOpen) =>
1358 make_struct(self, e, &["RangeTo"],
1361 (&Some(ref e1), &Some(ref e2), HalfOpen) =>
1362 make_struct(self, e, &["Range"],
1363 &[("start", e1), ("end", e2)]),
1365 (&None, &Some(ref e2), Closed) =>
1366 make_struct(self, e, &["RangeToInclusive"],
1369 (&Some(ref e1), &Some(ref e2), Closed) =>
1370 make_struct(self, e, &["RangeInclusive", "NonEmpty"],
1371 &[("start", e1), ("end", e2)]),
1373 _ => panic!(self.diagnostic()
1374 .span_fatal(e.span, "inclusive range with no end")),
1377 ExprKind::Path(ref qself, ref path) => {
1378 hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional))
1380 ExprKind::Break(opt_ident, ref opt_expr) => {
1381 hir::ExprBreak(self.lower_opt_sp_ident(opt_ident),
1382 opt_expr.as_ref().map(|x| P(self.lower_expr(x))))
1384 ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)),
1385 ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| P(self.lower_expr(x)))),
1386 ExprKind::InlineAsm(ref asm) => {
1387 let hir_asm = hir::InlineAsm {
1388 inputs: asm.inputs.iter().map(|&(ref c, _)| c.clone()).collect(),
1389 outputs: asm.outputs.iter().map(|out| {
1390 hir::InlineAsmOutput {
1391 constraint: out.constraint.clone(),
1393 is_indirect: out.is_indirect,
1396 asm: asm.asm.clone(),
1397 asm_str_style: asm.asm_str_style,
1398 clobbers: asm.clobbers.clone().into(),
1399 volatile: asm.volatile,
1400 alignstack: asm.alignstack,
1401 dialect: asm.dialect,
1402 expn_id: asm.expn_id,
1405 asm.outputs.iter().map(|out| self.lower_expr(&out.expr)).collect();
1407 asm.inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect();
1408 hir::ExprInlineAsm(P(hir_asm), outputs, inputs)
1410 ExprKind::Struct(ref path, ref fields, ref maybe_expr) => {
1411 hir::ExprStruct(self.lower_qpath(e.id, &None, path, ParamMode::Optional),
1412 fields.iter().map(|x| self.lower_field(x)).collect(),
1413 maybe_expr.as_ref().map(|x| P(self.lower_expr(x))))
1415 ExprKind::Paren(ref ex) => {
1416 let mut ex = self.lower_expr(ex);
1417 // include parens in span, but only if it is a super-span.
1418 if e.span.contains(ex.span) {
1421 // merge attributes into the inner expression.
1422 let mut attrs = e.attrs.clone();
1423 attrs.extend::<Vec<_>>(ex.attrs.into());
1428 // Desugar ExprIfLet
1429 // From: `if let <pat> = <sub_expr> <body> [<else_opt>]`
1430 ExprKind::IfLet(ref pat, ref sub_expr, ref body, ref else_opt) => {
1433 // match <sub_expr> {
1435 // [_ if <else_opt_if_cond> => <else_opt_if_body>,]
1436 // _ => [<else_opt> | ()]
1439 // `<pat> => <body>`
1441 let body = self.lower_block(body);
1442 let body_expr = P(self.expr_block(body, ThinVec::new()));
1443 let pat = self.lower_pat(pat);
1444 self.arm(hir_vec![pat], body_expr)
1447 // `[_ if <else_opt_if_cond> => <else_opt_if_body>,]`
1448 let mut else_opt = else_opt.as_ref().map(|e| P(self.lower_expr(e)));
1449 let else_if_arms = {
1450 let mut arms = vec![];
1452 let else_opt_continue = else_opt.and_then(|els| {
1453 els.and_then(|els| {
1456 hir::ExprIf(cond, then, else_opt) => {
1457 let pat_under = self.pat_wild(e.span);
1458 arms.push(hir::Arm {
1460 pats: hir_vec![pat_under],
1462 body: P(self.expr_block(then, ThinVec::new())),
1464 else_opt.map(|else_opt| (else_opt, true))
1466 _ => Some((P(els), false)),
1470 match else_opt_continue {
1471 Some((e, true)) => {
1474 Some((e, false)) => {
1487 let contains_else_clause = else_opt.is_some();
1489 // `_ => [<else_opt> | ()]`
1491 let pat_under = self.pat_wild(e.span);
1493 else_opt.unwrap_or_else(|| self.expr_tuple(e.span, hir_vec![]));
1494 self.arm(hir_vec![pat_under], else_expr)
1497 let mut arms = Vec::with_capacity(else_if_arms.len() + 2);
1499 arms.extend(else_if_arms);
1500 arms.push(else_arm);
1502 let sub_expr = P(self.lower_expr(sub_expr));
1503 // add attributes to the outer returned expr node
1504 return self.expr(e.span,
1505 hir::ExprMatch(sub_expr,
1507 hir::MatchSource::IfLetDesugar {
1508 contains_else_clause: contains_else_clause,
1513 // Desugar ExprWhileLet
1514 // From: `[opt_ident]: while let <pat> = <sub_expr> <body>`
1515 ExprKind::WhileLet(ref pat, ref sub_expr, ref body, opt_ident) => {
1518 // [opt_ident]: loop {
1519 // match <sub_expr> {
1525 // `<pat> => <body>`
1527 let body = self.lower_block(body);
1528 let body_expr = P(self.expr_block(body, ThinVec::new()));
1529 let pat = self.lower_pat(pat);
1530 self.arm(hir_vec![pat], body_expr)
1535 let pat_under = self.pat_wild(e.span);
1536 let break_expr = self.expr_break(e.span, ThinVec::new());
1537 self.arm(hir_vec![pat_under], break_expr)
1540 // `match <sub_expr> { ... }`
1541 let arms = hir_vec![pat_arm, break_arm];
1542 let sub_expr = P(self.lower_expr(sub_expr));
1543 let match_expr = self.expr(e.span,
1544 hir::ExprMatch(sub_expr,
1546 hir::MatchSource::WhileLetDesugar),
1549 // `[opt_ident]: loop { ... }`
1550 let loop_block = P(self.block_expr(P(match_expr)));
1551 let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident),
1552 hir::LoopSource::WhileLet);
1553 // add attributes to the outer returned expr node
1554 let attrs = e.attrs.clone();
1555 return hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs };
1558 // Desugar ExprForLoop
1559 // From: `[opt_ident]: for <pat> in <head> <body>`
1560 ExprKind::ForLoop(ref pat, ref head, ref body, opt_ident) => {
1564 // let result = match ::std::iter::IntoIterator::into_iter(<head>) {
1566 // [opt_ident]: loop {
1567 // match ::std::iter::Iterator::next(&mut iter) {
1568 // ::std::option::Option::Some(<pat>) => <body>,
1569 // ::std::option::Option::None => break
1578 let head = self.lower_expr(head);
1580 let iter = self.str_to_ident("iter");
1582 // `::std::option::Option::Some(<pat>) => <body>`
1584 let body_block = self.lower_block(body);
1585 let body_span = body_block.span;
1586 let body_expr = P(hir::Expr {
1588 node: hir::ExprBlock(body_block),
1590 attrs: ThinVec::new(),
1592 let pat = self.lower_pat(pat);
1593 let some_pat = self.pat_some(e.span, pat);
1595 self.arm(hir_vec![some_pat], body_expr)
1598 // `::std::option::Option::None => break`
1600 let break_expr = self.expr_break(e.span, ThinVec::new());
1601 let pat = self.pat_none(e.span);
1602 self.arm(hir_vec![pat], break_expr)
1606 let iter_pat = self.pat_ident_binding_mode(e.span, iter,
1607 hir::BindByValue(hir::MutMutable));
1609 // `match ::std::iter::Iterator::next(&mut iter) { ... }`
1611 let next_path = self.std_path(e.span, &["iter", "Iterator", "next"]);
1612 let iter = P(self.expr_ident(e.span, iter, iter_pat.id));
1613 let ref_mut_iter = self.expr_mut_addr_of(e.span, iter);
1614 let next_path = self.expr_path(next_path, ThinVec::new());
1615 let next_expr = P(self.expr_call(e.span, next_path,
1616 hir_vec![ref_mut_iter]));
1617 let arms = hir_vec![pat_arm, break_arm];
1620 hir::ExprMatch(next_expr, arms,
1621 hir::MatchSource::ForLoopDesugar),
1625 // `[opt_ident]: loop { ... }`
1626 let loop_block = P(self.block_expr(match_expr));
1627 let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident),
1628 hir::LoopSource::ForLoop);
1629 let loop_expr = P(hir::Expr {
1633 attrs: ThinVec::new(),
1636 // `mut iter => { ... }`
1637 let iter_arm = self.arm(hir_vec![iter_pat], loop_expr);
1639 // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
1640 let into_iter_expr = {
1641 let into_iter_path = self.std_path(e.span,
1642 &["iter", "IntoIterator", "into_iter"]);
1644 let into_iter = self.expr_path(into_iter_path, ThinVec::new());
1645 P(self.expr_call(e.span, into_iter, hir_vec![head]))
1648 let match_expr = P(self.expr_match(e.span,
1651 hir::MatchSource::ForLoopDesugar));
1653 // `{ let _result = ...; _result }`
1654 // underscore prevents an unused_variables lint if the head diverges
1655 let result_ident = self.str_to_ident("_result");
1656 let (let_stmt, let_stmt_binding) =
1657 self.stmt_let(e.span, false, result_ident, match_expr);
1659 let result = P(self.expr_ident(e.span, result_ident, let_stmt_binding));
1660 let block = P(self.block_all(e.span, hir_vec![let_stmt], Some(result)));
1661 // add the attributes to the outer returned expr node
1662 return self.expr_block(block, e.attrs.clone());
1665 // Desugar ExprKind::Try
1667 ExprKind::Try(ref sub_expr) => {
1671 // match { Carrier::translate( { <expr> } ) } {
1673 // Err(err) => { return Carrier::from_error(From::from(err)); }
1677 // { Carrier::translate( { <expr> } ) }
1680 let sub_expr = P(self.lower_expr(sub_expr));
1681 let sub_expr = self.signal_block_expr(hir_vec![],
1684 hir::PopUnstableBlock,
1687 let path = self.std_path(e.span, &["ops", "Carrier", "translate"]);
1688 let path = self.expr_path(path, ThinVec::new());
1689 let call = P(self.expr_call(e.span, path, hir_vec![sub_expr]));
1691 P(self.signal_block_expr(hir_vec![],
1694 hir::PushUnstableBlock,
1700 let val_ident = self.str_to_ident("val");
1701 let val_pat = self.pat_ident(e.span, val_ident);
1702 let val_expr = P(self.expr_ident(e.span, val_ident, val_pat.id));
1703 let ok_pat = self.pat_ok(e.span, val_pat);
1705 self.arm(hir_vec![ok_pat], val_expr)
1708 // Err(err) => { return Carrier::from_error(From::from(err)); }
1710 let err_ident = self.str_to_ident("err");
1711 let err_local = self.pat_ident(e.span, err_ident);
1713 let path = self.std_path(e.span, &["convert", "From", "from"]);
1714 let from = self.expr_path(path, ThinVec::new());
1715 let err_expr = self.expr_ident(e.span, err_ident, err_local.id);
1717 self.expr_call(e.span, from, hir_vec![err_expr])
1719 let from_err_expr = {
1720 let path = self.std_path(e.span, &["ops", "Carrier", "from_error"]);
1721 let from_err = self.expr_path(path, ThinVec::new());
1722 P(self.expr_call(e.span, from_err, hir_vec![from_expr]))
1725 let ret_expr = P(self.expr(e.span,
1726 hir::Expr_::ExprRet(Some(from_err_expr)),
1728 let ret_stmt = self.stmt_expr(ret_expr);
1729 let block = P(self.signal_block_stmt(ret_stmt, e.span,
1730 hir::PushUnstableBlock,
1733 let err_pat = self.pat_err(e.span, err_local);
1734 self.arm(hir_vec![err_pat], block)
1737 return self.expr_match(e.span, discr, hir_vec![err_arm, ok_arm],
1738 hir::MatchSource::TryDesugar);
1741 ExprKind::Mac(_) => panic!("Shouldn't exist here"),
1744 attrs: e.attrs.clone(),
1748 fn lower_stmt(&mut self, s: &Stmt) -> SmallVector<hir::Stmt> {
1749 SmallVector::one(match s.node {
1750 StmtKind::Local(ref l) => Spanned {
1751 node: hir::StmtDecl(P(Spanned {
1752 node: hir::DeclLocal(self.lower_local(l)),
1757 StmtKind::Item(ref it) => {
1758 // Can only use the ID once.
1759 let mut id = Some(s.id);
1760 return self.lower_item_id(it).into_iter().map(|item_id| Spanned {
1761 node: hir::StmtDecl(P(Spanned {
1762 node: hir::DeclItem(item_id),
1764 }), id.take().unwrap_or_else(|| self.next_id())),
1768 StmtKind::Expr(ref e) => {
1770 node: hir::StmtExpr(P(self.lower_expr(e)), s.id),
1774 StmtKind::Semi(ref e) => {
1776 node: hir::StmtSemi(P(self.lower_expr(e)), s.id),
1780 StmtKind::Mac(..) => panic!("Shouldn't exist here"),
1784 fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause {
1786 CaptureBy::Value => hir::CaptureByValue,
1787 CaptureBy::Ref => hir::CaptureByRef,
1791 fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility {
1793 Visibility::Public => hir::Public,
1794 Visibility::Crate(_) => hir::Visibility::Crate,
1795 Visibility::Restricted { ref path, id } => {
1796 hir::Visibility::Restricted {
1797 path: P(self.lower_path(path, ParamMode::Explicit)),
1801 Visibility::Inherited => hir::Inherited,
1805 fn lower_defaultness(&mut self, d: Defaultness, has_value: bool) -> hir::Defaultness {
1807 Defaultness::Default => hir::Defaultness::Default { has_value: has_value },
1808 Defaultness::Final => {
1810 hir::Defaultness::Final
1815 fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
1817 BlockCheckMode::Default => hir::DefaultBlock,
1818 BlockCheckMode::Unsafe(u) => hir::UnsafeBlock(self.lower_unsafe_source(u)),
1822 fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingMode {
1824 BindingMode::ByRef(m) => hir::BindByRef(self.lower_mutability(m)),
1825 BindingMode::ByValue(m) => hir::BindByValue(self.lower_mutability(m)),
1829 fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource {
1831 CompilerGenerated => hir::CompilerGenerated,
1832 UserProvided => hir::UserProvided,
1836 fn lower_impl_polarity(&mut self, i: ImplPolarity) -> hir::ImplPolarity {
1838 ImplPolarity::Positive => hir::ImplPolarity::Positive,
1839 ImplPolarity::Negative => hir::ImplPolarity::Negative,
1843 fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier {
1845 TraitBoundModifier::None => hir::TraitBoundModifier::None,
1846 TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe,
1850 // Helper methods for building HIR.
1852 fn arm(&mut self, pats: hir::HirVec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
1861 fn field(&mut self, name: Name, expr: P<hir::Expr>, span: Span) -> hir::Field {
1869 is_shorthand: false,
1873 fn expr_break(&mut self, span: Span, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
1874 P(self.expr(span, hir::ExprBreak(None, None), attrs))
1877 fn expr_call(&mut self, span: Span, e: P<hir::Expr>, args: hir::HirVec<hir::Expr>)
1879 self.expr(span, hir::ExprCall(e, args), ThinVec::new())
1882 fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> hir::Expr {
1883 let path = self.path_ident(span, id);
1884 let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(path)));
1885 let expr = self.expr(span, expr_path, ThinVec::new());
1888 let defs = self.resolver.definitions();
1889 Def::Local(defs.local_def_id(binding))
1891 self.resolver.record_resolution(expr.id, def);
1896 fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> hir::Expr {
1897 self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), ThinVec::new())
1900 fn expr_path(&mut self, path: hir::Path, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
1901 let def = self.resolver.resolve_generated_global_path(&path, true);
1902 let expr = self.expr(path.span, hir::ExprPath(hir::QPath::Resolved(None, P(path))), attrs);
1903 self.resolver.record_resolution(expr.id, def);
1907 fn expr_match(&mut self,
1910 arms: hir::HirVec<hir::Arm>,
1911 source: hir::MatchSource)
1913 self.expr(span, hir::ExprMatch(arg, arms, source), ThinVec::new())
1916 fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinVec<Attribute>) -> hir::Expr {
1917 self.expr(b.span, hir::ExprBlock(b), attrs)
1920 fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<hir::Expr>) -> P<hir::Expr> {
1921 P(self.expr(sp, hir::ExprTup(exprs), ThinVec::new()))
1924 fn expr_struct(&mut self,
1927 fields: hir::HirVec<hir::Field>,
1928 e: Option<P<hir::Expr>>,
1929 attrs: ThinVec<Attribute>) -> P<hir::Expr> {
1930 let def = self.resolver.resolve_generated_global_path(&path, false);
1931 let qpath = hir::QPath::Resolved(None, P(path));
1932 let expr = self.expr(sp, hir::ExprStruct(qpath, fields, e), attrs);
1933 self.resolver.record_resolution(expr.id, def);
1937 fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> hir::Expr {
1946 fn stmt_let(&mut self, sp: Span, mutbl: bool, ident: Name, ex: P<hir::Expr>)
1947 -> (hir::Stmt, NodeId) {
1948 let pat = if mutbl {
1949 self.pat_ident_binding_mode(sp, ident, hir::BindByValue(hir::MutMutable))
1951 self.pat_ident(sp, ident)
1953 let pat_id = pat.id;
1954 let local = P(hir::Local {
1960 attrs: ThinVec::new(),
1962 let decl = respan(sp, hir::DeclLocal(local));
1963 (respan(sp, hir::StmtDecl(P(decl), self.next_id())), pat_id)
1966 // Turns `<expr>` into `<expr>;`, note that this produces a StmtSemi, not a
1968 fn stmt_expr(&self, expr: P<hir::Expr>) -> hir::Stmt {
1971 node: hir::StmtSemi(expr, self.next_id()),
1975 fn block_expr(&mut self, expr: P<hir::Expr>) -> hir::Block {
1976 self.block_all(expr.span, hir::HirVec::new(), Some(expr))
1979 fn block_all(&mut self, span: Span, stmts: hir::HirVec<hir::Stmt>, expr: Option<P<hir::Expr>>)
1985 rules: hir::DefaultBlock,
1990 fn pat_ok(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
1991 let path = self.std_path(span, &["result", "Result", "Ok"]);
1992 self.pat_enum(span, path, hir_vec![pat])
1995 fn pat_err(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
1996 let path = self.std_path(span, &["result", "Result", "Err"]);
1997 self.pat_enum(span, path, hir_vec![pat])
2000 fn pat_some(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
2001 let path = self.std_path(span, &["option", "Option", "Some"]);
2002 self.pat_enum(span, path, hir_vec![pat])
2005 fn pat_none(&mut self, span: Span) -> P<hir::Pat> {
2006 let path = self.std_path(span, &["option", "Option", "None"]);
2007 self.pat_enum(span, path, hir_vec![])
2010 fn pat_enum(&mut self, span: Span, path: hir::Path, subpats: hir::HirVec<P<hir::Pat>>)
2012 let def = self.resolver.resolve_generated_global_path(&path, true);
2013 let qpath = hir::QPath::Resolved(None, P(path));
2014 let pt = if subpats.is_empty() {
2015 hir::PatKind::Path(qpath)
2017 hir::PatKind::TupleStruct(qpath, subpats, None)
2019 let pat = self.pat(span, pt);
2020 self.resolver.record_resolution(pat.id, def);
2024 fn pat_ident(&mut self, span: Span, name: Name) -> P<hir::Pat> {
2025 self.pat_ident_binding_mode(span, name, hir::BindByValue(hir::MutImmutable))
2028 fn pat_ident_binding_mode(&mut self, span: Span, name: Name, bm: hir::BindingMode)
2030 let pat_ident = hir::PatKind::Binding(bm,
2037 let pat = self.pat(span, pat_ident);
2039 let parent_def = self.parent_def;
2041 let defs = self.resolver.definitions();
2042 let def_path_data = DefPathData::Binding(name.as_str());
2043 let def_index = defs.create_def_with_parent(parent_def, pat.id, def_path_data);
2044 Def::Local(DefId::local(def_index))
2046 self.resolver.record_resolution(pat.id, def);
2051 fn pat_wild(&mut self, span: Span) -> P<hir::Pat> {
2052 self.pat(span, hir::PatKind::Wild)
2055 fn pat(&mut self, span: Span, pat: hir::PatKind) -> P<hir::Pat> {
2063 fn path_ident(&mut self, span: Span, id: Name) -> hir::Path {
2064 self.path(span, vec![id])
2067 fn path(&mut self, span: Span, strs: Vec<Name>) -> hir::Path {
2068 self.path_all(span, false, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new())
2071 fn path_global(&mut self, span: Span, strs: Vec<Name>) -> hir::Path {
2072 self.path_all(span, true, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new())
2075 fn path_all(&mut self,
2078 mut names: Vec<Name>,
2079 lifetimes: hir::HirVec<hir::Lifetime>,
2080 types: hir::HirVec<P<hir::Ty>>,
2081 bindings: hir::HirVec<hir::TypeBinding>)
2083 let last_identifier = names.pop().unwrap();
2084 let mut segments: Vec<hir::PathSegment> = names.into_iter().map(|name| {
2087 parameters: hir::PathParameters::none(),
2091 segments.push(hir::PathSegment {
2092 name: last_identifier,
2093 parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
2094 lifetimes: lifetimes,
2103 segments: segments.into(),
2107 fn std_path_components(&mut self, components: &[&str]) -> Vec<Name> {
2108 let mut v = Vec::new();
2109 if let Some(s) = self.crate_root {
2110 v.push(Symbol::intern(s));
2112 v.extend(components.iter().map(|s| Symbol::intern(s)));
2116 // Given suffix ["b","c","d"], returns path `::std::b::c::d` when
2117 // `fld.cx.use_std`, and `::core::b::c::d` otherwise.
2118 fn std_path(&mut self, span: Span, components: &[&str]) -> hir::Path {
2119 let idents = self.std_path_components(components);
2120 self.path_global(span, idents)
2123 fn signal_block_expr(&mut self,
2124 stmts: hir::HirVec<hir::Stmt>,
2127 rule: hir::BlockCheckMode,
2128 attrs: ThinVec<Attribute>)
2130 let id = self.next_id();
2131 let block = P(hir::Block {
2138 self.expr_block(block, attrs)
2141 fn signal_block_stmt(&mut self,
2144 rule: hir::BlockCheckMode,
2145 attrs: ThinVec<Attribute>)
2147 let id = self.next_id();
2148 let block = P(hir::Block {
2152 stmts: hir_vec![stmt],
2155 self.expr_block(block, attrs)
2158 fn ty(&mut self, span: Span, node: hir::Ty_) -> P<hir::Ty> {