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