2015-07-31 07:04:06 +00:00
|
|
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2015-09-30 05:23:52 +00:00
|
|
|
// Lowers the AST to the HIR.
|
|
|
|
//
|
|
|
|
// Since the AST and HIR are fairly similar, this is mostly a simple procedure,
|
|
|
|
// much like a fold. Where lowering involves a bit more work things get more
|
|
|
|
// interesting and there are some invariants you should know about. These mostly
|
|
|
|
// concern spans and ids.
|
|
|
|
//
|
|
|
|
// Spans are assigned to AST nodes during parsing and then are modified during
|
|
|
|
// expansion to indicate the origin of a node and the process it went through
|
|
|
|
// being expanded. Ids are assigned to AST nodes just before lowering.
|
|
|
|
//
|
|
|
|
// For the simpler lowering steps, ids and spans should be preserved. Unlike
|
|
|
|
// expansion we do not preserve the process of lowering in the spans, so spans
|
|
|
|
// should not be modified here. When creating a new node (as opposed to
|
|
|
|
// 'folding' an existing one), then you create a new id using `next_id()`.
|
|
|
|
//
|
|
|
|
// You must ensure that ids are unique. That means that you should only use the
|
2015-10-06 19:26:22 +00:00
|
|
|
// id from an AST node in a single HIR node (you can assume that AST node ids
|
2015-09-30 05:23:52 +00:00
|
|
|
// are unique). Every new node must have a unique id. Avoid cloning HIR nodes.
|
2015-10-06 19:26:22 +00:00
|
|
|
// If you do, you must then set the new node's id to a fresh one.
|
2015-09-30 05:23:52 +00:00
|
|
|
//
|
|
|
|
// Spans are used for error messages and for tools to map semantics back to
|
|
|
|
// source code. It is therefore not as important with spans as ids to be strict
|
|
|
|
// about use (you can't break the compiler by screwing up a span). Obviously, a
|
|
|
|
// HIR node can only have a single span. But multiple nodes can have the same
|
|
|
|
// span and spans don't need to be kept in order, etc. Where code is preserved
|
|
|
|
// by lowering, it should have the same span as in the AST. Where HIR nodes are
|
|
|
|
// new it is probably best to give a span for the whole AST node being lowered.
|
|
|
|
// All nodes should have real spans, don't use dummy spans. Tools are likely to
|
|
|
|
// get confused if the spans from leaf AST nodes occur in multiple places
|
|
|
|
// in the HIR, especially for multiple identifiers.
|
2015-07-31 07:04:06 +00:00
|
|
|
|
|
|
|
use hir;
|
2016-04-17 22:30:55 +00:00
|
|
|
use hir::map::Definitions;
|
|
|
|
use hir::map::definitions::DefPathData;
|
2016-05-02 23:26:18 +00:00
|
|
|
use hir::def_id::{DefIndex, DefId};
|
2016-09-14 21:51:46 +00:00
|
|
|
use hir::def::{Def, PathResolution};
|
2016-05-11 00:50:00 +00:00
|
|
|
use session::Session;
|
2016-10-22 00:33:36 +00:00
|
|
|
use util::nodemap::NodeMap;
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2015-11-18 09:16:25 +00:00
|
|
|
use std::collections::BTreeMap;
|
2016-01-13 06:24:34 +00:00
|
|
|
use std::iter;
|
2015-07-31 07:04:06 +00:00
|
|
|
use syntax::ast::*;
|
2016-06-22 01:16:56 +00:00
|
|
|
use syntax::errors;
|
2015-07-31 07:04:06 +00:00
|
|
|
use syntax::ptr::P;
|
2016-10-30 00:42:12 +00:00
|
|
|
use syntax::codemap::{self, respan, Spanned};
|
2015-09-28 02:00:15 +00:00
|
|
|
use syntax::std_inject;
|
2016-11-16 08:21:52 +00:00
|
|
|
use syntax::symbol::{Symbol, keywords};
|
2016-11-24 04:11:31 +00:00
|
|
|
use syntax::util::small_vector::SmallVector;
|
2015-11-17 22:32:12 +00:00
|
|
|
use syntax::visit::{self, Visitor};
|
2016-06-21 22:08:13 +00:00
|
|
|
use syntax_pos::Span;
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2015-09-30 03:17:37 +00:00
|
|
|
pub struct LoweringContext<'a> {
|
2015-09-28 02:00:15 +00:00
|
|
|
crate_root: Option<&'static str>,
|
2016-04-30 19:48:46 +00:00
|
|
|
// Use to assign ids to hir nodes that do not directly correspond to an ast node
|
2016-08-31 11:00:29 +00:00
|
|
|
sess: &'a Session,
|
2016-04-17 22:30:55 +00:00
|
|
|
// As we walk the AST we must keep track of the current 'parent' def id (in
|
|
|
|
// the form of a DefIndex) so that if we create a new node which introduces
|
|
|
|
// a definition, then we can properly create the def id.
|
2016-05-09 07:59:19 +00:00
|
|
|
parent_def: Option<DefIndex>,
|
|
|
|
resolver: &'a mut Resolver,
|
2016-11-24 04:11:31 +00:00
|
|
|
|
|
|
|
/// The items being lowered are collected here.
|
|
|
|
items: BTreeMap<NodeId, hir::Item>,
|
|
|
|
|
|
|
|
impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
|
2016-05-02 23:26:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub trait Resolver {
|
2016-05-06 08:24:04 +00:00
|
|
|
// Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc.
|
2016-11-25 11:21:19 +00:00
|
|
|
fn resolve_generated_global_path(&mut self, path: &mut hir::Path, is_value: bool);
|
2016-05-02 23:26:18 +00:00
|
|
|
|
2016-03-06 12:54:44 +00:00
|
|
|
// Obtain the resolution for a node id
|
|
|
|
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution>;
|
|
|
|
|
2016-05-06 08:24:04 +00:00
|
|
|
// Record the resolution of a path or binding generated by the lowerer when expanding.
|
|
|
|
fn record_resolution(&mut self, id: NodeId, def: Def);
|
|
|
|
|
2016-05-02 23:26:18 +00:00
|
|
|
// We must keep the set of definitions up to date as we add nodes that weren't in the AST.
|
2016-05-06 08:24:04 +00:00
|
|
|
// This should only return `None` during testing.
|
2016-08-29 02:12:03 +00:00
|
|
|
fn definitions(&mut self) -> &mut Definitions;
|
2015-09-25 04:03:28 +00:00
|
|
|
}
|
|
|
|
|
2016-05-11 00:50:00 +00:00
|
|
|
pub fn lower_crate(sess: &Session,
|
|
|
|
krate: &Crate,
|
|
|
|
resolver: &mut Resolver)
|
2016-05-10 05:29:13 +00:00
|
|
|
-> hir::Crate {
|
2016-05-11 00:50:00 +00:00
|
|
|
// We're constructing the HIR here; we don't care what we will
|
|
|
|
// read, since we haven't even constructed the *input* to
|
|
|
|
// incr. comp. yet.
|
|
|
|
let _ignore = sess.dep_graph.in_ignore();
|
|
|
|
|
2016-05-10 05:29:13 +00:00
|
|
|
LoweringContext {
|
2016-09-28 22:28:19 +00:00
|
|
|
crate_root: std_inject::injected_crate_name(krate),
|
2016-08-31 11:00:29 +00:00
|
|
|
sess: sess,
|
2016-05-10 05:29:13 +00:00
|
|
|
parent_def: None,
|
|
|
|
resolver: resolver,
|
2016-11-24 04:11:31 +00:00
|
|
|
items: BTreeMap::new(),
|
|
|
|
impl_items: BTreeMap::new(),
|
2016-05-10 05:29:13 +00:00
|
|
|
}.lower_crate(krate)
|
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-10-17 03:02:23 +00:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
|
|
|
enum ParamMode {
|
|
|
|
/// Any path in a type context.
|
|
|
|
Explicit,
|
|
|
|
/// The `module::Type` in `module::Type::method` in an expression.
|
|
|
|
Optional
|
|
|
|
}
|
|
|
|
|
2016-05-10 05:29:13 +00:00
|
|
|
impl<'a> LoweringContext<'a> {
|
2016-11-24 04:11:31 +00:00
|
|
|
fn lower_crate(mut self, c: &Crate) -> hir::Crate {
|
2016-05-10 01:11:59 +00:00
|
|
|
struct ItemLowerer<'lcx, 'interner: 'lcx> {
|
|
|
|
lctx: &'lcx mut LoweringContext<'interner>,
|
|
|
|
}
|
|
|
|
|
2016-06-12 07:51:31 +00:00
|
|
|
impl<'lcx, 'interner> Visitor for ItemLowerer<'lcx, 'interner> {
|
|
|
|
fn visit_item(&mut self, item: &Item) {
|
2016-11-24 04:11:31 +00:00
|
|
|
let hir_item = self.lctx.lower_item(item);
|
|
|
|
self.lctx.items.insert(item.id, hir_item);
|
2016-05-10 01:11:59 +00:00
|
|
|
visit::walk_item(self, item);
|
|
|
|
}
|
2016-11-02 22:25:31 +00:00
|
|
|
|
|
|
|
fn visit_impl_item(&mut self, item: &ImplItem) {
|
2016-11-10 14:47:00 +00:00
|
|
|
let id = self.lctx.lower_impl_item_ref(item).id;
|
2016-11-24 04:11:31 +00:00
|
|
|
let hir_item = self.lctx.lower_impl_item(item);
|
|
|
|
self.lctx.impl_items.insert(id, hir_item);
|
2016-11-02 22:25:31 +00:00
|
|
|
visit::walk_impl_item(self, item);
|
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
|
2016-11-24 04:11:31 +00:00
|
|
|
visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c);
|
2016-05-10 01:11:59 +00:00
|
|
|
|
|
|
|
hir::Crate {
|
|
|
|
module: self.lower_mod(&c.module),
|
|
|
|
attrs: self.lower_attrs(&c.attrs),
|
|
|
|
span: c.span,
|
|
|
|
exported_macros: c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect(),
|
2016-11-24 04:11:31 +00:00
|
|
|
items: self.items,
|
|
|
|
impl_items: self.impl_items,
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-28 02:00:15 +00:00
|
|
|
fn next_id(&self) -> NodeId {
|
2016-08-31 11:00:29 +00:00
|
|
|
self.sess.next_node_id()
|
2016-06-22 01:16:56 +00:00
|
|
|
}
|
|
|
|
|
2016-11-25 11:21:19 +00:00
|
|
|
fn expect_full_def(&mut self, id: NodeId) -> Def {
|
|
|
|
self.resolver.get_resolution(id).map_or(Def::Err, |pr| {
|
|
|
|
if pr.depth != 0 {
|
|
|
|
bug!("path not fully resolved: {:?}", pr);
|
|
|
|
}
|
|
|
|
pr.base_def
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-06-22 01:16:56 +00:00
|
|
|
fn diagnostic(&self) -> &errors::Handler {
|
2016-08-31 11:00:29 +00:00
|
|
|
self.sess.diagnostic()
|
2015-09-28 02:00:15 +00:00
|
|
|
}
|
2015-10-06 19:26:22 +00:00
|
|
|
|
2016-03-06 12:54:44 +00:00
|
|
|
fn str_to_ident(&self, s: &'static str) -> Name {
|
2016-11-16 08:21:52 +00:00
|
|
|
Symbol::gensym(s)
|
2015-10-06 19:26:22 +00:00
|
|
|
}
|
2016-03-15 17:03:42 +00:00
|
|
|
|
2016-10-30 00:42:12 +00:00
|
|
|
fn allow_internal_unstable(&self, reason: &'static str, mut span: Span) -> Span {
|
|
|
|
span.expn_id = self.sess.codemap().record_expansion(codemap::ExpnInfo {
|
|
|
|
call_site: span,
|
|
|
|
callee: codemap::NameAndSpan {
|
|
|
|
format: codemap::CompilerDesugaring(Symbol::intern(reason)),
|
|
|
|
span: Some(span),
|
|
|
|
allow_internal_unstable: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
span
|
|
|
|
}
|
|
|
|
|
2016-05-09 07:59:19 +00:00
|
|
|
fn with_parent_def<T, F>(&mut self, parent_id: NodeId, f: F) -> T
|
|
|
|
where F: FnOnce(&mut LoweringContext) -> T
|
|
|
|
{
|
|
|
|
let old_def = self.parent_def;
|
2016-08-29 02:12:03 +00:00
|
|
|
self.parent_def = {
|
|
|
|
let defs = self.resolver.definitions();
|
|
|
|
Some(defs.opt_def_index(parent_id).unwrap())
|
2016-05-09 07:59:19 +00:00
|
|
|
};
|
2016-05-06 08:24:04 +00:00
|
|
|
|
2016-05-09 07:59:19 +00:00
|
|
|
let result = f(self);
|
2016-04-17 22:30:55 +00:00
|
|
|
|
2016-05-09 07:59:19 +00:00
|
|
|
self.parent_def = old_def;
|
2016-04-17 22:30:55 +00:00
|
|
|
result
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-02 16:22:03 +00:00
|
|
|
fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
|
2016-06-10 21:12:39 +00:00
|
|
|
o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
|
2016-05-02 16:22:03 +00:00
|
|
|
}
|
|
|
|
|
2016-11-25 11:21:19 +00:00
|
|
|
fn lower_label(&mut self, id: NodeId, label: Option<Spanned<Ident>>) -> Option<hir::Label> {
|
|
|
|
label.map(|sp_ident| {
|
|
|
|
hir::Label {
|
|
|
|
span: sp_ident.span,
|
|
|
|
name: sp_ident.node.name,
|
|
|
|
loop_id: match self.expect_full_def(id) {
|
|
|
|
Def::Label(loop_id) => loop_id,
|
|
|
|
_ => DUMMY_NODE_ID
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_attrs(&mut self, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
|
|
|
|
attrs.clone().into()
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {
|
|
|
|
hir::Arm {
|
|
|
|
attrs: self.lower_attrs(&arm.attrs),
|
|
|
|
pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(),
|
2016-10-28 10:16:44 +00:00
|
|
|
guard: arm.guard.as_ref().map(|ref x| P(self.lower_expr(x))),
|
|
|
|
body: P(self.lower_expr(&arm.body)),
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding {
|
|
|
|
hir::TypeBinding {
|
|
|
|
id: b.id,
|
|
|
|
name: b.ident.name,
|
|
|
|
ty: self.lower_ty(&b.ty),
|
|
|
|
span: b.span,
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
|
|
|
|
P(hir::Ty {
|
|
|
|
id: t.id,
|
|
|
|
node: match t.node {
|
2016-09-20 14:54:24 +00:00
|
|
|
TyKind::Infer | TyKind::ImplicitSelf => hir::TyInfer,
|
|
|
|
TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)),
|
|
|
|
TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
|
|
|
|
TyKind::Rptr(ref region, ref mt) => {
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::TyRptr(self.lower_opt_lifetime(region), self.lower_mt(mt))
|
|
|
|
}
|
2016-09-20 14:54:24 +00:00
|
|
|
TyKind::BareFn(ref f) => {
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::TyBareFn(P(hir::BareFnTy {
|
|
|
|
lifetimes: self.lower_lifetime_defs(&f.lifetimes),
|
|
|
|
unsafety: self.lower_unsafety(f.unsafety),
|
|
|
|
abi: f.abi,
|
|
|
|
decl: self.lower_fn_decl(&f.decl),
|
|
|
|
}))
|
|
|
|
}
|
2016-09-20 14:54:24 +00:00
|
|
|
TyKind::Never => hir::TyNever,
|
2016-09-20 18:18:35 +00:00
|
|
|
TyKind::Tup(ref tys) => {
|
|
|
|
hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty)).collect())
|
|
|
|
}
|
2016-09-20 14:54:24 +00:00
|
|
|
TyKind::Paren(ref ty) => {
|
2016-05-10 01:11:59 +00:00
|
|
|
return self.lower_ty(ty);
|
|
|
|
}
|
2016-09-20 14:54:24 +00:00
|
|
|
TyKind::Path(ref qself, ref path) => {
|
2016-10-27 02:17:42 +00:00
|
|
|
hir::TyPath(self.lower_qpath(t.id, qself, path, ParamMode::Explicit))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-09-20 14:54:24 +00:00
|
|
|
TyKind::ObjectSum(ref ty, ref bounds) => {
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds))
|
|
|
|
}
|
2016-09-20 14:54:24 +00:00
|
|
|
TyKind::Array(ref ty, ref e) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
hir::TyArray(self.lower_ty(ty), P(self.lower_expr(e)))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-09-20 14:54:24 +00:00
|
|
|
TyKind::Typeof(ref expr) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
hir::TyTypeof(P(self.lower_expr(expr)))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-09-20 14:54:24 +00:00
|
|
|
TyKind::PolyTraitRef(ref bounds) => {
|
2016-08-01 01:25:32 +00:00
|
|
|
hir::TyPolyTraitRef(self.lower_bounds(bounds))
|
|
|
|
}
|
2016-09-20 14:54:24 +00:00
|
|
|
TyKind::ImplTrait(ref bounds) => {
|
2016-08-01 01:25:32 +00:00
|
|
|
hir::TyImplTrait(self.lower_bounds(bounds))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-09-20 14:54:24 +00:00
|
|
|
TyKind::Mac(_) => panic!("TyMac should have been expanded by now."),
|
2016-05-10 01:11:59 +00:00
|
|
|
},
|
|
|
|
span: t.span,
|
|
|
|
})
|
2015-12-07 14:17:41 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod {
|
|
|
|
hir::ForeignMod {
|
|
|
|
abi: fm.abi,
|
|
|
|
items: fm.items.iter().map(|x| self.lower_foreign_item(x)).collect(),
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
2015-12-01 17:38:40 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
|
|
|
|
Spanned {
|
|
|
|
node: hir::Variant_ {
|
|
|
|
name: v.node.name.name,
|
|
|
|
attrs: self.lower_attrs(&v.node.attrs),
|
|
|
|
data: self.lower_variant_data(&v.node.data),
|
2016-10-28 10:16:44 +00:00
|
|
|
disr_expr: v.node.disr_expr.as_ref().map(|e| P(self.lower_expr(e))),
|
2016-05-10 01:11:59 +00:00
|
|
|
},
|
|
|
|
span: v.span,
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-10-27 02:17:42 +00:00
|
|
|
fn lower_qpath(&mut self,
|
|
|
|
id: NodeId,
|
|
|
|
qself: &Option<QSelf>,
|
|
|
|
p: &Path,
|
|
|
|
param_mode: ParamMode)
|
|
|
|
-> hir::QPath {
|
|
|
|
let qself_position = qself.as_ref().map(|q| q.position);
|
|
|
|
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty));
|
|
|
|
|
|
|
|
let resolution = self.resolver.get_resolution(id)
|
|
|
|
.unwrap_or(PathResolution::new(Def::Err));
|
|
|
|
|
|
|
|
let proj_start = p.segments.len() - resolution.depth;
|
|
|
|
let path = P(hir::Path {
|
2016-05-10 01:11:59 +00:00
|
|
|
global: p.global,
|
2016-11-25 11:21:19 +00:00
|
|
|
def: resolution.base_def,
|
2016-10-27 02:17:42 +00:00
|
|
|
segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
|
|
|
|
let param_mode = match (qself_position, param_mode) {
|
|
|
|
(Some(j), ParamMode::Optional) if i < j => {
|
2016-10-17 03:02:23 +00:00
|
|
|
// This segment is part of the trait path in a
|
|
|
|
// qualified path - one of `a`, `b` or `Trait`
|
|
|
|
// in `<X as a::b::Trait>::T::U::method`.
|
|
|
|
ParamMode::Explicit
|
|
|
|
}
|
|
|
|
_ => param_mode
|
|
|
|
};
|
2016-10-27 02:17:42 +00:00
|
|
|
self.lower_path_segment(segment, param_mode)
|
2016-10-17 03:02:23 +00:00
|
|
|
}).collect(),
|
2016-05-10 01:11:59 +00:00
|
|
|
span: p.span,
|
2016-10-27 02:17:42 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
// Simple case, either no projections, or only fully-qualified.
|
|
|
|
// E.g. `std::mem::size_of` or `<I as Iterator>::Item`.
|
|
|
|
if resolution.depth == 0 {
|
|
|
|
return hir::QPath::Resolved(qself, path);
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-10-27 02:17:42 +00:00
|
|
|
|
|
|
|
// Create the innermost type that we're projecting from.
|
|
|
|
let mut ty = if path.segments.is_empty() {
|
|
|
|
// If the base path is empty that means there exists a
|
|
|
|
// syntactical `Self`, e.g. `&i32` in `<&i32>::clone`.
|
|
|
|
qself.expect("missing QSelf for <T>::...")
|
|
|
|
} else {
|
|
|
|
// Otherwise, the base path is an implicit `Self` type path,
|
|
|
|
// e.g. `Vec` in `Vec::new` or `<I as Iterator>::Item` in
|
|
|
|
// `<I as Iterator>::Item::default`.
|
|
|
|
let ty = self.ty(p.span, hir::TyPath(hir::QPath::Resolved(qself, path)));
|
|
|
|
|
|
|
|
// Associate that innermost path type with the base Def.
|
|
|
|
self.resolver.record_resolution(ty.id, resolution.base_def);
|
|
|
|
|
|
|
|
ty
|
|
|
|
};
|
|
|
|
|
|
|
|
// Anything after the base path are associated "extensions",
|
|
|
|
// out of which all but the last one are associated types,
|
|
|
|
// e.g. for `std::vec::Vec::<T>::IntoIter::Item::clone`:
|
|
|
|
// * base path is `std::vec::Vec<T>`
|
|
|
|
// * "extensions" are `IntoIter`, `Item` and `clone`
|
|
|
|
// * type nodes are:
|
|
|
|
// 1. `std::vec::Vec<T>` (created above)
|
|
|
|
// 2. `<std::vec::Vec<T>>::IntoIter`
|
|
|
|
// 3. `<<std::vec::Vec<T>>::IntoIter>::Item`
|
|
|
|
// * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
|
|
|
|
for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
|
|
|
|
let segment = P(self.lower_path_segment(segment, param_mode));
|
|
|
|
let qpath = hir::QPath::TypeRelative(ty, segment);
|
|
|
|
|
|
|
|
// It's finished, return the extension of the right node type.
|
|
|
|
if i == p.segments.len() - 1 {
|
|
|
|
return qpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wrap the associated extension in another type node.
|
|
|
|
ty = self.ty(p.span, hir::TyPath(qpath));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should've returned in the for loop above.
|
|
|
|
span_bug!(p.span, "lower_qpath: no final extension segment in {}..{}",
|
|
|
|
proj_start, p.segments.len())
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-11-24 04:11:31 +00:00
|
|
|
fn lower_path_extra(&mut self,
|
2016-11-25 11:21:19 +00:00
|
|
|
id: NodeId,
|
2016-11-24 04:11:31 +00:00
|
|
|
p: &Path,
|
|
|
|
name: Option<Name>,
|
|
|
|
param_mode: ParamMode)
|
|
|
|
-> hir::Path {
|
2016-10-27 02:17:42 +00:00
|
|
|
hir::Path {
|
|
|
|
global: p.global,
|
2016-11-25 11:21:19 +00:00
|
|
|
def: self.expect_full_def(id),
|
2016-10-27 02:17:42 +00:00
|
|
|
segments: p.segments.iter().map(|segment| {
|
|
|
|
self.lower_path_segment(segment, param_mode)
|
2016-11-24 04:11:31 +00:00
|
|
|
}).chain(name.map(|name| {
|
|
|
|
hir::PathSegment {
|
|
|
|
name: name,
|
|
|
|
parameters: hir::PathParameters::none()
|
|
|
|
}
|
|
|
|
})).collect(),
|
2016-10-27 02:17:42 +00:00
|
|
|
span: p.span,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-24 04:11:31 +00:00
|
|
|
fn lower_path(&mut self,
|
2016-11-25 11:21:19 +00:00
|
|
|
id: NodeId,
|
2016-11-24 04:11:31 +00:00
|
|
|
p: &Path,
|
|
|
|
param_mode: ParamMode)
|
|
|
|
-> hir::Path {
|
2016-11-25 11:21:19 +00:00
|
|
|
self.lower_path_extra(id, p, None, param_mode)
|
2016-11-24 04:11:31 +00:00
|
|
|
}
|
|
|
|
|
2016-10-27 02:17:42 +00:00
|
|
|
fn lower_path_segment(&mut self,
|
|
|
|
segment: &PathSegment,
|
|
|
|
param_mode: ParamMode)
|
|
|
|
-> hir::PathSegment {
|
|
|
|
let parameters = match segment.parameters {
|
2016-10-17 03:02:23 +00:00
|
|
|
PathParameters::AngleBracketed(ref data) => {
|
|
|
|
let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
|
|
|
|
hir::AngleBracketedParameters(data)
|
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
PathParameters::Parenthesized(ref data) =>
|
|
|
|
hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)),
|
2016-10-27 02:17:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
hir::PathSegment {
|
|
|
|
name: segment.identifier.name,
|
|
|
|
parameters: parameters,
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_angle_bracketed_parameter_data(&mut self,
|
2016-10-17 03:02:23 +00:00
|
|
|
data: &AngleBracketedParameterData,
|
|
|
|
param_mode: ParamMode)
|
2016-05-10 01:11:59 +00:00
|
|
|
-> hir::AngleBracketedParameterData {
|
|
|
|
let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data;
|
|
|
|
hir::AngleBracketedParameterData {
|
|
|
|
lifetimes: self.lower_lifetimes(lifetimes),
|
|
|
|
types: types.iter().map(|ty| self.lower_ty(ty)).collect(),
|
2016-10-17 03:02:23 +00:00
|
|
|
infer_types: types.is_empty() && param_mode == ParamMode::Optional,
|
2016-05-10 01:11:59 +00:00
|
|
|
bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(),
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_parenthesized_parameter_data(&mut self,
|
|
|
|
data: &ParenthesizedParameterData)
|
|
|
|
-> hir::ParenthesizedParameterData {
|
|
|
|
let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
|
|
|
|
hir::ParenthesizedParameterData {
|
|
|
|
inputs: inputs.iter().map(|ty| self.lower_ty(ty)).collect(),
|
|
|
|
output: output.as_ref().map(|ty| self.lower_ty(ty)),
|
|
|
|
span: span,
|
|
|
|
}
|
2015-10-06 03:03:56 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_local(&mut self, l: &Local) -> P<hir::Local> {
|
|
|
|
P(hir::Local {
|
|
|
|
id: l.id,
|
|
|
|
ty: l.ty.as_ref().map(|t| self.lower_ty(t)),
|
|
|
|
pat: self.lower_pat(&l.pat),
|
2016-10-28 10:16:44 +00:00
|
|
|
init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
|
2016-05-10 01:11:59 +00:00
|
|
|
span: l.span,
|
|
|
|
attrs: l.attrs.clone(),
|
|
|
|
})
|
2015-10-06 03:03:56 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
|
|
|
|
match m {
|
|
|
|
Mutability::Mutable => hir::MutMutable,
|
|
|
|
Mutability::Immutable => hir::MutImmutable,
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
|
|
|
|
hir::Arg {
|
|
|
|
id: arg.id,
|
|
|
|
pat: self.lower_pat(&arg.pat),
|
|
|
|
ty: self.lower_ty(&arg.ty),
|
|
|
|
}
|
2015-09-27 19:23:31 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_fn_decl(&mut self, decl: &FnDecl) -> P<hir::FnDecl> {
|
|
|
|
P(hir::FnDecl {
|
|
|
|
inputs: decl.inputs.iter().map(|x| self.lower_arg(x)).collect(),
|
|
|
|
output: match decl.output {
|
|
|
|
FunctionRetTy::Ty(ref ty) => hir::Return(self.lower_ty(ty)),
|
|
|
|
FunctionRetTy::Default(span) => hir::DefaultReturn(span),
|
|
|
|
},
|
|
|
|
variadic: decl.variadic,
|
|
|
|
})
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_ty_param_bound(&mut self, tpb: &TyParamBound) -> hir::TyParamBound {
|
|
|
|
match *tpb {
|
|
|
|
TraitTyParamBound(ref ty, modifier) => {
|
|
|
|
hir::TraitTyParamBound(self.lower_poly_trait_ref(ty),
|
|
|
|
self.lower_trait_bound_modifier(modifier))
|
|
|
|
}
|
|
|
|
RegionTyParamBound(ref lifetime) => {
|
|
|
|
hir::RegionTyParamBound(self.lower_lifetime(lifetime))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-10-22 00:33:36 +00:00
|
|
|
fn lower_ty_param(&mut self, tp: &TyParam, add_bounds: &[TyParamBound]) -> hir::TyParam {
|
2016-09-22 17:03:28 +00:00
|
|
|
let mut name = tp.ident.name;
|
|
|
|
|
|
|
|
// Don't expose `Self` (recovered "keyword used as ident" parse error).
|
|
|
|
// `rustc::ty` expects `Self` to be only used for a trait's `Self`.
|
|
|
|
// Instead, use gensym("Self") to create a distinct name that looks the same.
|
2016-11-16 08:21:52 +00:00
|
|
|
if name == keywords::SelfType.name() {
|
|
|
|
name = Symbol::gensym("Self");
|
2016-09-22 17:03:28 +00:00
|
|
|
}
|
|
|
|
|
2016-10-22 00:33:36 +00:00
|
|
|
let mut bounds = self.lower_bounds(&tp.bounds);
|
|
|
|
if !add_bounds.is_empty() {
|
|
|
|
bounds = bounds.into_iter().chain(self.lower_bounds(add_bounds).into_iter()).collect();
|
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::TyParam {
|
|
|
|
id: tp.id,
|
2016-09-22 17:03:28 +00:00
|
|
|
name: name,
|
2016-10-22 00:33:36 +00:00
|
|
|
bounds: bounds,
|
2016-05-10 01:11:59 +00:00
|
|
|
default: tp.default.as_ref().map(|x| self.lower_ty(x)),
|
|
|
|
span: tp.span,
|
2016-10-11 14:06:43 +00:00
|
|
|
pure_wrt_drop: tp.attrs.iter().any(|attr| attr.check_name("may_dangle")),
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-10-22 00:33:36 +00:00
|
|
|
fn lower_ty_params(&mut self, tps: &P<[TyParam]>, add_bounds: &NodeMap<Vec<TyParamBound>>)
|
|
|
|
-> hir::HirVec<hir::TyParam> {
|
|
|
|
tps.iter().map(|tp| {
|
|
|
|
self.lower_ty_param(tp, add_bounds.get(&tp.id).map_or(&[][..], |x| &x))
|
|
|
|
}).collect()
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
|
|
|
|
hir::Lifetime {
|
|
|
|
id: l.id,
|
|
|
|
name: l.name,
|
|
|
|
span: l.span,
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef {
|
|
|
|
hir::LifetimeDef {
|
|
|
|
lifetime: self.lower_lifetime(&l.lifetime),
|
|
|
|
bounds: self.lower_lifetimes(&l.bounds),
|
2016-10-11 14:06:43 +00:00
|
|
|
pure_wrt_drop: l.attrs.iter().any(|attr| attr.check_name("may_dangle")),
|
2015-10-02 00:53:28 +00:00
|
|
|
}
|
2015-10-25 15:33:51 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_lifetimes(&mut self, lts: &Vec<Lifetime>) -> hir::HirVec<hir::Lifetime> {
|
|
|
|
lts.iter().map(|l| self.lower_lifetime(l)).collect()
|
2015-10-06 03:03:56 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_lifetime_defs(&mut self, lts: &Vec<LifetimeDef>) -> hir::HirVec<hir::LifetimeDef> {
|
|
|
|
lts.iter().map(|l| self.lower_lifetime_def(l)).collect()
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_opt_lifetime(&mut self, o_lt: &Option<Lifetime>) -> Option<hir::Lifetime> {
|
|
|
|
o_lt.as_ref().map(|lt| self.lower_lifetime(lt))
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_generics(&mut self, g: &Generics) -> hir::Generics {
|
2016-10-22 00:33:36 +00:00
|
|
|
// Collect `?Trait` bounds in where clause and move them to parameter definitions.
|
|
|
|
let mut add_bounds = NodeMap();
|
|
|
|
for pred in &g.where_clause.predicates {
|
|
|
|
if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
|
|
|
|
'next_bound: for bound in &bound_pred.bounds {
|
|
|
|
if let TraitTyParamBound(_, TraitBoundModifier::Maybe) = *bound {
|
|
|
|
let report_error = |this: &mut Self| {
|
|
|
|
this.diagnostic().span_err(bound_pred.bounded_ty.span,
|
|
|
|
"`?Trait` bounds are only permitted at the \
|
|
|
|
point where a type parameter is declared");
|
|
|
|
};
|
|
|
|
// Check if the where clause type is a plain type parameter.
|
|
|
|
match bound_pred.bounded_ty.node {
|
|
|
|
TyKind::Path(None, ref path)
|
|
|
|
if !path.global && path.segments.len() == 1 &&
|
|
|
|
bound_pred.bound_lifetimes.is_empty() => {
|
|
|
|
if let Some(Def::TyParam(def_id)) =
|
|
|
|
self.resolver.get_resolution(bound_pred.bounded_ty.id)
|
|
|
|
.map(|d| d.base_def) {
|
|
|
|
if let Some(node_id) =
|
|
|
|
self.resolver.definitions().as_local_node_id(def_id) {
|
|
|
|
for ty_param in &g.ty_params {
|
|
|
|
if node_id == ty_param.id {
|
|
|
|
add_bounds.entry(ty_param.id).or_insert(Vec::new())
|
|
|
|
.push(bound.clone());
|
|
|
|
continue 'next_bound;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
report_error(self)
|
|
|
|
}
|
|
|
|
_ => report_error(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::Generics {
|
2016-10-22 00:33:36 +00:00
|
|
|
ty_params: self.lower_ty_params(&g.ty_params, &add_bounds),
|
2016-05-10 01:11:59 +00:00
|
|
|
lifetimes: self.lower_lifetime_defs(&g.lifetimes),
|
|
|
|
where_clause: self.lower_where_clause(&g.where_clause),
|
2016-08-10 17:39:12 +00:00
|
|
|
span: g.span,
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2015-09-20 11:00:18 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause {
|
|
|
|
hir::WhereClause {
|
|
|
|
id: wc.id,
|
|
|
|
predicates: wc.predicates
|
|
|
|
.iter()
|
|
|
|
.map(|predicate| self.lower_where_predicate(predicate))
|
|
|
|
.collect(),
|
|
|
|
}
|
2015-10-06 03:03:56 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate {
|
|
|
|
match *pred {
|
|
|
|
WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_lifetimes,
|
|
|
|
ref bounded_ty,
|
|
|
|
ref bounds,
|
|
|
|
span}) => {
|
|
|
|
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
|
|
|
|
bound_lifetimes: self.lower_lifetime_defs(bound_lifetimes),
|
|
|
|
bounded_ty: self.lower_ty(bounded_ty),
|
2016-10-22 00:33:36 +00:00
|
|
|
bounds: bounds.iter().filter_map(|bound| match *bound {
|
|
|
|
// Ignore `?Trait` bounds, they were copied into type parameters already.
|
|
|
|
TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
|
|
|
|
_ => Some(self.lower_ty_param_bound(bound))
|
|
|
|
}).collect(),
|
2016-05-10 01:11:59 +00:00
|
|
|
span: span,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
WherePredicate::RegionPredicate(WhereRegionPredicate{ ref lifetime,
|
|
|
|
ref bounds,
|
|
|
|
span}) => {
|
|
|
|
hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
|
|
|
|
span: span,
|
|
|
|
lifetime: self.lower_lifetime(lifetime),
|
|
|
|
bounds: bounds.iter().map(|bound| self.lower_lifetime(bound)).collect(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
WherePredicate::EqPredicate(WhereEqPredicate{ id,
|
|
|
|
ref path,
|
|
|
|
ref ty,
|
|
|
|
span}) => {
|
|
|
|
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
|
|
|
|
id: id,
|
2016-11-25 11:21:19 +00:00
|
|
|
path: self.lower_path(id, path, ParamMode::Explicit),
|
2016-05-10 01:11:59 +00:00
|
|
|
ty: self.lower_ty(ty),
|
|
|
|
span: span,
|
|
|
|
})
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
|
|
|
|
match *vdata {
|
|
|
|
VariantData::Struct(ref fields, id) => {
|
|
|
|
hir::VariantData::Struct(fields.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|f| self.lower_struct_field(f))
|
|
|
|
.collect(),
|
|
|
|
id)
|
|
|
|
}
|
|
|
|
VariantData::Tuple(ref fields, id) => {
|
|
|
|
hir::VariantData::Tuple(fields.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|f| self.lower_struct_field(f))
|
|
|
|
.collect(),
|
|
|
|
id)
|
|
|
|
}
|
|
|
|
VariantData::Unit(id) => hir::VariantData::Unit(id),
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
|
|
|
|
hir::TraitRef {
|
2016-11-25 11:21:19 +00:00
|
|
|
path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit),
|
2016-05-10 01:11:59 +00:00
|
|
|
ref_id: p.ref_id,
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn lower_poly_trait_ref(&mut self, p: &PolyTraitRef) -> hir::PolyTraitRef {
|
|
|
|
hir::PolyTraitRef {
|
|
|
|
bound_lifetimes: self.lower_lifetime_defs(&p.bound_lifetimes),
|
|
|
|
trait_ref: self.lower_trait_ref(&p.trait_ref),
|
|
|
|
span: p.span,
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField {
|
|
|
|
hir::StructField {
|
|
|
|
span: f.span,
|
|
|
|
id: f.id,
|
2016-11-16 08:21:52 +00:00
|
|
|
name: f.ident.map(|ident| ident.name).unwrap_or(Symbol::intern(&index.to_string())),
|
2016-05-10 01:11:59 +00:00
|
|
|
vis: self.lower_visibility(&f.vis),
|
|
|
|
ty: self.lower_ty(&f.ty),
|
|
|
|
attrs: self.lower_attrs(&f.attrs),
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_field(&mut self, f: &Field) -> hir::Field {
|
|
|
|
hir::Field {
|
|
|
|
name: respan(f.ident.span, f.ident.node.name),
|
2016-10-28 10:16:44 +00:00
|
|
|
expr: P(self.lower_expr(&f.expr)),
|
2016-05-10 01:11:59 +00:00
|
|
|
span: f.span,
|
2016-10-27 00:15:13 +00:00
|
|
|
is_shorthand: f.is_shorthand,
|
2016-04-17 22:30:55 +00:00
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_mt(&mut self, mt: &MutTy) -> hir::MutTy {
|
|
|
|
hir::MutTy {
|
|
|
|
ty: self.lower_ty(&mt.ty),
|
|
|
|
mutbl: self.lower_mutability(mt.mutbl),
|
2016-04-17 22:30:55 +00:00
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-10-22 00:33:36 +00:00
|
|
|
fn lower_bounds(&mut self, bounds: &[TyParamBound]) -> hir::TyParamBounds {
|
2016-05-10 01:11:59 +00:00
|
|
|
bounds.iter().map(|bound| self.lower_ty_param_bound(bound)).collect()
|
2015-11-17 22:32:12 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_block(&mut self, b: &Block) -> P<hir::Block> {
|
2016-06-23 09:51:18 +00:00
|
|
|
let mut expr = None;
|
|
|
|
|
2016-11-24 04:11:31 +00:00
|
|
|
let mut stmts = b.stmts.iter().flat_map(|s| self.lower_stmt(s)).collect::<Vec<_>>();
|
|
|
|
if let Some(last) = stmts.pop() {
|
2016-06-23 09:51:18 +00:00
|
|
|
if let hir::StmtExpr(e, _) = last.node {
|
|
|
|
expr = Some(e);
|
|
|
|
} else {
|
|
|
|
stmts.push(last);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
P(hir::Block {
|
|
|
|
id: b.id,
|
2016-06-23 09:51:18 +00:00
|
|
|
stmts: stmts.into(),
|
|
|
|
expr: expr,
|
2016-05-10 01:11:59 +00:00
|
|
|
rules: self.lower_block_check_mode(&b.rules),
|
|
|
|
span: b.span,
|
|
|
|
})
|
|
|
|
}
|
2015-11-17 22:32:12 +00:00
|
|
|
|
2016-11-24 04:11:31 +00:00
|
|
|
fn lower_item_kind(&mut self,
|
2016-11-25 11:21:19 +00:00
|
|
|
id: NodeId,
|
2016-11-24 04:11:31 +00:00
|
|
|
name: &mut Name,
|
|
|
|
attrs: &hir::HirVec<Attribute>,
|
|
|
|
vis: &mut hir::Visibility,
|
|
|
|
i: &ItemKind)
|
|
|
|
-> hir::Item_ {
|
2016-05-10 01:11:59 +00:00
|
|
|
match *i {
|
|
|
|
ItemKind::ExternCrate(string) => hir::ItemExternCrate(string),
|
|
|
|
ItemKind::Use(ref view_path) => {
|
2016-11-24 04:11:31 +00:00
|
|
|
let path = match view_path.node {
|
|
|
|
ViewPathSimple(_, ref path) => path,
|
|
|
|
ViewPathGlob(ref path) => path,
|
|
|
|
ViewPathList(ref path, ref path_list_idents) => {
|
|
|
|
for &Spanned { node: ref import, span } in path_list_idents {
|
|
|
|
// `use a::{self as x, b as y};` lowers to
|
|
|
|
// `use a as x; use a::b as y;`
|
|
|
|
let mut ident = import.name;
|
|
|
|
let suffix = if ident.name == keywords::SelfValue.name() {
|
|
|
|
if let Some(last) = path.segments.last() {
|
|
|
|
ident = last.identifier;
|
|
|
|
}
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(ident.name)
|
|
|
|
};
|
|
|
|
|
2016-11-25 11:21:19 +00:00
|
|
|
let mut path = self.lower_path_extra(import.id, path, suffix,
|
2016-11-24 04:11:31 +00:00
|
|
|
ParamMode::Explicit);
|
|
|
|
path.span = span;
|
|
|
|
self.items.insert(import.id, hir::Item {
|
|
|
|
id: import.id,
|
|
|
|
name: import.rename.unwrap_or(ident).name,
|
|
|
|
attrs: attrs.clone(),
|
|
|
|
node: hir::ItemUse(P(path), hir::UseKind::Single),
|
|
|
|
vis: vis.clone(),
|
|
|
|
span: span,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
path
|
|
|
|
}
|
|
|
|
};
|
2016-11-25 11:21:19 +00:00
|
|
|
let path = P(self.lower_path(id, path, ParamMode::Explicit));
|
2016-11-24 04:11:31 +00:00
|
|
|
let kind = match view_path.node {
|
|
|
|
ViewPathSimple(ident, _) => {
|
|
|
|
*name = ident.name;
|
|
|
|
hir::UseKind::Single
|
|
|
|
}
|
|
|
|
ViewPathGlob(_) => {
|
|
|
|
hir::UseKind::Glob
|
|
|
|
}
|
|
|
|
ViewPathList(..) => {
|
|
|
|
// Privatize the degenerate import base, used only to check
|
|
|
|
// the stability of `use a::{};`, to avoid it showing up as
|
|
|
|
// a reexport by accident when `pub`, e.g. in documentation.
|
|
|
|
*vis = hir::Inherited;
|
|
|
|
hir::UseKind::ListStem
|
|
|
|
}
|
|
|
|
};
|
|
|
|
hir::ItemUse(path, kind)
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ItemKind::Static(ref t, m, ref e) => {
|
|
|
|
hir::ItemStatic(self.lower_ty(t),
|
|
|
|
self.lower_mutability(m),
|
2016-10-28 10:16:44 +00:00
|
|
|
P(self.lower_expr(e)))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ItemKind::Const(ref t, ref e) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
hir::ItemConst(self.lower_ty(t), P(self.lower_expr(e)))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
|
2016-10-25 23:27:14 +00:00
|
|
|
let body = self.lower_block(body);
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::ItemFn(self.lower_fn_decl(decl),
|
|
|
|
self.lower_unsafety(unsafety),
|
|
|
|
self.lower_constness(constness),
|
|
|
|
abi,
|
|
|
|
self.lower_generics(generics),
|
2016-10-28 10:16:44 +00:00
|
|
|
P(self.expr_block(body, ThinVec::new())))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
|
|
|
|
ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
|
|
|
|
ItemKind::Ty(ref t, ref generics) => {
|
|
|
|
hir::ItemTy(self.lower_ty(t), self.lower_generics(generics))
|
|
|
|
}
|
|
|
|
ItemKind::Enum(ref enum_definition, ref generics) => {
|
|
|
|
hir::ItemEnum(hir::EnumDef {
|
|
|
|
variants: enum_definition.variants
|
|
|
|
.iter()
|
|
|
|
.map(|x| self.lower_variant(x))
|
|
|
|
.collect(),
|
|
|
|
},
|
|
|
|
self.lower_generics(generics))
|
|
|
|
}
|
|
|
|
ItemKind::Struct(ref struct_def, ref generics) => {
|
|
|
|
let struct_def = self.lower_variant_data(struct_def);
|
|
|
|
hir::ItemStruct(struct_def, self.lower_generics(generics))
|
|
|
|
}
|
2016-08-08 22:18:47 +00:00
|
|
|
ItemKind::Union(ref vdata, ref generics) => {
|
|
|
|
let vdata = self.lower_variant_data(vdata);
|
|
|
|
hir::ItemUnion(vdata, self.lower_generics(generics))
|
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
|
|
|
|
hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
|
|
|
|
self.lower_trait_ref(trait_ref))
|
|
|
|
}
|
|
|
|
ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
|
|
|
|
let new_impl_items = impl_items.iter()
|
2016-11-10 14:47:00 +00:00
|
|
|
.map(|item| self.lower_impl_item_ref(item))
|
2016-05-10 01:11:59 +00:00
|
|
|
.collect();
|
|
|
|
let ifce = ifce.as_ref().map(|trait_ref| self.lower_trait_ref(trait_ref));
|
|
|
|
hir::ItemImpl(self.lower_unsafety(unsafety),
|
|
|
|
self.lower_impl_polarity(polarity),
|
|
|
|
self.lower_generics(generics),
|
|
|
|
ifce,
|
|
|
|
self.lower_ty(ty),
|
|
|
|
new_impl_items)
|
|
|
|
}
|
|
|
|
ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => {
|
|
|
|
let bounds = self.lower_bounds(bounds);
|
|
|
|
let items = items.iter().map(|item| self.lower_trait_item(item)).collect();
|
|
|
|
hir::ItemTrait(self.lower_unsafety(unsafety),
|
|
|
|
self.lower_generics(generics),
|
|
|
|
bounds,
|
|
|
|
items)
|
|
|
|
}
|
|
|
|
ItemKind::Mac(_) => panic!("Shouldn't still be around"),
|
|
|
|
}
|
2015-10-06 03:03:56 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
|
|
|
|
self.with_parent_def(i.id, |this| {
|
|
|
|
hir::TraitItem {
|
|
|
|
id: i.id,
|
|
|
|
name: i.ident.name,
|
|
|
|
attrs: this.lower_attrs(&i.attrs),
|
|
|
|
node: match i.node {
|
|
|
|
TraitItemKind::Const(ref ty, ref default) => {
|
|
|
|
hir::ConstTraitItem(this.lower_ty(ty),
|
2016-10-28 10:16:44 +00:00
|
|
|
default.as_ref().map(|x| P(this.lower_expr(x))))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
TraitItemKind::Method(ref sig, ref body) => {
|
|
|
|
hir::MethodTraitItem(this.lower_method_sig(sig),
|
2016-10-25 23:27:14 +00:00
|
|
|
body.as_ref().map(|x| {
|
|
|
|
let body = this.lower_block(x);
|
2016-10-28 10:16:44 +00:00
|
|
|
P(this.expr_block(body, ThinVec::new()))
|
2016-10-25 23:27:14 +00:00
|
|
|
}))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
TraitItemKind::Type(ref bounds, ref default) => {
|
|
|
|
hir::TypeTraitItem(this.lower_bounds(bounds),
|
|
|
|
default.as_ref().map(|x| this.lower_ty(x)))
|
|
|
|
}
|
2016-06-11 01:00:07 +00:00
|
|
|
TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"),
|
2016-05-10 01:11:59 +00:00
|
|
|
},
|
|
|
|
span: i.span,
|
|
|
|
}
|
|
|
|
})
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
|
|
|
|
self.with_parent_def(i.id, |this| {
|
|
|
|
hir::ImplItem {
|
|
|
|
id: i.id,
|
|
|
|
name: i.ident.name,
|
|
|
|
attrs: this.lower_attrs(&i.attrs),
|
|
|
|
vis: this.lower_visibility(&i.vis),
|
2016-11-14 16:00:02 +00:00
|
|
|
defaultness: this.lower_defaultness(i.defaultness, true /* [1] */),
|
2016-05-10 01:11:59 +00:00
|
|
|
node: match i.node {
|
|
|
|
ImplItemKind::Const(ref ty, ref expr) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
hir::ImplItemKind::Const(this.lower_ty(ty), P(this.lower_expr(expr)))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ImplItemKind::Method(ref sig, ref body) => {
|
2016-10-25 23:27:14 +00:00
|
|
|
let body = this.lower_block(body);
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::ImplItemKind::Method(this.lower_method_sig(sig),
|
2016-10-28 10:16:44 +00:00
|
|
|
P(this.expr_block(body, ThinVec::new())))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)),
|
|
|
|
ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
|
|
|
|
},
|
|
|
|
span: i.span,
|
|
|
|
}
|
|
|
|
})
|
2016-11-14 16:00:02 +00:00
|
|
|
|
|
|
|
// [1] since `default impl` is not yet implemented, this is always true in impls
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-11-10 14:47:00 +00:00
|
|
|
fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
|
|
|
|
hir::ImplItemRef {
|
|
|
|
id: hir::ImplItemId { node_id: i.id },
|
|
|
|
name: i.ident.name,
|
|
|
|
span: i.span,
|
|
|
|
vis: self.lower_visibility(&i.vis),
|
2016-11-14 16:00:02 +00:00
|
|
|
defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
|
2016-11-10 14:47:00 +00:00
|
|
|
kind: match i.node {
|
|
|
|
ImplItemKind::Const(..) => hir::AssociatedItemKind::Const,
|
|
|
|
ImplItemKind::Type(..) => hir::AssociatedItemKind::Type,
|
|
|
|
ImplItemKind::Method(ref sig, _) => hir::AssociatedItemKind::Method {
|
|
|
|
has_self: sig.decl.get_self().is_some(),
|
|
|
|
},
|
|
|
|
ImplItemKind::Macro(..) => unimplemented!(),
|
|
|
|
},
|
|
|
|
}
|
2016-11-14 16:00:02 +00:00
|
|
|
|
|
|
|
// [1] since `default impl` is not yet implemented, this is always true in impls
|
2016-11-02 22:25:31 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
|
|
|
|
hir::Mod {
|
|
|
|
inner: m.inner,
|
2016-11-24 04:11:31 +00:00
|
|
|
item_ids: m.items.iter().flat_map(|x| self.lower_item_id(x)).collect(),
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_macro_def(&mut self, m: &MacroDef) -> hir::MacroDef {
|
|
|
|
hir::MacroDef {
|
|
|
|
name: m.ident.name,
|
|
|
|
attrs: self.lower_attrs(&m.attrs),
|
|
|
|
id: m.id,
|
|
|
|
span: m.span,
|
|
|
|
imported_from: m.imported_from.map(|x| x.name),
|
|
|
|
allow_internal_unstable: m.allow_internal_unstable,
|
|
|
|
body: m.body.clone().into(),
|
|
|
|
}
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-11-24 04:11:31 +00:00
|
|
|
fn lower_item_id(&mut self, i: &Item) -> SmallVector<hir::ItemId> {
|
|
|
|
if let ItemKind::Use(ref view_path) = i.node {
|
|
|
|
if let ViewPathList(_, ref imports) = view_path.node {
|
|
|
|
return iter::once(i.id).chain(imports.iter().map(|import| import.node.id))
|
|
|
|
.map(|id| hir::ItemId { id: id }).collect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SmallVector::one(hir::ItemId { id: i.id })
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
pub fn lower_item(&mut self, i: &Item) -> hir::Item {
|
2016-11-24 04:11:31 +00:00
|
|
|
let mut name = i.ident.name;
|
|
|
|
let attrs = self.lower_attrs(&i.attrs);
|
|
|
|
let mut vis = self.lower_visibility(&i.vis);
|
2016-05-10 01:11:59 +00:00
|
|
|
let node = self.with_parent_def(i.id, |this| {
|
2016-11-25 11:21:19 +00:00
|
|
|
this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node)
|
2016-05-10 01:11:59 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
hir::Item {
|
2016-04-17 22:30:55 +00:00
|
|
|
id: i.id,
|
2016-11-24 04:11:31 +00:00
|
|
|
name: name,
|
|
|
|
attrs: attrs,
|
2016-05-10 01:11:59 +00:00
|
|
|
node: node,
|
2016-11-24 04:11:31 +00:00
|
|
|
vis: vis,
|
2016-04-17 22:30:55 +00:00
|
|
|
span: i.span,
|
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
|
|
|
|
self.with_parent_def(i.id, |this| {
|
|
|
|
hir::ForeignItem {
|
|
|
|
id: i.id,
|
|
|
|
name: i.ident.name,
|
|
|
|
attrs: this.lower_attrs(&i.attrs),
|
|
|
|
node: match i.node {
|
|
|
|
ForeignItemKind::Fn(ref fdec, ref generics) => {
|
|
|
|
hir::ForeignItemFn(this.lower_fn_decl(fdec), this.lower_generics(generics))
|
|
|
|
}
|
|
|
|
ForeignItemKind::Static(ref t, m) => {
|
|
|
|
hir::ForeignItemStatic(this.lower_ty(t), m)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
vis: this.lower_visibility(&i.vis),
|
|
|
|
span: i.span,
|
|
|
|
}
|
|
|
|
})
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig {
|
2016-03-06 12:54:44 +00:00
|
|
|
let hir_sig = hir::MethodSig {
|
2016-05-10 01:11:59 +00:00
|
|
|
generics: self.lower_generics(&sig.generics),
|
|
|
|
abi: sig.abi,
|
|
|
|
unsafety: self.lower_unsafety(sig.unsafety),
|
|
|
|
constness: self.lower_constness(sig.constness),
|
|
|
|
decl: self.lower_fn_decl(&sig.decl),
|
2016-03-06 12:54:44 +00:00
|
|
|
};
|
2016-05-08 18:19:29 +00:00
|
|
|
// Check for `self: _` and `self: &_`
|
2016-03-06 12:54:44 +00:00
|
|
|
if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) {
|
|
|
|
match hir_sig.decl.get_self().map(|eself| eself.node) {
|
|
|
|
Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => {
|
2016-06-22 01:16:56 +00:00
|
|
|
self.diagnostic().span_err(sig.decl.inputs[0].ty.span,
|
2016-05-08 18:19:29 +00:00
|
|
|
"the type placeholder `_` is not allowed within types on item signatures");
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-03-06 12:54:44 +00:00
|
|
|
hir_sig
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
|
|
|
|
match u {
|
|
|
|
Unsafety::Unsafe => hir::Unsafety::Unsafe,
|
|
|
|
Unsafety::Normal => hir::Unsafety::Normal,
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-08-10 23:20:12 +00:00
|
|
|
fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
|
|
|
|
match c.node {
|
2016-05-10 01:11:59 +00:00
|
|
|
Constness::Const => hir::Constness::Const,
|
|
|
|
Constness::NotConst => hir::Constness::NotConst,
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
|
|
|
|
match u {
|
|
|
|
UnOp::Deref => hir::UnDeref,
|
|
|
|
UnOp::Not => hir::UnNot,
|
|
|
|
UnOp::Neg => hir::UnNeg,
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
|
|
|
|
Spanned {
|
|
|
|
node: match b.node {
|
|
|
|
BinOpKind::Add => hir::BiAdd,
|
|
|
|
BinOpKind::Sub => hir::BiSub,
|
|
|
|
BinOpKind::Mul => hir::BiMul,
|
|
|
|
BinOpKind::Div => hir::BiDiv,
|
|
|
|
BinOpKind::Rem => hir::BiRem,
|
|
|
|
BinOpKind::And => hir::BiAnd,
|
|
|
|
BinOpKind::Or => hir::BiOr,
|
|
|
|
BinOpKind::BitXor => hir::BiBitXor,
|
|
|
|
BinOpKind::BitAnd => hir::BiBitAnd,
|
|
|
|
BinOpKind::BitOr => hir::BiBitOr,
|
|
|
|
BinOpKind::Shl => hir::BiShl,
|
|
|
|
BinOpKind::Shr => hir::BiShr,
|
|
|
|
BinOpKind::Eq => hir::BiEq,
|
|
|
|
BinOpKind::Lt => hir::BiLt,
|
|
|
|
BinOpKind::Le => hir::BiLe,
|
|
|
|
BinOpKind::Ne => hir::BiNe,
|
|
|
|
BinOpKind::Ge => hir::BiGe,
|
|
|
|
BinOpKind::Gt => hir::BiGt,
|
|
|
|
},
|
|
|
|
span: b.span,
|
|
|
|
}
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
|
|
|
|
P(hir::Pat {
|
|
|
|
id: p.id,
|
|
|
|
node: match p.node {
|
|
|
|
PatKind::Wild => hir::PatKind::Wild,
|
|
|
|
PatKind::Ident(ref binding_mode, pth1, ref sub) => {
|
|
|
|
self.with_parent_def(p.id, |this| {
|
2016-06-03 20:15:00 +00:00
|
|
|
match this.resolver.get_resolution(p.id).map(|d| d.base_def) {
|
2016-03-06 12:54:44 +00:00
|
|
|
// `None` can occur in body-less function signatures
|
2016-11-25 11:21:19 +00:00
|
|
|
def @ None | def @ Some(Def::Local(_)) => {
|
|
|
|
let def_id = def.map(|d| d.def_id()).unwrap_or_else(|| {
|
|
|
|
this.resolver.definitions().local_def_id(p.id)
|
|
|
|
});
|
2016-03-06 12:54:44 +00:00
|
|
|
hir::PatKind::Binding(this.lower_binding_mode(binding_mode),
|
2016-11-25 11:21:19 +00:00
|
|
|
def_id,
|
2016-06-10 21:12:39 +00:00
|
|
|
respan(pth1.span, pth1.node.name),
|
2016-03-06 12:54:44 +00:00
|
|
|
sub.as_ref().map(|x| this.lower_pat(x)))
|
|
|
|
}
|
2016-11-25 11:21:19 +00:00
|
|
|
Some(def) => {
|
|
|
|
hir::PatKind::Path(hir::QPath::Resolved(None, P(hir::Path {
|
|
|
|
span: pth1.span,
|
|
|
|
global: false,
|
|
|
|
def: def,
|
|
|
|
segments: hir_vec![
|
|
|
|
hir::PathSegment::from_name(pth1.node.name)
|
|
|
|
],
|
|
|
|
})))
|
2016-10-27 02:17:42 +00:00
|
|
|
}
|
2016-03-06 12:54:44 +00:00
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
})
|
|
|
|
}
|
2016-10-28 10:16:44 +00:00
|
|
|
PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
|
2016-09-14 21:51:46 +00:00
|
|
|
PatKind::TupleStruct(ref path, ref pats, ddpos) => {
|
2016-10-27 02:17:42 +00:00
|
|
|
let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);
|
|
|
|
hir::PatKind::TupleStruct(qpath,
|
2016-10-17 03:02:23 +00:00
|
|
|
pats.iter().map(|x| self.lower_pat(x)).collect(),
|
|
|
|
ddpos)
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-10-17 03:02:23 +00:00
|
|
|
PatKind::Path(ref qself, ref path) => {
|
2016-10-27 02:17:42 +00:00
|
|
|
hir::PatKind::Path(self.lower_qpath(p.id, qself, path, ParamMode::Optional))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-10-27 02:17:42 +00:00
|
|
|
PatKind::Struct(ref path, ref fields, etc) => {
|
|
|
|
let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional);
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
let fs = fields.iter()
|
|
|
|
.map(|f| {
|
|
|
|
Spanned {
|
|
|
|
span: f.span,
|
|
|
|
node: hir::FieldPat {
|
|
|
|
name: f.node.ident.name,
|
|
|
|
pat: self.lower_pat(&f.node.pat),
|
|
|
|
is_shorthand: f.node.is_shorthand,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect();
|
2016-10-27 02:17:42 +00:00
|
|
|
hir::PatKind::Struct(qpath, fs, etc)
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-03-06 12:54:44 +00:00
|
|
|
PatKind::Tuple(ref elts, ddpos) => {
|
|
|
|
hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
|
|
|
|
PatKind::Ref(ref inner, mutbl) => {
|
|
|
|
hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl))
|
|
|
|
}
|
|
|
|
PatKind::Range(ref e1, ref e2) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
hir::PatKind::Range(P(self.lower_expr(e1)), P(self.lower_expr(e2)))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-09-20 14:54:24 +00:00
|
|
|
PatKind::Slice(ref before, ref slice, ref after) => {
|
2016-09-20 00:14:46 +00:00
|
|
|
hir::PatKind::Slice(before.iter().map(|x| self.lower_pat(x)).collect(),
|
2016-05-10 01:11:59 +00:00
|
|
|
slice.as_ref().map(|x| self.lower_pat(x)),
|
|
|
|
after.iter().map(|x| self.lower_pat(x)).collect())
|
|
|
|
}
|
|
|
|
PatKind::Mac(_) => panic!("Shouldn't exist here"),
|
|
|
|
},
|
|
|
|
span: p.span,
|
|
|
|
})
|
|
|
|
}
|
2015-10-06 03:03:56 +00:00
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
|
|
|
|
hir::Expr {
|
2016-05-10 01:11:59 +00:00
|
|
|
id: e.id,
|
|
|
|
node: match e.node {
|
|
|
|
// Issue #22181:
|
|
|
|
// Eventually a desugaring for `box EXPR`
|
|
|
|
// (similar to the desugaring above for `in PLACE BLOCK`)
|
|
|
|
// should go here, desugaring
|
|
|
|
//
|
2015-09-29 00:46:01 +00:00
|
|
|
// to:
|
|
|
|
//
|
2016-05-10 01:11:59 +00:00
|
|
|
// let mut place = BoxPlace::make_place();
|
2015-09-29 00:46:01 +00:00
|
|
|
// let raw_place = Place::pointer(&mut place);
|
2016-05-10 01:11:59 +00:00
|
|
|
// let value = $value;
|
|
|
|
// unsafe {
|
|
|
|
// ::std::ptr::write(raw_place, value);
|
|
|
|
// Boxed::finalize(place)
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// But for now there are type-inference issues doing that.
|
|
|
|
ExprKind::Box(ref e) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
hir::ExprBox(P(self.lower_expr(e)))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2015-10-06 03:03:56 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// Desugar ExprBox: `in (PLACE) EXPR`
|
|
|
|
ExprKind::InPlace(ref placer, ref value_expr) => {
|
|
|
|
// to:
|
|
|
|
//
|
|
|
|
// let p = PLACE;
|
|
|
|
// let mut place = Placer::make_place(p);
|
|
|
|
// let raw_place = Place::pointer(&mut place);
|
|
|
|
// push_unsafe!({
|
|
|
|
// std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
|
|
|
|
// InPlace::finalize(place)
|
|
|
|
// })
|
2016-10-28 10:16:44 +00:00
|
|
|
let placer_expr = P(self.lower_expr(placer));
|
|
|
|
let value_expr = P(self.lower_expr(value_expr));
|
2016-05-10 01:11:59 +00:00
|
|
|
|
|
|
|
let placer_ident = self.str_to_ident("placer");
|
|
|
|
let place_ident = self.str_to_ident("place");
|
|
|
|
let p_ptr_ident = self.str_to_ident("p_ptr");
|
|
|
|
|
|
|
|
let make_place = ["ops", "Placer", "make_place"];
|
|
|
|
let place_pointer = ["ops", "Place", "pointer"];
|
|
|
|
let move_val_init = ["intrinsics", "move_val_init"];
|
|
|
|
let inplace_finalize = ["ops", "InPlace", "finalize"];
|
|
|
|
|
2016-10-30 00:42:12 +00:00
|
|
|
let unstable_span = self.allow_internal_unstable("<-", e.span);
|
2016-05-10 01:11:59 +00:00
|
|
|
let make_call = |this: &mut LoweringContext, p, args| {
|
2016-10-30 00:42:12 +00:00
|
|
|
let path = P(this.expr_std_path(unstable_span, p, ThinVec::new()));
|
2016-10-28 10:16:44 +00:00
|
|
|
P(this.expr_call(e.span, path, args))
|
2016-05-10 01:11:59 +00:00
|
|
|
};
|
2015-09-28 04:24:42 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
let mk_stmt_let = |this: &mut LoweringContext, bind, expr| {
|
2016-06-18 04:01:57 +00:00
|
|
|
this.stmt_let(e.span, false, bind, expr)
|
2016-01-13 06:24:34 +00:00
|
|
|
};
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
let mk_stmt_let_mut = |this: &mut LoweringContext, bind, expr| {
|
2016-06-18 04:01:57 +00:00
|
|
|
this.stmt_let(e.span, true, bind, expr)
|
2016-05-10 01:11:59 +00:00
|
|
|
};
|
2016-01-13 06:24:34 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// let placer = <placer_expr> ;
|
|
|
|
let (s1, placer_binding) = {
|
|
|
|
mk_stmt_let(self, placer_ident, placer_expr)
|
|
|
|
};
|
2016-01-13 06:24:34 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// let mut place = Placer::make_place(placer);
|
|
|
|
let (s2, place_binding) = {
|
2016-06-18 04:01:57 +00:00
|
|
|
let placer = self.expr_ident(e.span, placer_ident, placer_binding);
|
2016-05-10 01:11:59 +00:00
|
|
|
let call = make_call(self, &make_place, hir_vec![placer]);
|
|
|
|
mk_stmt_let_mut(self, place_ident, call)
|
|
|
|
};
|
2016-01-13 06:24:34 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// let p_ptr = Place::pointer(&mut place);
|
|
|
|
let (s3, p_ptr_binding) = {
|
2016-10-28 10:16:44 +00:00
|
|
|
let agent = P(self.expr_ident(e.span, place_ident, place_binding));
|
2016-06-18 04:01:57 +00:00
|
|
|
let args = hir_vec![self.expr_mut_addr_of(e.span, agent)];
|
2016-05-10 01:11:59 +00:00
|
|
|
let call = make_call(self, &place_pointer, args);
|
|
|
|
mk_stmt_let(self, p_ptr_ident, call)
|
|
|
|
};
|
2016-01-13 06:24:34 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// pop_unsafe!(EXPR));
|
|
|
|
let pop_unsafe_expr = {
|
2016-05-10 01:15:11 +00:00
|
|
|
self.signal_block_expr(hir_vec![],
|
|
|
|
value_expr,
|
|
|
|
e.span,
|
2016-06-18 04:01:57 +00:00
|
|
|
hir::PopUnsafeBlock(hir::CompilerGenerated),
|
|
|
|
ThinVec::new())
|
2016-05-10 01:11:59 +00:00
|
|
|
};
|
2016-01-13 06:24:34 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// push_unsafe!({
|
|
|
|
// std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
|
|
|
|
// InPlace::finalize(place)
|
|
|
|
// })
|
|
|
|
let expr = {
|
2016-06-18 04:01:57 +00:00
|
|
|
let ptr = self.expr_ident(e.span, p_ptr_ident, p_ptr_binding);
|
2016-05-10 01:11:59 +00:00
|
|
|
let call_move_val_init =
|
|
|
|
hir::StmtSemi(
|
|
|
|
make_call(self, &move_val_init, hir_vec![ptr, pop_unsafe_expr]),
|
|
|
|
self.next_id());
|
|
|
|
let call_move_val_init = respan(e.span, call_move_val_init);
|
|
|
|
|
2016-06-18 04:01:57 +00:00
|
|
|
let place = self.expr_ident(e.span, place_ident, place_binding);
|
2016-05-10 01:11:59 +00:00
|
|
|
let call = make_call(self, &inplace_finalize, hir_vec![place]);
|
2016-10-28 10:16:44 +00:00
|
|
|
P(self.signal_block_expr(hir_vec![call_move_val_init],
|
|
|
|
call,
|
|
|
|
e.span,
|
|
|
|
hir::PushUnsafeBlock(hir::CompilerGenerated),
|
|
|
|
ThinVec::new()))
|
2016-05-10 01:11:59 +00:00
|
|
|
};
|
2016-01-13 06:24:34 +00:00
|
|
|
|
2016-10-30 00:42:12 +00:00
|
|
|
let block = self.block_all(e.span, hir_vec![s1, s2, s3], Some(expr));
|
|
|
|
// add the attributes to the outer returned expr node
|
|
|
|
return self.expr_block(P(block), e.attrs.clone());
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-01-13 06:24:34 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
ExprKind::Vec(ref exprs) => {
|
2016-09-20 00:14:46 +00:00
|
|
|
hir::ExprArray(exprs.iter().map(|x| self.lower_expr(x)).collect())
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ExprKind::Repeat(ref expr, ref count) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
let expr = P(self.lower_expr(expr));
|
|
|
|
let count = P(self.lower_expr(count));
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::ExprRepeat(expr, count)
|
|
|
|
}
|
|
|
|
ExprKind::Tup(ref elts) => {
|
|
|
|
hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect())
|
|
|
|
}
|
|
|
|
ExprKind::Call(ref f, ref args) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
let f = P(self.lower_expr(f));
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
|
|
|
|
}
|
|
|
|
ExprKind::MethodCall(i, ref tps, ref args) => {
|
|
|
|
let tps = tps.iter().map(|x| self.lower_ty(x)).collect();
|
|
|
|
let args = args.iter().map(|x| self.lower_expr(x)).collect();
|
|
|
|
hir::ExprMethodCall(respan(i.span, i.node.name), tps, args)
|
|
|
|
}
|
|
|
|
ExprKind::Binary(binop, ref lhs, ref rhs) => {
|
|
|
|
let binop = self.lower_binop(binop);
|
2016-10-28 10:16:44 +00:00
|
|
|
let lhs = P(self.lower_expr(lhs));
|
|
|
|
let rhs = P(self.lower_expr(rhs));
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::ExprBinary(binop, lhs, rhs)
|
|
|
|
}
|
|
|
|
ExprKind::Unary(op, ref ohs) => {
|
|
|
|
let op = self.lower_unop(op);
|
2016-10-28 10:16:44 +00:00
|
|
|
let ohs = P(self.lower_expr(ohs));
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::ExprUnary(op, ohs)
|
|
|
|
}
|
|
|
|
ExprKind::Lit(ref l) => hir::ExprLit(P((**l).clone())),
|
|
|
|
ExprKind::Cast(ref expr, ref ty) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
let expr = P(self.lower_expr(expr));
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::ExprCast(expr, self.lower_ty(ty))
|
|
|
|
}
|
|
|
|
ExprKind::Type(ref expr, ref ty) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
let expr = P(self.lower_expr(expr));
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::ExprType(expr, self.lower_ty(ty))
|
|
|
|
}
|
|
|
|
ExprKind::AddrOf(m, ref ohs) => {
|
|
|
|
let m = self.lower_mutability(m);
|
2016-10-28 10:16:44 +00:00
|
|
|
let ohs = P(self.lower_expr(ohs));
|
2016-05-10 01:11:59 +00:00
|
|
|
hir::ExprAddrOf(m, ohs)
|
|
|
|
}
|
|
|
|
// More complicated than you might expect because the else branch
|
|
|
|
// might be `if let`.
|
|
|
|
ExprKind::If(ref cond, ref blk, ref else_opt) => {
|
|
|
|
let else_opt = else_opt.as_ref().map(|els| {
|
|
|
|
match els.node {
|
|
|
|
ExprKind::IfLet(..) => {
|
|
|
|
// wrap the if-let expr in a block
|
|
|
|
let span = els.span;
|
2016-10-28 10:16:44 +00:00
|
|
|
let els = P(self.lower_expr(els));
|
2016-05-10 01:11:59 +00:00
|
|
|
let id = self.next_id();
|
|
|
|
let blk = P(hir::Block {
|
|
|
|
stmts: hir_vec![],
|
|
|
|
expr: Some(els),
|
|
|
|
id: id,
|
|
|
|
rules: hir::DefaultBlock,
|
|
|
|
span: span,
|
|
|
|
});
|
2016-10-28 10:16:44 +00:00
|
|
|
P(self.expr_block(blk, ThinVec::new()))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-10-28 10:16:44 +00:00
|
|
|
_ => P(self.lower_expr(els)),
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
});
|
2016-01-13 06:24:34 +00:00
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
hir::ExprIf(P(self.lower_expr(cond)), self.lower_block(blk), else_opt)
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ExprKind::While(ref cond, ref body, opt_ident) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
hir::ExprWhile(P(self.lower_expr(cond)), self.lower_block(body),
|
2016-05-02 16:22:03 +00:00
|
|
|
self.lower_opt_sp_ident(opt_ident))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ExprKind::Loop(ref body, opt_ident) => {
|
Implement the `loop_break_value` feature.
This implements RFC 1624, tracking issue #37339.
- `FnCtxt` (in typeck) gets a stack of `LoopCtxt`s, which store the
currently deduced type of that loop, the desired type, and a list of
break expressions currently seen. `loop` loops get a fresh type
variable as their initial type (this logic is stolen from that for
arrays). `while` loops get `()`.
- `break {expr}` looks up the broken loop, and unifies the type of
`expr` with the type of the loop.
- `break` with no expr unifies the loop's type with `()`.
- When building MIR, `loop` loops no longer construct a `()` value at
termination of the loop; rather, the `break` expression assigns the
result of the loop. `while` loops are unchanged.
- `break` respects contexts in which expressions may not end with braced
blocks. That is, `while break { break-value } { while-body }` is
illegal; this preserves backwards compatibility.
- The RFC did not make it clear, but I chose to make `break ()` inside
of a `while` loop illegal, just in case we wanted to do anything with
that design space in the future.
This is my first time dealing with this part of rustc so I'm sure
there's plenty of problems to pick on here ^_^
2016-10-29 22:15:06 +00:00
|
|
|
hir::ExprLoop(self.lower_block(body),
|
|
|
|
self.lower_opt_sp_ident(opt_ident),
|
|
|
|
hir::LoopSource::Loop)
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ExprKind::Match(ref expr, ref arms) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
hir::ExprMatch(P(self.lower_expr(expr)),
|
2016-05-10 01:11:59 +00:00
|
|
|
arms.iter().map(|x| self.lower_arm(x)).collect(),
|
|
|
|
hir::MatchSource::Normal)
|
|
|
|
}
|
|
|
|
ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => {
|
|
|
|
self.with_parent_def(e.id, |this| {
|
|
|
|
hir::ExprClosure(this.lower_capture_clause(capture_clause),
|
|
|
|
this.lower_fn_decl(decl),
|
2016-10-28 10:16:44 +00:00
|
|
|
P(this.lower_expr(body)),
|
2016-05-10 01:11:59 +00:00
|
|
|
fn_decl_span)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk)),
|
|
|
|
ExprKind::Assign(ref el, ref er) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
hir::ExprAssign(P(self.lower_expr(el)), P(self.lower_expr(er)))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ExprKind::AssignOp(op, ref el, ref er) => {
|
|
|
|
hir::ExprAssignOp(self.lower_binop(op),
|
2016-10-28 10:16:44 +00:00
|
|
|
P(self.lower_expr(el)),
|
|
|
|
P(self.lower_expr(er)))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ExprKind::Field(ref el, ident) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
hir::ExprField(P(self.lower_expr(el)), respan(ident.span, ident.node.name))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ExprKind::TupField(ref el, ident) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
hir::ExprTupField(P(self.lower_expr(el)), ident)
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ExprKind::Index(ref el, ref er) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er)))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ExprKind::Range(ref e1, ref e2, lims) => {
|
|
|
|
fn make_struct(this: &mut LoweringContext,
|
|
|
|
ast_expr: &Expr,
|
|
|
|
path: &[&str],
|
2016-10-28 10:16:44 +00:00
|
|
|
fields: &[(&str, &P<Expr>)]) -> hir::Expr {
|
2016-11-25 11:21:19 +00:00
|
|
|
let struct_path = &iter::once(&"ops").chain(path).map(|s| *s)
|
|
|
|
.collect::<Vec<_>>();
|
2016-10-30 00:42:12 +00:00
|
|
|
let unstable_span = this.allow_internal_unstable("...", ast_expr.span);
|
2016-05-10 01:11:59 +00:00
|
|
|
|
2016-10-30 00:42:12 +00:00
|
|
|
if fields.len() == 0 {
|
|
|
|
this.expr_std_path(unstable_span, struct_path,
|
2016-11-25 11:21:19 +00:00
|
|
|
ast_expr.attrs.clone())
|
2016-05-10 01:11:59 +00:00
|
|
|
} else {
|
|
|
|
let fields = fields.into_iter().map(|&(s, e)| {
|
2016-10-28 10:16:44 +00:00
|
|
|
let expr = P(this.lower_expr(&e));
|
2016-11-10 17:08:21 +00:00
|
|
|
let unstable_span = this.allow_internal_unstable("...", e.span);
|
|
|
|
this.field(Symbol::intern(s), expr, unstable_span)
|
2016-05-10 01:11:59 +00:00
|
|
|
}).collect();
|
|
|
|
let attrs = ast_expr.attrs.clone();
|
|
|
|
|
2016-10-30 00:42:12 +00:00
|
|
|
this.expr_std_struct(unstable_span, struct_path, fields, None, attrs)
|
|
|
|
}
|
2015-10-06 03:03:56 +00:00
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
|
|
|
|
use syntax::ast::RangeLimits::*;
|
|
|
|
|
|
|
|
return match (e1, e2, lims) {
|
|
|
|
(&None, &None, HalfOpen) =>
|
2016-05-10 01:15:11 +00:00
|
|
|
make_struct(self, e, &["RangeFull"], &[]),
|
2016-05-10 01:11:59 +00:00
|
|
|
|
|
|
|
(&Some(ref e1), &None, HalfOpen) =>
|
|
|
|
make_struct(self, e, &["RangeFrom"],
|
|
|
|
&[("start", e1)]),
|
|
|
|
|
|
|
|
(&None, &Some(ref e2), HalfOpen) =>
|
|
|
|
make_struct(self, e, &["RangeTo"],
|
|
|
|
&[("end", e2)]),
|
|
|
|
|
|
|
|
(&Some(ref e1), &Some(ref e2), HalfOpen) =>
|
|
|
|
make_struct(self, e, &["Range"],
|
|
|
|
&[("start", e1), ("end", e2)]),
|
|
|
|
|
|
|
|
(&None, &Some(ref e2), Closed) =>
|
|
|
|
make_struct(self, e, &["RangeToInclusive"],
|
|
|
|
&[("end", e2)]),
|
|
|
|
|
|
|
|
(&Some(ref e1), &Some(ref e2), Closed) =>
|
|
|
|
make_struct(self, e, &["RangeInclusive", "NonEmpty"],
|
|
|
|
&[("start", e1), ("end", e2)]),
|
|
|
|
|
2016-06-22 01:16:56 +00:00
|
|
|
_ => panic!(self.diagnostic()
|
2016-05-10 01:11:59 +00:00
|
|
|
.span_fatal(e.span, "inclusive range with no end")),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
ExprKind::Path(ref qself, ref path) => {
|
2016-10-27 02:17:42 +00:00
|
|
|
hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
Implement the `loop_break_value` feature.
This implements RFC 1624, tracking issue #37339.
- `FnCtxt` (in typeck) gets a stack of `LoopCtxt`s, which store the
currently deduced type of that loop, the desired type, and a list of
break expressions currently seen. `loop` loops get a fresh type
variable as their initial type (this logic is stolen from that for
arrays). `while` loops get `()`.
- `break {expr}` looks up the broken loop, and unifies the type of
`expr` with the type of the loop.
- `break` with no expr unifies the loop's type with `()`.
- When building MIR, `loop` loops no longer construct a `()` value at
termination of the loop; rather, the `break` expression assigns the
result of the loop. `while` loops are unchanged.
- `break` respects contexts in which expressions may not end with braced
blocks. That is, `while break { break-value } { while-body }` is
illegal; this preserves backwards compatibility.
- The RFC did not make it clear, but I chose to make `break ()` inside
of a `while` loop illegal, just in case we wanted to do anything with
that design space in the future.
This is my first time dealing with this part of rustc so I'm sure
there's plenty of problems to pick on here ^_^
2016-10-29 22:15:06 +00:00
|
|
|
ExprKind::Break(opt_ident, ref opt_expr) => {
|
2016-11-25 11:21:19 +00:00
|
|
|
hir::ExprBreak(self.lower_label(e.id, opt_ident),
|
Implement the `loop_break_value` feature.
This implements RFC 1624, tracking issue #37339.
- `FnCtxt` (in typeck) gets a stack of `LoopCtxt`s, which store the
currently deduced type of that loop, the desired type, and a list of
break expressions currently seen. `loop` loops get a fresh type
variable as their initial type (this logic is stolen from that for
arrays). `while` loops get `()`.
- `break {expr}` looks up the broken loop, and unifies the type of
`expr` with the type of the loop.
- `break` with no expr unifies the loop's type with `()`.
- When building MIR, `loop` loops no longer construct a `()` value at
termination of the loop; rather, the `break` expression assigns the
result of the loop. `while` loops are unchanged.
- `break` respects contexts in which expressions may not end with braced
blocks. That is, `while break { break-value } { while-body }` is
illegal; this preserves backwards compatibility.
- The RFC did not make it clear, but I chose to make `break ()` inside
of a `while` loop illegal, just in case we wanted to do anything with
that design space in the future.
This is my first time dealing with this part of rustc so I'm sure
there's plenty of problems to pick on here ^_^
2016-10-29 22:15:06 +00:00
|
|
|
opt_expr.as_ref().map(|x| P(self.lower_expr(x))))
|
|
|
|
}
|
2016-11-25 11:21:19 +00:00
|
|
|
ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_label(e.id, opt_ident)),
|
2016-10-28 10:16:44 +00:00
|
|
|
ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| P(self.lower_expr(x)))),
|
2016-11-03 08:38:17 +00:00
|
|
|
ExprKind::InlineAsm(ref asm) => {
|
|
|
|
let hir_asm = hir::InlineAsm {
|
|
|
|
inputs: asm.inputs.iter().map(|&(ref c, _)| c.clone()).collect(),
|
|
|
|
outputs: asm.outputs.iter().map(|out| {
|
|
|
|
hir::InlineAsmOutput {
|
|
|
|
constraint: out.constraint.clone(),
|
|
|
|
is_rw: out.is_rw,
|
|
|
|
is_indirect: out.is_indirect,
|
|
|
|
}
|
|
|
|
}).collect(),
|
|
|
|
asm: asm.asm.clone(),
|
|
|
|
asm_str_style: asm.asm_str_style,
|
|
|
|
clobbers: asm.clobbers.clone().into(),
|
|
|
|
volatile: asm.volatile,
|
|
|
|
alignstack: asm.alignstack,
|
|
|
|
dialect: asm.dialect,
|
|
|
|
expn_id: asm.expn_id,
|
|
|
|
};
|
|
|
|
let outputs =
|
|
|
|
asm.outputs.iter().map(|out| self.lower_expr(&out.expr)).collect();
|
|
|
|
let inputs =
|
|
|
|
asm.inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect();
|
|
|
|
hir::ExprInlineAsm(P(hir_asm), outputs, inputs)
|
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
ExprKind::Struct(ref path, ref fields, ref maybe_expr) => {
|
2016-10-27 02:17:42 +00:00
|
|
|
hir::ExprStruct(self.lower_qpath(e.id, &None, path, ParamMode::Optional),
|
2016-05-10 01:11:59 +00:00
|
|
|
fields.iter().map(|x| self.lower_field(x)).collect(),
|
2016-10-28 10:16:44 +00:00
|
|
|
maybe_expr.as_ref().map(|x| P(self.lower_expr(x))))
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
ExprKind::Paren(ref ex) => {
|
2016-10-28 10:16:44 +00:00
|
|
|
let mut ex = self.lower_expr(ex);
|
|
|
|
// include parens in span, but only if it is a super-span.
|
|
|
|
if e.span.contains(ex.span) {
|
|
|
|
ex.span = e.span;
|
|
|
|
}
|
|
|
|
// merge attributes into the inner expression.
|
|
|
|
let mut attrs = e.attrs.clone();
|
|
|
|
attrs.extend::<Vec<_>>(ex.attrs.into());
|
|
|
|
ex.attrs = attrs;
|
|
|
|
return ex;
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2015-09-28 04:24:42 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// Desugar ExprIfLet
|
|
|
|
// From: `if let <pat> = <sub_expr> <body> [<else_opt>]`
|
|
|
|
ExprKind::IfLet(ref pat, ref sub_expr, ref body, ref else_opt) => {
|
|
|
|
// to:
|
|
|
|
//
|
|
|
|
// match <sub_expr> {
|
|
|
|
// <pat> => <body>,
|
|
|
|
// [_ if <else_opt_if_cond> => <else_opt_if_body>,]
|
|
|
|
// _ => [<else_opt> | ()]
|
|
|
|
// }
|
|
|
|
|
|
|
|
// `<pat> => <body>`
|
|
|
|
let pat_arm = {
|
|
|
|
let body = self.lower_block(body);
|
2016-10-28 10:16:44 +00:00
|
|
|
let body_expr = P(self.expr_block(body, ThinVec::new()));
|
2016-05-10 01:15:11 +00:00
|
|
|
let pat = self.lower_pat(pat);
|
|
|
|
self.arm(hir_vec![pat], body_expr)
|
2016-05-10 01:11:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// `[_ if <else_opt_if_cond> => <else_opt_if_body>,]`
|
2016-10-28 10:16:44 +00:00
|
|
|
let mut else_opt = else_opt.as_ref().map(|e| P(self.lower_expr(e)));
|
2016-05-10 01:11:59 +00:00
|
|
|
let else_if_arms = {
|
|
|
|
let mut arms = vec![];
|
|
|
|
loop {
|
|
|
|
let else_opt_continue = else_opt.and_then(|els| {
|
|
|
|
els.and_then(|els| {
|
|
|
|
match els.node {
|
|
|
|
// else if
|
|
|
|
hir::ExprIf(cond, then, else_opt) => {
|
2016-05-10 01:15:11 +00:00
|
|
|
let pat_under = self.pat_wild(e.span);
|
2016-05-10 01:11:59 +00:00
|
|
|
arms.push(hir::Arm {
|
|
|
|
attrs: hir_vec![],
|
|
|
|
pats: hir_vec![pat_under],
|
|
|
|
guard: Some(cond),
|
2016-10-28 10:16:44 +00:00
|
|
|
body: P(self.expr_block(then, ThinVec::new())),
|
2016-05-10 01:11:59 +00:00
|
|
|
});
|
|
|
|
else_opt.map(|else_opt| (else_opt, true))
|
|
|
|
}
|
|
|
|
_ => Some((P(els), false)),
|
2015-10-06 03:03:56 +00:00
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
})
|
|
|
|
});
|
|
|
|
match else_opt_continue {
|
|
|
|
Some((e, true)) => {
|
|
|
|
else_opt = Some(e);
|
|
|
|
}
|
|
|
|
Some((e, false)) => {
|
|
|
|
else_opt = Some(e);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
else_opt = None;
|
|
|
|
break;
|
2015-09-28 04:24:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
arms
|
|
|
|
};
|
2015-09-28 04:24:42 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
let contains_else_clause = else_opt.is_some();
|
2015-09-28 04:24:42 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// `_ => [<else_opt> | ()]`
|
|
|
|
let else_arm = {
|
2016-05-10 01:15:11 +00:00
|
|
|
let pat_under = self.pat_wild(e.span);
|
2016-05-10 01:11:59 +00:00
|
|
|
let else_expr =
|
2016-06-18 04:01:57 +00:00
|
|
|
else_opt.unwrap_or_else(|| self.expr_tuple(e.span, hir_vec![]));
|
2016-05-10 01:15:11 +00:00
|
|
|
self.arm(hir_vec![pat_under], else_expr)
|
2016-05-10 01:11:59 +00:00
|
|
|
};
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
let mut arms = Vec::with_capacity(else_if_arms.len() + 2);
|
|
|
|
arms.push(pat_arm);
|
|
|
|
arms.extend(else_if_arms);
|
|
|
|
arms.push(else_arm);
|
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
let sub_expr = P(self.lower_expr(sub_expr));
|
2016-05-10 01:11:59 +00:00
|
|
|
// add attributes to the outer returned expr node
|
2016-05-10 01:15:11 +00:00
|
|
|
return self.expr(e.span,
|
|
|
|
hir::ExprMatch(sub_expr,
|
|
|
|
arms.into(),
|
|
|
|
hir::MatchSource::IfLetDesugar {
|
|
|
|
contains_else_clause: contains_else_clause,
|
|
|
|
}),
|
|
|
|
e.attrs.clone());
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// Desugar ExprWhileLet
|
|
|
|
// From: `[opt_ident]: while let <pat> = <sub_expr> <body>`
|
|
|
|
ExprKind::WhileLet(ref pat, ref sub_expr, ref body, opt_ident) => {
|
|
|
|
// to:
|
|
|
|
//
|
|
|
|
// [opt_ident]: loop {
|
|
|
|
// match <sub_expr> {
|
|
|
|
// <pat> => <body>,
|
|
|
|
// _ => break
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// `<pat> => <body>`
|
|
|
|
let pat_arm = {
|
|
|
|
let body = self.lower_block(body);
|
2016-10-28 10:16:44 +00:00
|
|
|
let body_expr = P(self.expr_block(body, ThinVec::new()));
|
2016-05-10 01:15:11 +00:00
|
|
|
let pat = self.lower_pat(pat);
|
|
|
|
self.arm(hir_vec![pat], body_expr)
|
2016-05-10 01:11:59 +00:00
|
|
|
};
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// `_ => break`
|
|
|
|
let break_arm = {
|
2016-05-10 01:15:11 +00:00
|
|
|
let pat_under = self.pat_wild(e.span);
|
2016-06-18 04:01:57 +00:00
|
|
|
let break_expr = self.expr_break(e.span, ThinVec::new());
|
2016-05-10 01:15:11 +00:00
|
|
|
self.arm(hir_vec![pat_under], break_expr)
|
2016-05-10 01:11:59 +00:00
|
|
|
};
|
2016-05-02 00:02:38 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// `match <sub_expr> { ... }`
|
|
|
|
let arms = hir_vec![pat_arm, break_arm];
|
2016-10-28 10:16:44 +00:00
|
|
|
let sub_expr = P(self.lower_expr(sub_expr));
|
2016-05-10 01:15:11 +00:00
|
|
|
let match_expr = self.expr(e.span,
|
|
|
|
hir::ExprMatch(sub_expr,
|
|
|
|
arms,
|
|
|
|
hir::MatchSource::WhileLetDesugar),
|
2016-06-18 04:01:57 +00:00
|
|
|
ThinVec::new());
|
2016-05-10 01:11:59 +00:00
|
|
|
|
|
|
|
// `[opt_ident]: loop { ... }`
|
2016-10-28 10:16:44 +00:00
|
|
|
let loop_block = P(self.block_expr(P(match_expr)));
|
Implement the `loop_break_value` feature.
This implements RFC 1624, tracking issue #37339.
- `FnCtxt` (in typeck) gets a stack of `LoopCtxt`s, which store the
currently deduced type of that loop, the desired type, and a list of
break expressions currently seen. `loop` loops get a fresh type
variable as their initial type (this logic is stolen from that for
arrays). `while` loops get `()`.
- `break {expr}` looks up the broken loop, and unifies the type of
`expr` with the type of the loop.
- `break` with no expr unifies the loop's type with `()`.
- When building MIR, `loop` loops no longer construct a `()` value at
termination of the loop; rather, the `break` expression assigns the
result of the loop. `while` loops are unchanged.
- `break` respects contexts in which expressions may not end with braced
blocks. That is, `while break { break-value } { while-body }` is
illegal; this preserves backwards compatibility.
- The RFC did not make it clear, but I chose to make `break ()` inside
of a `while` loop illegal, just in case we wanted to do anything with
that design space in the future.
This is my first time dealing with this part of rustc so I'm sure
there's plenty of problems to pick on here ^_^
2016-10-29 22:15:06 +00:00
|
|
|
let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident),
|
|
|
|
hir::LoopSource::WhileLet);
|
2016-05-10 01:11:59 +00:00
|
|
|
// add attributes to the outer returned expr node
|
|
|
|
let attrs = e.attrs.clone();
|
2016-10-28 10:16:44 +00:00
|
|
|
return hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs };
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-05-02 23:26:18 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// Desugar ExprForLoop
|
|
|
|
// From: `[opt_ident]: for <pat> in <head> <body>`
|
|
|
|
ExprKind::ForLoop(ref pat, ref head, ref body, opt_ident) => {
|
|
|
|
// to:
|
|
|
|
//
|
|
|
|
// {
|
|
|
|
// let result = match ::std::iter::IntoIterator::into_iter(<head>) {
|
|
|
|
// mut iter => {
|
|
|
|
// [opt_ident]: loop {
|
|
|
|
// match ::std::iter::Iterator::next(&mut iter) {
|
|
|
|
// ::std::option::Option::Some(<pat>) => <body>,
|
|
|
|
// ::std::option::Option::None => break
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
// result
|
|
|
|
// }
|
|
|
|
|
|
|
|
// expand <head>
|
|
|
|
let head = self.lower_expr(head);
|
|
|
|
|
|
|
|
let iter = self.str_to_ident("iter");
|
|
|
|
|
|
|
|
// `::std::option::Option::Some(<pat>) => <body>`
|
|
|
|
let pat_arm = {
|
|
|
|
let body_block = self.lower_block(body);
|
|
|
|
let body_span = body_block.span;
|
|
|
|
let body_expr = P(hir::Expr {
|
|
|
|
id: self.next_id(),
|
|
|
|
node: hir::ExprBlock(body_block),
|
|
|
|
span: body_span,
|
2016-06-18 04:01:57 +00:00
|
|
|
attrs: ThinVec::new(),
|
2016-05-10 01:11:59 +00:00
|
|
|
});
|
|
|
|
let pat = self.lower_pat(pat);
|
2016-05-10 01:15:11 +00:00
|
|
|
let some_pat = self.pat_some(e.span, pat);
|
2016-05-02 00:02:38 +00:00
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
self.arm(hir_vec![some_pat], body_expr)
|
2015-11-12 17:31:05 +00:00
|
|
|
};
|
2016-05-02 00:02:38 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// `::std::option::Option::None => break`
|
|
|
|
let break_arm = {
|
2016-06-18 04:01:57 +00:00
|
|
|
let break_expr = self.expr_break(e.span, ThinVec::new());
|
2016-05-10 01:15:11 +00:00
|
|
|
let pat = self.pat_none(e.span);
|
|
|
|
self.arm(hir_vec![pat], break_expr)
|
2016-05-10 01:11:59 +00:00
|
|
|
};
|
2016-05-02 00:02:38 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// `mut iter`
|
2016-05-10 01:15:11 +00:00
|
|
|
let iter_pat = self.pat_ident_binding_mode(e.span, iter,
|
|
|
|
hir::BindByValue(hir::MutMutable));
|
2016-05-10 01:11:59 +00:00
|
|
|
|
|
|
|
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
|
|
|
|
let match_expr = {
|
2016-10-28 10:16:44 +00:00
|
|
|
let iter = P(self.expr_ident(e.span, iter, iter_pat.id));
|
2016-06-18 04:01:57 +00:00
|
|
|
let ref_mut_iter = self.expr_mut_addr_of(e.span, iter);
|
2016-11-25 11:21:19 +00:00
|
|
|
let next_path = &["iter", "Iterator", "next"];
|
2016-10-30 00:42:12 +00:00
|
|
|
let next_path = P(self.expr_std_path(e.span, next_path, ThinVec::new()));
|
2016-10-28 10:16:44 +00:00
|
|
|
let next_expr = P(self.expr_call(e.span, next_path,
|
|
|
|
hir_vec![ref_mut_iter]));
|
2016-05-10 01:11:59 +00:00
|
|
|
let arms = hir_vec![pat_arm, break_arm];
|
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
P(self.expr(e.span,
|
|
|
|
hir::ExprMatch(next_expr, arms,
|
|
|
|
hir::MatchSource::ForLoopDesugar),
|
|
|
|
ThinVec::new()))
|
2016-05-10 01:11:59 +00:00
|
|
|
};
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// `[opt_ident]: loop { ... }`
|
2016-10-28 10:16:44 +00:00
|
|
|
let loop_block = P(self.block_expr(match_expr));
|
Implement the `loop_break_value` feature.
This implements RFC 1624, tracking issue #37339.
- `FnCtxt` (in typeck) gets a stack of `LoopCtxt`s, which store the
currently deduced type of that loop, the desired type, and a list of
break expressions currently seen. `loop` loops get a fresh type
variable as their initial type (this logic is stolen from that for
arrays). `while` loops get `()`.
- `break {expr}` looks up the broken loop, and unifies the type of
`expr` with the type of the loop.
- `break` with no expr unifies the loop's type with `()`.
- When building MIR, `loop` loops no longer construct a `()` value at
termination of the loop; rather, the `break` expression assigns the
result of the loop. `while` loops are unchanged.
- `break` respects contexts in which expressions may not end with braced
blocks. That is, `while break { break-value } { while-body }` is
illegal; this preserves backwards compatibility.
- The RFC did not make it clear, but I chose to make `break ()` inside
of a `while` loop illegal, just in case we wanted to do anything with
that design space in the future.
This is my first time dealing with this part of rustc so I'm sure
there's plenty of problems to pick on here ^_^
2016-10-29 22:15:06 +00:00
|
|
|
let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident),
|
|
|
|
hir::LoopSource::ForLoop);
|
2016-06-18 04:01:57 +00:00
|
|
|
let loop_expr = P(hir::Expr {
|
|
|
|
id: e.id,
|
|
|
|
node: loop_expr,
|
|
|
|
span: e.span,
|
|
|
|
attrs: ThinVec::new(),
|
|
|
|
});
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// `mut iter => { ... }`
|
2016-05-10 01:15:11 +00:00
|
|
|
let iter_arm = self.arm(hir_vec![iter_pat], loop_expr);
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
|
|
|
|
let into_iter_expr = {
|
2016-11-25 11:21:19 +00:00
|
|
|
let into_iter_path = &["iter", "IntoIterator", "into_iter"];
|
2016-10-30 00:42:12 +00:00
|
|
|
let into_iter = P(self.expr_std_path(e.span, into_iter_path,
|
|
|
|
ThinVec::new()));
|
2016-10-28 10:16:44 +00:00
|
|
|
P(self.expr_call(e.span, into_iter, hir_vec![head]))
|
2016-05-02 00:02:38 +00:00
|
|
|
};
|
2016-05-10 01:11:59 +00:00
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
let match_expr = P(self.expr_match(e.span,
|
|
|
|
into_iter_expr,
|
|
|
|
hir_vec![iter_arm],
|
|
|
|
hir::MatchSource::ForLoopDesugar));
|
2016-05-10 01:11:59 +00:00
|
|
|
|
|
|
|
// `{ let _result = ...; _result }`
|
|
|
|
// underscore prevents an unused_variables lint if the head diverges
|
|
|
|
let result_ident = self.str_to_ident("_result");
|
|
|
|
let (let_stmt, let_stmt_binding) =
|
2016-06-18 04:01:57 +00:00
|
|
|
self.stmt_let(e.span, false, result_ident, match_expr);
|
2016-05-10 01:11:59 +00:00
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
let result = P(self.expr_ident(e.span, result_ident, let_stmt_binding));
|
|
|
|
let block = P(self.block_all(e.span, hir_vec![let_stmt], Some(result)));
|
2016-05-10 01:11:59 +00:00
|
|
|
// add the attributes to the outer returned expr node
|
2016-05-10 01:15:11 +00:00
|
|
|
return self.expr_block(block, e.attrs.clone());
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Desugar ExprKind::Try
|
|
|
|
// From: `<expr>?`
|
|
|
|
ExprKind::Try(ref sub_expr) => {
|
|
|
|
// to:
|
|
|
|
//
|
2016-10-30 00:42:12 +00:00
|
|
|
// match Carrier::translate(<expr>) {
|
|
|
|
// Ok(val) => val,
|
|
|
|
// Err(err) => return Carrier::from_error(From::from(err))
|
2016-05-10 01:11:59 +00:00
|
|
|
// }
|
2016-10-30 00:42:12 +00:00
|
|
|
let unstable_span = self.allow_internal_unstable("?", e.span);
|
2016-05-10 01:11:59 +00:00
|
|
|
|
2016-10-30 00:42:12 +00:00
|
|
|
// Carrier::translate(<expr>)
|
2016-05-03 01:01:54 +00:00
|
|
|
let discr = {
|
|
|
|
// expand <expr>
|
2016-10-30 00:42:12 +00:00
|
|
|
let sub_expr = self.lower_expr(sub_expr);
|
2016-05-03 01:01:54 +00:00
|
|
|
|
2016-11-25 11:21:19 +00:00
|
|
|
let path = &["ops", "Carrier", "translate"];
|
2016-10-30 00:42:12 +00:00
|
|
|
let path = P(self.expr_std_path(unstable_span, path, ThinVec::new()));
|
|
|
|
P(self.expr_call(e.span, path, hir_vec![sub_expr]))
|
2016-05-03 01:01:54 +00:00
|
|
|
};
|
2016-05-10 01:11:59 +00:00
|
|
|
|
|
|
|
// Ok(val) => val
|
|
|
|
let ok_arm = {
|
|
|
|
let val_ident = self.str_to_ident("val");
|
2016-05-10 01:15:11 +00:00
|
|
|
let val_pat = self.pat_ident(e.span, val_ident);
|
2016-10-28 10:16:44 +00:00
|
|
|
let val_expr = P(self.expr_ident(e.span, val_ident, val_pat.id));
|
2016-05-10 01:15:11 +00:00
|
|
|
let ok_pat = self.pat_ok(e.span, val_pat);
|
2016-05-10 01:11:59 +00:00
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
self.arm(hir_vec![ok_pat], val_expr)
|
2016-02-28 22:38:48 +00:00
|
|
|
};
|
|
|
|
|
2016-10-30 00:42:12 +00:00
|
|
|
// Err(err) => return Carrier::from_error(From::from(err))
|
2016-05-10 01:11:59 +00:00
|
|
|
let err_arm = {
|
|
|
|
let err_ident = self.str_to_ident("err");
|
2016-05-10 01:15:11 +00:00
|
|
|
let err_local = self.pat_ident(e.span, err_ident);
|
2016-05-10 01:11:59 +00:00
|
|
|
let from_expr = {
|
2016-11-25 11:21:19 +00:00
|
|
|
let path = &["convert", "From", "from"];
|
2016-10-30 00:42:12 +00:00
|
|
|
let from = P(self.expr_std_path(e.span, path, ThinVec::new()));
|
2016-06-18 04:01:57 +00:00
|
|
|
let err_expr = self.expr_ident(e.span, err_ident, err_local.id);
|
2016-05-10 01:11:59 +00:00
|
|
|
|
2016-06-18 04:01:57 +00:00
|
|
|
self.expr_call(e.span, from, hir_vec![err_expr])
|
2016-05-10 01:11:59 +00:00
|
|
|
};
|
2016-05-03 01:01:54 +00:00
|
|
|
let from_err_expr = {
|
2016-11-25 11:21:19 +00:00
|
|
|
let path = &["ops", "Carrier", "from_error"];
|
2016-10-30 00:42:12 +00:00
|
|
|
let from_err = P(self.expr_std_path(unstable_span, path,
|
|
|
|
ThinVec::new()));
|
2016-10-28 10:16:44 +00:00
|
|
|
P(self.expr_call(e.span, from_err, hir_vec![from_expr]))
|
2016-05-10 01:11:59 +00:00
|
|
|
};
|
2016-05-03 01:01:54 +00:00
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
let ret_expr = P(self.expr(e.span,
|
|
|
|
hir::Expr_::ExprRet(Some(from_err_expr)),
|
|
|
|
ThinVec::new()));
|
2016-05-03 01:01:54 +00:00
|
|
|
|
|
|
|
let err_pat = self.pat_err(e.span, err_local);
|
2016-10-30 00:42:12 +00:00
|
|
|
self.arm(hir_vec![err_pat], ret_expr)
|
2016-05-10 01:11:59 +00:00
|
|
|
};
|
2016-05-02 00:02:38 +00:00
|
|
|
|
2016-05-03 01:01:54 +00:00
|
|
|
return self.expr_match(e.span, discr, hir_vec![err_arm, ok_arm],
|
2016-06-18 04:01:57 +00:00
|
|
|
hir::MatchSource::TryDesugar);
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2016-02-28 22:38:48 +00:00
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
ExprKind::Mac(_) => panic!("Shouldn't exist here"),
|
|
|
|
},
|
|
|
|
span: e.span,
|
|
|
|
attrs: e.attrs.clone(),
|
2016-10-28 10:16:44 +00:00
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2016-11-24 04:11:31 +00:00
|
|
|
fn lower_stmt(&mut self, s: &Stmt) -> SmallVector<hir::Stmt> {
|
|
|
|
SmallVector::one(match s.node {
|
2016-06-17 02:30:01 +00:00
|
|
|
StmtKind::Local(ref l) => Spanned {
|
|
|
|
node: hir::StmtDecl(P(Spanned {
|
|
|
|
node: hir::DeclLocal(self.lower_local(l)),
|
2016-05-10 01:11:59 +00:00
|
|
|
span: s.span,
|
2016-06-17 02:30:01 +00:00
|
|
|
}), s.id),
|
|
|
|
span: s.span,
|
|
|
|
},
|
2016-11-24 04:11:31 +00:00
|
|
|
StmtKind::Item(ref it) => {
|
|
|
|
// Can only use the ID once.
|
|
|
|
let mut id = Some(s.id);
|
|
|
|
return self.lower_item_id(it).into_iter().map(|item_id| Spanned {
|
|
|
|
node: hir::StmtDecl(P(Spanned {
|
|
|
|
node: hir::DeclItem(item_id),
|
|
|
|
span: s.span,
|
|
|
|
}), id.take().unwrap_or_else(|| self.next_id())),
|
2016-06-17 02:30:01 +00:00
|
|
|
span: s.span,
|
2016-11-24 04:11:31 +00:00
|
|
|
}).collect();
|
|
|
|
}
|
2016-06-17 02:30:01 +00:00
|
|
|
StmtKind::Expr(ref e) => {
|
2016-05-10 01:11:59 +00:00
|
|
|
Spanned {
|
2016-10-28 10:16:44 +00:00
|
|
|
node: hir::StmtExpr(P(self.lower_expr(e)), s.id),
|
2016-05-10 01:11:59 +00:00
|
|
|
span: s.span,
|
|
|
|
}
|
2015-12-07 14:17:41 +00:00
|
|
|
}
|
2016-06-17 02:30:01 +00:00
|
|
|
StmtKind::Semi(ref e) => {
|
2016-05-10 01:11:59 +00:00
|
|
|
Spanned {
|
2016-10-28 10:16:44 +00:00
|
|
|
node: hir::StmtSemi(P(self.lower_expr(e)), s.id),
|
2016-05-10 01:11:59 +00:00
|
|
|
span: s.span,
|
|
|
|
}
|
2015-12-07 14:17:41 +00:00
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
StmtKind::Mac(..) => panic!("Shouldn't exist here"),
|
2016-11-24 04:11:31 +00:00
|
|
|
})
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause {
|
|
|
|
match c {
|
|
|
|
CaptureBy::Value => hir::CaptureByValue,
|
|
|
|
CaptureBy::Ref => hir::CaptureByRef,
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility {
|
|
|
|
match *v {
|
|
|
|
Visibility::Public => hir::Public,
|
|
|
|
Visibility::Crate(_) => hir::Visibility::Crate,
|
2016-10-17 03:02:23 +00:00
|
|
|
Visibility::Restricted { ref path, id } => {
|
|
|
|
hir::Visibility::Restricted {
|
2016-11-25 11:21:19 +00:00
|
|
|
path: P(self.lower_path(id, path, ParamMode::Explicit)),
|
2016-10-17 03:02:23 +00:00
|
|
|
id: id
|
|
|
|
}
|
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
Visibility::Inherited => hir::Inherited,
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-11-14 16:00:02 +00:00
|
|
|
fn lower_defaultness(&mut self, d: Defaultness, has_value: bool) -> hir::Defaultness {
|
2016-05-10 01:11:59 +00:00
|
|
|
match d {
|
2016-11-14 16:00:02 +00:00
|
|
|
Defaultness::Default => hir::Defaultness::Default { has_value: has_value },
|
|
|
|
Defaultness::Final => {
|
|
|
|
assert!(has_value);
|
|
|
|
hir::Defaultness::Final
|
|
|
|
}
|
2016-05-10 01:11:59 +00:00
|
|
|
}
|
2015-12-18 22:38:28 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
|
|
|
|
match *b {
|
|
|
|
BlockCheckMode::Default => hir::DefaultBlock,
|
|
|
|
BlockCheckMode::Unsafe(u) => hir::UnsafeBlock(self.lower_unsafe_source(u)),
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_binding_mode(&mut self, b: &BindingMode) -> hir::BindingMode {
|
|
|
|
match *b {
|
|
|
|
BindingMode::ByRef(m) => hir::BindByRef(self.lower_mutability(m)),
|
|
|
|
BindingMode::ByValue(m) => hir::BindByValue(self.lower_mutability(m)),
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource {
|
|
|
|
match u {
|
|
|
|
CompilerGenerated => hir::CompilerGenerated,
|
|
|
|
UserProvided => hir::UserProvided,
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_impl_polarity(&mut self, i: ImplPolarity) -> hir::ImplPolarity {
|
|
|
|
match i {
|
|
|
|
ImplPolarity::Positive => hir::ImplPolarity::Positive,
|
|
|
|
ImplPolarity::Negative => hir::ImplPolarity::Negative,
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:11:59 +00:00
|
|
|
fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier {
|
|
|
|
match f {
|
|
|
|
TraitBoundModifier::None => hir::TraitBoundModifier::None,
|
|
|
|
TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe,
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
// Helper methods for building HIR.
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
fn arm(&mut self, pats: hir::HirVec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
|
|
|
|
hir::Arm {
|
|
|
|
attrs: hir_vec![],
|
|
|
|
pats: pats,
|
|
|
|
guard: None,
|
|
|
|
body: expr,
|
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
fn field(&mut self, name: Name, expr: P<hir::Expr>, span: Span) -> hir::Field {
|
|
|
|
hir::Field {
|
|
|
|
name: Spanned {
|
|
|
|
node: name,
|
|
|
|
span: span,
|
|
|
|
},
|
2016-01-13 06:24:34 +00:00
|
|
|
span: span,
|
2016-05-10 01:15:11 +00:00
|
|
|
expr: expr,
|
2016-10-27 00:15:13 +00:00
|
|
|
is_shorthand: false,
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2016-01-13 06:24:34 +00:00
|
|
|
}
|
|
|
|
|
2016-06-18 04:01:57 +00:00
|
|
|
fn expr_break(&mut self, span: Span, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
|
Implement the `loop_break_value` feature.
This implements RFC 1624, tracking issue #37339.
- `FnCtxt` (in typeck) gets a stack of `LoopCtxt`s, which store the
currently deduced type of that loop, the desired type, and a list of
break expressions currently seen. `loop` loops get a fresh type
variable as their initial type (this logic is stolen from that for
arrays). `while` loops get `()`.
- `break {expr}` looks up the broken loop, and unifies the type of
`expr` with the type of the loop.
- `break` with no expr unifies the loop's type with `()`.
- When building MIR, `loop` loops no longer construct a `()` value at
termination of the loop; rather, the `break` expression assigns the
result of the loop. `while` loops are unchanged.
- `break` respects contexts in which expressions may not end with braced
blocks. That is, `while break { break-value } { while-body }` is
illegal; this preserves backwards compatibility.
- The RFC did not make it clear, but I chose to make `break ()` inside
of a `while` loop illegal, just in case we wanted to do anything with
that design space in the future.
This is my first time dealing with this part of rustc so I'm sure
there's plenty of problems to pick on here ^_^
2016-10-29 22:15:06 +00:00
|
|
|
P(self.expr(span, hir::ExprBreak(None, None), attrs))
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
fn expr_call(&mut self, span: Span, e: P<hir::Expr>, args: hir::HirVec<hir::Expr>)
|
|
|
|
-> hir::Expr {
|
2016-06-18 04:01:57 +00:00
|
|
|
self.expr(span, hir::ExprCall(e, args), ThinVec::new())
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> hir::Expr {
|
2016-08-29 02:12:03 +00:00
|
|
|
let def = {
|
|
|
|
let defs = self.resolver.definitions();
|
2016-08-31 11:08:22 +00:00
|
|
|
Def::Local(defs.local_def_id(binding))
|
2016-08-29 02:12:03 +00:00
|
|
|
};
|
2016-11-25 11:21:19 +00:00
|
|
|
|
|
|
|
let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(hir::Path {
|
|
|
|
span: span,
|
|
|
|
global: false,
|
|
|
|
def: def,
|
|
|
|
segments: hir_vec![hir::PathSegment::from_name(id)],
|
|
|
|
})));
|
|
|
|
let expr = self.expr(span, expr_path, ThinVec::new());
|
2016-05-10 01:15:11 +00:00
|
|
|
self.resolver.record_resolution(expr.id, def);
|
2016-05-06 08:24:04 +00:00
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
expr
|
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> hir::Expr {
|
2016-06-18 04:01:57 +00:00
|
|
|
self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), ThinVec::new())
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-11-25 11:21:19 +00:00
|
|
|
fn expr_std_path(&mut self,
|
|
|
|
span: Span,
|
|
|
|
components: &[&str],
|
|
|
|
attrs: ThinVec<Attribute>)
|
2016-10-30 00:42:12 +00:00
|
|
|
-> hir::Expr {
|
2016-11-25 11:21:19 +00:00
|
|
|
let path = self.std_path(span, components, true);
|
|
|
|
let def = path.def;
|
|
|
|
let expr = self.expr(span, hir::ExprPath(hir::QPath::Resolved(None, P(path))), attrs);
|
2016-05-10 01:15:11 +00:00
|
|
|
self.resolver.record_resolution(expr.id, def);
|
2016-10-30 00:42:12 +00:00
|
|
|
expr
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
fn expr_match(&mut self,
|
|
|
|
span: Span,
|
|
|
|
arg: P<hir::Expr>,
|
|
|
|
arms: hir::HirVec<hir::Arm>,
|
2016-06-18 04:01:57 +00:00
|
|
|
source: hir::MatchSource)
|
2016-10-28 10:16:44 +00:00
|
|
|
-> hir::Expr {
|
2016-06-18 04:01:57 +00:00
|
|
|
self.expr(span, hir::ExprMatch(arg, arms, source), ThinVec::new())
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinVec<Attribute>) -> hir::Expr {
|
2016-05-10 01:15:11 +00:00
|
|
|
self.expr(b.span, hir::ExprBlock(b), attrs)
|
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<hir::Expr>) -> P<hir::Expr> {
|
|
|
|
P(self.expr(sp, hir::ExprTup(exprs), ThinVec::new()))
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2015-09-28 04:24:42 +00:00
|
|
|
|
2016-11-25 11:21:19 +00:00
|
|
|
fn expr_std_struct(&mut self,
|
|
|
|
span: Span,
|
|
|
|
components: &[&str],
|
|
|
|
fields: hir::HirVec<hir::Field>,
|
|
|
|
e: Option<P<hir::Expr>>,
|
2016-10-30 00:42:12 +00:00
|
|
|
attrs: ThinVec<Attribute>) -> hir::Expr {
|
2016-11-25 11:21:19 +00:00
|
|
|
let path = self.std_path(span, components, false);
|
|
|
|
let def = path.def;
|
2016-10-27 02:17:42 +00:00
|
|
|
let qpath = hir::QPath::Resolved(None, P(path));
|
2016-11-25 11:21:19 +00:00
|
|
|
let expr = self.expr(span, hir::ExprStruct(qpath, fields, e), attrs);
|
2016-05-10 01:15:11 +00:00
|
|
|
self.resolver.record_resolution(expr.id, def);
|
2016-10-30 00:42:12 +00:00
|
|
|
expr
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2016-05-02 23:26:18 +00:00
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> hir::Expr {
|
|
|
|
hir::Expr {
|
2016-05-10 01:15:11 +00:00
|
|
|
id: self.next_id(),
|
|
|
|
node: node,
|
|
|
|
span: span,
|
|
|
|
attrs: attrs,
|
2016-10-28 10:16:44 +00:00
|
|
|
}
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2016-01-13 06:24:34 +00:00
|
|
|
|
2016-06-18 04:01:57 +00:00
|
|
|
fn stmt_let(&mut self, sp: Span, mutbl: bool, ident: Name, ex: P<hir::Expr>)
|
2016-05-10 01:15:11 +00:00
|
|
|
-> (hir::Stmt, NodeId) {
|
|
|
|
let pat = if mutbl {
|
|
|
|
self.pat_ident_binding_mode(sp, ident, hir::BindByValue(hir::MutMutable))
|
|
|
|
} else {
|
|
|
|
self.pat_ident(sp, ident)
|
|
|
|
};
|
|
|
|
let pat_id = pat.id;
|
|
|
|
let local = P(hir::Local {
|
|
|
|
pat: pat,
|
|
|
|
ty: None,
|
|
|
|
init: Some(ex),
|
|
|
|
id: self.next_id(),
|
|
|
|
span: sp,
|
2016-06-18 04:01:57 +00:00
|
|
|
attrs: ThinVec::new(),
|
2016-05-10 01:15:11 +00:00
|
|
|
});
|
|
|
|
let decl = respan(sp, hir::DeclLocal(local));
|
|
|
|
(respan(sp, hir::StmtDecl(P(decl), self.next_id())), pat_id)
|
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-10-28 10:16:44 +00:00
|
|
|
fn block_expr(&mut self, expr: P<hir::Expr>) -> hir::Block {
|
2016-05-10 01:15:11 +00:00
|
|
|
self.block_all(expr.span, hir::HirVec::new(), Some(expr))
|
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
fn block_all(&mut self, span: Span, stmts: hir::HirVec<hir::Stmt>, expr: Option<P<hir::Expr>>)
|
2016-10-28 10:16:44 +00:00
|
|
|
-> hir::Block {
|
|
|
|
hir::Block {
|
2016-05-10 01:15:11 +00:00
|
|
|
stmts: stmts,
|
|
|
|
expr: expr,
|
|
|
|
id: self.next_id(),
|
|
|
|
rules: hir::DefaultBlock,
|
|
|
|
span: span,
|
2016-10-28 10:16:44 +00:00
|
|
|
}
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
fn pat_ok(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
|
2016-11-25 11:21:19 +00:00
|
|
|
self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat])
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
fn pat_err(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
|
2016-11-25 11:21:19 +00:00
|
|
|
self.pat_std_enum(span, &["result", "Result", "Err"], hir_vec![pat])
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2016-02-28 22:38:48 +00:00
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
fn pat_some(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
|
2016-11-25 11:21:19 +00:00
|
|
|
self.pat_std_enum(span, &["option", "Option", "Some"], hir_vec![pat])
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2016-02-28 22:38:48 +00:00
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
fn pat_none(&mut self, span: Span) -> P<hir::Pat> {
|
2016-11-25 11:21:19 +00:00
|
|
|
self.pat_std_enum(span, &["option", "Option", "None"], hir_vec![])
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-11-25 11:21:19 +00:00
|
|
|
fn pat_std_enum(&mut self,
|
|
|
|
span: Span,
|
|
|
|
components: &[&str],
|
|
|
|
subpats: hir::HirVec<P<hir::Pat>>)
|
|
|
|
-> P<hir::Pat> {
|
|
|
|
let path = self.std_path(span, components, true);
|
|
|
|
let def = path.def;
|
2016-10-27 02:17:42 +00:00
|
|
|
let qpath = hir::QPath::Resolved(None, P(path));
|
2016-05-10 01:15:11 +00:00
|
|
|
let pt = if subpats.is_empty() {
|
2016-10-27 02:17:42 +00:00
|
|
|
hir::PatKind::Path(qpath)
|
2016-05-10 01:15:11 +00:00
|
|
|
} else {
|
2016-10-27 02:17:42 +00:00
|
|
|
hir::PatKind::TupleStruct(qpath, subpats, None)
|
2016-05-10 01:15:11 +00:00
|
|
|
};
|
|
|
|
let pat = self.pat(span, pt);
|
|
|
|
self.resolver.record_resolution(pat.id, def);
|
|
|
|
pat
|
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-03-06 12:54:44 +00:00
|
|
|
fn pat_ident(&mut self, span: Span, name: Name) -> P<hir::Pat> {
|
|
|
|
self.pat_ident_binding_mode(span, name, hir::BindByValue(hir::MutImmutable))
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-03-06 12:54:44 +00:00
|
|
|
fn pat_ident_binding_mode(&mut self, span: Span, name: Name, bm: hir::BindingMode)
|
2016-05-10 01:15:11 +00:00
|
|
|
-> P<hir::Pat> {
|
2016-11-25 11:21:19 +00:00
|
|
|
let id = self.next_id();
|
2016-05-10 01:15:11 +00:00
|
|
|
let parent_def = self.parent_def;
|
2016-11-25 11:21:19 +00:00
|
|
|
let def_id = {
|
2016-08-29 02:12:03 +00:00
|
|
|
let defs = self.resolver.definitions();
|
2016-08-06 00:10:04 +00:00
|
|
|
let def_path_data = DefPathData::Binding(name.as_str());
|
2016-11-25 11:21:19 +00:00
|
|
|
let def_index = defs.create_def_with_parent(parent_def, id, def_path_data);
|
|
|
|
DefId::local(def_index)
|
2016-08-29 02:12:03 +00:00
|
|
|
};
|
2016-11-25 11:21:19 +00:00
|
|
|
self.resolver.record_resolution(id, Def::Local(def_id));
|
2015-09-28 04:24:42 +00:00
|
|
|
|
2016-11-25 11:21:19 +00:00
|
|
|
P(hir::Pat {
|
|
|
|
id: id,
|
|
|
|
node: hir::PatKind::Binding(bm,
|
|
|
|
def_id,
|
|
|
|
Spanned {
|
|
|
|
span: span,
|
|
|
|
node: name,
|
|
|
|
},
|
|
|
|
None),
|
|
|
|
span: span,
|
|
|
|
})
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
fn pat_wild(&mut self, span: Span) -> P<hir::Pat> {
|
|
|
|
self.pat(span, hir::PatKind::Wild)
|
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-05-10 01:15:11 +00:00
|
|
|
fn pat(&mut self, span: Span, pat: hir::PatKind) -> P<hir::Pat> {
|
|
|
|
P(hir::Pat {
|
|
|
|
id: self.next_id(),
|
|
|
|
node: pat,
|
|
|
|
span: span,
|
|
|
|
})
|
|
|
|
}
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-11-25 11:21:19 +00:00
|
|
|
/// Given suffix ["b","c","d"], returns path `::std::b::c::d` when
|
|
|
|
/// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
|
|
|
|
/// The path is also resolved according to `is_value`.
|
|
|
|
fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path {
|
|
|
|
let idents = self.crate_root.iter().chain(components);
|
2015-09-28 02:00:15 +00:00
|
|
|
|
2016-11-25 11:21:19 +00:00
|
|
|
let segments: Vec<_> = idents.map(|name| {
|
|
|
|
hir::PathSegment::from_name(Symbol::intern(name))
|
2016-05-10 01:15:11 +00:00
|
|
|
}).collect();
|
2015-09-29 00:17:46 +00:00
|
|
|
|
2016-11-25 11:21:19 +00:00
|
|
|
let mut path = hir::Path {
|
|
|
|
span: span,
|
|
|
|
global: true,
|
|
|
|
def: Def::Err,
|
2016-05-10 01:15:11 +00:00
|
|
|
segments: segments.into(),
|
2016-11-25 11:21:19 +00:00
|
|
|
};
|
2016-05-10 01:15:11 +00:00
|
|
|
|
2016-11-25 11:21:19 +00:00
|
|
|
self.resolver.resolve_generated_global_path(&mut path, is_value);
|
|
|
|
path
|
2016-05-10 01:15:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn signal_block_expr(&mut self,
|
|
|
|
stmts: hir::HirVec<hir::Stmt>,
|
|
|
|
expr: P<hir::Expr>,
|
|
|
|
span: Span,
|
|
|
|
rule: hir::BlockCheckMode,
|
2016-06-18 04:01:57 +00:00
|
|
|
attrs: ThinVec<Attribute>)
|
2016-10-28 10:16:44 +00:00
|
|
|
-> hir::Expr {
|
2016-05-10 01:15:11 +00:00
|
|
|
let id = self.next_id();
|
|
|
|
let block = P(hir::Block {
|
|
|
|
rules: rule,
|
|
|
|
span: span,
|
|
|
|
id: id,
|
|
|
|
stmts: stmts,
|
|
|
|
expr: Some(expr),
|
|
|
|
});
|
|
|
|
self.expr_block(block, attrs)
|
|
|
|
}
|
2016-05-03 01:01:54 +00:00
|
|
|
|
2016-10-27 02:17:42 +00:00
|
|
|
fn ty(&mut self, span: Span, node: hir::Ty_) -> P<hir::Ty> {
|
|
|
|
P(hir::Ty {
|
|
|
|
id: self.next_id(),
|
|
|
|
node: node,
|
|
|
|
span: span,
|
|
|
|
})
|
|
|
|
}
|
2015-09-29 00:17:46 +00:00
|
|
|
}
|