rustc: separate bodies for static/(associated)const and embedded constants.

This commit is contained in:
Eduard-Mihai Burtescu 2016-12-21 12:32:59 +02:00
parent 864928297d
commit e64f64a2fc
72 changed files with 637 additions and 655 deletions

View File

@ -327,10 +327,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
self.opt_expr(base, field_cfg) self.opt_expr(base, field_cfg)
} }
hir::ExprRepeat(ref elem, ref count) => {
self.straightline(expr, pred, [elem, count].iter().map(|&e| &**e))
}
hir::ExprAssign(ref l, ref r) | hir::ExprAssign(ref l, ref r) |
hir::ExprAssignOp(_, ref l, ref r) => { hir::ExprAssignOp(_, ref l, ref r) => {
self.straightline(expr, pred, [r, l].iter().map(|&e| &**e)) self.straightline(expr, pred, [r, l].iter().map(|&e| &**e))
@ -347,7 +343,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
hir::ExprType(ref e, _) | hir::ExprType(ref e, _) |
hir::ExprUnary(_, ref e) | hir::ExprUnary(_, ref e) |
hir::ExprField(ref e, _) | hir::ExprField(ref e, _) |
hir::ExprTupField(ref e, _) => { hir::ExprTupField(ref e, _) |
hir::ExprRepeat(ref e, _) => {
self.straightline(expr, pred, Some(&**e).into_iter()) self.straightline(expr, pred, Some(&**e).into_iter())
} }

View File

@ -50,7 +50,6 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>
let task_id = (self.dep_node_fn)(trait_item_def_id); let task_id = (self.dep_node_fn)(trait_item_def_id);
let _task = self.tcx.dep_graph.in_task(task_id.clone()); let _task = self.tcx.dep_graph.in_task(task_id.clone());
debug!("Started task {:?}", task_id); debug!("Started task {:?}", task_id);
assert!(!self.tcx.map.is_inlined_def_id(trait_item_def_id));
self.tcx.dep_graph.read(DepNode::Hir(trait_item_def_id)); self.tcx.dep_graph.read(DepNode::Hir(trait_item_def_id));
self.visitor.visit_trait_item(i); self.visitor.visit_trait_item(i);
debug!("Ended task {:?}", task_id); debug!("Ended task {:?}", task_id);

View File

@ -203,10 +203,10 @@ pub trait Visitor<'v> : Sized {
/// visit_nested_item, does nothing by default unless you override /// visit_nested_item, does nothing by default unless you override
/// `nested_visit_map` to return `Some(_)`, in which case it will walk the /// `nested_visit_map` to return `Some(_)`, in which case it will walk the
/// body. /// body.
fn visit_body(&mut self, id: ExprId) { fn visit_nested_body(&mut self, id: BodyId) {
let opt_expr = self.nested_visit_map().intra().map(|map| map.expr(id)); let opt_body = self.nested_visit_map().intra().map(|map| map.body(id));
if let Some(expr) = opt_expr { if let Some(body) = opt_body {
self.visit_expr(expr); self.visit_body(body);
} }
} }
@ -216,6 +216,10 @@ pub trait Visitor<'v> : Sized {
walk_item(self, i) walk_item(self, i)
} }
fn visit_body(&mut self, b: &'v Body) {
walk_body(self, b);
}
/// When invoking `visit_all_item_likes()`, you need to supply an /// When invoking `visit_all_item_likes()`, you need to supply an
/// item-like visitor. This method converts a "intra-visit" /// item-like visitor. This method converts a "intra-visit"
/// visitor into an item-like visitor that walks the entire tree. /// visitor into an item-like visitor that walks the entire tree.
@ -264,8 +268,6 @@ pub trait Visitor<'v> : Sized {
fn visit_expr(&mut self, ex: &'v Expr) { fn visit_expr(&mut self, ex: &'v Expr) {
walk_expr(self, ex) walk_expr(self, ex)
} }
fn visit_expr_post(&mut self, _ex: &'v Expr) {
}
fn visit_ty(&mut self, t: &'v Ty) { fn visit_ty(&mut self, t: &'v Ty) {
walk_ty(self, t) walk_ty(self, t)
} }
@ -278,7 +280,7 @@ pub trait Visitor<'v> : Sized {
fn visit_fn_decl(&mut self, fd: &'v FnDecl) { fn visit_fn_decl(&mut self, fd: &'v FnDecl) {
walk_fn_decl(self, fd) walk_fn_decl(self, fd)
} }
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: ExprId, s: Span, id: NodeId) { fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: BodyId, s: Span, id: NodeId) {
walk_fn(self, fk, fd, b, s, id) walk_fn(self, fk, fd, b, s, id)
} }
fn visit_trait_item(&mut self, ti: &'v TraitItem) { fn visit_trait_item(&mut self, ti: &'v TraitItem) {
@ -392,6 +394,10 @@ pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_node_i
} }
} }
pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) {
visitor.visit_expr(&body.value);
}
pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) { pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
visitor.visit_id(local.id); visitor.visit_id(local.id);
visitor.visit_pat(&local.pat); visitor.visit_pat(&local.pat);
@ -437,11 +443,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_id(item.id); visitor.visit_id(item.id);
visitor.visit_path(path, item.id); visitor.visit_path(path, item.id);
} }
ItemStatic(ref typ, _, ref expr) | ItemStatic(ref typ, _, body) |
ItemConst(ref typ, ref expr) => { ItemConst(ref typ, body) => {
visitor.visit_id(item.id); visitor.visit_id(item.id);
visitor.visit_ty(typ); visitor.visit_ty(typ);
visitor.visit_expr(expr); visitor.visit_nested_body(body);
} }
ItemFn(ref declaration, unsafety, constness, abi, ref generics, body_id) => { ItemFn(ref declaration, unsafety, constness, abi, ref generics, body_id) => {
visitor.visit_fn(FnKind::ItemFn(item.name, visitor.visit_fn(FnKind::ItemFn(item.name,
@ -523,7 +529,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
generics, generics,
parent_item_id, parent_item_id,
variant.span); variant.span);
walk_list!(visitor, visit_expr, &variant.node.disr_expr); walk_list!(visitor, visit_nested_body, variant.node.disr_expr);
walk_list!(visitor, visit_attribute, &variant.node.attrs); walk_list!(visitor, visit_attribute, &variant.node.attrs);
} }
@ -556,9 +562,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
visitor.visit_ty(ty); visitor.visit_ty(ty);
walk_list!(visitor, visit_ty_param_bound, bounds); walk_list!(visitor, visit_ty_param_bound, bounds);
} }
TyArray(ref ty, ref expression) => { TyArray(ref ty, length) => {
visitor.visit_ty(ty); visitor.visit_ty(ty);
visitor.visit_expr(expression) visitor.visit_nested_body(length)
} }
TyPolyTraitRef(ref bounds) => { TyPolyTraitRef(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds); walk_list!(visitor, visit_ty_param_bound, bounds);
@ -566,8 +572,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
TyImplTrait(ref bounds) => { TyImplTrait(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds); walk_list!(visitor, visit_ty_param_bound, bounds);
} }
TyTypeof(ref expression) => { TyTypeof(expression) => {
visitor.visit_expr(expression) visitor.visit_nested_body(expression)
} }
TyInfer => {} TyInfer => {}
} }
@ -775,35 +781,23 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V, pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
function_kind: FnKind<'v>, function_kind: FnKind<'v>,
function_declaration: &'v FnDecl, function_declaration: &'v FnDecl,
body_id: ExprId, body_id: BodyId,
_span: Span, _span: Span,
id: NodeId) { id: NodeId) {
visitor.visit_id(id); visitor.visit_id(id);
visitor.visit_fn_decl(function_declaration); visitor.visit_fn_decl(function_declaration);
walk_fn_kind(visitor, function_kind); walk_fn_kind(visitor, function_kind);
visitor.visit_body(body_id) visitor.visit_nested_body(body_id)
}
pub fn walk_fn_with_body<'v, V: Visitor<'v>>(visitor: &mut V,
function_kind: FnKind<'v>,
function_declaration: &'v FnDecl,
body: &'v Expr,
_span: Span,
id: NodeId) {
visitor.visit_id(id);
visitor.visit_fn_decl(function_declaration);
walk_fn_kind(visitor, function_kind);
visitor.visit_expr(body)
} }
pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) { pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
visitor.visit_name(trait_item.span, trait_item.name); visitor.visit_name(trait_item.span, trait_item.name);
walk_list!(visitor, visit_attribute, &trait_item.attrs); walk_list!(visitor, visit_attribute, &trait_item.attrs);
match trait_item.node { match trait_item.node {
TraitItemKind::Const(ref ty, ref default) => { TraitItemKind::Const(ref ty, default) => {
visitor.visit_id(trait_item.id); visitor.visit_id(trait_item.id);
visitor.visit_ty(ty); visitor.visit_ty(ty);
walk_list!(visitor, visit_expr, default); walk_list!(visitor, visit_nested_body, default);
} }
TraitItemKind::Method(ref sig, None) => { TraitItemKind::Method(ref sig, None) => {
visitor.visit_id(trait_item.id); visitor.visit_id(trait_item.id);
@ -846,10 +840,10 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
visitor.visit_defaultness(defaultness); visitor.visit_defaultness(defaultness);
walk_list!(visitor, visit_attribute, attrs); walk_list!(visitor, visit_attribute, attrs);
match *node { match *node {
ImplItemKind::Const(ref ty, ref expr) => { ImplItemKind::Const(ref ty, body) => {
visitor.visit_id(impl_item.id); visitor.visit_id(impl_item.id);
visitor.visit_ty(ty); visitor.visit_ty(ty);
visitor.visit_expr(expr); visitor.visit_nested_body(body);
} }
ImplItemKind::Method(ref sig, body_id) => { ImplItemKind::Method(ref sig, body_id) => {
visitor.visit_fn(FnKind::Method(impl_item.name, visitor.visit_fn(FnKind::Method(impl_item.name,
@ -928,9 +922,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
ExprArray(ref subexpressions) => { ExprArray(ref subexpressions) => {
walk_list!(visitor, visit_expr, subexpressions); walk_list!(visitor, visit_expr, subexpressions);
} }
ExprRepeat(ref element, ref count) => { ExprRepeat(ref element, count) => {
visitor.visit_expr(element); visitor.visit_expr(element);
visitor.visit_expr(count) visitor.visit_nested_body(count)
} }
ExprStruct(ref qpath, ref fields, ref optional_base) => { ExprStruct(ref qpath, ref fields, ref optional_base) => {
visitor.visit_qpath(qpath, expression.id, expression.span); visitor.visit_qpath(qpath, expression.id, expression.span);
@ -1037,8 +1031,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
} }
} }
} }
visitor.visit_expr_post(expression)
} }
pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) { pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
@ -1125,12 +1117,12 @@ impl<'a, 'ast> Visitor<'ast> for IdRangeComputingVisitor<'a, 'ast> {
/// Computes the id range for a single fn body, ignoring nested items. /// Computes the id range for a single fn body, ignoring nested items.
pub fn compute_id_range_for_fn_body<'v>(fk: FnKind<'v>, pub fn compute_id_range_for_fn_body<'v>(fk: FnKind<'v>,
decl: &'v FnDecl, decl: &'v FnDecl,
body: &'v Expr, body: BodyId,
sp: Span, sp: Span,
id: NodeId, id: NodeId,
map: &map::Map<'v>) map: &map::Map<'v>)
-> IdRange { -> IdRange {
let mut visitor = IdRangeComputingVisitor::new(map); let mut visitor = IdRangeComputingVisitor::new(map);
walk_fn_with_body(&mut visitor, fk, decl, body, sp, id); visitor.visit_fn(fk, decl, body, sp, id);
visitor.result() visitor.result()
} }

View File

@ -46,8 +46,7 @@ use hir::map::definitions::DefPathData;
use hir::def_id::{DefIndex, DefId}; use hir::def_id::{DefIndex, DefId};
use hir::def::{Def, PathResolution}; use hir::def::{Def, PathResolution};
use session::Session; use session::Session;
use util::nodemap::NodeMap; use util::nodemap::{NodeMap, FxHashMap};
use rustc_data_structures::fnv::FnvHashMap;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::iter; use std::iter;
@ -70,7 +69,6 @@ pub struct LoweringContext<'a> {
// the form of a DefIndex) so that if we create a new node which introduces // 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. // a definition, then we can properly create the def id.
parent_def: Option<DefIndex>, parent_def: Option<DefIndex>,
exprs: FnvHashMap<hir::ExprId, hir::Expr>,
resolver: &'a mut Resolver, resolver: &'a mut Resolver,
/// The items being lowered are collected here. /// The items being lowered are collected here.
@ -78,6 +76,7 @@ pub struct LoweringContext<'a> {
trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>, trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>,
impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>, impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
bodies: FxHashMap<hir::BodyId, hir::Body>,
} }
pub trait Resolver { pub trait Resolver {
@ -105,11 +104,11 @@ pub fn lower_crate(sess: &Session,
crate_root: std_inject::injected_crate_name(krate), crate_root: std_inject::injected_crate_name(krate),
sess: sess, sess: sess,
parent_def: None, parent_def: None,
exprs: FnvHashMap(),
resolver: resolver, resolver: resolver,
items: BTreeMap::new(), items: BTreeMap::new(),
trait_items: BTreeMap::new(), trait_items: BTreeMap::new(),
impl_items: BTreeMap::new(), impl_items: BTreeMap::new(),
bodies: FxHashMap(),
}.lower_crate(krate) }.lower_crate(krate)
} }
@ -136,7 +135,7 @@ impl<'a> LoweringContext<'a> {
items: self.items, items: self.items,
trait_items: self.trait_items, trait_items: self.trait_items,
impl_items: self.impl_items, impl_items: self.impl_items,
exprs: self.exprs, bodies: self.bodies,
} }
} }
@ -171,9 +170,12 @@ impl<'a> LoweringContext<'a> {
visit::walk_crate(&mut item_lowerer, c); visit::walk_crate(&mut item_lowerer, c);
} }
fn record_expr(&mut self, expr: hir::Expr) -> hir::ExprId { fn record_body(&mut self, value: hir::Expr) -> hir::BodyId {
let id = hir::ExprId(expr.id); let body = hir::Body {
self.exprs.insert(id, expr); value: value
};
let id = body.id();
self.bodies.insert(id, body);
id id
} }
@ -305,11 +307,14 @@ impl<'a> LoweringContext<'a> {
TyKind::ObjectSum(ref ty, ref bounds) => { TyKind::ObjectSum(ref ty, ref bounds) => {
hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds)) hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds))
} }
TyKind::Array(ref ty, ref e) => { TyKind::Array(ref ty, ref length) => {
hir::TyArray(self.lower_ty(ty), P(self.lower_expr(e))) let length = self.lower_expr(length);
hir::TyArray(self.lower_ty(ty),
self.record_body(length))
} }
TyKind::Typeof(ref expr) => { TyKind::Typeof(ref expr) => {
hir::TyTypeof(P(self.lower_expr(expr))) let expr = self.lower_expr(expr);
hir::TyTypeof(self.record_body(expr))
} }
TyKind::PolyTraitRef(ref bounds) => { TyKind::PolyTraitRef(ref bounds) => {
hir::TyPolyTraitRef(self.lower_bounds(bounds)) hir::TyPolyTraitRef(self.lower_bounds(bounds))
@ -336,7 +341,10 @@ impl<'a> LoweringContext<'a> {
name: v.node.name.name, name: v.node.name.name,
attrs: self.lower_attrs(&v.node.attrs), attrs: self.lower_attrs(&v.node.attrs),
data: self.lower_variant_data(&v.node.data), data: self.lower_variant_data(&v.node.data),
disr_expr: v.node.disr_expr.as_ref().map(|e| P(self.lower_expr(e))), disr_expr: v.node.disr_expr.as_ref().map(|e| {
let e = self.lower_expr(e);
self.record_body(e)
}),
}, },
span: v.span, span: v.span,
} }
@ -858,17 +866,20 @@ impl<'a> LoweringContext<'a> {
hir::ItemUse(path, kind) hir::ItemUse(path, kind)
} }
ItemKind::Static(ref t, m, ref e) => { ItemKind::Static(ref t, m, ref e) => {
let value = self.lower_expr(e);
hir::ItemStatic(self.lower_ty(t), hir::ItemStatic(self.lower_ty(t),
self.lower_mutability(m), self.lower_mutability(m),
P(self.lower_expr(e))) self.record_body(value))
} }
ItemKind::Const(ref t, ref e) => { ItemKind::Const(ref t, ref e) => {
hir::ItemConst(self.lower_ty(t), P(self.lower_expr(e))) let value = self.lower_expr(e);
hir::ItemConst(self.lower_ty(t),
self.record_body(value))
} }
ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
let body = self.lower_block(body); let body = self.lower_block(body);
let body = self.expr_block(body, ThinVec::new()); let body = self.expr_block(body, ThinVec::new());
let body_id = self.record_expr(body); let body_id = self.record_body(body);
hir::ItemFn(self.lower_fn_decl(decl), hir::ItemFn(self.lower_fn_decl(decl),
self.lower_unsafety(unsafety), self.lower_unsafety(unsafety),
self.lower_constness(constness), self.lower_constness(constness),
@ -935,14 +946,17 @@ impl<'a> LoweringContext<'a> {
node: match i.node { node: match i.node {
TraitItemKind::Const(ref ty, ref default) => { TraitItemKind::Const(ref ty, ref default) => {
hir::TraitItemKind::Const(this.lower_ty(ty), hir::TraitItemKind::Const(this.lower_ty(ty),
default.as_ref().map(|x| P(this.lower_expr(x)))) default.as_ref().map(|x| {
let value = this.lower_expr(x);
this.record_body(value)
}))
} }
TraitItemKind::Method(ref sig, ref body) => { TraitItemKind::Method(ref sig, ref body) => {
hir::TraitItemKind::Method(this.lower_method_sig(sig), hir::TraitItemKind::Method(this.lower_method_sig(sig),
body.as_ref().map(|x| { body.as_ref().map(|x| {
let body = this.lower_block(x); let body = this.lower_block(x);
let expr = this.expr_block(body, ThinVec::new()); let expr = this.expr_block(body, ThinVec::new());
this.record_expr(expr) this.record_body(expr)
})) }))
} }
TraitItemKind::Type(ref bounds, ref default) => { TraitItemKind::Type(ref bounds, ref default) => {
@ -990,13 +1004,15 @@ impl<'a> LoweringContext<'a> {
defaultness: this.lower_defaultness(i.defaultness, true /* [1] */), defaultness: this.lower_defaultness(i.defaultness, true /* [1] */),
node: match i.node { node: match i.node {
ImplItemKind::Const(ref ty, ref expr) => { ImplItemKind::Const(ref ty, ref expr) => {
hir::ImplItemKind::Const(this.lower_ty(ty), P(this.lower_expr(expr))) let value = this.lower_expr(expr);
let body_id = this.record_body(value);
hir::ImplItemKind::Const(this.lower_ty(ty), body_id)
} }
ImplItemKind::Method(ref sig, ref body) => { ImplItemKind::Method(ref sig, ref body) => {
let body = this.lower_block(body); let body = this.lower_block(body);
let expr = this.expr_block(body, ThinVec::new()); let expr = this.expr_block(body, ThinVec::new());
let expr_id = this.record_expr(expr); let body_id = this.record_body(expr);
hir::ImplItemKind::Method(this.lower_method_sig(sig), expr_id) hir::ImplItemKind::Method(this.lower_method_sig(sig), body_id)
} }
ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)), ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)),
ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
@ -1350,8 +1366,8 @@ impl<'a> LoweringContext<'a> {
} }
ExprKind::Repeat(ref expr, ref count) => { ExprKind::Repeat(ref expr, ref count) => {
let expr = P(self.lower_expr(expr)); let expr = P(self.lower_expr(expr));
let count = P(self.lower_expr(count)); let count = self.lower_expr(count);
hir::ExprRepeat(expr, count) hir::ExprRepeat(expr, self.record_body(count))
} }
ExprKind::Tup(ref elts) => { ExprKind::Tup(ref elts) => {
hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect()) hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect())
@ -1434,7 +1450,7 @@ impl<'a> LoweringContext<'a> {
let expr = this.lower_expr(body); let expr = this.lower_expr(body);
hir::ExprClosure(this.lower_capture_clause(capture_clause), hir::ExprClosure(this.lower_capture_clause(capture_clause),
this.lower_fn_decl(decl), this.lower_fn_decl(decl),
this.record_expr(expr), this.record_body(expr),
fn_decl_span) fn_decl_span)
}) })
} }

View File

@ -48,7 +48,7 @@ pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; }
/// Components shared by fn-like things (fn items, methods, closures). /// Components shared by fn-like things (fn items, methods, closures).
pub struct FnParts<'a> { pub struct FnParts<'a> {
pub decl: &'a FnDecl, pub decl: &'a FnDecl,
pub body: ast::ExprId, pub body: ast::BodyId,
pub kind: FnKind<'a>, pub kind: FnKind<'a>,
pub span: Span, pub span: Span,
pub id: NodeId, pub id: NodeId,
@ -115,7 +115,7 @@ struct ItemFnParts<'a> {
abi: abi::Abi, abi: abi::Abi,
vis: &'a ast::Visibility, vis: &'a ast::Visibility,
generics: &'a ast::Generics, generics: &'a ast::Generics,
body: ast::ExprId, body: ast::BodyId,
id: NodeId, id: NodeId,
span: Span, span: Span,
attrs: &'a [Attribute], attrs: &'a [Attribute],
@ -125,14 +125,14 @@ struct ItemFnParts<'a> {
/// for use when implementing FnLikeNode operations. /// for use when implementing FnLikeNode operations.
struct ClosureParts<'a> { struct ClosureParts<'a> {
decl: &'a FnDecl, decl: &'a FnDecl,
body: ast::ExprId, body: ast::BodyId,
id: NodeId, id: NodeId,
span: Span, span: Span,
attrs: &'a [Attribute], attrs: &'a [Attribute],
} }
impl<'a> ClosureParts<'a> { impl<'a> ClosureParts<'a> {
fn new(d: &'a FnDecl, b: ast::ExprId, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self { fn new(d: &'a FnDecl, b: ast::BodyId, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
ClosureParts { ClosureParts {
decl: d, decl: d,
body: b, body: b,
@ -172,9 +172,9 @@ impl<'a> FnLikeNode<'a> {
} }
} }
pub fn body(self) -> ast::ExprId { pub fn body(self) -> ast::BodyId {
self.handle(|i: ItemFnParts<'a>| i.body, self.handle(|i: ItemFnParts<'a>| i.body,
|_, _, _: &'a ast::MethodSig, _, body: ast::ExprId, _, _| body, |_, _, _: &'a ast::MethodSig, _, body: ast::BodyId, _, _| body,
|c: ClosureParts<'a>| c.body) |c: ClosureParts<'a>| c.body)
} }
@ -227,7 +227,7 @@ impl<'a> FnLikeNode<'a> {
Name, Name,
&'a ast::MethodSig, &'a ast::MethodSig,
Option<&'a ast::Visibility>, Option<&'a ast::Visibility>,
ast::ExprId, ast::BodyId,
Span, Span,
&'a [Attribute]) &'a [Attribute])
-> A, -> A,

View File

@ -99,15 +99,21 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
} }
fn visit_nested_trait_item(&mut self, item_id: TraitItemId) { fn visit_nested_trait_item(&mut self, item_id: TraitItemId) {
if !self.ignore_nested_items {
self.visit_trait_item(self.krate.trait_item(item_id)) self.visit_trait_item(self.krate.trait_item(item_id))
} }
}
fn visit_nested_impl_item(&mut self, item_id: ImplItemId) { fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
if !self.ignore_nested_items {
self.visit_impl_item(self.krate.impl_item(item_id)) self.visit_impl_item(self.krate.impl_item(item_id))
} }
}
fn visit_body(&mut self, id: ExprId) { fn visit_nested_body(&mut self, id: BodyId) {
self.visit_expr(self.krate.expr(id)) if !self.ignore_nested_items {
self.visit_body(self.krate.body(id))
}
} }
fn visit_item(&mut self, i: &'ast Item) { fn visit_item(&mut self, i: &'ast Item) {
@ -117,11 +123,6 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
self.with_parent(i.id, |this| { self.with_parent(i.id, |this| {
match i.node { match i.node {
ItemEnum(ref enum_definition, _) => {
for v in &enum_definition.variants {
this.insert(v.node.data.id(), NodeVariant(v));
}
}
ItemStruct(ref struct_def, _) => { ItemStruct(ref struct_def, _) => {
// If this is a tuple-like struct, register the constructor. // If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() { if !struct_def.is_struct() {
@ -213,7 +214,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
} }
fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl, fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
b: ExprId, s: Span, id: NodeId) { b: BodyId, s: Span, id: NodeId) {
assert_eq!(self.parent_node, id); assert_eq!(self.parent_node, id);
intravisit::walk_fn(self, fk, fd, b, s, id); intravisit::walk_fn(self, fk, fd, b, s, id);
} }
@ -247,6 +248,14 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
self.insert_entry(macro_def.id, NotPresent); self.insert_entry(macro_def.id, NotPresent);
} }
fn visit_variant(&mut self, v: &'ast Variant, g: &'ast Generics, item_id: NodeId) {
let id = v.node.data.id();
self.insert(id, NodeVariant(v));
self.with_parent(id, |this| {
intravisit::walk_variant(this, v, g, item_id);
});
}
fn visit_struct_field(&mut self, field: &'ast StructField) { fn visit_struct_field(&mut self, field: &'ast StructField) {
self.insert(field.id, NodeField(field)); self.insert(field.id, NodeField(field));
self.with_parent(field.id, |this| { self.with_parent(field.id, |this| {

View File

@ -16,7 +16,7 @@ use syntax::ext::hygiene::Mark;
use syntax::visit; use syntax::visit;
use syntax::symbol::{Symbol, keywords}; use syntax::symbol::{Symbol, keywords};
/// Creates def ids for nodes in the HIR. /// Creates def ids for nodes in the AST.
pub struct DefCollector<'a> { pub struct DefCollector<'a> {
definitions: &'a mut Definitions, definitions: &'a mut Definitions,
parent_def: Option<DefIndex>, parent_def: Option<DefIndex>,

View File

@ -220,7 +220,6 @@ impl DefPath {
} }
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum DefPathData { pub enum DefPathData {
// Root: these should only be used for the root nodes, because // Root: these should only be used for the root nodes, because
@ -339,7 +338,7 @@ impl Definitions {
data, data,
self.table.def_key(self.node_to_def_index[&node_id])); self.table.def_key(self.node_to_def_index[&node_id]));
assert!(parent.is_some() ^ (data == DefPathData::CrateRoot)); assert_eq!(parent.is_some(), data != DefPathData::CrateRoot);
// Find a unique DefKey. This basically means incrementing the disambiguator // Find a unique DefKey. This basically means incrementing the disambiguator
// until we get no match. // until we get no match.

View File

@ -266,7 +266,6 @@ impl<'ast> Map<'ast> {
EntryTraitItem(_, item) => { EntryTraitItem(_, item) => {
let def_id = self.local_def_id(id); let def_id = self.local_def_id(id);
assert!(!self.is_inlined_def_id(def_id));
if let Some(last_id) = last_expr { if let Some(last_id) = last_expr {
// The body of the item may have a separate dep node // The body of the item may have a separate dep node
@ -289,8 +288,19 @@ impl<'ast> Map<'ast> {
return DepNode::Hir(def_id); return DepNode::Hir(def_id);
} }
EntryVariant(p, v) => {
id = p;
if last_expr.is_some() {
if v.node.disr_expr.map(|e| e.node_id) == last_expr {
// The enum parent holds both Hir and HirBody nodes.
let def_id = self.local_def_id(id);
return DepNode::HirBody(def_id);
}
}
}
EntryForeignItem(p, _) | EntryForeignItem(p, _) |
EntryVariant(p, _) |
EntryField(p, _) | EntryField(p, _) |
EntryStmt(p, _) | EntryStmt(p, _) |
EntryTy(p, _) | EntryTy(p, _) |
@ -317,7 +327,7 @@ impl<'ast> Map<'ast> {
bug!("node {} has inlined ancestor but is not inlined", id0), bug!("node {} has inlined ancestor but is not inlined", id0),
NotPresent => NotPresent =>
// Some nodes, notably struct fields, are not // Some nodes, notably macro definitions, are not
// present in the map for whatever reason, but // present in the map for whatever reason, but
// they *do* have def-ids. So if we encounter an // they *do* have def-ids. So if we encounter an
// empty hole, check for that case. // empty hole, check for that case.
@ -369,21 +379,25 @@ impl<'ast> Map<'ast> {
fn is_item_body(&self, node_id: NodeId, item: &Item) -> bool { fn is_item_body(&self, node_id: NodeId, item: &Item) -> bool {
match item.node { match item.node {
ItemFn(_, _, _, _, _, body) => body.node_id() == node_id, ItemConst(_, body) |
ItemStatic(.., body) |
ItemFn(_, _, _, _, _, body) => body.node_id == node_id,
_ => false _ => false
} }
} }
fn is_trait_item_body(&self, node_id: NodeId, item: &TraitItem) -> bool { fn is_trait_item_body(&self, node_id: NodeId, item: &TraitItem) -> bool {
match item.node { match item.node {
TraitItemKind::Method(_, Some(body)) => body.node_id() == node_id, TraitItemKind::Const(_, Some(body)) |
TraitItemKind::Method(_, Some(body)) => body.node_id == node_id,
_ => false _ => false
} }
} }
fn is_impl_item_body(&self, node_id: NodeId, item: &ImplItem) -> bool { fn is_impl_item_body(&self, node_id: NodeId, item: &ImplItem) -> bool {
match item.node { match item.node {
ImplItemKind::Method(_, body) => body.node_id() == node_id, ImplItemKind::Const(_, body) |
ImplItemKind::Method(_, body) => body.node_id == node_id,
_ => false _ => false
} }
} }
@ -459,6 +473,14 @@ impl<'ast> Map<'ast> {
self.forest.krate.impl_item(id) self.forest.krate.impl_item(id)
} }
pub fn body(&self, id: BodyId) -> &'ast Body {
self.read(id.node_id);
// NB: intentionally bypass `self.forest.krate()` so that we
// do not trigger a read of the whole krate here
self.forest.krate.body(id)
}
/// Get the attributes on the krate. This is preferable to /// Get the attributes on the krate. This is preferable to
/// invoking `krate.attrs` because it registers a tighter /// invoking `krate.attrs` because it registers a tighter
/// dep-graph access. /// dep-graph access.
@ -709,10 +731,6 @@ impl<'ast> Map<'ast> {
} }
} }
pub fn expr(&self, id: ExprId) -> &'ast Expr {
self.expect_expr(id.node_id())
}
/// Returns the name associated with the given NodeId's AST. /// Returns the name associated with the given NodeId's AST.
pub fn name(&self, id: NodeId) -> Name { pub fn name(&self, id: NodeId) -> Name {
match self.get(id) { match self.get(id) {
@ -793,7 +811,7 @@ impl<'ast> Map<'ast> {
Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v), Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v),
Some(RootCrate) => self.forest.krate.span, Some(RootCrate) => self.forest.krate.span,
Some(RootInlinedParent(parent)) => parent.body.span, Some(RootInlinedParent(parent)) => parent.body.value.span,
Some(NotPresent) | None => { Some(NotPresent) | None => {
bug!("hir::map::Map::span: id not in map: {:?}", id) bug!("hir::map::Map::span: id not in map: {:?}", id)
} }

View File

@ -31,8 +31,7 @@ pub use self::PathParameters::*;
use hir::def::Def; use hir::def::Def;
use hir::def_id::DefId; use hir::def_id::DefId;
use util::nodemap::{NodeMap, FxHashSet}; use util::nodemap::{NodeMap, FxHashMap, FxHashSet};
use rustc_data_structures::fnv::FnvHashMap;
use syntax_pos::{Span, ExpnId, DUMMY_SP}; use syntax_pos::{Span, ExpnId, DUMMY_SP};
use syntax::codemap::{self, Spanned}; use syntax::codemap::{self, Spanned};
@ -40,7 +39,7 @@ use syntax::abi::Abi;
use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect}; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect};
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem}; use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
use syntax::ptr::P; use syntax::ptr::P;
use syntax::symbol::Symbol; use syntax::symbol::{Symbol, keywords};
use syntax::tokenstream::TokenTree; use syntax::tokenstream::TokenTree;
use syntax::util::ThinVec; use syntax::util::ThinVec;
@ -432,7 +431,7 @@ pub struct Crate {
pub trait_items: BTreeMap<TraitItemId, TraitItem>, pub trait_items: BTreeMap<TraitItemId, TraitItem>,
pub impl_items: BTreeMap<ImplItemId, ImplItem>, pub impl_items: BTreeMap<ImplItemId, ImplItem>,
pub exprs: FnvHashMap<ExprId, Expr>, pub bodies: FxHashMap<BodyId, Body>,
} }
impl Crate { impl Crate {
@ -472,8 +471,8 @@ impl Crate {
} }
} }
pub fn expr(&self, id: ExprId) -> &Expr { pub fn body(&self, id: BodyId) -> &Body {
&self.exprs[&id] &self.bodies[&id]
} }
} }
@ -862,11 +861,21 @@ pub enum UnsafeSource {
} }
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct ExprId(NodeId); pub struct BodyId {
pub node_id: NodeId,
}
impl ExprId { /// The body of a function or constant value.
pub fn node_id(self) -> NodeId { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
self.0 pub struct Body {
pub value: Expr
}
impl Body {
pub fn id(&self) -> BodyId {
BodyId {
node_id: self.value.id
}
} }
} }
@ -879,12 +888,6 @@ pub struct Expr {
pub attrs: ThinVec<Attribute>, pub attrs: ThinVec<Attribute>,
} }
impl Expr {
pub fn expr_id(&self) -> ExprId {
ExprId(self.id)
}
}
impl fmt::Debug for Expr { impl fmt::Debug for Expr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "expr({}: {})", self.id, print::expr_to_string(self)) write!(f, "expr({}: {})", self.id, print::expr_to_string(self))
@ -944,7 +947,7 @@ pub enum Expr_ {
/// A closure (for example, `move |a, b, c| {a + b + c}`). /// A closure (for example, `move |a, b, c| {a + b + c}`).
/// ///
/// The final span is the span of the argument block `|...|` /// The final span is the span of the argument block `|...|`
ExprClosure(CaptureClause, P<FnDecl>, ExprId, Span), ExprClosure(CaptureClause, P<FnDecl>, BodyId, Span),
/// A block (`{ ... }`) /// A block (`{ ... }`)
ExprBlock(P<Block>), ExprBlock(P<Block>),
@ -988,7 +991,7 @@ pub enum Expr_ {
/// ///
/// For example, `[1; 5]`. The first expression is the element /// For example, `[1; 5]`. The first expression is the element
/// to be repeated; the second is the number of times to repeat it. /// to be repeated; the second is the number of times to repeat it.
ExprRepeat(P<Expr>, P<Expr>), ExprRepeat(P<Expr>, BodyId),
} }
/// Optionally `Self`-qualified value/type path or associated extension. /// Optionally `Self`-qualified value/type path or associated extension.
@ -1104,9 +1107,9 @@ pub struct TraitItem {
pub enum TraitItemKind { pub enum TraitItemKind {
/// An associated constant with an optional value (otherwise `impl`s /// An associated constant with an optional value (otherwise `impl`s
/// must contain a value) /// must contain a value)
Const(P<Ty>, Option<P<Expr>>), Const(P<Ty>, Option<BodyId>),
/// A method with an optional body /// A method with an optional body
Method(MethodSig, Option<ExprId>), Method(MethodSig, Option<BodyId>),
/// An associated type with (possibly empty) bounds and optional concrete /// An associated type with (possibly empty) bounds and optional concrete
/// type /// type
Type(TyParamBounds, Option<P<Ty>>), Type(TyParamBounds, Option<P<Ty>>),
@ -1137,9 +1140,9 @@ pub struct ImplItem {
pub enum ImplItemKind { pub enum ImplItemKind {
/// An associated constant of the given type, set to the constant result /// An associated constant of the given type, set to the constant result
/// of the expression /// of the expression
Const(P<Ty>, P<Expr>), Const(P<Ty>, BodyId),
/// A method implementation with the given signature and body /// A method implementation with the given signature and body
Method(MethodSig, ExprId), Method(MethodSig, BodyId),
/// An associated type /// An associated type
Type(P<Ty>), Type(P<Ty>),
} }
@ -1192,7 +1195,7 @@ pub enum Ty_ {
/// A variable length slice (`[T]`) /// A variable length slice (`[T]`)
TySlice(P<Ty>), TySlice(P<Ty>),
/// A fixed length array (`[T; n]`) /// A fixed length array (`[T; n]`)
TyArray(P<Ty>, P<Expr>), TyArray(P<Ty>, BodyId),
/// A raw pointer (`*const T` or `*mut T`) /// A raw pointer (`*const T` or `*mut T`)
TyPtr(MutTy), TyPtr(MutTy),
/// A reference (`&'a T` or `&'a mut T`) /// A reference (`&'a T` or `&'a mut T`)
@ -1216,7 +1219,7 @@ pub enum Ty_ {
/// An `impl TraitA+TraitB` type. /// An `impl TraitA+TraitB` type.
TyImplTrait(TyParamBounds), TyImplTrait(TyParamBounds),
/// Unused for now /// Unused for now
TyTypeof(P<Expr>), TyTypeof(BodyId),
/// TyInfer means the type should be inferred instead of it having been /// TyInfer means the type should be inferred instead of it having been
/// specified. This can appear anywhere in a type. /// specified. This can appear anywhere in a type.
TyInfer, TyInfer,
@ -1371,7 +1374,7 @@ pub struct Variant_ {
pub attrs: HirVec<Attribute>, pub attrs: HirVec<Attribute>,
pub data: VariantData, pub data: VariantData,
/// Explicit discriminant, eg `Foo = 1` /// Explicit discriminant, eg `Foo = 1`
pub disr_expr: Option<P<Expr>>, pub disr_expr: Option<BodyId>,
} }
pub type Variant = Spanned<Variant_>; pub type Variant = Spanned<Variant_>;
@ -1530,11 +1533,11 @@ pub enum Item_ {
ItemUse(P<Path>, UseKind), ItemUse(P<Path>, UseKind),
/// A `static` item /// A `static` item
ItemStatic(P<Ty>, Mutability, P<Expr>), ItemStatic(P<Ty>, Mutability, BodyId),
/// A `const` item /// A `const` item
ItemConst(P<Ty>, P<Expr>), ItemConst(P<Ty>, BodyId),
/// A function declaration /// A function declaration
ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, ExprId), ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, BodyId),
/// A module /// A module
ItemMod(Mod), ItemMod(Mod),
/// An external module /// An external module

View File

@ -462,7 +462,7 @@ impl<'a> State<'a> {
pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> { pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> {
self.print_inner_attributes(attrs)?; self.print_inner_attributes(attrs)?;
for item_id in &_mod.item_ids { for &item_id in &_mod.item_ids {
self.print_item_id(item_id)?; self.print_item_id(item_id)?;
} }
Ok(()) Ok(())
@ -545,16 +545,16 @@ impl<'a> State<'a> {
hir::TyImplTrait(ref bounds) => { hir::TyImplTrait(ref bounds) => {
self.print_bounds("impl ", &bounds[..])?; self.print_bounds("impl ", &bounds[..])?;
} }
hir::TyArray(ref ty, ref v) => { hir::TyArray(ref ty, v) => {
word(&mut self.s, "[")?; word(&mut self.s, "[")?;
self.print_type(&ty)?; self.print_type(&ty)?;
word(&mut self.s, "; ")?; word(&mut self.s, "; ")?;
self.print_expr(&v)?; self.print_body_id(v)?;
word(&mut self.s, "]")?; word(&mut self.s, "]")?;
} }
hir::TyTypeof(ref e) => { hir::TyTypeof(e) => {
word(&mut self.s, "typeof(")?; word(&mut self.s, "typeof(")?;
self.print_expr(&e)?; self.print_body_id(e)?;
word(&mut self.s, ")")?; word(&mut self.s, ")")?;
} }
hir::TyInfer => { hir::TyInfer => {
@ -600,7 +600,7 @@ impl<'a> State<'a> {
fn print_associated_const(&mut self, fn print_associated_const(&mut self,
name: ast::Name, name: ast::Name,
ty: &hir::Ty, ty: &hir::Ty,
default: Option<&hir::Expr>, default: Option<hir::BodyId>,
vis: &hir::Visibility) vis: &hir::Visibility)
-> io::Result<()> { -> io::Result<()> {
word(&mut self.s, &visibility_qualified(vis, ""))?; word(&mut self.s, &visibility_qualified(vis, ""))?;
@ -611,7 +611,7 @@ impl<'a> State<'a> {
if let Some(expr) = default { if let Some(expr) = default {
space(&mut self.s)?; space(&mut self.s)?;
self.word_space("=")?; self.word_space("=")?;
self.print_expr(expr)?; self.print_body_id(expr)?;
} }
word(&mut self.s, ";") word(&mut self.s, ";")
} }
@ -634,7 +634,7 @@ impl<'a> State<'a> {
word(&mut self.s, ";") word(&mut self.s, ";")
} }
pub fn print_item_id(&mut self, item_id: &hir::ItemId) -> io::Result<()> { pub fn print_item_id(&mut self, item_id: hir::ItemId) -> io::Result<()> {
if let Some(krate) = self.krate { if let Some(krate) = self.krate {
// skip nested items if krate context was not provided // skip nested items if krate context was not provided
let item = &krate.items[&item_id.id]; let item = &krate.items[&item_id.id];
@ -644,9 +644,9 @@ impl<'a> State<'a> {
} }
} }
pub fn print_expr_id(&mut self, expr_id: &hir::ExprId) -> io::Result<()> { fn print_body_id(&mut self, body_id: hir::BodyId) -> io::Result<()> {
if let Some(krate) = self.krate { if let Some(krate) = self.krate {
let expr = &krate.exprs[expr_id]; let expr = &krate.body(body_id).value;
self.print_expr(expr) self.print_expr(expr)
} else { } else {
Ok(()) Ok(())
@ -697,7 +697,7 @@ impl<'a> State<'a> {
self.end()?; // end inner head-block self.end()?; // end inner head-block
self.end()?; // end outer head-block self.end()?; // end outer head-block
} }
hir::ItemStatic(ref ty, m, ref expr) => { hir::ItemStatic(ref ty, m, expr) => {
self.head(&visibility_qualified(&item.vis, "static"))?; self.head(&visibility_qualified(&item.vis, "static"))?;
if m == hir::MutMutable { if m == hir::MutMutable {
self.word_space("mut")?; self.word_space("mut")?;
@ -709,11 +709,11 @@ impl<'a> State<'a> {
self.end()?; // end the head-ibox self.end()?; // end the head-ibox
self.word_space("=")?; self.word_space("=")?;
self.print_expr(&expr)?; self.print_body_id(expr)?;
word(&mut self.s, ";")?; word(&mut self.s, ";")?;
self.end()?; // end the outer cbox self.end()?; // end the outer cbox
} }
hir::ItemConst(ref ty, ref expr) => { hir::ItemConst(ref ty, expr) => {
self.head(&visibility_qualified(&item.vis, "const"))?; self.head(&visibility_qualified(&item.vis, "const"))?;
self.print_name(item.name)?; self.print_name(item.name)?;
self.word_space(":")?; self.word_space(":")?;
@ -722,11 +722,11 @@ impl<'a> State<'a> {
self.end()?; // end the head-ibox self.end()?; // end the head-ibox
self.word_space("=")?; self.word_space("=")?;
self.print_expr(&expr)?; self.print_body_id(expr)?;
word(&mut self.s, ";")?; word(&mut self.s, ";")?;
self.end()?; // end the outer cbox self.end()?; // end the outer cbox
} }
hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, ref body) => { hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, body) => {
self.head("")?; self.head("")?;
self.print_fn(decl, self.print_fn(decl,
unsafety, unsafety,
@ -738,7 +738,7 @@ impl<'a> State<'a> {
word(&mut self.s, " ")?; word(&mut self.s, " ")?;
self.end()?; // need to close a box self.end()?; // need to close a box
self.end()?; // need to close a box self.end()?; // need to close a box
self.print_expr_id(body)?; self.print_body_id(body)?;
} }
hir::ItemMod(ref _mod) => { hir::ItemMod(ref _mod) => {
self.head(&visibility_qualified(&item.vis, "mod"))?; self.head(&visibility_qualified(&item.vis, "mod"))?;
@ -985,14 +985,12 @@ impl<'a> State<'a> {
self.head("")?; self.head("")?;
let generics = hir::Generics::empty(); let generics = hir::Generics::empty();
self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?; self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?;
match v.node.disr_expr { if let Some(d) = v.node.disr_expr {
Some(ref d) => {
space(&mut self.s)?; space(&mut self.s)?;
self.word_space("=")?; self.word_space("=")?;
self.print_expr(&d) self.print_body_id(d)?;
}
_ => Ok(()),
} }
Ok(())
} }
pub fn print_method_sig(&mut self, pub fn print_method_sig(&mut self,
name: ast::Name, name: ast::Name,
@ -1024,22 +1022,19 @@ impl<'a> State<'a> {
self.maybe_print_comment(ti.span.lo)?; self.maybe_print_comment(ti.span.lo)?;
self.print_outer_attributes(&ti.attrs)?; self.print_outer_attributes(&ti.attrs)?;
match ti.node { match ti.node {
hir::TraitItemKind::Const(ref ty, ref default) => { hir::TraitItemKind::Const(ref ty, default) => {
self.print_associated_const(ti.name, self.print_associated_const(ti.name, &ty, default, &hir::Inherited)?;
&ty,
default.as_ref().map(|expr| &**expr),
&hir::Inherited)?;
} }
hir::TraitItemKind::Method(ref sig, ref body) => { hir::TraitItemKind::Method(ref sig, body) => {
if body.is_some() { if body.is_some() {
self.head("")?; self.head("")?;
} }
self.print_method_sig(ti.name, sig, &hir::Inherited)?; self.print_method_sig(ti.name, sig, &hir::Inherited)?;
if let Some(ref body) = *body { if let Some(body) = body {
self.nbsp()?; self.nbsp()?;
self.end()?; // need to close a box self.end()?; // need to close a box
self.end()?; // need to close a box self.end()?; // need to close a box
self.print_expr_id(body)?; self.print_body_id(body)?;
} else { } else {
word(&mut self.s, ";")?; word(&mut self.s, ";")?;
} }
@ -1075,16 +1070,16 @@ impl<'a> State<'a> {
} }
match ii.node { match ii.node {
hir::ImplItemKind::Const(ref ty, ref expr) => { hir::ImplItemKind::Const(ref ty, expr) => {
self.print_associated_const(ii.name, &ty, Some(&expr), &ii.vis)?; self.print_associated_const(ii.name, &ty, Some(expr), &ii.vis)?;
} }
hir::ImplItemKind::Method(ref sig, ref body) => { hir::ImplItemKind::Method(ref sig, body) => {
self.head("")?; self.head("")?;
self.print_method_sig(ii.name, sig, &ii.vis)?; self.print_method_sig(ii.name, sig, &ii.vis)?;
self.nbsp()?; self.nbsp()?;
self.end()?; // need to close a box self.end()?; // need to close a box
self.end()?; // need to close a box self.end()?; // need to close a box
self.print_expr_id(body)?; self.print_body_id(body)?;
} }
hir::ImplItemKind::Type(ref ty) => { hir::ImplItemKind::Type(ref ty) => {
self.print_associated_type(ii.name, None, Some(ty))?; self.print_associated_type(ii.name, None, Some(ty))?;
@ -1256,12 +1251,12 @@ impl<'a> State<'a> {
self.end() self.end()
} }
fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::Expr) -> io::Result<()> { fn print_expr_repeat(&mut self, element: &hir::Expr, count: hir::BodyId) -> io::Result<()> {
self.ibox(indent_unit)?; self.ibox(indent_unit)?;
word(&mut self.s, "[")?; word(&mut self.s, "[")?;
self.print_expr(element)?; self.print_expr(element)?;
self.word_space(";")?; self.word_space(";")?;
self.print_expr(count)?; self.print_body_id(count)?;
word(&mut self.s, "]")?; word(&mut self.s, "]")?;
self.end() self.end()
} }
@ -1372,8 +1367,8 @@ impl<'a> State<'a> {
hir::ExprArray(ref exprs) => { hir::ExprArray(ref exprs) => {
self.print_expr_vec(exprs)?; self.print_expr_vec(exprs)?;
} }
hir::ExprRepeat(ref element, ref count) => { hir::ExprRepeat(ref element, count) => {
self.print_expr_repeat(&element, &count)?; self.print_expr_repeat(&element, count)?;
} }
hir::ExprStruct(ref qpath, ref fields, ref wth) => { hir::ExprStruct(ref qpath, ref fields, ref wth) => {
self.print_expr_struct(qpath, &fields[..], wth)?; self.print_expr_struct(qpath, &fields[..], wth)?;
@ -1444,14 +1439,14 @@ impl<'a> State<'a> {
} }
self.bclose_(expr.span, indent_unit)?; self.bclose_(expr.span, indent_unit)?;
} }
hir::ExprClosure(capture_clause, ref decl, ref body, _fn_decl_span) => { hir::ExprClosure(capture_clause, ref decl, body, _fn_decl_span) => {
self.print_capture_clause(capture_clause)?; self.print_capture_clause(capture_clause)?;
self.print_fn_block_args(&decl)?; self.print_fn_block_args(&decl)?;
space(&mut self.s)?; space(&mut self.s)?;
// this is a bare expression // this is a bare expression
self.print_expr_id(body)?; self.print_body_id(body)?;
self.end()?; // need to close a box self.end()?; // need to close a box
// a box will be closed by print_expr, but we didn't want an overall // a box will be closed by print_expr, but we didn't want an overall
@ -1625,7 +1620,7 @@ impl<'a> State<'a> {
} }
self.end() self.end()
} }
hir::DeclItem(ref item) => { hir::DeclItem(item) => {
self.print_item_id(item) self.print_item_id(item)
} }
} }

View File

@ -821,6 +821,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
self.with_lint_attrs(&e.attrs, |cx| { self.with_lint_attrs(&e.attrs, |cx| {
run_lints!(cx, check_expr, late_passes, e); run_lints!(cx, check_expr, late_passes, e);
hir_visit::walk_expr(cx, e); hir_visit::walk_expr(cx, e);
run_lints!(cx, check_expr_post, late_passes, e);
}) })
} }
@ -835,8 +836,8 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
} }
fn visit_fn(&mut self, fk: hir_visit::FnKind<'tcx>, decl: &'tcx hir::FnDecl, fn visit_fn(&mut self, fk: hir_visit::FnKind<'tcx>, decl: &'tcx hir::FnDecl,
body_id: hir::ExprId, span: Span, id: ast::NodeId) { body_id: hir::BodyId, span: Span, id: ast::NodeId) {
let body = self.tcx.map.expr(body_id); let body = self.tcx.map.body(body_id);
run_lints!(self, check_fn, late_passes, fk, decl, body, span, id); run_lints!(self, check_fn, late_passes, fk, decl, body, span, id);
hir_visit::walk_fn(self, fk, decl, body_id, span, id); hir_visit::walk_fn(self, fk, decl, body_id, span, id);
run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id); run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id);
@ -909,10 +910,6 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
hir_visit::walk_decl(self, d); hir_visit::walk_decl(self, d);
} }
fn visit_expr_post(&mut self, e: &'tcx hir::Expr) {
run_lints!(self, check_expr_post, late_passes, e);
}
fn visit_generics(&mut self, g: &'tcx hir::Generics) { fn visit_generics(&mut self, g: &'tcx hir::Generics) {
run_lints!(self, check_generics, late_passes, g); run_lints!(self, check_generics, late_passes, g);
hir_visit::walk_generics(self, g); hir_visit::walk_generics(self, g);

View File

@ -162,14 +162,14 @@ pub trait LateLintPass<'a, 'tcx>: LintPass {
_: &LateContext<'a, 'tcx>, _: &LateContext<'a, 'tcx>,
_: FnKind<'tcx>, _: FnKind<'tcx>,
_: &'tcx hir::FnDecl, _: &'tcx hir::FnDecl,
_: &'tcx hir::Expr, _: &'tcx hir::Body,
_: Span, _: Span,
_: ast::NodeId) { } _: ast::NodeId) { }
fn check_fn_post(&mut self, fn check_fn_post(&mut self,
_: &LateContext<'a, 'tcx>, _: &LateContext<'a, 'tcx>,
_: FnKind<'tcx>, _: FnKind<'tcx>,
_: &'tcx hir::FnDecl, _: &'tcx hir::FnDecl,
_: &'tcx hir::Expr, _: &'tcx hir::Body,
_: Span, _: Span,
_: ast::NodeId) { } _: ast::NodeId) { }
fn check_trait_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::TraitItem) { } fn check_trait_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::TraitItem) { }

View File

@ -38,7 +38,6 @@ use std::rc::Rc;
use syntax::ast; use syntax::ast;
use syntax::attr; use syntax::attr;
use syntax::ext::base::SyntaxExtension; use syntax::ext::base::SyntaxExtension;
use syntax::ptr::P;
use syntax::symbol::Symbol; use syntax::symbol::Symbol;
use syntax_pos::Span; use syntax_pos::Span;
use rustc_back::target::Target; use rustc_back::target::Target;
@ -140,7 +139,7 @@ pub struct NativeLibrary {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct InlinedItem { pub struct InlinedItem {
pub def_id: DefId, pub def_id: DefId,
pub body: P<hir::Expr>, pub body: hir::Body,
pub const_fn_args: Vec<Option<DefId>>, pub const_fn_args: Vec<Option<DefId>>,
} }
@ -149,7 +148,7 @@ pub struct InlinedItem {
#[derive(Clone, PartialEq, Eq, RustcEncodable, Hash, Debug)] #[derive(Clone, PartialEq, Eq, RustcEncodable, Hash, Debug)]
pub struct InlinedItemRef<'a> { pub struct InlinedItemRef<'a> {
pub def_id: DefId, pub def_id: DefId,
pub body: &'a hir::Expr, pub body: &'a hir::Body,
pub const_fn_args: Vec<Option<DefId>>, pub const_fn_args: Vec<Option<DefId>>,
} }
@ -160,31 +159,31 @@ fn get_fn_args(decl: &hir::FnDecl) -> Vec<Option<DefId>> {
}).collect() }).collect()
} }
impl<'a> InlinedItemRef<'a> { impl<'a, 'tcx> InlinedItemRef<'tcx> {
pub fn from_item<'b, 'tcx>(def_id: DefId, pub fn from_item(def_id: DefId,
item: &'a hir::Item, item: &hir::Item,
tcx: TyCtxt<'b, 'a, 'tcx>) tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> InlinedItemRef<'a> { -> InlinedItemRef<'tcx> {
let (body, args) = match item.node { let (body_id, args) = match item.node {
hir::ItemFn(ref decl, _, _, _, _, body_id) => hir::ItemFn(ref decl, _, _, _, _, body_id) =>
(tcx.map.expr(body_id), get_fn_args(decl)), (body_id, get_fn_args(decl)),
hir::ItemConst(_, ref body) => (&**body, Vec::new()), hir::ItemConst(_, body_id) => (body_id, vec![]),
_ => bug!("InlinedItemRef::from_item wrong kind") _ => bug!("InlinedItemRef::from_item wrong kind")
}; };
InlinedItemRef { InlinedItemRef {
def_id: def_id, def_id: def_id,
body: body, body: tcx.map.body(body_id),
const_fn_args: args const_fn_args: args
} }
} }
pub fn from_trait_item(def_id: DefId, pub fn from_trait_item(def_id: DefId,
item: &'a hir::TraitItem, item: &hir::TraitItem,
_tcx: TyCtxt) tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> InlinedItemRef<'a> { -> InlinedItemRef<'tcx> {
let (body, args) = match item.node { let (body_id, args) = match item.node {
hir::TraitItemKind::Const(_, Some(ref body)) => hir::TraitItemKind::Const(_, Some(body_id)) =>
(&**body, Vec::new()), (body_id, vec![]),
hir::TraitItemKind::Const(_, None) => { hir::TraitItemKind::Const(_, None) => {
bug!("InlinedItemRef::from_trait_item called for const without body") bug!("InlinedItemRef::from_trait_item called for const without body")
}, },
@ -192,33 +191,33 @@ impl<'a> InlinedItemRef<'a> {
}; };
InlinedItemRef { InlinedItemRef {
def_id: def_id, def_id: def_id,
body: body, body: tcx.map.body(body_id),
const_fn_args: args const_fn_args: args
} }
} }
pub fn from_impl_item<'b, 'tcx>(def_id: DefId, pub fn from_impl_item(def_id: DefId,
item: &'a hir::ImplItem, item: &hir::ImplItem,
tcx: TyCtxt<'b, 'a, 'tcx>) tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> InlinedItemRef<'a> { -> InlinedItemRef<'tcx> {
let (body, args) = match item.node { let (body_id, args) = match item.node {
hir::ImplItemKind::Method(ref sig, body_id) => hir::ImplItemKind::Method(ref sig, body_id) =>
(tcx.map.expr(body_id), get_fn_args(&sig.decl)), (body_id, get_fn_args(&sig.decl)),
hir::ImplItemKind::Const(_, ref body) => hir::ImplItemKind::Const(_, body_id) =>
(&**body, Vec::new()), (body_id, vec![]),
_ => bug!("InlinedItemRef::from_impl_item wrong kind") _ => bug!("InlinedItemRef::from_impl_item wrong kind")
}; };
InlinedItemRef { InlinedItemRef {
def_id: def_id, def_id: def_id,
body: body, body: tcx.map.body(body_id),
const_fn_args: args const_fn_args: args
} }
} }
pub fn visit<V>(&self, visitor: &mut V) pub fn visit<V>(&self, visitor: &mut V)
where V: Visitor<'a> where V: Visitor<'tcx>
{ {
visitor.visit_expr(&self.body); visitor.visit_body(self.body);
} }
} }
@ -226,7 +225,7 @@ impl InlinedItem {
pub fn visit<'ast,V>(&'ast self, visitor: &mut V) pub fn visit<'ast,V>(&'ast self, visitor: &mut V)
where V: Visitor<'ast> where V: Visitor<'ast>
{ {
visitor.visit_expr(&self.body); visitor.visit_body(&self.body);
} }
} }

View File

@ -194,7 +194,7 @@ fn build_nodeid_to_index(decl: Option<&hir::FnDecl>,
intravisit::walk_fn_decl(&mut formals, decl); intravisit::walk_fn_decl(&mut formals, decl);
impl<'a, 'v> intravisit::Visitor<'v> for Formals<'a> { impl<'a, 'v> intravisit::Visitor<'v> for Formals<'a> {
fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> { fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> {
panic!("should not encounter fn bodies or items") intravisit::NestedVisitorMap::None
} }
fn visit_pat(&mut self, p: &hir::Pat) { fn visit_pat(&mut self, p: &hir::Pat) {
@ -502,7 +502,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> { impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> {
// ^^^^^^^^^^^^^ only needed for pretty printing // ^^^^^^^^^^^^^ only needed for pretty printing
pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Expr) { pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Body) {
//! Performs the data flow analysis. //! Performs the data flow analysis.
if self.bits_per_id == 0 { if self.bits_per_id == 0 {
@ -534,11 +534,11 @@ impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> {
} }
fn pretty_print_to<'b>(&self, wr: Box<io::Write + 'b>, fn pretty_print_to<'b>(&self, wr: Box<io::Write + 'b>,
body: &hir::Expr) -> io::Result<()> { body: &hir::Body) -> io::Result<()> {
let mut ps = pprust::rust_printer_annotated(wr, self, None); let mut ps = pprust::rust_printer_annotated(wr, self, None);
ps.cbox(pprust::indent_unit)?; ps.cbox(pprust::indent_unit)?;
ps.ibox(0)?; ps.ibox(0)?;
ps.print_expr(body)?; ps.print_expr(&body.value)?;
pp::eof(&mut ps.s) pp::eof(&mut ps.s)
} }
} }

View File

@ -551,19 +551,19 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
match impl_item.node { match impl_item.node {
hir::ImplItemKind::Const(_, ref expr) => { hir::ImplItemKind::Const(_, body_id) => {
if !self.symbol_is_live(impl_item.id, None) { if !self.symbol_is_live(impl_item.id, None) {
self.warn_dead_code(impl_item.id, impl_item.span, self.warn_dead_code(impl_item.id, impl_item.span,
impl_item.name, "associated const"); impl_item.name, "associated const");
} }
intravisit::walk_expr(self, expr) self.visit_nested_body(body_id)
} }
hir::ImplItemKind::Method(_, body_id) => { hir::ImplItemKind::Method(_, body_id) => {
if !self.symbol_is_live(impl_item.id, None) { if !self.symbol_is_live(impl_item.id, None) {
self.warn_dead_code(impl_item.id, impl_item.span, self.warn_dead_code(impl_item.id, impl_item.span,
impl_item.name, "method"); impl_item.name, "method");
} }
self.visit_body(body_id) self.visit_nested_body(body_id)
} }
hir::ImplItemKind::Type(..) => {} hir::ImplItemKind::Type(..) => {}
} }
@ -572,11 +572,9 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
// Overwrite so that we don't warn the trait item itself. // Overwrite so that we don't warn the trait item itself.
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
match trait_item.node { match trait_item.node {
hir::TraitItemKind::Const(_, Some(ref body)) => { hir::TraitItemKind::Const(_, Some(body_id)) |
intravisit::walk_expr(self, body)
}
hir::TraitItemKind::Method(_, Some(body_id)) => { hir::TraitItemKind::Method(_, Some(body_id)) => {
self.visit_body(body_id) self.visit_nested_body(body_id)
} }
hir::TraitItemKind::Const(_, None) | hir::TraitItemKind::Const(_, None) |
hir::TraitItemKind::Method(_, None) | hir::TraitItemKind::Method(_, None) |

View File

@ -98,7 +98,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> {
} }
fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, fn_decl: &'tcx hir::FnDecl, fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, fn_decl: &'tcx hir::FnDecl,
body_id: hir::ExprId, span: Span, id: ast::NodeId) { body_id: hir::BodyId, span: Span, id: ast::NodeId) {
let (is_item_fn, is_unsafe_fn) = match fn_kind { let (is_item_fn, is_unsafe_fn) = match fn_kind {
FnKind::ItemFn(_, _, unsafety, ..) => FnKind::ItemFn(_, _, unsafety, ..) =>

View File

@ -289,9 +289,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
pub fn walk_fn(&mut self, pub fn walk_fn(&mut self,
decl: &hir::FnDecl, decl: &hir::FnDecl,
body: &hir::Expr) { body: &hir::Body) {
self.walk_arg_patterns(decl, body); self.walk_arg_patterns(decl, &body.value);
self.consume_expr(body); self.consume_expr(&body.value);
} }
fn walk_arg_patterns(&mut self, fn walk_arg_patterns(&mut self,
@ -537,9 +537,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
} }
} }
hir::ExprRepeat(ref base, ref count) => { hir::ExprRepeat(ref base, _) => {
self.consume_expr(&base); self.consume_expr(&base);
self.consume_expr(&count);
} }
hir::ExprClosure(.., fn_decl_span) => { hir::ExprClosure(.., fn_decl_span) => {

View File

@ -34,13 +34,13 @@ struct ItemVisitor<'a, 'tcx: 'a> {
} }
impl<'a, 'tcx> ItemVisitor<'a, 'tcx> { impl<'a, 'tcx> ItemVisitor<'a, 'tcx> {
fn visit_const(&mut self, item_id: ast::NodeId, expr: &'tcx hir::Expr) { fn visit_const(&mut self, item_id: ast::NodeId, body: hir::BodyId) {
let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id); let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id);
self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| { self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| {
let mut visitor = ExprVisitor { let mut visitor = ExprVisitor {
infcx: &infcx infcx: &infcx
}; };
visitor.visit_expr(expr); visitor.visit_nested_body(body);
}); });
} }
} }
@ -122,33 +122,33 @@ impl<'a, 'tcx> Visitor<'tcx> for ItemVisitor<'a, 'tcx> {
} }
// const, static and N in [T; N]. // const, static and N in [T; N].
fn visit_expr(&mut self, expr: &'tcx hir::Expr) { fn visit_body(&mut self, body: &'tcx hir::Body) {
self.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { self.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
let mut visitor = ExprVisitor { let mut visitor = ExprVisitor {
infcx: &infcx infcx: &infcx
}; };
visitor.visit_expr(expr); visitor.visit_body(body);
}); });
} }
fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
if let hir::TraitItemKind::Const(_, Some(ref expr)) = item.node { if let hir::TraitItemKind::Const(_, Some(body)) = item.node {
self.visit_const(item.id, expr); self.visit_const(item.id, body);
} else { } else {
intravisit::walk_trait_item(self, item); intravisit::walk_trait_item(self, item);
} }
} }
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
if let hir::ImplItemKind::Const(_, ref expr) = item.node { if let hir::ImplItemKind::Const(_, body) = item.node {
self.visit_const(item.id, expr); self.visit_const(item.id, body);
} else { } else {
intravisit::walk_impl_item(self, item); intravisit::walk_impl_item(self, item);
} }
} }
fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
b: hir::ExprId, s: Span, id: ast::NodeId) { b: hir::BodyId, s: Span, id: ast::NodeId) {
if let FnKind::Closure(..) = fk { if let FnKind::Closure(..) = fk {
span_bug!(s, "intrinsicck: closure outside of function") span_bug!(s, "intrinsicck: closure outside of function")
} }

View File

@ -188,7 +188,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IrMaps<'a, 'tcx> {
} }
fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
b: hir::ExprId, s: Span, id: NodeId) { b: hir::BodyId, s: Span, id: NodeId) {
visit_fn(self, fk, fd, b, s, id); visit_fn(self, fk, fd, b, s, id);
} }
fn visit_local(&mut self, l: &'tcx hir::Local) { visit_local(self, l); } fn visit_local(&mut self, l: &'tcx hir::Local) { visit_local(self, l); }
@ -354,13 +354,9 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::OnlyBodies(&self.ir.tcx.map) NestedVisitorMap::None
} }
fn visit_fn(&mut self, _: FnKind<'tcx>, _: &'tcx hir::FnDecl,
_: hir::ExprId, _: Span, _: NodeId) {
// do not check contents of nested fns
}
fn visit_local(&mut self, l: &'tcx hir::Local) { fn visit_local(&mut self, l: &'tcx hir::Local) {
check_local(self, l); check_local(self, l);
} }
@ -375,7 +371,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
fk: FnKind<'tcx>, fk: FnKind<'tcx>,
decl: &'tcx hir::FnDecl, decl: &'tcx hir::FnDecl,
body_id: hir::ExprId, body_id: hir::BodyId,
sp: Span, sp: Span,
id: ast::NodeId) { id: ast::NodeId) {
debug!("visit_fn"); debug!("visit_fn");
@ -408,14 +404,14 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
clean_exit_var: fn_maps.add_variable(CleanExit) clean_exit_var: fn_maps.add_variable(CleanExit)
}; };
let body = ir.tcx.map.expr(body_id); let body = ir.tcx.map.body(body_id);
// compute liveness // compute liveness
let mut lsets = Liveness::new(&mut fn_maps, specials); let mut lsets = Liveness::new(&mut fn_maps, specials);
let entry_ln = lsets.compute(body); let entry_ln = lsets.compute(&body.value);
// check for various error conditions // check for various error conditions
lsets.visit_expr(body); lsets.visit_body(body);
lsets.check_ret(id, sp, fk, entry_ln, body); lsets.check_ret(id, sp, fk, entry_ln, body);
lsets.warn_about_unused_args(decl, entry_ln); lsets.warn_about_unused_args(decl, entry_ln);
} }
@ -942,7 +938,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
loop. The next-node for a continue is the top of this loop. loop. The next-node for a continue is the top of this loop.
*/ */
let node = self.live_node(expr.id, expr.span); let node = self.live_node(expr.id, expr.span);
self.with_loop_nodes(blk_id.node_id(), succ, node, |this| { self.with_loop_nodes(blk_id.node_id, succ, node, |this| {
// the construction of a closure itself is not important, // the construction of a closure itself is not important,
// but we have to consider the closed over variables. // but we have to consider the closed over variables.
@ -1088,11 +1084,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.propagate_through_exprs(exprs, succ) self.propagate_through_exprs(exprs, succ)
} }
hir::ExprRepeat(ref element, ref count) => {
let succ = self.propagate_through_expr(&count, succ);
self.propagate_through_expr(&element, succ)
}
hir::ExprStruct(_, ref fields, ref with_expr) => { hir::ExprStruct(_, ref fields, ref with_expr) => {
let succ = self.propagate_through_opt_expr(with_expr.as_ref().map(|e| &**e), succ); let succ = self.propagate_through_opt_expr(with_expr.as_ref().map(|e| &**e), succ);
fields.iter().rev().fold(succ, |succ, field| { fields.iter().rev().fold(succ, |succ, field| {
@ -1149,7 +1140,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprAddrOf(_, ref e) | hir::ExprAddrOf(_, ref e) |
hir::ExprCast(ref e, _) | hir::ExprCast(ref e, _) |
hir::ExprType(ref e, _) | hir::ExprType(ref e, _) |
hir::ExprUnary(_, ref e) => { hir::ExprUnary(_, ref e) |
hir::ExprRepeat(ref e, _) => {
self.propagate_through_expr(&e, succ) self.propagate_through_expr(&e, succ)
} }
@ -1443,7 +1435,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
sp: Span, sp: Span,
fk: FnKind, fk: FnKind,
entry_ln: LiveNode, entry_ln: LiveNode,
body: &hir::Expr) body: &hir::Body)
{ {
let fn_ty = if let FnKind::Closure(_) = fk { let fn_ty = if let FnKind::Closure(_) = fk {
self.ir.tcx.tables().node_id_to_type(id) self.ir.tcx.tables().node_id_to_type(id)
@ -1460,7 +1452,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// and must outlive the *call-site* of the function. // and must outlive the *call-site* of the function.
let fn_ret = let fn_ret =
self.ir.tcx.liberate_late_bound_regions( self.ir.tcx.liberate_late_bound_regions(
self.ir.tcx.region_maps.call_site_extent(id, body.id), self.ir.tcx.region_maps.call_site_extent(id, body.value.id),
&fn_ret); &fn_ret);
if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {

View File

@ -705,7 +705,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
}; };
match fn_expr.node { match fn_expr.node {
hir::ExprClosure(.., body_id, _) => body_id.node_id(), hir::ExprClosure(.., body_id, _) => body_id.node_id,
_ => bug!() _ => bug!()
} }
}; };

View File

@ -250,15 +250,15 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
match item.node { match item.node {
hir::ItemFn(.., body) => { hir::ItemFn(.., body) => {
if item_might_be_inlined(&item) { if item_might_be_inlined(&item) {
self.visit_body(body); self.visit_nested_body(body);
} }
} }
// Reachable constants will be inlined into other crates // Reachable constants will be inlined into other crates
// unconditionally, so we need to make sure that their // unconditionally, so we need to make sure that their
// contents are also reachable. // contents are also reachable.
hir::ItemConst(_, ref init) => { hir::ItemConst(_, init) => {
self.visit_expr(&init); self.visit_nested_body(init);
} }
// These are normal, nothing reachable about these // These are normal, nothing reachable about these
@ -278,24 +278,22 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
hir::TraitItemKind::Method(_, None) => { hir::TraitItemKind::Method(_, None) => {
// Keep going, nothing to get exported // Keep going, nothing to get exported
} }
hir::TraitItemKind::Const(_, Some(ref body)) => { hir::TraitItemKind::Const(_, Some(body_id)) |
self.visit_expr(body);
}
hir::TraitItemKind::Method(_, Some(body_id)) => { hir::TraitItemKind::Method(_, Some(body_id)) => {
self.visit_body(body_id); self.visit_nested_body(body_id);
} }
hir::TraitItemKind::Type(..) => {} hir::TraitItemKind::Type(..) => {}
} }
} }
ast_map::NodeImplItem(impl_item) => { ast_map::NodeImplItem(impl_item) => {
match impl_item.node { match impl_item.node {
hir::ImplItemKind::Const(_, ref expr) => { hir::ImplItemKind::Const(_, body) => {
self.visit_expr(&expr); self.visit_nested_body(body);
} }
hir::ImplItemKind::Method(ref sig, body) => { hir::ImplItemKind::Method(ref sig, body) => {
let did = self.tcx.map.get_parent_did(search_item); let did = self.tcx.map.get_parent_did(search_item);
if method_might_be_inlined(self.tcx, sig, impl_item, did) { if method_might_be_inlined(self.tcx, sig, impl_item, did) {
self.visit_body(body) self.visit_nested_body(body)
} }
} }
hir::ImplItemKind::Type(_) => {} hir::ImplItemKind::Type(_) => {}

View File

@ -1088,7 +1088,7 @@ fn resolve_item_like<'a, 'tcx, F>(visitor: &mut RegionResolutionVisitor<'tcx, 'a
fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
kind: FnKind<'tcx>, kind: FnKind<'tcx>,
decl: &'tcx hir::FnDecl, decl: &'tcx hir::FnDecl,
body_id: hir::ExprId, body_id: hir::BodyId,
sp: Span, sp: Span,
id: ast::NodeId) { id: ast::NodeId) {
debug!("region::resolve_fn(id={:?}, \ debug!("region::resolve_fn(id={:?}, \
@ -1101,22 +1101,22 @@ fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
visitor.cx.parent); visitor.cx.parent);
visitor.cx.parent = visitor.new_code_extent( visitor.cx.parent = visitor.new_code_extent(
CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id() }); CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id });
let fn_decl_scope = visitor.new_code_extent( let fn_decl_scope = visitor.new_code_extent(
CodeExtentData::ParameterScope { fn_id: id, body_id: body_id.node_id() }); CodeExtentData::ParameterScope { fn_id: id, body_id: body_id.node_id });
if let Some(root_id) = visitor.cx.root_id { if let Some(root_id) = visitor.cx.root_id {
visitor.region_maps.record_fn_parent(body_id.node_id(), root_id); visitor.region_maps.record_fn_parent(body_id.node_id, root_id);
} }
let outer_cx = visitor.cx; let outer_cx = visitor.cx;
let outer_ts = mem::replace(&mut visitor.terminating_scopes, NodeSet()); let outer_ts = mem::replace(&mut visitor.terminating_scopes, NodeSet());
visitor.terminating_scopes.insert(body_id.node_id()); visitor.terminating_scopes.insert(body_id.node_id);
// The arguments and `self` are parented to the fn. // The arguments and `self` are parented to the fn.
visitor.cx = Context { visitor.cx = Context {
root_id: Some(body_id.node_id()), root_id: Some(body_id.node_id),
parent: ROOT_CODE_EXTENT, parent: ROOT_CODE_EXTENT,
var_parent: fn_decl_scope, var_parent: fn_decl_scope,
}; };
@ -1126,11 +1126,11 @@ fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
// The body of the every fn is a root scope. // The body of the every fn is a root scope.
visitor.cx = Context { visitor.cx = Context {
root_id: Some(body_id.node_id()), root_id: Some(body_id.node_id),
parent: fn_decl_scope, parent: fn_decl_scope,
var_parent: fn_decl_scope var_parent: fn_decl_scope
}; };
visitor.visit_body(body_id); visitor.visit_nested_body(body_id);
// Restore context we had at the start. // Restore context we had at the start.
visitor.cx = outer_cx; visitor.cx = outer_cx;
@ -1195,7 +1195,7 @@ impl<'ast, 'a> Visitor<'ast> for RegionResolutionVisitor<'ast, 'a> {
} }
fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl,
b: hir::ExprId, s: Span, n: NodeId) { b: hir::BodyId, s: Span, n: NodeId) {
resolve_fn(self, fk, fd, b, s, n); resolve_fn(self, fk, fd, b, s, n);
} }
fn visit_arm(&mut self, a: &'ast Arm) { fn visit_arm(&mut self, a: &'ast Arm) {

View File

@ -206,7 +206,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
} }
fn visit_fn(&mut self, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl, fn visit_fn(&mut self, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl,
b: hir::ExprId, s: Span, fn_id: ast::NodeId) { b: hir::BodyId, s: Span, fn_id: ast::NodeId) {
match fk { match fk {
FnKind::ItemFn(_, generics, ..) => { FnKind::ItemFn(_, generics, ..) => {
self.visit_early_late(fn_id,decl, generics, |this| { self.visit_early_late(fn_id,decl, generics, |this| {
@ -407,7 +407,7 @@ fn signal_shadowing_problem(sess: &Session, name: ast::Name, orig: Original, sha
// Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning // Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning
// if one of the label shadows a lifetime or another label. // if one of the label shadows a lifetime or another label.
fn extract_labels(ctxt: &mut LifetimeContext, b: hir::ExprId) { fn extract_labels(ctxt: &mut LifetimeContext, b: hir::BodyId) {
struct GatherLabels<'a> { struct GatherLabels<'a> {
sess: &'a Session, sess: &'a Session,
scope: Scope<'a>, scope: Scope<'a>,
@ -419,7 +419,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: hir::ExprId) {
scope: ctxt.scope, scope: ctxt.scope,
labels_in_fn: &mut ctxt.labels_in_fn, labels_in_fn: &mut ctxt.labels_in_fn,
}; };
gather.visit_expr(ctxt.hir_map.expr(b)); gather.visit_body(ctxt.hir_map.body(b));
return; return;
impl<'v, 'a> Visitor<'v> for GatherLabels<'a> { impl<'v, 'a> Visitor<'v> for GatherLabels<'a> {
@ -501,7 +501,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
fn add_scope_and_walk_fn(&mut self, fn add_scope_and_walk_fn(&mut self,
fk: FnKind<'tcx>, fk: FnKind<'tcx>,
fd: &'tcx hir::FnDecl, fd: &'tcx hir::FnDecl,
fb: hir::ExprId, fb: hir::BodyId,
_span: Span, _span: Span,
fn_id: ast::NodeId) { fn_id: ast::NodeId) {
match fk { match fk {
@ -522,8 +522,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// `self.labels_in_fn`. // `self.labels_in_fn`.
extract_labels(self, fb); extract_labels(self, fb);
self.with(FnScope { fn_id: fn_id, body_id: fb.node_id(), s: self.scope }, self.with(FnScope { fn_id: fn_id, body_id: fb.node_id, s: self.scope },
|_old_scope, this| this.visit_body(fb)) |_old_scope, this| this.visit_nested_body(fb))
} }
// FIXME(#37666) this works around a limitation in the region inferencer // FIXME(#37666) this works around a limitation in the region inferencer

View File

@ -1206,7 +1206,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
tcx.construct_parameter_environment( tcx.construct_parameter_environment(
impl_item.span, impl_item.span,
tcx.map.local_def_id(id), tcx.map.local_def_id(id),
tcx.region_maps.call_site_extent(id, body.node_id())) tcx.region_maps.call_site_extent(id, body.node_id))
} }
} }
} }
@ -1227,7 +1227,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
// to the method id). // to the method id).
let extent = if let Some(body_id) = *body { let extent = if let Some(body_id) = *body {
// default impl: use call_site extent as free_id_outlive bound. // default impl: use call_site extent as free_id_outlive bound.
tcx.region_maps.call_site_extent(id, body_id.node_id()) tcx.region_maps.call_site_extent(id, body_id.node_id)
} else { } else {
// no default impl: use item extent as free_id_outlive bound. // no default impl: use item extent as free_id_outlive bound.
tcx.region_maps.item_extent(id) tcx.region_maps.item_extent(id)
@ -1248,7 +1248,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
tcx.construct_parameter_environment( tcx.construct_parameter_environment(
item.span, item.span,
fn_def_id, fn_def_id,
tcx.region_maps.call_site_extent(id, body_id.node_id())) tcx.region_maps.call_site_extent(id, body_id.node_id))
} }
hir::ItemEnum(..) | hir::ItemEnum(..) |
hir::ItemStruct(..) | hir::ItemStruct(..) |
@ -1284,7 +1284,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
tcx.construct_parameter_environment( tcx.construct_parameter_environment(
expr.span, expr.span,
base_def_id, base_def_id,
tcx.region_maps.call_site_extent(id, body.node_id())) tcx.region_maps.call_site_extent(id, body.node_id))
} else { } else {
tcx.empty_parameter_environment() tcx.empty_parameter_environment()
} }

View File

@ -190,8 +190,8 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
all_loans: &[Loan<'tcx>], all_loans: &[Loan<'tcx>],
fn_id: ast::NodeId, fn_id: ast::NodeId,
decl: &hir::FnDecl, decl: &hir::FnDecl,
body: &hir::Expr) { body: &hir::Body) {
debug!("check_loans(body id={})", body.id); debug!("check_loans(body id={})", body.value.id);
let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env); let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env);

View File

@ -42,13 +42,13 @@ mod move_error;
pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
fn_id: NodeId, fn_id: NodeId,
decl: &hir::FnDecl, decl: &hir::FnDecl,
body: &hir::Expr) body: &hir::Body)
-> (Vec<Loan<'tcx>>, -> (Vec<Loan<'tcx>>,
move_data::MoveData<'tcx>) { move_data::MoveData<'tcx>) {
let mut glcx = GatherLoanCtxt { let mut glcx = GatherLoanCtxt {
bccx: bccx, bccx: bccx,
all_loans: Vec::new(), all_loans: Vec::new(),
item_ub: bccx.tcx.region_maps.node_extent(body.id), item_ub: bccx.tcx.region_maps.node_extent(body.value.id),
move_data: MoveData::new(), move_data: MoveData::new(),
move_error_collector: move_error::MoveErrorCollector::new(), move_error_collector: move_error::MoveErrorCollector::new(),
}; };
@ -548,14 +548,14 @@ impl<'a, 'tcx> Visitor<'tcx> for StaticInitializerCtxt<'a, 'tcx> {
pub fn gather_loans_in_static_initializer<'a, 'tcx>(bccx: &mut BorrowckCtxt<'a, 'tcx>, pub fn gather_loans_in_static_initializer<'a, 'tcx>(bccx: &mut BorrowckCtxt<'a, 'tcx>,
item_id: ast::NodeId, item_id: ast::NodeId,
expr: &'tcx hir::Expr) { body: hir::BodyId) {
debug!("gather_loans_in_static_initializer(expr={:?})", expr); debug!("gather_loans_in_static_initializer(expr={:?})", body);
let mut sicx = StaticInitializerCtxt { let mut sicx = StaticInitializerCtxt {
bccx: bccx, bccx: bccx,
item_id: item_id item_id: item_id
}; };
sicx.visit_expr(expr); sicx.visit_nested_body(body);
} }

View File

@ -11,10 +11,7 @@
use borrowck::BorrowckCtxt; use borrowck::BorrowckCtxt;
use syntax::ast::{self, MetaItem}; use syntax::ast::{self, MetaItem};
use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::DUMMY_SP;
use rustc::hir;
use rustc::hir::intravisit::{FnKind};
use rustc::mir::{self, BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location}; use rustc::mir::{self, BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location};
use rustc::session::Session; use rustc::session::Session;
@ -55,27 +52,14 @@ pub struct MoveDataParamEnv<'tcx> {
} }
pub fn borrowck_mir(bcx: &mut BorrowckCtxt, pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
fk: FnKind,
_decl: &hir::FnDecl,
body: &hir::Expr,
_sp: Span,
id: ast::NodeId, id: ast::NodeId,
attributes: &[ast::Attribute]) { attributes: &[ast::Attribute]) {
match fk {
FnKind::ItemFn(name, ..) |
FnKind::Method(name, ..) => {
debug!("borrowck_mir({}) UNIMPLEMENTED", name);
}
FnKind::Closure(_) => {
debug!("borrowck_mir closure (body.id={}) UNIMPLEMENTED", body.id);
}
}
let tcx = bcx.tcx; let tcx = bcx.tcx;
let def_id = tcx.map.local_def_id(id);
debug!("borrowck_mir({}) UNIMPLEMENTED", tcx.item_path_str(def_id));
let mir = &tcx.item_mir(def_id);
let param_env = ty::ParameterEnvironment::for_item(tcx, id); let param_env = ty::ParameterEnvironment::for_item(tcx, id);
let mir = &tcx.item_mir(tcx.map.local_def_id(id));
let move_data = MoveData::gather_moves(mir, tcx, &param_env); let move_data = MoveData::gather_moves(mir, tcx, &param_env);
let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
let flow_inits = let flow_inits =

View File

@ -68,7 +68,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowckCtxt<'a, 'tcx> {
} }
fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
b: hir::ExprId, s: Span, id: ast::NodeId) { b: hir::BodyId, s: Span, id: ast::NodeId) {
match fk { match fk {
FnKind::ItemFn(..) | FnKind::ItemFn(..) |
FnKind::Method(..) => { FnKind::Method(..) => {
@ -88,15 +88,15 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowckCtxt<'a, 'tcx> {
} }
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
if let hir::TraitItemKind::Const(_, Some(ref expr)) = ti.node { if let hir::TraitItemKind::Const(_, Some(expr)) = ti.node {
gather_loans::gather_loans_in_static_initializer(self, ti.id, &expr); gather_loans::gather_loans_in_static_initializer(self, ti.id, expr);
} }
intravisit::walk_trait_item(self, ti); intravisit::walk_trait_item(self, ti);
} }
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
if let hir::ImplItemKind::Const(_, ref expr) = ii.node { if let hir::ImplItemKind::Const(_, expr) = ii.node {
gather_loans::gather_loans_in_static_initializer(self, ii.id, &expr); gather_loans::gather_loans_in_static_initializer(self, ii.id, expr);
} }
intravisit::walk_impl_item(self, ii); intravisit::walk_impl_item(self, ii);
} }
@ -141,9 +141,9 @@ fn borrowck_item<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, item: &'tcx hir::I
// loan step is intended for things that have a data // loan step is intended for things that have a data
// flow dependent conditions. // flow dependent conditions.
match item.node { match item.node {
hir::ItemStatic(.., ref ex) | hir::ItemStatic(.., ex) |
hir::ItemConst(_, ref ex) => { hir::ItemConst(_, ex) => {
gather_loans::gather_loans_in_static_initializer(this, item.id, &ex); gather_loans::gather_loans_in_static_initializer(this, item.id, ex);
} }
_ => { } _ => { }
} }
@ -161,21 +161,21 @@ pub struct AnalysisData<'a, 'tcx: 'a> {
fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
fk: FnKind<'tcx>, fk: FnKind<'tcx>,
decl: &'tcx hir::FnDecl, decl: &'tcx hir::FnDecl,
body_id: hir::ExprId, body_id: hir::BodyId,
sp: Span, sp: Span,
id: ast::NodeId, id: ast::NodeId,
attributes: &[ast::Attribute]) { attributes: &[ast::Attribute]) {
debug!("borrowck_fn(id={})", id); debug!("borrowck_fn(id={})", id);
let body = this.tcx.map.expr(body_id); let body = this.tcx.map.body(body_id);
if attributes.iter().any(|item| item.check_name("rustc_mir_borrowck")) { if attributes.iter().any(|item| item.check_name("rustc_mir_borrowck")) {
this.with_temp_region_map(id, |this| { this.with_temp_region_map(id, |this| {
mir::borrowck_mir(this, fk, decl, body, sp, id, attributes) mir::borrowck_mir(this, id, attributes)
}); });
} }
let cfg = cfg::CFG::new(this.tcx, body); let cfg = cfg::CFG::new(this.tcx, &body.value);
let AnalysisData { all_loans, let AnalysisData { all_loans,
loans: loan_dfcx, loans: loan_dfcx,
move_data: flowed_moves } = move_data: flowed_moves } =
@ -204,14 +204,14 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
fk: FnKind<'tcx>, fk: FnKind<'tcx>,
decl: &'tcx hir::FnDecl, decl: &'tcx hir::FnDecl,
cfg: &cfg::CFG, cfg: &cfg::CFG,
body: &'tcx hir::Expr, body: &'tcx hir::Body,
sp: Span, sp: Span,
id: ast::NodeId) id: ast::NodeId)
-> AnalysisData<'a, 'tcx> -> AnalysisData<'a, 'tcx>
{ {
// Check the body of fn items. // Check the body of fn items.
let tcx = this.tcx; let tcx = this.tcx;
let id_range = intravisit::compute_id_range_for_fn_body(fk, decl, body, sp, id, &tcx.map); let id_range = intravisit::compute_id_range_for_fn_body(fk, decl, body.id(), sp, id, &tcx.map);
let (all_loans, move_data) = let (all_loans, move_data) =
gather_loans::gather_loans_in_fn(this, id, decl, body); gather_loans::gather_loans_in_fn(this, id, decl, body);
@ -263,7 +263,7 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
} }
}; };
let body = tcx.map.expr(fn_parts.body); let body = tcx.map.body(fn_parts.body);
let dataflow_data = build_borrowck_dataflow_data(&mut bccx, let dataflow_data = build_borrowck_dataflow_data(&mut bccx,
fn_parts.kind, fn_parts.kind,
@ -416,7 +416,7 @@ pub fn closure_to_block(closure_id: ast::NodeId,
match tcx.map.get(closure_id) { match tcx.map.get(closure_id) {
hir_map::NodeExpr(expr) => match expr.node { hir_map::NodeExpr(expr) => match expr.node {
hir::ExprClosure(.., body_id, _) => { hir::ExprClosure(.., body_id, _) => {
body_id.node_id() body_id.node_id
} }
_ => { _ => {
bug!("encountered non-closure id: {}", closure_id) bug!("encountered non-closure id: {}", closure_id)

View File

@ -656,7 +656,7 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> {
cfg: &cfg::CFG, cfg: &cfg::CFG,
id_range: IdRange, id_range: IdRange,
decl: &hir::FnDecl, decl: &hir::FnDecl,
body: &hir::Expr) body: &hir::Body)
-> FlowedMoveData<'a, 'tcx> { -> FlowedMoveData<'a, 'tcx> {
let mut dfcx_moves = let mut dfcx_moves =
DataFlowContext::new(tcx, DataFlowContext::new(tcx,

View File

@ -67,7 +67,7 @@ impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> {
} }
fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
b: hir::ExprId, s: Span, id: ast::NodeId) { b: hir::BodyId, s: Span, id: ast::NodeId) {
if let FnKind::Closure(..) = fk { if let FnKind::Closure(..) = fk {
span_bug!(s, "check_match: closure outside of function") span_bug!(s, "check_match: closure outside of function")
} }
@ -120,7 +120,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
} }
fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
b: hir::ExprId, s: Span, n: ast::NodeId) { b: hir::BodyId, s: Span, n: ast::NodeId) {
intravisit::walk_fn(self, fk, fd, b, s, n); intravisit::walk_fn(self, fk, fd, b, s, n);
for input in &fd.inputs { for input in &fd.inputs {

View File

@ -576,18 +576,18 @@ https://doc.rust-lang.org/reference.html#ffi-attributes
E0306: r##" E0306: r##"
In an array literal `[x; N]`, `N` is the number of elements in the array. This In an array type `[T; N]`, `N` is the number of elements in the array. This
must be an unsigned integer. Erroneous code example: must be an unsigned integer. Erroneous code example:
```compile_fail,E0306 ```compile_fail,E0306
let x = [0i32; true]; // error: expected positive integer for repeat count, const X: [i32; true] = [0]; // error: expected `usize` for array length,
// found boolean // found boolean
``` ```
Working example: Working example:
``` ```
let x = [0i32; 2]; const X: [i32; 1] = [0];
``` ```
"##, "##,
} }

View File

@ -56,15 +56,17 @@ macro_rules! math {
fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
variant_def: DefId) variant_def: DefId)
-> Option<&'tcx Expr> { -> Option<&'tcx Expr> {
fn variant_expr<'a>(variants: &'a [hir::Variant], id: ast::NodeId) let variant_expr = |variants: &'tcx [hir::Variant], id: ast::NodeId |
-> Option<&'a Expr> { -> Option<&'tcx Expr> {
for variant in variants { for variant in variants {
if variant.node.data.id() == id { if variant.node.data.id() == id {
return variant.node.disr_expr.as_ref().map(|e| &**e); return variant.node.disr_expr.map(|e| {
&tcx.map.body(e).value
});
} }
} }
None None
} };
if let Some(variant_node_id) = tcx.map.as_local_node_id(variant_def) { if let Some(variant_node_id) = tcx.map.as_local_node_id(variant_def) {
let enum_node_id = tcx.map.get_parent(variant_node_id); let enum_node_id = tcx.map.get_parent(variant_node_id);
@ -96,21 +98,24 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
match tcx.map.find(node_id) { match tcx.map.find(node_id) {
None => None, None => None,
Some(ast_map::NodeItem(it)) => match it.node { Some(ast_map::NodeItem(it)) => match it.node {
hir::ItemConst(ref ty, ref const_expr) => { hir::ItemConst(ref ty, body) => {
Some((&const_expr, tcx.ast_ty_to_prim_ty(ty))) Some((&tcx.map.body(body).value,
tcx.ast_ty_to_prim_ty(ty)))
} }
_ => None _ => None
}, },
Some(ast_map::NodeTraitItem(ti)) => match ti.node { Some(ast_map::NodeTraitItem(ti)) => match ti.node {
hir::TraitItemKind::Const(ref ty, ref expr_option) => { hir::TraitItemKind::Const(ref ty, default) => {
if let Some(substs) = substs { if let Some(substs) = substs {
// If we have a trait item and the substitutions for it, // If we have a trait item and the substitutions for it,
// `resolve_trait_associated_const` will select an impl // `resolve_trait_associated_const` will select an impl
// or the default. // or the default.
let trait_id = tcx.map.get_parent(node_id); let trait_id = tcx.map.get_parent(node_id);
let trait_id = tcx.map.local_def_id(trait_id); let trait_id = tcx.map.local_def_id(trait_id);
let default_value = expr_option.as_ref() let default_value = default.map(|body| {
.map(|expr| (&**expr, tcx.ast_ty_to_prim_ty(ty))); (&tcx.map.body(body).value,
tcx.ast_ty_to_prim_ty(ty))
});
resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs) resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs)
} else { } else {
// Technically, without knowing anything about the // Technically, without knowing anything about the
@ -125,8 +130,9 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
_ => None _ => None
}, },
Some(ast_map::NodeImplItem(ii)) => match ii.node { Some(ast_map::NodeImplItem(ii)) => match ii.node {
hir::ImplItemKind::Const(ref ty, ref expr) => { hir::ImplItemKind::Const(ref ty, body) => {
Some((&expr, tcx.ast_ty_to_prim_ty(ty))) Some((&tcx.map.body(body).value,
tcx.ast_ty_to_prim_ty(ty)))
} }
_ => None _ => None
}, },
@ -142,8 +148,8 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
} }
let mut used_substs = false; let mut used_substs = false;
let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) { let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
Some((&InlinedItem { body: ref const_expr, .. }, _)) => { Some((&InlinedItem { ref body, .. }, _)) => {
Some((&**const_expr, Some(tcx.sess.cstore.item_type(tcx, def_id)))) Some((&body.value, Some(tcx.sess.cstore.item_type(tcx, def_id))))
} }
_ => None _ => None
}; };
@ -864,18 +870,18 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Struct(_) => signal!(e, UnimplementedConstVal("tuple struct constructors")), Struct(_) => signal!(e, UnimplementedConstVal("tuple struct constructors")),
callee => signal!(e, CallOn(callee)), callee => signal!(e, CallOn(callee)),
}; };
let (arg_defs, body_id) = match lookup_const_fn_by_id(tcx, did) { let (arg_defs, body) = match lookup_const_fn_by_id(tcx, did) {
Some(ConstFnNode::Inlined(ii)) => (ii.const_fn_args.clone(), ii.body.expr_id()), Some(ConstFnNode::Inlined(ii)) => (ii.const_fn_args.clone(), &ii.body),
Some(ConstFnNode::Local(fn_like)) => Some(ConstFnNode::Local(fn_like)) =>
(fn_like.decl().inputs.iter() (fn_like.decl().inputs.iter()
.map(|arg| match arg.pat.node { .map(|arg| match arg.pat.node {
hir::PatKind::Binding(_, def_id, _, _) => Some(def_id), hir::PatKind::Binding(_, def_id, _, _) => Some(def_id),
_ => None _ => None
}).collect(), }).collect(),
fn_like.body()), tcx.map.body(fn_like.body())),
None => signal!(e, NonConstPath), None => signal!(e, NonConstPath),
}; };
let result = tcx.map.expr(body_id); let result = &body.value;
assert_eq!(arg_defs.len(), args.len()); assert_eq!(arg_defs.len(), args.len());
let mut call_args = DefIdMap(); let mut call_args = DefIdMap();
@ -893,7 +899,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
} }
} }
debug!("const call({:?})", call_args); debug!("const call({:?})", call_args);
eval_const_expr_partial(tcx, &result, ty_hint, Some(&call_args))? eval_const_expr_partial(tcx, result, ty_hint, Some(&call_args))?
}, },
hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety) { hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety) {
Ok(val) => val, Ok(val) => val,
@ -953,11 +959,12 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
} }
} }
hir::ExprArray(ref v) => Array(e.id, v.len() as u64), hir::ExprArray(ref v) => Array(e.id, v.len() as u64),
hir::ExprRepeat(_, ref n) => { hir::ExprRepeat(_, n) => {
let len_hint = ty_hint.checked_or(tcx.types.usize); let len_hint = ty_hint.checked_or(tcx.types.usize);
let n = &tcx.map.body(n).value;
Repeat( Repeat(
e.id, e.id,
match eval_const_expr_partial(tcx, &n, len_hint, fn_args)? { match eval_const_expr_partial(tcx, n, len_hint, fn_args)? {
Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type), Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type),
Integral(_) => signal!(e, RepeatCountNotNatural), Integral(_) => signal!(e, RepeatCountNotNatural),
_ => signal!(e, RepeatCountNotInt), _ => signal!(e, RepeatCountNotInt),

View File

@ -702,8 +702,8 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
let cfg = match code { let cfg = match code {
blocks::Code::Expr(expr) => cfg::CFG::new(tcx, expr), blocks::Code::Expr(expr) => cfg::CFG::new(tcx, expr),
blocks::Code::FnLike(fn_like) => { blocks::Code::FnLike(fn_like) => {
let body = tcx.map.expr(fn_like.body()); let body = tcx.map.body(fn_like.body());
cfg::CFG::new(tcx, body) cfg::CFG::new(tcx, &body.value)
}, },
}; };
let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges; let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges;

View File

@ -188,7 +188,7 @@ enum SawAbiComponent<'a> {
SawTraitItem(SawTraitOrImplItemComponent), SawTraitItem(SawTraitOrImplItemComponent),
SawImplItem(SawTraitOrImplItemComponent), SawImplItem(SawTraitOrImplItemComponent),
SawStructField, SawStructField,
SawVariant, SawVariant(bool),
SawQPath, SawQPath,
SawPathSegment, SawPathSegment,
SawPathParameters, SawPathParameters,
@ -584,7 +584,7 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
g: &'tcx Generics, g: &'tcx Generics,
item_id: NodeId) { item_id: NodeId) {
debug!("visit_variant: st={:?}", self.st); debug!("visit_variant: st={:?}", self.st);
SawVariant.hash(self.st); SawVariant(v.node.disr_expr.is_some()).hash(self.st);
hash_attrs!(self, &v.node.attrs); hash_attrs!(self, &v.node.attrs);
visit::walk_variant(self, v, g, item_id) visit::walk_variant(self, v, g, item_id)
} }
@ -616,7 +616,12 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
// implicitly hashing the discriminant of SawExprComponent. // implicitly hashing the discriminant of SawExprComponent.
hash_span!(self, ex.span, force_span); hash_span!(self, ex.span, force_span);
hash_attrs!(self, &ex.attrs); hash_attrs!(self, &ex.attrs);
visit::walk_expr(self, ex)
// Always hash nested constant bodies (e.g. n in `[x; n]`).
let hash_bodies = self.hash_bodies;
self.hash_bodies = true;
visit::walk_expr(self, ex);
self.hash_bodies = hash_bodies;
} }
fn visit_stmt(&mut self, s: &'tcx Stmt) { fn visit_stmt(&mut self, s: &'tcx Stmt) {
@ -686,7 +691,12 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
debug!("visit_ty: st={:?}", self.st); debug!("visit_ty: st={:?}", self.st);
SawTy(saw_ty(&t.node)).hash(self.st); SawTy(saw_ty(&t.node)).hash(self.st);
hash_span!(self, t.span); hash_span!(self, t.span);
visit::walk_ty(self, t)
// Always hash nested constant bodies (e.g. N in `[T; N]`).
let hash_bodies = self.hash_bodies;
self.hash_bodies = true;
visit::walk_ty(self, t);
self.hash_bodies = hash_bodies;
} }
fn visit_generics(&mut self, g: &'tcx Generics) { fn visit_generics(&mut self, g: &'tcx Generics) {
@ -1159,7 +1169,7 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
items: _, items: _,
trait_items: _, trait_items: _,
impl_items: _, impl_items: _,
exprs: _, bodies: _,
} = *krate; } = *krate;
visit::Visitor::visit_mod(self, module, span, ast::CRATE_NODE_ID); visit::Visitor::visit_mod(self, module, span, ast::CRATE_NODE_ID);

View File

@ -243,7 +243,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
cx: &LateContext, cx: &LateContext,
fk: FnKind, fk: FnKind,
_: &hir::FnDecl, _: &hir::FnDecl,
_: &hir::Expr, _: &hir::Body,
span: Span, span: Span,
id: ast::NodeId) { id: ast::NodeId) {
match fk { match fk {

View File

@ -222,7 +222,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode {
cx: &LateContext, cx: &LateContext,
fk: FnKind<'tcx>, fk: FnKind<'tcx>,
_: &hir::FnDecl, _: &hir::FnDecl,
_: &hir::Expr, _: &hir::Body,
span: Span, span: Span,
_: ast::NodeId) { _: ast::NodeId) {
match fk { match fk {
@ -674,7 +674,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
cx: &LateContext, cx: &LateContext,
fn_kind: FnKind, fn_kind: FnKind,
_: &hir::FnDecl, _: &hir::FnDecl,
blk: &hir::Expr, body: &hir::Body,
sp: Span, sp: Span,
id: ast::NodeId) { id: ast::NodeId) {
let method = match fn_kind { let method = match fn_kind {
@ -712,7 +712,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
// to have behaviour like the above, rather than // to have behaviour like the above, rather than
// e.g. accidentally recurring after an assert. // e.g. accidentally recurring after an assert.
let cfg = cfg::CFG::new(cx.tcx, blk); let cfg = cfg::CFG::new(cx.tcx, &body.value);
let mut work_queue = vec![cfg.entry]; let mut work_queue = vec![cfg.entry];
let mut reached_exit_without_self_call = false; let mut reached_exit_without_self_call = false;

View File

@ -98,7 +98,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedMut {
cx: &LateContext, cx: &LateContext,
_: FnKind, _: FnKind,
decl: &hir::FnDecl, decl: &hir::FnDecl,
_: &hir::Expr, _: &hir::Body,
_: Span, _: Span,
_: ast::NodeId) { _: ast::NodeId) {
for a in &decl.inputs { for a in &decl.inputs {

View File

@ -485,7 +485,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
.insert(def_id, None); .insert(def_id, None);
} }
Some(&InlinedItem { ref body, .. }) => { Some(&InlinedItem { ref body, .. }) => {
let inlined_root_node_id = find_inlined_item_root(body.id); let inlined_root_node_id = find_inlined_item_root(body.value.id);
cache_inlined_item(def_id, inlined_root_node_id, inlined_root_node_id); cache_inlined_item(def_id, inlined_root_node_id, inlined_root_node_id);
} }
} }

View File

@ -802,7 +802,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
_ => None, _ => None,
}, },
mir: match item.node { mir: match item.node {
hir::ItemStatic(..) | hir::ItemStatic(..) if self.tcx.sess.opts.debugging_opts.always_encode_mir => {
self.encode_mir(def_id)
}
hir::ItemConst(..) => self.encode_mir(def_id), hir::ItemConst(..) => self.encode_mir(def_id),
hir::ItemFn(_, _, constness, _, ref generics, _) => { hir::ItemFn(_, _, constness, _, ref generics, _) => {
let tps_len = generics.ty_params.len(); let tps_len = generics.ty_params.len();

View File

@ -126,7 +126,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
arguments: A, arguments: A,
abi: Abi, abi: Abi,
return_ty: Ty<'gcx>, return_ty: Ty<'gcx>,
ast_body: &'gcx hir::Expr) body_id: hir::BodyId)
-> Mir<'tcx> -> Mir<'tcx>
where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)> where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
{ {
@ -136,17 +136,17 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
let span = tcx.map.span(fn_id); let span = tcx.map.span(fn_id);
let mut builder = Builder::new(hir, span, arguments.len(), return_ty); let mut builder = Builder::new(hir, span, arguments.len(), return_ty);
let body_id = ast_body.id;
let call_site_extent = let call_site_extent =
tcx.region_maps.lookup_code_extent( tcx.region_maps.lookup_code_extent(
CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id }); CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id.node_id });
let arg_extent = let arg_extent =
tcx.region_maps.lookup_code_extent( tcx.region_maps.lookup_code_extent(
CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body_id }); CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body_id.node_id });
let mut block = START_BLOCK; let mut block = START_BLOCK;
unpack!(block = builder.in_scope(call_site_extent, block, |builder| { unpack!(block = builder.in_scope(call_site_extent, block, |builder| {
unpack!(block = builder.in_scope(arg_extent, block, |builder| { unpack!(block = builder.in_scope(arg_extent, block, |builder| {
builder.args_and_body(block, &arguments, arg_extent, ast_body) let ast_expr = &tcx.map.body(body_id).value;
builder.args_and_body(block, &arguments, arg_extent, ast_expr)
})); }));
// Attribute epilogue to function's closing brace // Attribute epilogue to function's closing brace
let fn_end = Span { lo: span.hi, ..span }; let fn_end = Span { lo: span.hi, ..span };
@ -197,9 +197,10 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
item_id: ast::NodeId, item_id: ast::NodeId,
ast_expr: &'tcx hir::Expr) body_id: hir::BodyId)
-> Mir<'tcx> { -> Mir<'tcx> {
let tcx = hir.tcx(); let tcx = hir.tcx();
let ast_expr = &tcx.map.body(body_id).value;
let ty = tcx.tables().expr_ty_adjusted(ast_expr); let ty = tcx.tables().expr_ty_adjusted(ast_expr);
let span = tcx.map.span(item_id); let span = tcx.map.span(item_id);
let mut builder = Builder::new(hir, span, 0, ty); let mut builder = Builder::new(hir, span, 0, ty);

View File

@ -575,7 +575,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
} }
// Now comes the rote stuff: // Now comes the rote stuff:
hir::ExprRepeat(ref v, ref c) => { hir::ExprRepeat(ref v, c) => {
let c = &cx.tcx.map.body(c).value;
ExprKind::Repeat { ExprKind::Repeat {
value: v.to_ref(), value: v.to_ref(),
count: TypedConstVal { count: TypedConstVal {
@ -585,7 +586,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
ConstVal::Integral(ConstInt::Usize(u)) => u, ConstVal::Integral(ConstInt::Usize(u)) => u,
other => bug!("constant evaluation of repeat count yielded {:?}", other), other => bug!("constant evaluation of repeat count yielded {:?}", other),
}, },
}, }
} }
} }
hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() }, hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() },
@ -780,7 +781,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
let body_id = match cx.tcx.map.find(closure_expr_id) { let body_id = match cx.tcx.map.find(closure_expr_id) {
Some(map::NodeExpr(expr)) => { Some(map::NodeExpr(expr)) => {
match expr.node { match expr.node {
hir::ExprClosure(.., body_id, _) => body_id.node_id(), hir::ExprClosure(.., body, _) => body.node_id,
_ => { _ => {
span_bug!(expr.span, "closure expr is not a closure expr"); span_bug!(expr.span, "closure expr is not a closure expr");
} }

View File

@ -129,16 +129,17 @@ impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> {
} }
impl<'a, 'gcx> BuildMir<'a, 'gcx> { impl<'a, 'gcx> BuildMir<'a, 'gcx> {
fn build_const_integer(&mut self, expr: &'gcx hir::Expr) { fn build_const_integer(&mut self, body: hir::BodyId) {
let body = self.tcx.map.body(body);
// FIXME(eddyb) Closures should have separate // FIXME(eddyb) Closures should have separate
// function definition IDs and expression IDs. // function definition IDs and expression IDs.
// Type-checking should not let closures get // Type-checking should not let closures get
// this far in an integer constant position. // this far in an integer constant position.
if let hir::ExprClosure(..) = expr.node { if let hir::ExprClosure(..) = body.value.node {
return; return;
} }
self.cx(MirSource::Const(expr.id)).build(|cx| { self.cx(MirSource::Const(body.value.id)).build(|cx| {
build::construct_const(cx, expr.id, expr) build::construct_const(cx, body.value.id, body.id())
}); });
} }
} }
@ -151,12 +152,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
// Const and static items. // Const and static items.
fn visit_item(&mut self, item: &'tcx hir::Item) { fn visit_item(&mut self, item: &'tcx hir::Item) {
match item.node { match item.node {
hir::ItemConst(_, ref expr) => { hir::ItemConst(_, expr) => {
self.cx(MirSource::Const(item.id)).build(|cx| { self.cx(MirSource::Const(item.id)).build(|cx| {
build::construct_const(cx, item.id, expr) build::construct_const(cx, item.id, expr)
}); });
} }
hir::ItemStatic(_, m, ref expr) => { hir::ItemStatic(_, m, expr) => {
self.cx(MirSource::Static(item.id, m)).build(|cx| { self.cx(MirSource::Static(item.id, m)).build(|cx| {
build::construct_const(cx, item.id, expr) build::construct_const(cx, item.id, expr)
}); });
@ -168,7 +169,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
// Trait associated const defaults. // Trait associated const defaults.
fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
if let hir::TraitItemKind::Const(_, Some(ref expr)) = item.node { if let hir::TraitItemKind::Const(_, Some(expr)) = item.node {
self.cx(MirSource::Const(item.id)).build(|cx| { self.cx(MirSource::Const(item.id)).build(|cx| {
build::construct_const(cx, item.id, expr) build::construct_const(cx, item.id, expr)
}); });
@ -178,7 +179,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
// Impl associated const. // Impl associated const.
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
if let hir::ImplItemKind::Const(_, ref expr) = item.node { if let hir::ImplItemKind::Const(_, expr) = item.node {
self.cx(MirSource::Const(item.id)).build(|cx| { self.cx(MirSource::Const(item.id)).build(|cx| {
build::construct_const(cx, item.id, expr) build::construct_const(cx, item.id, expr)
}); });
@ -188,7 +189,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
// Repeat counts, i.e. [expr; constant]. // Repeat counts, i.e. [expr; constant].
fn visit_expr(&mut self, expr: &'tcx hir::Expr) { fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
if let hir::ExprRepeat(_, ref count) = expr.node { if let hir::ExprRepeat(_, count) = expr.node {
self.build_const_integer(count); self.build_const_integer(count);
} }
intravisit::walk_expr(self, expr); intravisit::walk_expr(self, expr);
@ -196,7 +197,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
// Array lengths, i.e. [T; constant]. // Array lengths, i.e. [T; constant].
fn visit_ty(&mut self, ty: &'tcx hir::Ty) { fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
if let hir::TyArray(_, ref length) = ty.node { if let hir::TyArray(_, length) = ty.node {
self.build_const_integer(length); self.build_const_integer(length);
} }
intravisit::walk_ty(self, ty); intravisit::walk_ty(self, ty);
@ -205,7 +206,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
// Enum variant discriminant values. // Enum variant discriminant values.
fn visit_variant(&mut self, v: &'tcx hir::Variant, fn visit_variant(&mut self, v: &'tcx hir::Variant,
g: &'tcx hir::Generics, item_id: ast::NodeId) { g: &'tcx hir::Generics, item_id: ast::NodeId) {
if let Some(ref expr) = v.node.disr_expr { if let Some(expr) = v.node.disr_expr {
self.build_const_integer(expr); self.build_const_integer(expr);
} }
intravisit::walk_variant(self, v, g, item_id); intravisit::walk_variant(self, v, g, item_id);
@ -214,7 +215,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
fn visit_fn(&mut self, fn visit_fn(&mut self,
fk: FnKind<'tcx>, fk: FnKind<'tcx>,
decl: &'tcx hir::FnDecl, decl: &'tcx hir::FnDecl,
body_id: hir::ExprId, body_id: hir::BodyId,
span: Span, span: Span,
id: ast::NodeId) { id: ast::NodeId) {
// fetch the fully liberated fn signature (that is, all bound // fetch the fully liberated fn signature (that is, all bound
@ -227,7 +228,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
}; };
let (abi, implicit_argument) = if let FnKind::Closure(..) = fk { let (abi, implicit_argument) = if let FnKind::Closure(..) = fk {
(Abi::Rust, Some((closure_self_ty(self.tcx, id, body_id.node_id()), None))) (Abi::Rust, Some((closure_self_ty(self.tcx, id, body_id.node_id), None)))
} else { } else {
let def_id = self.tcx.map.local_def_id(id); let def_id = self.tcx.map.local_def_id(id);
(self.tcx.item_type(def_id).fn_abi(), None) (self.tcx.item_type(def_id).fn_abi(), None)
@ -241,11 +242,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
(fn_sig.inputs()[index], Some(&*arg.pat)) (fn_sig.inputs()[index], Some(&*arg.pat))
}); });
let body = self.tcx.map.expr(body_id);
let arguments = implicit_argument.into_iter().chain(explicit_arguments); let arguments = implicit_argument.into_iter().chain(explicit_arguments);
self.cx(MirSource::Fn(id)).build(|cx| { self.cx(MirSource::Fn(id)).build(|cx| {
build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body) build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body_id)
}); });
intravisit::walk_fn(self, fk, decl, body_id, span, id); intravisit::walk_fn(self, fk, decl, body_id, span, id);

View File

@ -100,6 +100,11 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
.enter(|infcx| f(&mut euv::ExprUseVisitor::new(self, &infcx))) .enter(|infcx| f(&mut euv::ExprUseVisitor::new(self, &infcx)))
} }
fn global_body(&mut self, mode: Mode, body: hir::BodyId) -> ConstQualif {
let expr = &self.tcx.map.body(body).value;
self.global_expr(mode, expr)
}
fn global_expr(&mut self, mode: Mode, expr: &'gcx hir::Expr) -> ConstQualif { fn global_expr(&mut self, mode: Mode, expr: &'gcx hir::Expr) -> ConstQualif {
assert!(mode != Mode::Var); assert!(mode != Mode::Var);
match self.tcx.const_qualif_map.borrow_mut().entry(expr.id) { match self.tcx.const_qualif_map.borrow_mut().entry(expr.id) {
@ -134,7 +139,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
fn fn_like(&mut self, fn fn_like(&mut self,
fk: FnKind<'gcx>, fk: FnKind<'gcx>,
fd: &'gcx hir::FnDecl, fd: &'gcx hir::FnDecl,
b: hir::ExprId, b: hir::BodyId,
s: Span, s: Span,
fn_id: ast::NodeId) fn_id: ast::NodeId)
-> ConstQualif { -> ConstQualif {
@ -160,7 +165,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
}; };
let qualif = self.with_mode(mode, |this| { let qualif = self.with_mode(mode, |this| {
let body = this.tcx.map.expr(b); let body = this.tcx.map.body(b);
this.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, body)); this.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, body));
intravisit::walk_fn(this, fk, fd, b, s, fn_id); intravisit::walk_fn(this, fk, fd, b, s, fn_id);
this.qualif this.qualif
@ -197,7 +202,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
true true
}, },
Some(ConstFnNode::Inlined(ii)) => { Some(ConstFnNode::Inlined(ii)) => {
let node_id = ii.body.id; let node_id = ii.body.value.id;
let qualif = match self.tcx.const_qualif_map.borrow_mut().entry(node_id) { let qualif = match self.tcx.const_qualif_map.borrow_mut().entry(node_id) {
Entry::Occupied(entry) => *entry.get(), Entry::Occupied(entry) => *entry.get(),
@ -241,19 +246,19 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
debug!("visit_item(item={})", self.tcx.map.node_to_string(i.id)); debug!("visit_item(item={})", self.tcx.map.node_to_string(i.id));
assert_eq!(self.mode, Mode::Var); assert_eq!(self.mode, Mode::Var);
match i.node { match i.node {
hir::ItemStatic(_, hir::MutImmutable, ref expr) => { hir::ItemStatic(_, hir::MutImmutable, expr) => {
self.global_expr(Mode::Static, &expr); self.global_body(Mode::Static, expr);
} }
hir::ItemStatic(_, hir::MutMutable, ref expr) => { hir::ItemStatic(_, hir::MutMutable, expr) => {
self.global_expr(Mode::StaticMut, &expr); self.global_body(Mode::StaticMut, expr);
} }
hir::ItemConst(_, ref expr) => { hir::ItemConst(_, expr) => {
self.global_expr(Mode::Const, &expr); self.global_body(Mode::Const, expr);
} }
hir::ItemEnum(ref enum_definition, _) => { hir::ItemEnum(ref enum_definition, _) => {
for var in &enum_definition.variants { for var in &enum_definition.variants {
if let Some(ref ex) = var.node.disr_expr { if let Some(ex) = var.node.disr_expr {
self.global_expr(Mode::Const, &ex); self.global_body(Mode::Const, ex);
} }
} }
} }
@ -265,9 +270,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
fn visit_trait_item(&mut self, t: &'tcx hir::TraitItem) { fn visit_trait_item(&mut self, t: &'tcx hir::TraitItem) {
match t.node { match t.node {
hir::TraitItemKind::Const(_, ref default) => { hir::TraitItemKind::Const(_, default) => {
if let Some(ref expr) = *default { if let Some(expr) = default {
self.global_expr(Mode::Const, &expr); self.global_body(Mode::Const, expr);
} else { } else {
intravisit::walk_trait_item(self, t); intravisit::walk_trait_item(self, t);
} }
@ -278,8 +283,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
fn visit_impl_item(&mut self, i: &'tcx hir::ImplItem) { fn visit_impl_item(&mut self, i: &'tcx hir::ImplItem) {
match i.node { match i.node {
hir::ImplItemKind::Const(_, ref expr) => { hir::ImplItemKind::Const(_, expr) => {
self.global_expr(Mode::Const, &expr); self.global_body(Mode::Const, expr);
} }
_ => self.with_mode(Mode::Var, |v| intravisit::walk_impl_item(v, i)), _ => self.with_mode(Mode::Var, |v| intravisit::walk_impl_item(v, i)),
} }
@ -288,7 +293,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
fn visit_fn(&mut self, fn visit_fn(&mut self,
fk: FnKind<'tcx>, fk: FnKind<'tcx>,
fd: &'tcx hir::FnDecl, fd: &'tcx hir::FnDecl,
b: hir::ExprId, b: hir::BodyId,
s: Span, s: Span,
fn_id: ast::NodeId) { fn_id: ast::NodeId) {
self.fn_like(fk, fd, b, s, fn_id); self.fn_like(fk, fd, b, s, fn_id);

View File

@ -177,7 +177,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
fn visit_fn(&mut self, fn visit_fn(&mut self,
fk: hir_visit::FnKind<'v>, fk: hir_visit::FnKind<'v>,
fd: &'v hir::FnDecl, fd: &'v hir::FnDecl,
b: hir::ExprId, b: hir::BodyId,
s: Span, s: Span,
id: NodeId) { id: NodeId) {
self.record("FnDecl", Id::None, fd); self.record("FnDecl", Id::None, fd);

View File

@ -84,7 +84,7 @@ impl<'a, 'ast> Visitor<'ast> for CheckLoopVisitor<'a, 'ast> {
self.with_context(Loop(LoopKind::Loop(source)), |v| v.visit_block(&b)); self.with_context(Loop(LoopKind::Loop(source)), |v| v.visit_block(&b));
} }
hir::ExprClosure(.., b, _) => { hir::ExprClosure(.., b, _) => {
self.with_context(Closure, |v| v.visit_body(b)); self.with_context(Closure, |v| v.visit_nested_body(b));
} }
hir::ExprBreak(label, ref opt_expr) => { hir::ExprBreak(label, ref opt_expr) => {
if opt_expr.is_some() { if opt_expr.is_some() {

View File

@ -39,7 +39,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RvalueContext<'a, 'tcx> {
fn visit_fn(&mut self, fn visit_fn(&mut self,
fk: intravisit::FnKind<'tcx>, fk: intravisit::FnKind<'tcx>,
fd: &'tcx hir::FnDecl, fd: &'tcx hir::FnDecl,
b: hir::ExprId, b: hir::BodyId,
s: Span, s: Span,
fn_id: ast::NodeId) { fn_id: ast::NodeId) {
// FIXME (@jroesch) change this to be an inference context // FIXME (@jroesch) change this to be an inference context
@ -50,7 +50,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RvalueContext<'a, 'tcx> {
tcx: infcx.tcx, tcx: infcx.tcx,
param_env: &param_env param_env: &param_env
}; };
let body = infcx.tcx.map.expr(b); let body = infcx.tcx.map.body(b);
let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx); let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx);
euv.walk_fn(fd, body); euv.walk_fn(fd, body);
}); });

View File

@ -30,7 +30,7 @@ struct CheckCrateVisitor<'a, 'ast: 'a> {
// variant definitions with the discriminant expression that applies to // variant definitions with the discriminant expression that applies to
// each one. If the variant uses the default values (starting from `0`), // each one. If the variant uses the default values (starting from `0`),
// then `None` is stored. // then `None` is stored.
discriminant_map: NodeMap<Option<&'ast hir::Expr>>, discriminant_map: NodeMap<Option<hir::BodyId>>,
detected_recursive_ids: NodeSet, detected_recursive_ids: NodeSet,
} }
@ -108,7 +108,7 @@ struct CheckItemRecursionVisitor<'a, 'b: 'a, 'ast: 'b> {
root_span: &'b Span, root_span: &'b Span,
sess: &'b Session, sess: &'b Session,
ast_map: &'b ast_map::Map<'ast>, ast_map: &'b ast_map::Map<'ast>,
discriminant_map: &'a mut NodeMap<Option<&'ast hir::Expr>>, discriminant_map: &'a mut NodeMap<Option<hir::BodyId>>,
idstack: Vec<ast::NodeId>, idstack: Vec<ast::NodeId>,
detected_recursive_ids: &'a mut NodeSet, detected_recursive_ids: &'a mut NodeSet,
} }
@ -189,7 +189,7 @@ impl<'a, 'b: 'a, 'ast: 'b> CheckItemRecursionVisitor<'a, 'b, 'ast> {
variant_stack.push(variant.node.data.id()); variant_stack.push(variant.node.data.id());
// When we find an expression, every variant currently on the stack // When we find an expression, every variant currently on the stack
// is affected by that expression. // is affected by that expression.
if let Some(ref expr) = variant.node.disr_expr { if let Some(expr) = variant.node.disr_expr {
for id in &variant_stack { for id in &variant_stack {
self.discriminant_map.insert(*id, Some(expr)); self.discriminant_map.insert(*id, Some(expr));
} }
@ -226,19 +226,15 @@ impl<'a, 'b: 'a, 'ast: 'b> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'b, '
_: &'ast hir::Generics, _: &'ast hir::Generics,
_: ast::NodeId) { _: ast::NodeId) {
let variant_id = variant.node.data.id(); let variant_id = variant.node.data.id();
let maybe_expr; let maybe_expr = *self.discriminant_map.get(&variant_id).unwrap_or_else(|| {
if let Some(get_expr) = self.discriminant_map.get(&variant_id) {
// This is necessary because we need to let the `discriminant_map`
// borrow fall out of scope, so that we can reborrow farther down.
maybe_expr = (*get_expr).clone();
} else {
span_bug!(variant.span, span_bug!(variant.span,
"`check_static_recursion` attempted to visit \ "`check_static_recursion` attempted to visit \
variant with unknown discriminant") variant with unknown discriminant")
} });
// If `maybe_expr` is `None`, that's because no discriminant is // If `maybe_expr` is `None`, that's because no discriminant is
// specified that affects this variant. Thus, no risk of recursion. // specified that affects this variant. Thus, no risk of recursion.
if let Some(expr) = maybe_expr { if let Some(expr) = maybe_expr {
let expr = &self.ast_map.body(expr).value;
self.with_item_id_pushed(expr.id, |v| intravisit::walk_expr(v, expr), expr.span); self.with_item_id_pushed(expr.id, |v| intravisit::walk_expr(v, expr), expr.span);
} }
} }

View File

@ -576,6 +576,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.span)) let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.span))
.map_or(Def::Err, |d| d.def()); .map_or(Def::Err, |d| d.def());
self.record_def(ty.id, PathResolution::new(def)); self.record_def(ty.id, PathResolution::new(def));
} else if let TyKind::Array(ref element, ref length) = ty.node {
self.visit_ty(element);
self.with_constant_rib(|this| {
this.visit_expr(length);
});
return;
} }
visit::walk_ty(self, ty); visit::walk_ty(self, ty);
} }
@ -2733,6 +2739,13 @@ impl<'a> Resolver<'a> {
self.visit_ty(ty); self.visit_ty(ty);
} }
} }
ExprKind::Repeat(ref element, ref count) => {
self.visit_expr(element);
self.with_constant_rib(|this| {
this.visit_expr(count);
});
}
ExprKind::Call(ref callee, ref arguments) => { ExprKind::Call(ref callee, ref arguments) => {
self.resolve_expr(callee, Some(&expr.node)); self.resolve_expr(callee, Some(&expr.node));
for argument in arguments { for argument in arguments {

View File

@ -1664,8 +1664,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
}; };
self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0 self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0
} }
hir::TyArray(ref ty, ref e) => { hir::TyArray(ref ty, length) => {
if let Ok(length) = eval_length(tcx.global_tcx(), &e, "array length") { let e = &tcx.map.body(length).value;
if let Ok(length) = eval_length(tcx.global_tcx(), e, "array length") {
tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), length) tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), length)
} else { } else {
self.tcx().types.err self.tcx().types.err

View File

@ -25,7 +25,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
expr: &hir::Expr, expr: &hir::Expr,
_capture: hir::CaptureClause, _capture: hir::CaptureClause,
decl: &'gcx hir::FnDecl, decl: &'gcx hir::FnDecl,
body_id: hir::ExprId, body_id: hir::BodyId,
expected: Expectation<'tcx>) expected: Expectation<'tcx>)
-> Ty<'tcx> { -> Ty<'tcx> {
debug!("check_expr_closure(expr={:?},expected={:?})", debug!("check_expr_closure(expr={:?},expected={:?})",
@ -39,7 +39,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Some(ty) => self.deduce_expectations_from_expected_type(ty), Some(ty) => self.deduce_expectations_from_expected_type(ty),
None => (None, None), None => (None, None),
}; };
let body = self.tcx.map.expr(body_id); let body = self.tcx.map.body(body_id);
self.check_closure(expr, expected_kind, decl, body, expected_sig) self.check_closure(expr, expected_kind, decl, body, expected_sig)
} }
@ -47,7 +47,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
expr: &hir::Expr, expr: &hir::Expr,
opt_kind: Option<ty::ClosureKind>, opt_kind: Option<ty::ClosureKind>,
decl: &'gcx hir::FnDecl, decl: &'gcx hir::FnDecl,
body: &'gcx hir::Expr, body: &'gcx hir::Body,
expected_sig: Option<ty::FnSig<'tcx>>) expected_sig: Option<ty::FnSig<'tcx>>)
-> Ty<'tcx> { -> Ty<'tcx> {
debug!("check_closure opt_kind={:?} expected_sig={:?}", debug!("check_closure opt_kind={:?} expected_sig={:?}",
@ -73,10 +73,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type); debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type);
let fn_sig = self.tcx let extent = self.tcx.region_maps.call_site_extent(expr.id, body.value.id);
.liberate_late_bound_regions(self.tcx.region_maps.call_site_extent(expr.id, body.id), let fn_sig = self.tcx.liberate_late_bound_regions(extent, &fn_ty.sig);
&fn_ty.sig); let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
let fn_sig = (**self).normalize_associated_types_in(body.span, body.id, &fn_sig); body.value.id, &fn_sig);
check_fn(self, check_fn(self,
hir::Unsafety::Normal, hir::Unsafety::Normal,
@ -84,7 +84,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
&fn_sig, &fn_sig,
decl, decl,
expr.id, expr.id,
&body); body);
// Tuple up the arguments and insert the resulting function type into // Tuple up the arguments and insert the resulting function type into
// the `closures` table. // the `closures` table.

View File

@ -550,14 +550,25 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
fn visit_ty(&mut self, t: &'tcx hir::Ty) { fn visit_ty(&mut self, t: &'tcx hir::Ty) {
match t.node { match t.node {
hir::TyArray(_, ref expr) => { hir::TyArray(_, length) => {
check_const_with_type(self.ccx, &expr, self.ccx.tcx.types.usize, expr.id); check_const_with_type(self.ccx, length, self.ccx.tcx.types.usize, length.node_id);
} }
_ => {} _ => {}
} }
intravisit::walk_ty(self, t); intravisit::walk_ty(self, t);
} }
fn visit_expr(&mut self, e: &'tcx hir::Expr) {
match e.node {
hir::ExprRepeat(_, count) => {
check_const_with_type(self.ccx, count, self.ccx.tcx.types.usize, count.node_id);
}
_ => {}
}
intravisit::walk_expr(self, e);
}
} }
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> { impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> {
@ -639,28 +650,28 @@ pub fn check_drop_impls(ccx: &CrateCtxt) -> CompileResult {
fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
decl: &'tcx hir::FnDecl, decl: &'tcx hir::FnDecl,
body_id: hir::ExprId, body_id: hir::BodyId,
fn_id: ast::NodeId, fn_id: ast::NodeId,
span: Span) { span: Span) {
let body = ccx.tcx.map.expr(body_id); let body = ccx.tcx.map.body(body_id);
let raw_fty = ccx.tcx.item_type(ccx.tcx.map.local_def_id(fn_id)); let raw_fty = ccx.tcx.item_type(ccx.tcx.map.local_def_id(fn_id));
let fn_ty = match raw_fty.sty { let fn_ty = match raw_fty.sty {
ty::TyFnDef(.., f) => f, ty::TyFnDef(.., f) => f,
_ => span_bug!(body.span, "check_bare_fn: function type expected") _ => span_bug!(body.value.span, "check_bare_fn: function type expected")
}; };
check_abi(ccx, span, fn_ty.abi); check_abi(ccx, span, fn_ty.abi);
ccx.inherited(fn_id).enter(|inh| { ccx.inherited(fn_id).enter(|inh| {
// Compute the fty from point of view of inside fn. // Compute the fty from point of view of inside fn.
let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body_id.node_id()); let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body_id.node_id);
let fn_sig = let fn_sig =
fn_ty.sig.subst(inh.tcx, &inh.parameter_environment.free_substs); fn_ty.sig.subst(inh.tcx, &inh.parameter_environment.free_substs);
let fn_sig = let fn_sig =
inh.tcx.liberate_late_bound_regions(fn_scope, &fn_sig); inh.tcx.liberate_late_bound_regions(fn_scope, &fn_sig);
let fn_sig = let fn_sig =
inh.normalize_associated_types_in(body.span, body_id.node_id(), &fn_sig); inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig);
let fcx = check_fn(&inh, fn_ty.unsafety, fn_id, &fn_sig, decl, fn_id, body); let fcx = check_fn(&inh, fn_ty.unsafety, fn_id, &fn_sig, decl, fn_id, body);
@ -670,7 +681,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
fcx.check_casts(); fcx.check_casts();
fcx.select_all_obligations_or_error(); // Casts can introduce new obligations. fcx.select_all_obligations_or_error(); // Casts can introduce new obligations.
fcx.regionck_fn(fn_id, decl, body_id); fcx.regionck_fn(fn_id, decl, body);
fcx.resolve_type_vars_in_fn(decl, body, fn_id); fcx.resolve_type_vars_in_fn(decl, body, fn_id);
}); });
} }
@ -740,21 +751,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
intravisit::walk_pat(self, p); intravisit::walk_pat(self, p);
} }
fn visit_block(&mut self, b: &'gcx hir::Block) {
// non-obvious: the `blk` variable maps to region lb, so
// we have to keep this up-to-date. This
// is... unfortunate. It'd be nice to not need this.
intravisit::walk_block(self, b);
}
// Since an expr occurs as part of the type fixed size arrays we
// need to record the type for that node
fn visit_ty(&mut self, t: &'gcx hir::Ty) { fn visit_ty(&mut self, t: &'gcx hir::Ty) {
match t.node { match t.node {
hir::TyArray(ref ty, ref count_expr) => {
self.visit_ty(&ty);
self.fcx.check_expr_with_hint(&count_expr, self.fcx.tcx.types.usize);
}
hir::TyBareFn(ref function_declaration) => { hir::TyBareFn(ref function_declaration) => {
intravisit::walk_fn_decl_nopat(self, &function_declaration.decl); intravisit::walk_fn_decl_nopat(self, &function_declaration.decl);
walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes); walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
@ -765,7 +763,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
// Don't descend into the bodies of nested closures // Don't descend into the bodies of nested closures
fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl, fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
_: hir::ExprId, _: Span, _: ast::NodeId) { } _: hir::BodyId, _: Span, _: ast::NodeId) { }
} }
/// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
@ -780,7 +778,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
fn_sig: &ty::FnSig<'tcx>, fn_sig: &ty::FnSig<'tcx>,
decl: &'gcx hir::FnDecl, decl: &'gcx hir::FnDecl,
fn_id: ast::NodeId, fn_id: ast::NodeId,
body: &'gcx hir::Expr) body: &'gcx hir::Body)
-> FnCtxt<'a, 'gcx, 'tcx> -> FnCtxt<'a, 'gcx, 'tcx>
{ {
let mut fn_sig = fn_sig.clone(); let mut fn_sig = fn_sig.clone();
@ -789,7 +787,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
// Create the function context. This is either derived from scratch or, // Create the function context. This is either derived from scratch or,
// in the case of function expressions, based on the outer context. // in the case of function expressions, based on the outer context.
let mut fcx = FnCtxt::new(inherited, None, body.id); let mut fcx = FnCtxt::new(inherited, None, body.value.id);
let ret_ty = fn_sig.output(); let ret_ty = fn_sig.output();
*fcx.ps.borrow_mut() = UnsafetyState::function(unsafety, unsafety_id); *fcx.ps.borrow_mut() = UnsafetyState::function(unsafety, unsafety_id);
@ -822,12 +820,12 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
fcx.write_ty(input.id, arg_ty); fcx.write_ty(input.id, arg_ty);
} }
visit.visit_expr(body); visit.visit_body(body);
} }
inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig); inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig);
fcx.check_expr_coercable_to_type(body, fcx.ret_ty.unwrap()); fcx.check_expr_coercable_to_type(&body.value, fcx.ret_ty.unwrap());
fcx fcx
} }
@ -852,8 +850,8 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
let _indenter = indenter(); let _indenter = indenter();
match it.node { match it.node {
// Consts can play a role in type-checking, so they are included here. // Consts can play a role in type-checking, so they are included here.
hir::ItemStatic(.., ref e) | hir::ItemStatic(.., e) |
hir::ItemConst(_, ref e) => check_const(ccx, &e, it.id), hir::ItemConst(_, e) => check_const(ccx, e, it.id),
hir::ItemEnum(ref enum_definition, _) => { hir::ItemEnum(ref enum_definition, _) => {
check_enum_variants(ccx, check_enum_variants(ccx,
it.span, it.span,
@ -937,8 +935,8 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
for impl_item_ref in impl_item_refs { for impl_item_ref in impl_item_refs {
let impl_item = ccx.tcx.map.impl_item(impl_item_ref.id); let impl_item = ccx.tcx.map.impl_item(impl_item_ref.id);
match impl_item.node { match impl_item.node {
hir::ImplItemKind::Const(_, ref expr) => { hir::ImplItemKind::Const(_, expr) => {
check_const(ccx, &expr, impl_item.id) check_const(ccx, expr, impl_item.id)
} }
hir::ImplItemKind::Method(ref sig, body_id) => { hir::ImplItemKind::Method(ref sig, body_id) => {
check_bare_fn(ccx, &sig.decl, body_id, impl_item.id, impl_item.span); check_bare_fn(ccx, &sig.decl, body_id, impl_item.id, impl_item.span);
@ -953,8 +951,8 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
for trait_item_ref in trait_item_refs { for trait_item_ref in trait_item_refs {
let trait_item = ccx.tcx.map.trait_item(trait_item_ref.id); let trait_item = ccx.tcx.map.trait_item(trait_item_ref.id);
match trait_item.node { match trait_item.node {
hir::TraitItemKind::Const(_, Some(ref expr)) => { hir::TraitItemKind::Const(_, Some(expr)) => {
check_const(ccx, &expr, trait_item.id) check_const(ccx, expr, trait_item.id)
} }
hir::TraitItemKind::Method(ref sig, Some(body_id)) => { hir::TraitItemKind::Method(ref sig, Some(body_id)) => {
check_bare_fn(ccx, &sig.decl, body_id, trait_item.id, trait_item.span); check_bare_fn(ccx, &sig.decl, body_id, trait_item.id, trait_item.span);
@ -1127,7 +1125,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
compare_impl_method(ccx, compare_impl_method(ccx,
&ty_impl_item, &ty_impl_item,
impl_item.span, impl_item.span,
body_id.node_id(), body_id.node_id,
&ty_trait_item, &ty_trait_item,
impl_trait_ref, impl_trait_ref,
trait_span, trait_span,
@ -1137,7 +1135,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
compare_impl_method(ccx, compare_impl_method(ccx,
&ty_impl_item, &ty_impl_item,
impl_item.span, impl_item.span,
body_id.node_id(), body_id.node_id,
&ty_trait_item, &ty_trait_item,
impl_trait_ref, impl_trait_ref,
trait_span, trait_span,
@ -1248,37 +1246,38 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
/// Checks a constant with a given type. /// Checks a constant with a given type.
fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
expr: &'tcx hir::Expr, body: hir::BodyId,
expected_type: Ty<'tcx>, expected_type: Ty<'tcx>,
id: ast::NodeId) { id: ast::NodeId) {
let body = ccx.tcx.map.body(body);
ccx.inherited(id).enter(|inh| { ccx.inherited(id).enter(|inh| {
let fcx = FnCtxt::new(&inh, None, expr.id); let fcx = FnCtxt::new(&inh, None, body.value.id);
fcx.require_type_is_sized(expected_type, expr.span, traits::ConstSized); fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
// Gather locals in statics (because of block expressions). // Gather locals in statics (because of block expressions).
// This is technically unnecessary because locals in static items are forbidden, // This is technically unnecessary because locals in static items are forbidden,
// but prevents type checking from blowing up before const checking can properly // but prevents type checking from blowing up before const checking can properly
// emit an error. // emit an error.
GatherLocalsVisitor { fcx: &fcx }.visit_expr(expr); GatherLocalsVisitor { fcx: &fcx }.visit_body(body);
fcx.check_expr_coercable_to_type(expr, expected_type); fcx.check_expr_coercable_to_type(&body.value, expected_type);
fcx.select_all_obligations_and_apply_defaults(); fcx.select_all_obligations_and_apply_defaults();
fcx.closure_analyze(expr); fcx.closure_analyze(body);
fcx.select_obligations_where_possible(); fcx.select_obligations_where_possible();
fcx.check_casts(); fcx.check_casts();
fcx.select_all_obligations_or_error(); fcx.select_all_obligations_or_error();
fcx.regionck_expr(expr); fcx.regionck_expr(body);
fcx.resolve_type_vars_in_expr(expr, id); fcx.resolve_type_vars_in_expr(body, id);
}); });
} }
fn check_const<'a, 'tcx>(ccx: &CrateCtxt<'a,'tcx>, fn check_const<'a, 'tcx>(ccx: &CrateCtxt<'a,'tcx>,
expr: &'tcx hir::Expr, body: hir::BodyId,
id: ast::NodeId) { id: ast::NodeId) {
let decl_ty = ccx.tcx.item_type(ccx.tcx.map.local_def_id(id)); let decl_ty = ccx.tcx.item_type(ccx.tcx.map.local_def_id(id));
check_const_with_type(ccx, expr, decl_ty, id); check_const_with_type(ccx, body, decl_ty, id);
} }
/// Checks whether a type can be represented in memory. In particular, it /// Checks whether a type can be represented in memory. In particular, it
@ -1353,8 +1352,8 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
let repr_type_ty = ccx.tcx.enum_repr_type(Some(&hint)).to_ty(ccx.tcx); let repr_type_ty = ccx.tcx.enum_repr_type(Some(&hint)).to_ty(ccx.tcx);
for v in vs { for v in vs {
if let Some(ref e) = v.node.disr_expr { if let Some(e) = v.node.disr_expr {
check_const_with_type(ccx, e, repr_type_ty, e.id); check_const_with_type(ccx, e, repr_type_ty, e.node_id);
} }
} }
@ -1370,11 +1369,11 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
let variant_i_node_id = ccx.tcx.map.as_local_node_id(variants[i].did).unwrap(); let variant_i_node_id = ccx.tcx.map.as_local_node_id(variants[i].did).unwrap();
let variant_i = ccx.tcx.map.expect_variant(variant_i_node_id); let variant_i = ccx.tcx.map.expect_variant(variant_i_node_id);
let i_span = match variant_i.node.disr_expr { let i_span = match variant_i.node.disr_expr {
Some(ref expr) => expr.span, Some(expr) => ccx.tcx.map.span(expr.node_id),
None => ccx.tcx.map.span(variant_i_node_id) None => ccx.tcx.map.span(variant_i_node_id)
}; };
let span = match v.node.disr_expr { let span = match v.node.disr_expr {
Some(ref expr) => expr.span, Some(expr) => ccx.tcx.map.span(expr.node_id),
None => v.span None => v.span
}; };
struct_span_err!(ccx.tcx.sess, span, E0081, struct_span_err!(ccx.tcx.sess, span, E0081,
@ -1648,12 +1647,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
match self.locals.borrow().get(&nid) { match self.locals.borrow().get(&nid) {
Some(&t) => t, Some(&t) => t,
None => { None => {
struct_span_err!(self.tcx.sess, span, E0513, span_bug!(span, "no type for local variable {}",
"no type for local variable {}", self.tcx.map.node_to_string(nid));
self.tcx.map.node_to_string(nid))
.span_label(span, &"no type for variable")
.emit();
self.tcx.types.err
} }
} }
} }
@ -3826,10 +3821,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.check_method_call(expr, name, args, &tps[..], expected, lvalue_pref) self.check_method_call(expr, name, args, &tps[..], expected, lvalue_pref)
} }
hir::ExprCast(ref e, ref t) => { hir::ExprCast(ref e, ref t) => {
if let hir::TyArray(_, ref count_expr) = t.node {
self.check_expr_with_hint(&count_expr, tcx.types.usize);
}
// Find the type of `e`. Supply hints based on the type we are casting to, // Find the type of `e`. Supply hints based on the type we are casting to,
// if appropriate. // if appropriate.
let t_cast = self.to_ty(t); let t_cast = self.to_ty(t);
@ -3891,9 +3882,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
tcx.mk_array(unified, args.len()) tcx.mk_array(unified, args.len())
} }
hir::ExprRepeat(ref element, ref count_expr) => { hir::ExprRepeat(ref element, count) => {
self.check_expr_has_type(&count_expr, tcx.types.usize); let count_expr = &tcx.map.body(count).value;
let count = eval_length(self.tcx.global_tcx(), &count_expr, "repeat count") let count = eval_length(self.tcx.global_tcx(), count_expr, "repeat count")
.unwrap_or(0); .unwrap_or(0);
let uty = match expected { let uty = match expected {

View File

@ -113,12 +113,13 @@ macro_rules! ignore_err {
// PUBLIC ENTRY POINTS // PUBLIC ENTRY POINTS
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn regionck_expr(&self, e: &'gcx hir::Expr) { pub fn regionck_expr(&self, body: &'gcx hir::Body) {
let mut rcx = RegionCtxt::new(self, RepeatingScope(e.id), e.id, Subject(e.id)); let id = body.value.id;
let mut rcx = RegionCtxt::new(self, RepeatingScope(id), id, Subject(id));
if self.err_count_since_creation() == 0 { if self.err_count_since_creation() == 0 {
// regionck assumes typeck succeeded // regionck assumes typeck succeeded
rcx.visit_expr(e); rcx.visit_body(body);
rcx.visit_region_obligations(e.id); rcx.visit_region_obligations(id);
} }
rcx.resolve_regions_and_report_errors(); rcx.resolve_regions_and_report_errors();
} }
@ -141,14 +142,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn regionck_fn(&self, pub fn regionck_fn(&self,
fn_id: ast::NodeId, fn_id: ast::NodeId,
decl: &hir::FnDecl, decl: &hir::FnDecl,
body_id: hir::ExprId) { body: &'gcx hir::Body) {
debug!("regionck_fn(id={})", fn_id); debug!("regionck_fn(id={})", fn_id);
let node_id = body_id.node_id(); let node_id = body.value.id;
let mut rcx = RegionCtxt::new(self, RepeatingScope(node_id), node_id, Subject(fn_id)); let mut rcx = RegionCtxt::new(self, RepeatingScope(node_id), node_id, Subject(fn_id));
if self.err_count_since_creation() == 0 { if self.err_count_since_creation() == 0 {
// regionck assumes typeck succeeded // regionck assumes typeck succeeded
rcx.visit_fn_body(fn_id, decl, body_id, self.tcx.map.span(fn_id)); rcx.visit_fn_body(fn_id, decl, body, self.tcx.map.span(fn_id));
} }
rcx.free_region_map.relate_free_regions_from_predicates( rcx.free_region_map.relate_free_regions_from_predicates(
@ -268,14 +269,16 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
fn visit_fn_body(&mut self, fn visit_fn_body(&mut self,
id: ast::NodeId, // the id of the fn itself id: ast::NodeId, // the id of the fn itself
fn_decl: &hir::FnDecl, fn_decl: &hir::FnDecl,
body_id: hir::ExprId, body: &'gcx hir::Body,
span: Span) span: Span)
{ {
// When we enter a function, we can derive // When we enter a function, we can derive
debug!("visit_fn_body(id={})", id); debug!("visit_fn_body(id={})", id);
let body_id = body.id();
let call_site = self.tcx.region_maps.lookup_code_extent( let call_site = self.tcx.region_maps.lookup_code_extent(
region::CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id() }); region::CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id });
let old_call_site_scope = self.set_call_site_scope(Some(call_site)); let old_call_site_scope = self.set_call_site_scope(Some(call_site));
let fn_sig = { let fn_sig = {
@ -298,20 +301,19 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
let fn_sig_tys: Vec<_> = let fn_sig_tys: Vec<_> =
fn_sig.inputs().iter().cloned().chain(Some(fn_sig.output())).collect(); fn_sig.inputs().iter().cloned().chain(Some(fn_sig.output())).collect();
let old_body_id = self.set_body_id(body_id.node_id()); let old_body_id = self.set_body_id(body_id.node_id);
self.relate_free_regions(&fn_sig_tys[..], body_id.node_id(), span); self.relate_free_regions(&fn_sig_tys[..], body_id.node_id, span);
self.link_fn_args(self.tcx.region_maps.node_extent(body_id.node_id()), self.link_fn_args(self.tcx.region_maps.node_extent(body_id.node_id),
&fn_decl.inputs[..]); &fn_decl.inputs[..]);
let body = self.tcx.map.expr(body_id); self.visit_body(body);
self.visit_expr(body); self.visit_region_obligations(body_id.node_id);
self.visit_region_obligations(body_id.node_id());
let call_site_scope = self.call_site_scope.unwrap(); let call_site_scope = self.call_site_scope.unwrap();
debug!("visit_fn_body body.id {} call_site_scope: {:?}", debug!("visit_fn_body body.id {:?} call_site_scope: {:?}",
body.id, call_site_scope); body.id(), call_site_scope);
let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope)); let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope));
self.type_of_node_must_outlive(infer::CallReturn(span), self.type_of_node_must_outlive(infer::CallReturn(span),
body_id.node_id(), body_id.node_id,
call_site_region); call_site_region);
self.region_bound_pairs.truncate(old_region_bounds_pairs_len); self.region_bound_pairs.truncate(old_region_bounds_pairs_len);
@ -478,12 +480,13 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
// regions, until regionck, as described in #3238. // regions, until regionck, as described in #3238.
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
NestedVisitorMap::OnlyBodies(&self.tcx.map) NestedVisitorMap::None
} }
fn visit_fn(&mut self, _fk: intravisit::FnKind<'gcx>, fd: &'gcx hir::FnDecl, fn visit_fn(&mut self, _fk: intravisit::FnKind<'gcx>, fd: &'gcx hir::FnDecl,
b: hir::ExprId, span: Span, id: ast::NodeId) { b: hir::BodyId, span: Span, id: ast::NodeId) {
self.visit_fn_body(id, fd, b, span) let body = self.tcx.map.body(b);
self.visit_fn_body(id, fd, body, span)
} }
//visit_pat: visit_pat, // (..) see above //visit_pat: visit_pat, // (..) see above
@ -826,8 +829,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
fn check_expr_fn_block(&mut self, fn check_expr_fn_block(&mut self,
expr: &'gcx hir::Expr, expr: &'gcx hir::Expr,
body_id: hir::ExprId) { body_id: hir::BodyId) {
let repeating_scope = self.set_repeating_scope(body_id.node_id()); let repeating_scope = self.set_repeating_scope(body_id.node_id);
intravisit::walk_expr(self, expr); intravisit::walk_expr(self, expr);
self.set_repeating_scope(repeating_scope); self.set_repeating_scope(repeating_scope);
} }

View File

@ -57,12 +57,12 @@ use rustc::util::nodemap::NodeMap;
// PUBLIC ENTRY POINTS // PUBLIC ENTRY POINTS
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn closure_analyze(&self, body: &'gcx hir::Expr) { pub fn closure_analyze(&self, body: &'gcx hir::Body) {
let mut seed = SeedBorrowKind::new(self); let mut seed = SeedBorrowKind::new(self);
seed.visit_expr(body); seed.visit_body(body);
let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds); let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds);
adjust.visit_expr(body); adjust.visit_body(body);
// it's our job to process these. // it's our job to process these.
assert!(self.deferred_call_resolutions.borrow().is_empty()); assert!(self.deferred_call_resolutions.borrow().is_empty());
@ -79,13 +79,15 @@ struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> Visitor<'gcx> for SeedBorrowKind<'a, 'gcx, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
NestedVisitorMap::OnlyBodies(&self.fcx.tcx.map) NestedVisitorMap::None
} }
fn visit_expr(&mut self, expr: &'gcx hir::Expr) { fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
match expr.node { match expr.node {
hir::ExprClosure(cc, _, body_id, _) => { hir::ExprClosure(cc, _, body_id, _) => {
self.check_closure(expr, cc, body_id); let body = self.fcx.tcx.map.body(body_id);
self.visit_body(body);
self.check_closure(expr, cc);
} }
_ => { } _ => { }
@ -102,8 +104,7 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> {
fn check_closure(&mut self, fn check_closure(&mut self,
expr: &hir::Expr, expr: &hir::Expr,
capture_clause: hir::CaptureClause, capture_clause: hir::CaptureClause)
_body_id: hir::ExprId)
{ {
let closure_def_id = self.fcx.tcx.map.local_def_id(expr.id); let closure_def_id = self.fcx.tcx.map.local_def_id(expr.id);
if !self.fcx.tables.borrow().closure_kinds.contains_key(&closure_def_id) { if !self.fcx.tables.borrow().closure_kinds.contains_key(&closure_def_id) {
@ -157,15 +158,14 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
id: ast::NodeId, id: ast::NodeId,
span: Span, span: Span,
decl: &hir::FnDecl, decl: &hir::FnDecl,
body_id: hir::ExprId) { body: &hir::Body) {
/*! /*!
* Analysis starting point. * Analysis starting point.
*/ */
debug!("analyze_closure(id={:?}, body.id={:?})", id, body_id); debug!("analyze_closure(id={:?}, body.id={:?})", id, body.id());
{ {
let body = self.fcx.tcx.map.expr(body_id);
let mut euv = let mut euv =
euv::ExprUseVisitor::with_options(self, euv::ExprUseVisitor::with_options(self,
self.fcx, self.fcx,
@ -491,17 +491,20 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for AdjustBorrowKind<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> Visitor<'gcx> for AdjustBorrowKind<'a, 'gcx, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
NestedVisitorMap::OnlyBodies(&self.fcx.tcx.map) NestedVisitorMap::None
} }
fn visit_fn(&mut self, fn visit_fn(&mut self,
fn_kind: intravisit::FnKind<'gcx>, fn_kind: intravisit::FnKind<'gcx>,
decl: &'gcx hir::FnDecl, decl: &'gcx hir::FnDecl,
body: hir::ExprId, body: hir::BodyId,
span: Span, span: Span,
id: ast::NodeId) id: ast::NodeId)
{ {
intravisit::walk_fn(self, fn_kind, decl, body, span, id); intravisit::walk_fn(self, fn_kind, decl, body, span, id);
let body = self.fcx.tcx.map.body(body);
self.visit_body(body);
self.analyze_closure(id, span, decl, body); self.analyze_closure(id, span, decl, body);
} }
} }

View File

@ -337,7 +337,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
fn check_item_fn(&mut self, fn check_item_fn(&mut self,
item: &hir::Item, item: &hir::Item,
body_id: hir::ExprId) body_id: hir::BodyId)
{ {
self.for_item(item).with_fcx(|fcx, this| { self.for_item(item).with_fcx(|fcx, this| {
let free_substs = &fcx.parameter_environment.free_substs; let free_substs = &fcx.parameter_environment.free_substs;
@ -354,7 +354,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs); let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs);
let mut implied_bounds = vec![]; let mut implied_bounds = vec![];
let free_id_outlive = fcx.tcx.region_maps.call_site_extent(item.id, body_id.node_id()); let free_id_outlive = fcx.tcx.region_maps.call_site_extent(item.id, body_id.node_id);
this.check_fn_or_method(fcx, item.span, bare_fn_ty, &predicates, this.check_fn_or_method(fcx, item.span, bare_fn_ty, &predicates,
free_id_outlive, &mut implied_bounds); free_id_outlive, &mut implied_bounds);
implied_bounds implied_bounds

View File

@ -34,10 +34,10 @@ use rustc::hir::{self, PatKind};
// Entry point functions // Entry point functions
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn resolve_type_vars_in_expr(&self, e: &'gcx hir::Expr, item_id: ast::NodeId) { pub fn resolve_type_vars_in_expr(&self, body: &'gcx hir::Body, item_id: ast::NodeId) {
assert_eq!(self.writeback_errors.get(), false); assert_eq!(self.writeback_errors.get(), false);
let mut wbcx = WritebackCx::new(self); let mut wbcx = WritebackCx::new(self);
wbcx.visit_expr(e); wbcx.visit_body(body);
wbcx.visit_upvar_borrow_map(); wbcx.visit_upvar_borrow_map();
wbcx.visit_closures(); wbcx.visit_closures();
wbcx.visit_liberated_fn_sigs(); wbcx.visit_liberated_fn_sigs();
@ -48,11 +48,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn resolve_type_vars_in_fn(&self, pub fn resolve_type_vars_in_fn(&self,
decl: &'gcx hir::FnDecl, decl: &'gcx hir::FnDecl,
body: &'gcx hir::Expr, body: &'gcx hir::Body,
item_id: ast::NodeId) { item_id: ast::NodeId) {
assert_eq!(self.writeback_errors.get(), false); assert_eq!(self.writeback_errors.get(), false);
let mut wbcx = WritebackCx::new(self); let mut wbcx = WritebackCx::new(self);
wbcx.visit_expr(body); wbcx.visit_body(body);
for arg in &decl.inputs { for arg in &decl.inputs {
wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id); wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id);
wbcx.visit_pat(&arg.pat); wbcx.visit_pat(&arg.pat);
@ -188,7 +188,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
NestedVisitorMap::OnlyBodies(&self.fcx.tcx.map) NestedVisitorMap::None
} }
fn visit_stmt(&mut self, s: &'gcx hir::Stmt) { fn visit_stmt(&mut self, s: &'gcx hir::Stmt) {
@ -211,10 +211,13 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
self.visit_method_map_entry(ResolvingExpr(e.span), self.visit_method_map_entry(ResolvingExpr(e.span),
MethodCall::expr(e.id)); MethodCall::expr(e.id));
if let hir::ExprClosure(_, ref decl, ..) = e.node { if let hir::ExprClosure(_, ref decl, body, _) = e.node {
for input in &decl.inputs { for input in &decl.inputs {
self.visit_node_id(ResolvingExpr(e.span), input.id); self.visit_node_id(ResolvingExpr(e.span), input.id);
} }
let body = self.fcx.tcx.map.body(body);
self.visit_body(body);
} }
intravisit::walk_expr(self, e); intravisit::walk_expr(self, e);
@ -257,10 +260,6 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
fn visit_ty(&mut self, t: &'gcx hir::Ty) { fn visit_ty(&mut self, t: &'gcx hir::Ty) {
match t.node { match t.node {
hir::TyArray(ref ty, ref count_expr) => {
self.visit_ty(&ty);
self.write_ty_to_tcx(count_expr.id, self.tcx().types.usize);
}
hir::TyBareFn(ref function_declaration) => { hir::TyBareFn(ref function_declaration) => {
intravisit::walk_fn_decl_nopat(self, &function_declaration.decl); intravisit::walk_fn_decl_nopat(self, &function_declaration.decl);
walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes); walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);

View File

@ -1095,7 +1095,8 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
let mut prev_disr = None::<ty::Disr>; let mut prev_disr = None::<ty::Disr>;
let variants = def.variants.iter().map(|v| { let variants = def.variants.iter().map(|v| {
let wrapped_disr = prev_disr.map_or(initial, |d| d.wrap_incr()); let wrapped_disr = prev_disr.map_or(initial, |d| d.wrap_incr());
let disr = if let Some(ref e) = v.node.disr_expr { let disr = if let Some(e) = v.node.disr_expr {
let e = &tcx.map.body(e).value;
evaluate_disr_expr(ccx, repr_type, e) evaluate_disr_expr(ccx, repr_type, e)
} else if let Some(disr) = repr_type.disr_incr(tcx, prev_disr) { } else if let Some(disr) = repr_type.disr_incr(tcx, prev_disr) {
Some(disr) Some(disr)

View File

@ -3866,45 +3866,6 @@ extern "platform-intrinsic" {
``` ```
"##, "##,
E0513: r##"
The type of the variable couldn't be found out.
Erroneous code example:
```compile_fail,E0513
use std::mem;
unsafe {
let size = mem::size_of::<u32>();
mem::transmute_copy::<u32, [u8; size]>(&8_8);
// error: no type for local variable
}
```
To fix this error, please use a constant size instead of `size`. To make
this error more obvious, you could run:
```compile_fail,E0080
use std::mem;
unsafe {
mem::transmute_copy::<u32, [u8; mem::size_of::<u32>()]>(&8_8);
// error: constant evaluation error
}
```
So now, you can fix your code by setting the size directly:
```
use std::mem;
unsafe {
mem::transmute_copy::<u32, [u8; 4]>(&8_8);
// `u32` is 4 bytes so we replace the `mem::size_of` call with its size
}
```
"##,
E0516: r##" E0516: r##"
The `typeof` keyword is currently reserved but unimplemented. The `typeof` keyword is currently reserved but unimplemented.
Erroneous code example: Erroneous code example:

View File

@ -1270,9 +1270,9 @@ impl Clean<PolyTrait> for hir::PolyTraitRef {
impl Clean<Item> for hir::TraitItem { impl Clean<Item> for hir::TraitItem {
fn clean(&self, cx: &DocContext) -> Item { fn clean(&self, cx: &DocContext) -> Item {
let inner = match self.node { let inner = match self.node {
hir::TraitItemKind::Const(ref ty, ref default) => { hir::TraitItemKind::Const(ref ty, default) => {
AssociatedConstItem(ty.clean(cx), AssociatedConstItem(ty.clean(cx),
default.as_ref().map(|e| pprust::expr_to_string(&e))) default.map(|e| print_const_expr(cx, e)))
} }
hir::TraitItemKind::Method(ref sig, Some(_)) => { hir::TraitItemKind::Method(ref sig, Some(_)) => {
MethodItem(sig.clean(cx)) MethodItem(sig.clean(cx))
@ -1300,9 +1300,9 @@ impl Clean<Item> for hir::TraitItem {
impl Clean<Item> for hir::ImplItem { impl Clean<Item> for hir::ImplItem {
fn clean(&self, cx: &DocContext) -> Item { fn clean(&self, cx: &DocContext) -> Item {
let inner = match self.node { let inner = match self.node {
hir::ImplItemKind::Const(ref ty, ref expr) => { hir::ImplItemKind::Const(ref ty, expr) => {
AssociatedConstItem(ty.clean(cx), AssociatedConstItem(ty.clean(cx),
Some(pprust::expr_to_string(expr))) Some(print_const_expr(cx, expr)))
} }
hir::ImplItemKind::Method(ref sig, _) => { hir::ImplItemKind::Method(ref sig, _) => {
MethodItem(sig.clean(cx)) MethodItem(sig.clean(cx))
@ -1687,11 +1687,12 @@ impl Clean<Type> for hir::Ty {
BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx), BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
type_: box m.ty.clean(cx)}, type_: box m.ty.clean(cx)},
TySlice(ref ty) => Vector(box ty.clean(cx)), TySlice(ref ty) => Vector(box ty.clean(cx)),
TyArray(ref ty, ref e) => { TyArray(ref ty, e) => {
use rustc_const_math::{ConstInt, ConstUsize}; use rustc_const_math::{ConstInt, ConstUsize};
use rustc_const_eval::eval_const_expr; use rustc_const_eval::eval_const_expr;
use rustc::middle::const_val::ConstVal; use rustc::middle::const_val::ConstVal;
let e = &cx.tcx.map.body(e).value;
let n = match eval_const_expr(cx.tcx, e) { let n = match eval_const_expr(cx.tcx, e) {
ConstVal::Integral(ConstInt::Usize(u)) => match u { ConstVal::Integral(ConstInt::Usize(u)) => match u {
ConstUsize::Us16(u) => u.to_string(), ConstUsize::Us16(u) => u.to_string(),
@ -2372,7 +2373,7 @@ impl Clean<Item> for doctree::Static {
inner: StaticItem(Static { inner: StaticItem(Static {
type_: self.type_.clean(cx), type_: self.type_.clean(cx),
mutability: self.mutability.clean(cx), mutability: self.mutability.clean(cx),
expr: pprust::expr_to_string(&self.expr), expr: print_const_expr(cx, self.expr),
}), }),
} }
} }
@ -2396,7 +2397,7 @@ impl Clean<Item> for doctree::Constant {
deprecation: self.depr.clean(cx), deprecation: self.depr.clean(cx),
inner: ConstantItem(Constant { inner: ConstantItem(Constant {
type_: self.type_.clean(cx), type_: self.type_.clean(cx),
expr: pprust::expr_to_string(&self.expr), expr: print_const_expr(cx, self.expr),
}), }),
} }
} }
@ -2724,6 +2725,10 @@ fn name_from_pat(p: &hir::Pat) -> String {
} }
} }
fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String {
pprust::expr_to_string(&cx.tcx.map.body(body).value)
}
/// Given a type Path, resolve it to a Type using the TyCtxt /// Given a type Path, resolve it to a Type using the TyCtxt
fn resolve_type(cx: &DocContext, fn resolve_type(cx: &DocContext,
path: Path, path: Path,

View File

@ -174,7 +174,7 @@ pub struct Typedef {
pub struct Static { pub struct Static {
pub type_: P<hir::Ty>, pub type_: P<hir::Ty>,
pub mutability: hir::Mutability, pub mutability: hir::Mutability,
pub expr: P<hir::Expr>, pub expr: hir::BodyId,
pub name: Name, pub name: Name,
pub attrs: hir::HirVec<ast::Attribute>, pub attrs: hir::HirVec<ast::Attribute>,
pub vis: hir::Visibility, pub vis: hir::Visibility,
@ -186,7 +186,7 @@ pub struct Static {
pub struct Constant { pub struct Constant {
pub type_: P<hir::Ty>, pub type_: P<hir::Ty>,
pub expr: P<hir::Expr>, pub expr: hir::BodyId,
pub name: Name, pub name: Name,
pub attrs: hir::HirVec<ast::Attribute>, pub attrs: hir::HirVec<ast::Attribute>,
pub vis: hir::Visibility, pub vis: hir::Visibility,

View File

@ -1,19 +0,0 @@
// Copyright 2016 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.
use std::mem;
fn main() {
unsafe {
let size = mem::size_of::<u32>();
mem::transmute_copy::<u32, [u8; size]>(&8_8); //~ ERROR E0513
//~| NOTE no type for variable
}
}

View File

@ -25,7 +25,9 @@ impl Foo for Def {
} }
pub fn test<A: Foo, B: Foo>() { pub fn test<A: Foo, B: Foo>() {
let _array = [4; <A as Foo>::Y]; //~ ERROR E0080 let _array = [4; <A as Foo>::Y];
//~^ ERROR cannot use an outer type parameter in this context [E0402]
//~| ERROR constant evaluation error [E0080]
//~| non-constant path in constant //~| non-constant path in constant
} }

View File

@ -26,7 +26,9 @@ impl Foo for Def {
pub fn test<A: Foo, B: Foo>() { pub fn test<A: Foo, B: Foo>() {
let _array: [u32; <A as Foo>::Y]; let _array: [u32; <A as Foo>::Y];
//~^ ERROR the trait bound `A: Foo` is not satisfied //~^ ERROR cannot use an outer type parameter in this context [E0402]
//~| ERROR constant evaluation error [E0080]
//~| non-constant path in constant
} }
fn main() { fn main() {

View File

@ -16,6 +16,4 @@ fn main() {
//~| expected type `usize` //~| expected type `usize`
//~| found type `S` //~| found type `S`
//~| expected usize, found struct `S` //~| expected usize, found struct `S`
//~| ERROR expected `usize` for repeat count, found struct [E0306]
//~| expected `usize`
} }

View File

@ -12,8 +12,8 @@
fn main() { fn main() {
fn bar(n: isize) { fn bar(n: isize) {
// FIXME (#24414): This error message needs improvement.
let _x: [isize; n]; let _x: [isize; n];
//~^ ERROR no type for local variable //~^ ERROR attempt to use a non-constant value in a constant [E0435]
//~| ERROR constant evaluation error [E0080]
} }
} }

View File

@ -13,8 +13,9 @@
fn main() { fn main() {
fn bar(n: usize) { fn bar(n: usize) {
let _x = [0; n]; let _x = [0; n];
//~^ ERROR constant evaluation error //~^ ERROR attempt to use a non-constant value in a constant [E0435]
//~| non-constant path in constant expression //~| NOTE non-constant used with constant
//~| NOTE `n` is a variable //~| NOTE unresolved path in constant expression
//~| ERROR constant evaluation error [E0080]
} }
} }

View File

@ -13,43 +13,30 @@
fn main() { fn main() {
let n = 1; let n = 1;
let a = [0; n]; let a = [0; n];
//~^ ERROR constant evaluation error //~^ ERROR attempt to use a non-constant value in a constant [E0435]
//~| non-constant path in constant expression
let b = [0; ()]; let b = [0; ()];
//~^ ERROR mismatched types //~^ ERROR mismatched types
//~| expected type `usize` //~| expected type `usize`
//~| found type `()` //~| found type `()`
//~| expected usize, found () //~| expected usize, found ()
//~| ERROR expected `usize` for repeat count, found tuple [E0306]
//~| expected `usize`
let c = [0; true]; let c = [0; true];
//~^ ERROR mismatched types //~^ ERROR mismatched types
//~| expected usize, found bool //~| expected usize, found bool
//~| ERROR expected `usize` for repeat count, found boolean [E0306]
//~| expected `usize`
let d = [0; 0.5]; let d = [0; 0.5];
//~^ ERROR mismatched types //~^ ERROR mismatched types
//~| expected type `usize` //~| expected type `usize`
//~| found type `{float}` //~| found type `{float}`
//~| expected usize, found floating-point variable //~| expected usize, found floating-point variable
//~| ERROR expected `usize` for repeat count, found float [E0306]
//~| expected `usize`
let e = [0; "foo"]; let e = [0; "foo"];
//~^ ERROR mismatched types //~^ ERROR mismatched types
//~| expected type `usize` //~| expected type `usize`
//~| found type `&'static str` //~| found type `&'static str`
//~| expected usize, found reference //~| expected usize, found reference
//~| ERROR expected `usize` for repeat count, found string literal [E0306]
//~| expected `usize`
let f = [0; -4_isize]; let f = [0; -4_isize];
//~^ ERROR constant evaluation error //~^ ERROR mismatched types
//~| expected usize, found isize
//~| ERROR mismatched types
//~| expected usize, found isize //~| expected usize, found isize
let f = [0_usize; -1_isize]; let f = [0_usize; -1_isize];
//~^ ERROR constant evaluation error //~^ ERROR mismatched types
//~| expected usize, found isize
//~| ERROR mismatched types
//~| expected usize, found isize //~| expected usize, found isize
struct G { struct G {
g: (), g: (),
@ -59,6 +46,4 @@ fn main() {
//~| expected type `usize` //~| expected type `usize`
//~| found type `main::G` //~| found type `main::G`
//~| expected usize, found struct `main::G` //~| expected usize, found struct `main::G`
//~| ERROR expected `usize` for repeat count, found struct [E0306]
//~| expected `usize`
} }

View File

@ -66,8 +66,10 @@ const CONST_CHANGE_TYPE_2: Option<u64> = None;
const CONST_CHANGE_VALUE_1: i16 = 1; const CONST_CHANGE_VALUE_1: i16 = 1;
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
const CONST_CHANGE_VALUE_1: i16 = 2; const CONST_CHANGE_VALUE_1: i16 = 2;
@ -78,8 +80,10 @@ const CONST_CHANGE_VALUE_1: i16 = 2;
const CONST_CHANGE_VALUE_2: i16 = 1 + 1; const CONST_CHANGE_VALUE_2: i16 = 1 + 1;
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
const CONST_CHANGE_VALUE_2: i16 = 1 + 2; const CONST_CHANGE_VALUE_2: i16 = 1 + 2;
@ -89,8 +93,10 @@ const CONST_CHANGE_VALUE_2: i16 = 1 + 2;
const CONST_CHANGE_VALUE_3: i16 = 2 + 3; const CONST_CHANGE_VALUE_3: i16 = 2 + 3;
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
const CONST_CHANGE_VALUE_3: i16 = 2 * 3; const CONST_CHANGE_VALUE_3: i16 = 2 * 3;
@ -100,8 +106,10 @@ const CONST_CHANGE_VALUE_3: i16 = 2 * 3;
const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 3; const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 3;
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 4; const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 4;

View File

@ -108,8 +108,10 @@ enum EnumChangeValueCStyleVariant0 {
} }
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
enum EnumChangeValueCStyleVariant0 { enum EnumChangeValueCStyleVariant0 {
@ -126,6 +128,8 @@ enum EnumChangeValueCStyleVariant1 {
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_dirty(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_clean(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_dirty(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
enum EnumChangeValueCStyleVariant1 { enum EnumChangeValueCStyleVariant1 {

View File

@ -119,9 +119,11 @@ static STATIC_CHANGE_TYPE_2: Option<u16> = None;
static STATIC_CHANGE_VALUE_1: i16 = 1; static STATIC_CHANGE_VALUE_1: i16 = 1;
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")] #[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
static STATIC_CHANGE_VALUE_1: i16 = 2; static STATIC_CHANGE_VALUE_1: i16 = 2;
@ -131,9 +133,11 @@ static STATIC_CHANGE_VALUE_1: i16 = 2;
static STATIC_CHANGE_VALUE_2: i16 = 1 + 1; static STATIC_CHANGE_VALUE_2: i16 = 1 + 1;
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")] #[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
static STATIC_CHANGE_VALUE_2: i16 = 1 + 2; static STATIC_CHANGE_VALUE_2: i16 = 1 + 2;
@ -142,9 +146,11 @@ static STATIC_CHANGE_VALUE_2: i16 = 1 + 2;
static STATIC_CHANGE_VALUE_3: i16 = 2 + 3; static STATIC_CHANGE_VALUE_3: i16 = 2 + 3;
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")] #[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
static STATIC_CHANGE_VALUE_3: i16 = 2 * 3; static STATIC_CHANGE_VALUE_3: i16 = 2 * 3;
@ -153,9 +159,11 @@ static STATIC_CHANGE_VALUE_3: i16 = 2 * 3;
static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 3; static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 3;
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_metadata_dirty(cfg="cfail2")] #[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")] #[rustc_metadata_clean(cfg="cfail3")]
static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 4; static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 4;

View File

@ -23,14 +23,14 @@ fn main() { }
mod x { mod x {
#[cfg(rpass1)] #[cfg(rpass1)]
pub fn x() { pub fn x() {
println!("1"); println!("{}", "1");
} }
#[cfg(rpass2)] #[cfg(rpass2)]
#[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
#[rustc_dirty(label="TransCrateItem", cfg="rpass2")] #[rustc_dirty(label="TransCrateItem", cfg="rpass2")]
pub fn x() { pub fn x() {
println!("2"); println!("{}", "2");
} }
} }

View File

@ -41,12 +41,12 @@ impl LintPass for Pass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_fn(&mut self, cx: &LateContext, fn check_fn(&mut self, cx: &LateContext,
fk: FnKind, _: &hir::FnDecl, expr: &hir::Expr, fk: FnKind, _: &hir::FnDecl, body: &hir::Body,
span: Span, node: ast::NodeId) span: Span, node: ast::NodeId)
{ {
if let FnKind::Closure(..) = fk { return } if let FnKind::Closure(..) = fk { return }
let mut extent = cx.tcx.region_maps.node_extent(expr.id); let mut extent = cx.tcx.region_maps.node_extent(body.value.id);
while let Some(parent) = cx.tcx.region_maps.opt_encl_scope(extent) { while let Some(parent) = cx.tcx.region_maps.opt_encl_scope(extent) {
extent = parent; extent = parent;
} }