use syntax::ext::mtwt;
use syntax::ptr::P;
use syntax::codemap::{respan, Spanned, Span};
-use syntax::owned_slice::OwnedSlice;
use syntax::parse::token;
use syntax::std_inject;
use syntax::visit::{self, Visitor};
cached_id: Cell<u32>,
// Keep track of gensym'ed idents.
gensym_cache: RefCell<HashMap<(NodeId, &'static str), hir::Ident>>,
- // A copy of cached_id, but is also set to an id while it is being cached.
+ // A copy of cached_id, but is also set to an id while a node is lowered for
+ // the first time.
gensym_key: Cell<u32>,
}
}
fn next_id(&self) -> NodeId {
- let cached = self.cached_id.get();
- if cached == 0 {
+ let cached_id = self.cached_id.get();
+ if cached_id == 0 {
return self.id_assigner.next_node_id();
}
- self.cached_id.set(cached + 1);
- cached
+ self.cached_id.set(cached_id + 1);
+ cached_id
}
fn str_to_ident(&self, s: &'static str) -> hir::Ident {
- let cached_id = self.gensym_key.get();
- if cached_id == 0 {
+ let gensym_key = self.gensym_key.get();
+ if gensym_key == 0 {
return hir::Ident::from_name(token::gensym(s));
}
- let cached = self.gensym_cache.borrow().contains_key(&(cached_id, s));
+ let cached = self.gensym_cache.borrow().contains_key(&(gensym_key, s));
if cached {
- self.gensym_cache.borrow()[&(cached_id, s)]
+ self.gensym_cache.borrow()[&(gensym_key, s)]
} else {
let result = hir::Ident::from_name(token::gensym(s));
- self.gensym_cache.borrow_mut().insert((cached_id, s), result);
+ self.gensym_cache.borrow_mut().insert((gensym_key, s), result);
result
}
}
}
+// Utility fn for setting and unsetting the cached id.
+fn cache_ids<'a, OP, R>(lctx: &LoweringContext, expr_id: NodeId, op: OP) -> R
+ where OP: FnOnce(&LoweringContext) -> R
+{
+ // Only reset the id if it was previously 0, i.e., was not cached.
+ // If it was cached, we are in a nested node, but our id count will
+ // still count towards the parent's count.
+ let reset_cached_id = lctx.cached_id.get() == 0;
+ // We always reset gensym_key so that if we use the same name in a nested
+ // node and after that node, they get different values.
+ let old_gensym_key = lctx.gensym_key.get();
+
+ {
+ let id_cache: &mut HashMap<_, _> = &mut lctx.id_cache.borrow_mut();
+
+ if id_cache.contains_key(&expr_id) {
+ let cached_id = lctx.cached_id.get();
+ if cached_id == 0 {
+ // We're entering a node where we need to track ids, but are not
+ // yet tracking.
+ lctx.cached_id.set(id_cache[&expr_id]);
+ } else {
+ // We're already tracking - check that the tracked id is the same
+ // as the expected id.
+ assert!(cached_id == id_cache[&expr_id], "id mismatch");
+ }
+ lctx.gensym_key.set(id_cache[&expr_id]);
+ } else {
+ // We've never lowered this node before, remember it for next time.
+ let next_id = lctx.id_assigner.peek_node_id();
+ id_cache.insert(expr_id, next_id);
+ lctx.gensym_key.set(next_id);
+ // self.cached_id is not set when we lower a node for the first time,
+ // only on re-lowering.
+ }
+ }
+
+ let result = op(lctx);
+
+ if reset_cached_id {
+ lctx.cached_id.set(0);
+ }
+ lctx.gensym_key.set(old_gensym_key);
+
+ result
+}
+
pub fn lower_ident(_lctx: &LoweringContext, ident: Ident) -> hir::Ident {
hir::Ident {
name: mtwt::resolve(ident),
}
}
+pub fn lower_attrs(_lctx: &LoweringContext, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
+ attrs.clone().into()
+}
+
pub fn lower_view_path(lctx: &LoweringContext, view_path: &ViewPath) -> P<hir::ViewPath> {
P(Spanned {
node: match view_path.node {
pub fn lower_arm(lctx: &LoweringContext, arm: &Arm) -> hir::Arm {
hir::Arm {
- attrs: arm.attrs.clone(),
+ attrs: lower_attrs(lctx, &arm.attrs),
pats: arm.pats.iter().map(|x| lower_pat(lctx, x)).collect(),
guard: arm.guard.as_ref().map(|ref x| lower_expr(lctx, x)),
body: lower_expr(lctx, &arm.body),
Spanned {
node: hir::Variant_ {
name: v.node.name.name,
- attrs: v.node.attrs.clone(),
+ attrs: lower_attrs(lctx, &v.node.attrs),
data: lower_variant_data(lctx, &v.node.data),
disr_expr: v.node.disr_expr.as_ref().map(|e| lower_expr(lctx, e)),
},
path_parameters: &PathParameters)
-> hir::PathParameters {
match *path_parameters {
- AngleBracketedParameters(ref data) =>
+ PathParameters::AngleBracketed(ref data) =>
hir::AngleBracketedParameters(lower_angle_bracketed_parameter_data(lctx, data)),
- ParenthesizedParameters(ref data) =>
+ PathParameters::Parenthesized(ref data) =>
hir::ParenthesizedParameters(lower_parenthesized_parameter_data(lctx, data)),
}
}
}
pub fn lower_ty_params(lctx: &LoweringContext,
- tps: &OwnedSlice<TyParam>)
- -> OwnedSlice<hir::TyParam> {
+ tps: &P<[TyParam]>)
+ -> hir::HirVec<hir::TyParam> {
tps.iter().map(|tp| lower_ty_param(lctx, tp)).collect()
}
}
}
-pub fn lower_lifetimes(lctx: &LoweringContext, lts: &Vec<Lifetime>) -> Vec<hir::Lifetime> {
+pub fn lower_lifetimes(lctx: &LoweringContext, lts: &Vec<Lifetime>) -> hir::HirVec<hir::Lifetime> {
lts.iter().map(|l| lower_lifetime(lctx, l)).collect()
}
pub fn lower_lifetime_defs(lctx: &LoweringContext,
lts: &Vec<LifetimeDef>)
- -> Vec<hir::LifetimeDef> {
+ -> hir::HirVec<hir::LifetimeDef> {
lts.iter().map(|l| lower_lifetime_def(lctx, l)).collect()
}
id: f.node.id,
kind: lower_struct_field_kind(lctx, &f.node.kind),
ty: lower_ty(lctx, &f.node.ty),
- attrs: f.node.attrs.clone(),
+ attrs: lower_attrs(lctx, &f.node.attrs),
},
span: f.span,
}
}
pub fn lower_opt_bounds(lctx: &LoweringContext,
- b: &Option<OwnedSlice<TyParamBound>>)
- -> Option<OwnedSlice<hir::TyParamBound>> {
+ b: &Option<TyParamBounds>)
+ -> Option<hir::TyParamBounds> {
b.as_ref().map(|ref bounds| lower_bounds(lctx, bounds))
}
hir::TraitItem {
id: i.id,
name: i.ident.name,
- attrs: i.attrs.clone(),
+ attrs: lower_attrs(lctx, &i.attrs),
node: match i.node {
ConstTraitItem(ref ty, ref default) => {
hir::ConstTraitItem(lower_ty(lctx, ty),
hir::ImplItem {
id: i.id,
name: i.ident.name,
- attrs: i.attrs.clone(),
+ attrs: lower_attrs(lctx, &i.attrs),
vis: lower_visibility(lctx, i.vis),
node: match i.node {
ImplItemKind::Const(ref ty, ref expr) => {
hir::Crate {
module: lower_mod(lctx, &c.module),
- attrs: c.attrs.clone(),
- config: c.config.clone(),
+ attrs: lower_attrs(lctx, &c.attrs),
+ config: c.config.clone().into(),
span: c.span,
exported_macros: c.exported_macros.iter().map(|m| lower_macro_def(lctx, m)).collect(),
items: items,
}
}
-pub fn lower_macro_def(_lctx: &LoweringContext, m: &MacroDef) -> hir::MacroDef {
+pub fn lower_macro_def(lctx: &LoweringContext, m: &MacroDef) -> hir::MacroDef {
hir::MacroDef {
name: m.ident.name,
- attrs: m.attrs.clone(),
+ attrs: lower_attrs(lctx, &m.attrs),
id: m.id,
span: m.span,
imported_from: m.imported_from.map(|x| x.name),
export: m.export,
use_locally: m.use_locally,
allow_internal_unstable: m.allow_internal_unstable,
- body: m.body.clone(),
+ body: m.body.clone().into(),
}
}
hir::Item {
id: i.id,
name: i.ident.name,
- attrs: i.attrs.clone(),
+ attrs: lower_attrs(lctx, &i.attrs),
node: node,
vis: lower_visibility(lctx, i.vis),
span: i.span,
hir::ForeignItem {
id: i.id,
name: i.ident.name,
- attrs: i.attrs.clone(),
+ attrs: lower_attrs(lctx, &i.attrs),
node: match i.node {
ForeignItemFn(ref fdec, ref generics) => {
hir::ForeignItemFn(lower_fn_decl(lctx, fdec), lower_generics(lctx, generics))
})
}
-// Utility fn for setting and unsetting the cached id.
-fn cache_ids<'a, OP, R>(lctx: &LoweringContext, expr_id: NodeId, op: OP) -> R
- where OP: FnOnce(&LoweringContext) -> R
-{
- // Only reset the id if it was previously 0, i.e., was not cached.
- // If it was cached, we are in a nested node, but our id count will
- // still count towards the parent's count.
- let reset_cached_id = lctx.cached_id.get() == 0;
-
- {
- let id_cache: &mut HashMap<_, _> = &mut lctx.id_cache.borrow_mut();
-
- if id_cache.contains_key(&expr_id) {
- let cached_id = lctx.cached_id.get();
- if cached_id == 0 {
- // We're entering a node where we need to track ids, but are not
- // yet tracking.
- lctx.cached_id.set(id_cache[&expr_id]);
- lctx.gensym_key.set(id_cache[&expr_id]);
- } else {
- // We're already tracking - check that the tracked id is the same
- // as the expected id.
- assert!(cached_id == id_cache[&expr_id], "id mismatch");
- }
- } else {
- let next_id = lctx.id_assigner.peek_node_id();
- id_cache.insert(expr_id, next_id);
- lctx.gensym_key.set(next_id);
- }
- }
-
- let result = op(lctx);
-
- if reset_cached_id {
- lctx.cached_id.set(0);
- lctx.gensym_key.set(0);
- }
-
- result
-}
-
pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
P(hir::Expr {
id: e.id,
// let placer = <placer_expr> ;
let s1 = {
let placer_expr = signal_block_expr(lctx,
- vec![],
+ hir_vec![],
placer_expr,
e.span,
hir::PopUnstableBlock,
// let mut place = Placer::make_place(placer);
let s2 = {
let placer = expr_ident(lctx, e.span, placer_ident, None);
- let call = make_call(lctx, &make_place, vec![placer]);
+ let call = make_call(lctx, &make_place, hir_vec![placer]);
mk_stmt_let_mut(lctx, place_ident, call)
};
// let p_ptr = Place::pointer(&mut place);
let s3 = {
let agent = expr_ident(lctx, e.span, place_ident, None);
- let args = vec![expr_mut_addr_of(lctx, e.span, agent, None)];
+ let args = hir_vec![expr_mut_addr_of(lctx, e.span, agent, None)];
let call = make_call(lctx, &place_pointer, args);
mk_stmt_let(lctx, p_ptr_ident, call)
};
// pop_unsafe!(EXPR));
let pop_unsafe_expr = {
let value_expr = signal_block_expr(lctx,
- vec![],
+ hir_vec![],
value_expr,
e.span,
hir::PopUnstableBlock,
None);
signal_block_expr(lctx,
- vec![],
+ hir_vec![],
value_expr,
e.span,
hir::PopUnsafeBlock(hir::CompilerGenerated), None)
let ptr = expr_ident(lctx, e.span, p_ptr_ident, None);
let call_move_val_init =
hir::StmtSemi(
- make_call(lctx, &move_val_init, vec![ptr, pop_unsafe_expr]),
+ make_call(lctx, &move_val_init, hir_vec![ptr, pop_unsafe_expr]),
lctx.next_id());
let call_move_val_init = respan(e.span, call_move_val_init);
let place = expr_ident(lctx, e.span, place_ident, None);
- let call = make_call(lctx, &inplace_finalize, vec![place]);
+ let call = make_call(lctx, &inplace_finalize, hir_vec![place]);
signal_block_expr(lctx,
- vec![call_move_val_init],
+ hir_vec![call_move_val_init],
call,
e.span,
hir::PushUnsafeBlock(hir::CompilerGenerated), None)
};
signal_block_expr(lctx,
- vec![s1, s2, s3],
+ hir_vec![s1, s2, s3],
expr,
e.span,
hir::PushUnstableBlock,
let expr = lower_expr(lctx, expr);
hir::ExprCast(expr, lower_ty(lctx, ty))
}
+ ExprType(ref expr, ref ty) => {
+ let expr = lower_expr(lctx, expr);
+ hir::ExprType(expr, lower_ty(lctx, ty))
+ }
ExprAddrOf(m, ref ohs) => {
let m = lower_mutability(lctx, m);
let ohs = lower_expr(lctx, ohs);
let els = lower_expr(lctx, els);
let id = lctx.next_id();
let blk = P(hir::Block {
- stmts: vec![],
+ stmts: hir_vec![],
expr: Some(els),
id: id,
rules: hir::DefaultBlock,
.collect(),
asm: asm.clone(),
asm_str_style: asm_str_style,
- clobbers: clobbers.clone(),
+ clobbers: clobbers.clone().into(),
volatile: volatile,
alignstack: alignstack,
dialect: dialect,
let pat_arm = {
let body = lower_block(lctx, body);
let body_expr = expr_block(lctx, body, None);
- arm(vec![lower_pat(lctx, pat)], body_expr)
+ arm(hir_vec![lower_pat(lctx, pat)], body_expr)
};
// `[_ if <else_opt_if_cond> => <else_opt_if_body>,]`
hir::ExprIf(cond, then, else_opt) => {
let pat_under = pat_wild(lctx, e.span);
arms.push(hir::Arm {
- attrs: vec![],
- pats: vec![pat_under],
+ attrs: hir_vec![],
+ pats: hir_vec![pat_under],
guard: Some(cond),
body: expr_block(lctx, then, None),
});
let pat_under = pat_wild(lctx, e.span);
let else_expr =
else_opt.unwrap_or_else(
- || expr_tuple(lctx, e.span, vec![], None));
- arm(vec![pat_under], else_expr)
+ || expr_tuple(lctx, e.span, hir_vec![], None));
+ arm(hir_vec![pat_under], else_expr)
};
let mut arms = Vec::with_capacity(else_if_arms.len() + 2);
expr(lctx,
e.span,
hir::ExprMatch(sub_expr,
- arms,
+ arms.into(),
hir::MatchSource::IfLetDesugar {
contains_else_clause: contains_else_clause,
}),
let pat_arm = {
let body = lower_block(lctx, body);
let body_expr = expr_block(lctx, body, None);
- arm(vec![lower_pat(lctx, pat)], body_expr)
+ arm(hir_vec![lower_pat(lctx, pat)], body_expr)
};
// `_ => break`
let break_arm = {
let pat_under = pat_wild(lctx, e.span);
let break_expr = expr_break(lctx, e.span, None);
- arm(vec![pat_under], break_expr)
+ arm(hir_vec![pat_under], break_expr)
};
// `match <sub_expr> { ... }`
- let arms = vec![pat_arm, break_arm];
+ let arms = hir_vec![pat_arm, break_arm];
let sub_expr = lower_expr(lctx, sub_expr);
let match_expr = expr(lctx,
e.span,
let pat = lower_pat(lctx, pat);
let some_pat = pat_some(lctx, e.span, pat);
- arm(vec![some_pat], body_expr)
+ arm(hir_vec![some_pat], body_expr)
};
// `::std::option::Option::None => break`
let break_arm = {
let break_expr = expr_break(lctx, e.span, None);
- arm(vec![pat_none(lctx, e.span)], break_expr)
+ arm(hir_vec![pat_none(lctx, e.span)], break_expr)
};
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
let next_expr = expr_call(lctx,
e.span,
next_path,
- vec![ref_mut_iter],
+ hir_vec![ref_mut_iter],
None);
- let arms = vec![pat_arm, break_arm];
+ let arms = hir_vec![pat_arm, break_arm];
expr(lctx,
e.span,
e.span,
iter,
hir::BindByValue(hir::MutMutable));
- arm(vec![iter_pat], loop_expr)
+ arm(hir_vec![iter_pat], loop_expr)
};
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
};
let into_iter = expr_path(lctx, into_iter_path, None);
- expr_call(lctx, e.span, into_iter, vec![head], None)
+ expr_call(lctx, e.span, into_iter, hir_vec![head], None)
};
let match_expr = expr_match(lctx,
e.span,
into_iter_expr,
- vec![iter_arm],
+ hir_vec![iter_arm],
hir::MatchSource::ForLoopDesugar,
None);
- // `{ let result = ...; result }`
- let result_ident = lctx.str_to_ident("result");
+ // `{ let _result = ...; _result }`
+ // underscore prevents an unused_variables lint if the head diverges
+ let result_ident = lctx.str_to_ident("_result");
let let_stmt = stmt_let(lctx, e.span, false, result_ident, match_expr, None);
let result = expr_ident(lctx, e.span, result_ident, None);
- let block = block_all(lctx, e.span, vec![let_stmt], Some(result));
+ let block = block_all(lctx, e.span, hir_vec![let_stmt], Some(result));
// add the attributes to the outer returned expr node
expr_block(lctx, block, e.attrs.clone())
});
pub fn lower_binding_mode(lctx: &LoweringContext, b: &BindingMode) -> hir::BindingMode {
match *b {
- BindByRef(m) => hir::BindByRef(lower_mutability(lctx, m)),
- BindByValue(m) => hir::BindByValue(lower_mutability(lctx, m)),
+ BindingMode::ByRef(m) => hir::BindByRef(lower_mutability(lctx, m)),
+ BindingMode::ByValue(m) => hir::BindByValue(lower_mutability(lctx, m)),
}
}
// Helper methods for building HIR.
-fn arm(pats: Vec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
+fn arm(pats: hir::HirVec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
hir::Arm {
- attrs: vec![],
+ attrs: hir_vec![],
pats: pats,
guard: None,
body: expr,
fn expr_call(lctx: &LoweringContext,
span: Span,
e: P<hir::Expr>,
- args: Vec<P<hir::Expr>>,
+ args: hir::HirVec<P<hir::Expr>>,
attrs: ThinAttributes)
-> P<hir::Expr> {
expr(lctx, span, hir::ExprCall(e, args), attrs)
fn expr_match(lctx: &LoweringContext,
span: Span,
arg: P<hir::Expr>,
- arms: Vec<hir::Arm>,
+ arms: hir::HirVec<hir::Arm>,
source: hir::MatchSource,
attrs: ThinAttributes)
-> P<hir::Expr> {
expr(lctx, b.span, hir::ExprBlock(b), attrs)
}
-fn expr_tuple(lctx: &LoweringContext, sp: Span, exprs: Vec<P<hir::Expr>>,
+fn expr_tuple(lctx: &LoweringContext, sp: Span, exprs: hir::HirVec<P<hir::Expr>>,
attrs: ThinAttributes) -> P<hir::Expr> {
expr(lctx, sp, hir::ExprTup(exprs), attrs)
}
}
fn block_expr(lctx: &LoweringContext, expr: P<hir::Expr>) -> P<hir::Block> {
- block_all(lctx, expr.span, Vec::new(), Some(expr))
+ block_all(lctx, expr.span, hir::HirVec::new(), Some(expr))
}
fn block_all(lctx: &LoweringContext,
span: Span,
- stmts: Vec<hir::Stmt>,
+ stmts: hir::HirVec<hir::Stmt>,
expr: Option<P<hir::Expr>>)
-> P<hir::Block> {
P(hir::Block {
fn pat_some(lctx: &LoweringContext, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
let some = std_path(lctx, &["option", "Option", "Some"]);
let path = path_global(span, some);
- pat_enum(lctx, span, path, vec![pat])
+ pat_enum(lctx, span, path, hir_vec![pat])
}
fn pat_none(lctx: &LoweringContext, span: Span) -> P<hir::Pat> {
let none = std_path(lctx, &["option", "Option", "None"]);
let path = path_global(span, none);
- pat_enum(lctx, span, path, vec![])
+ pat_enum(lctx, span, path, hir_vec![])
}
fn pat_enum(lctx: &LoweringContext,
span: Span,
path: hir::Path,
- subpats: Vec<P<hir::Pat>>)
+ subpats: hir::HirVec<P<hir::Pat>>)
-> P<hir::Pat> {
let pt = hir::PatEnum(path, Some(subpats));
pat(lctx, span, pt)
}
fn path(span: Span, strs: Vec<hir::Ident>) -> hir::Path {
- path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new())
+ path_all(span, false, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new())
}
fn path_global(span: Span, strs: Vec<hir::Ident>) -> hir::Path {
- path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new())
+ path_all(span, true, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new())
}
fn path_all(sp: Span,
global: bool,
mut idents: Vec<hir::Ident>,
- lifetimes: Vec<hir::Lifetime>,
- types: Vec<P<hir::Ty>>,
- bindings: Vec<hir::TypeBinding>)
+ lifetimes: hir::HirVec<hir::Lifetime>,
+ types: hir::HirVec<P<hir::Ty>>,
+ bindings: hir::HirVec<hir::TypeBinding>)
-> hir::Path {
let last_identifier = idents.pop().unwrap();
let mut segments: Vec<hir::PathSegment> = idents.into_iter()
identifier: last_identifier,
parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
lifetimes: lifetimes,
- types: OwnedSlice::from_vec(types),
- bindings: OwnedSlice::from_vec(bindings),
+ types: types,
+ bindings: bindings,
}),
});
hir::Path {
span: sp,
global: global,
- segments: segments,
+ segments: segments.into(),
}
}
}
fn signal_block_expr(lctx: &LoweringContext,
- stmts: Vec<hir::Stmt>,
+ stmts: hir::HirVec<hir::Stmt>,
expr: P<hir::Expr>,
span: Span,
rule: hir::BlockCheckMode,
let ast_while_let = assigner.fold_expr(ast_while_let);
let ast_for = quote_expr!(&cx,
for i in 0..10 {
- foo(i);
+ for j in 0..10 {
+ foo(i, j);
+ }
});
let ast_for = assigner.fold_expr(ast_for);
let ast_in = quote_expr!(&cx, in HEAP { foo() });