diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index f21d98a0fc7f9..4d66bba9f07ee 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -327,10 +327,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { 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::ExprAssignOp(_, ref l, ref r) => { 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::ExprUnary(_, 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()) } diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 2637d34c5c56e..26e1dc7e0490c 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -51,6 +51,12 @@ impl DepGraph { } } + /// True if we are actually building the full dep-graph. + #[inline] + pub fn is_fully_enabled(&self) -> bool { + self.data.thread.is_fully_enabled() + } + pub fn query(&self) -> DepGraphQuery { self.data.thread.query() } diff --git a/src/librustc/dep_graph/visit.rs b/src/librustc/dep_graph/visit.rs index f6a22e47cf212..1990574ca9a83 100644 --- a/src/librustc/dep_graph/visit.rs +++ b/src/librustc/dep_graph/visit.rs @@ -45,6 +45,16 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx> debug!("Ended task {:?}", task_id); } + fn visit_trait_item(&mut self, i: &'tcx hir::TraitItem) { + let trait_item_def_id = self.tcx.map.local_def_id(i.id); + let task_id = (self.dep_node_fn)(trait_item_def_id); + let _task = self.tcx.dep_graph.in_task(task_id.clone()); + debug!("Started task {:?}", task_id); + self.tcx.dep_graph.read(DepNode::Hir(trait_item_def_id)); + self.visitor.visit_trait_item(i); + debug!("Ended task {:?}", task_id); + } + fn visit_impl_item(&mut self, i: &'tcx hir::ImplItem) { let impl_item_def_id = self.tcx.map.local_def_id(i.id); let task_id = (self.dep_node_fn)(impl_item_def_id); diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 474d7d508c45b..4b171193b4af1 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -177,6 +177,17 @@ pub trait Visitor<'v> : Sized { } } + /// Like `visit_nested_item()`, but for trait items. See + /// `visit_nested_item()` for advice on when to override this + /// method. + #[allow(unused_variables)] + fn visit_nested_trait_item(&mut self, id: TraitItemId) { + let opt_item = self.nested_visit_map().inter().map(|map| map.trait_item(id)); + if let Some(item) = opt_item { + self.visit_trait_item(item); + } + } + /// Like `visit_nested_item()`, but for impl items. See /// `visit_nested_item()` for advice on when to override this /// method. @@ -192,10 +203,10 @@ pub trait Visitor<'v> : Sized { /// visit_nested_item, does nothing by default unless you override /// `nested_visit_map` to return `Some(_)`, in which case it will walk the /// body. - fn visit_body(&mut self, id: ExprId) { - let opt_expr = self.nested_visit_map().intra().map(|map| map.expr(id)); - if let Some(expr) = opt_expr { - self.visit_expr(expr); + fn visit_nested_body(&mut self, id: BodyId) { + let opt_body = self.nested_visit_map().intra().map(|map| map.body(id)); + if let Some(body) = opt_body { + self.visit_body(body); } } @@ -205,6 +216,10 @@ pub trait Visitor<'v> : Sized { 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 /// item-like visitor. This method converts a "intra-visit" /// visitor into an item-like visitor that walks the entire tree. @@ -253,8 +268,6 @@ pub trait Visitor<'v> : Sized { fn visit_expr(&mut self, ex: &'v Expr) { walk_expr(self, ex) } - fn visit_expr_post(&mut self, _ex: &'v Expr) { - } fn visit_ty(&mut self, t: &'v Ty) { walk_ty(self, t) } @@ -267,12 +280,15 @@ pub trait Visitor<'v> : Sized { fn visit_fn_decl(&mut self, fd: &'v FnDecl) { 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) } fn visit_trait_item(&mut self, ti: &'v TraitItem) { walk_trait_item(self, ti) } + fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) { + walk_trait_item_ref(self, ii) + } fn visit_impl_item(&mut self, ii: &'v ImplItem) { walk_impl_item(self, ii) } @@ -378,6 +394,14 @@ 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) { + for argument in &body.arguments { + visitor.visit_id(argument.id); + visitor.visit_pat(&argument.pat); + } + visitor.visit_expr(&body.value); +} + pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) { visitor.visit_id(local.id); visitor.visit_pat(&local.pat); @@ -423,11 +447,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_id(item.id); visitor.visit_path(path, item.id); } - ItemStatic(ref typ, _, ref expr) | - ItemConst(ref typ, ref expr) => { + ItemStatic(ref typ, _, body) | + ItemConst(ref typ, body) => { visitor.visit_id(item.id); visitor.visit_ty(typ); - visitor.visit_expr(expr); + visitor.visit_nested_body(body); } ItemFn(ref declaration, unsafety, constness, abi, ref generics, body_id) => { visitor.visit_fn(FnKind::ItemFn(item.name, @@ -469,9 +493,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_generics(type_parameters); walk_list!(visitor, visit_trait_ref, opt_trait_reference); visitor.visit_ty(typ); - for impl_item_ref in impl_item_refs { - visitor.visit_impl_item_ref(impl_item_ref); - } + walk_list!(visitor, visit_impl_item_ref, impl_item_refs); } ItemStruct(ref struct_definition, ref generics) | ItemUnion(ref struct_definition, ref generics) => { @@ -479,11 +501,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_id(item.id); visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span); } - ItemTrait(_, ref generics, ref bounds, ref methods) => { + ItemTrait(_, ref generics, ref bounds, ref trait_item_refs) => { visitor.visit_id(item.id); visitor.visit_generics(generics); walk_list!(visitor, visit_ty_param_bound, bounds); - walk_list!(visitor, visit_trait_item, methods); + walk_list!(visitor, visit_trait_item_ref, trait_item_refs); } } walk_list!(visitor, visit_attribute, &item.attrs); @@ -511,7 +533,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, generics, parent_item_id, 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); } @@ -544,9 +566,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { visitor.visit_ty(ty); walk_list!(visitor, visit_ty_param_bound, bounds); } - TyArray(ref ty, ref expression) => { + TyArray(ref ty, length) => { visitor.visit_ty(ty); - visitor.visit_expr(expression) + visitor.visit_nested_body(length) } TyPolyTraitRef(ref bounds) => { walk_list!(visitor, visit_ty_param_bound, bounds); @@ -554,8 +576,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { TyImplTrait(ref bounds) => { walk_list!(visitor, visit_ty_param_bound, bounds); } - TyTypeof(ref expression) => { - visitor.visit_expr(expression) + TyTypeof(expression) => { + visitor.visit_nested_body(expression) } TyInfer => {} } @@ -662,9 +684,12 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v visitor.visit_name(foreign_item.span, foreign_item.name); match foreign_item.node { - ForeignItemFn(ref function_declaration, ref generics) => { + ForeignItemFn(ref function_declaration, ref names, ref generics) => { + visitor.visit_generics(generics); visitor.visit_fn_decl(function_declaration); - visitor.visit_generics(generics) + for name in names { + visitor.visit_name(name.span, name.node); + } } ForeignItemStatic(ref typ, _) => visitor.visit_ty(typ), } @@ -732,18 +757,8 @@ pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionR } pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) { - for argument in &function_declaration.inputs { - visitor.visit_id(argument.id); - visitor.visit_pat(&argument.pat); - visitor.visit_ty(&argument.ty) - } - walk_fn_ret_ty(visitor, &function_declaration.output) -} - -pub fn walk_fn_decl_nopat<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) { - for argument in &function_declaration.inputs { - visitor.visit_id(argument.id); - visitor.visit_ty(&argument.ty) + for ty in &function_declaration.inputs { + visitor.visit_ty(ty) } walk_fn_ret_ty(visitor, &function_declaration.output) } @@ -763,42 +778,33 @@ 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, function_kind: FnKind<'v>, function_declaration: &'v FnDecl, - body_id: ExprId, + body_id: BodyId, _span: Span, id: NodeId) { visitor.visit_id(id); visitor.visit_fn_decl(function_declaration); walk_fn_kind(visitor, function_kind); - visitor.visit_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) + visitor.visit_nested_body(body_id) } 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); walk_list!(visitor, visit_attribute, &trait_item.attrs); match trait_item.node { - ConstTraitItem(ref ty, ref default) => { + TraitItemKind::Const(ref ty, default) => { visitor.visit_id(trait_item.id); visitor.visit_ty(ty); - walk_list!(visitor, visit_expr, default); + walk_list!(visitor, visit_nested_body, default); } - MethodTraitItem(ref sig, None) => { + TraitItemKind::Method(ref sig, TraitMethod::Required(ref names)) => { visitor.visit_id(trait_item.id); visitor.visit_generics(&sig.generics); visitor.visit_fn_decl(&sig.decl); + for name in names { + visitor.visit_name(name.span, name.node); + } } - MethodTraitItem(ref sig, Some(body_id)) => { + TraitItemKind::Method(ref sig, TraitMethod::Provided(body_id)) => { visitor.visit_fn(FnKind::Method(trait_item.name, sig, None, @@ -808,7 +814,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai trait_item.span, trait_item.id); } - TypeTraitItem(ref bounds, ref default) => { + TraitItemKind::Type(ref bounds, ref default) => { visitor.visit_id(trait_item.id); walk_list!(visitor, visit_ty_param_bound, bounds); walk_list!(visitor, visit_ty, default); @@ -816,6 +822,15 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai } } +pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: &'v TraitItemRef) { + // NB: Deliberately force a compilation error if/when new fields are added. + let TraitItemRef { id, name, ref kind, span, ref defaultness } = *trait_item_ref; + visitor.visit_nested_trait_item(id); + visitor.visit_name(span, name); + visitor.visit_associated_item_kind(kind); + visitor.visit_defaultness(defaultness); +} + pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) { // NB: Deliberately force a compilation error if/when new fields are added. let ImplItem { id: _, name, ref vis, ref defaultness, ref attrs, ref node, span } = *impl_item; @@ -825,10 +840,10 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt visitor.visit_defaultness(defaultness); walk_list!(visitor, visit_attribute, attrs); match *node { - ImplItemKind::Const(ref ty, ref expr) => { + ImplItemKind::Const(ref ty, body) => { visitor.visit_id(impl_item.id); visitor.visit_ty(ty); - visitor.visit_expr(expr); + visitor.visit_nested_body(body); } ImplItemKind::Method(ref sig, body_id) => { visitor.visit_fn(FnKind::Method(impl_item.name, @@ -907,9 +922,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { ExprArray(ref subexpressions) => { walk_list!(visitor, visit_expr, subexpressions); } - ExprRepeat(ref element, ref count) => { + ExprRepeat(ref element, count) => { visitor.visit_expr(element); - visitor.visit_expr(count) + visitor.visit_nested_body(count) } ExprStruct(ref qpath, ref fields, ref optional_base) => { visitor.visit_qpath(qpath, expression.id, expression.span); @@ -1016,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) { @@ -1100,16 +1113,3 @@ impl<'a, 'ast> Visitor<'ast> for IdRangeComputingVisitor<'a, 'ast> { self.result.add(id); } } - -/// Computes the id range for a single fn body, ignoring nested items. -pub fn compute_id_range_for_fn_body<'v>(fk: FnKind<'v>, - decl: &'v FnDecl, - body: &'v Expr, - sp: Span, - id: NodeId, - map: &map::Map<'v>) - -> IdRange { - let mut visitor = IdRangeComputingVisitor::new(map); - walk_fn_with_body(&mut visitor, fk, decl, body, sp, id); - visitor.result() -} diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs index 71ef7131440b8..f359ca2016359 100644 --- a/src/librustc/hir/itemlikevisit.rs +++ b/src/librustc/hir/itemlikevisit.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::{Item, ImplItem}; +use super::{Item, ImplItem, TraitItem}; use super::intravisit::Visitor; /// The "item-like visitor" visitor defines only the top-level methods @@ -58,6 +58,7 @@ use super::intravisit::Visitor; /// needed. pub trait ItemLikeVisitor<'hir> { fn visit_item(&mut self, item: &'hir Item); + fn visit_trait_item(&mut self, trait_item: &'hir TraitItem); fn visit_impl_item(&mut self, impl_item: &'hir ImplItem); } @@ -80,6 +81,10 @@ impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V> self.visitor.visit_item(item); } + fn visit_trait_item(&mut self, trait_item: &'hir TraitItem) { + self.visitor.visit_trait_item(trait_item); + } + fn visit_impl_item(&mut self, impl_item: &'hir ImplItem) { self.visitor.visit_impl_item(impl_item); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 1cf5e35a0957f..9a2658f48f3d9 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -46,12 +46,10 @@ use hir::map::definitions::DefPathData; use hir::def_id::{DefIndex, DefId}; use hir::def::{Def, PathResolution}; use session::Session; -use util::nodemap::NodeMap; -use rustc_data_structures::fnv::FnvHashMap; +use util::nodemap::{NodeMap, FxHashMap}; use std::collections::BTreeMap; use std::iter; -use std::mem; use syntax::ast::*; use syntax::errors; @@ -71,13 +69,14 @@ pub struct LoweringContext<'a> { // 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. parent_def: Option, - exprs: FnvHashMap, resolver: &'a mut Resolver, /// The items being lowered are collected here. items: BTreeMap, + trait_items: BTreeMap, impl_items: BTreeMap, + bodies: FxHashMap, } pub trait Resolver { @@ -105,10 +104,11 @@ pub fn lower_crate(sess: &Session, crate_root: std_inject::injected_crate_name(krate), sess: sess, parent_def: None, - exprs: FnvHashMap(), resolver: resolver, items: BTreeMap::new(), + trait_items: BTreeMap::new(), impl_items: BTreeMap::new(), + bodies: FxHashMap(), }.lower_crate(krate) } @@ -133,8 +133,9 @@ impl<'a> LoweringContext<'a> { span: c.span, exported_macros: exported_macros, items: self.items, + trait_items: self.trait_items, impl_items: self.impl_items, - exprs: mem::replace(&mut self.exprs, FnvHashMap()), + bodies: self.bodies, } } @@ -150,8 +151,15 @@ impl<'a> LoweringContext<'a> { visit::walk_item(self, item); } + fn visit_trait_item(&mut self, item: &'lcx TraitItem) { + let id = hir::TraitItemId { node_id: item.id }; + let hir_item = self.lctx.lower_trait_item(item); + self.lctx.trait_items.insert(id, hir_item); + visit::walk_trait_item(self, item); + } + fn visit_impl_item(&mut self, item: &'lcx ImplItem) { - let id = self.lctx.lower_impl_item_ref(item).id; + let id = hir::ImplItemId { node_id: item.id }; let hir_item = self.lctx.lower_impl_item(item); self.lctx.impl_items.insert(id, hir_item); visit::walk_impl_item(self, item); @@ -162,9 +170,16 @@ impl<'a> LoweringContext<'a> { visit::walk_crate(&mut item_lowerer, c); } - fn record_expr(&mut self, expr: hir::Expr) -> hir::ExprId { - let id = hir::ExprId(expr.id); - self.exprs.insert(id, expr); + fn record_body(&mut self, value: hir::Expr, decl: Option<&FnDecl>) + -> hir::BodyId { + let body = hir::Body { + arguments: decl.map_or(hir_vec![], |decl| { + decl.inputs.iter().map(|x| self.lower_arg(x)).collect() + }), + value: value + }; + let id = body.id(); + self.bodies.insert(id, body); id } @@ -259,7 +274,7 @@ impl<'a> LoweringContext<'a> { P(hir::Ty { id: t.id, node: match t.node { - TyKind::Infer | TyKind::ImplicitSelf => hir::TyInfer, + TyKind::Infer => hir::TyInfer, TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)), TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)), TyKind::Rptr(ref region, ref mt) => { @@ -283,14 +298,27 @@ impl<'a> LoweringContext<'a> { TyKind::Path(ref qself, ref path) => { hir::TyPath(self.lower_qpath(t.id, qself, path, ParamMode::Explicit)) } + TyKind::ImplicitSelf => { + hir::TyPath(hir::QPath::Resolved(None, P(hir::Path { + def: self.expect_full_def(t.id), + segments: hir_vec![hir::PathSegment { + name: keywords::SelfType.name(), + parameters: hir::PathParameters::none() + }], + span: t.span, + }))) + } TyKind::ObjectSum(ref ty, ref bounds) => { hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds)) } - TyKind::Array(ref ty, ref e) => { - hir::TyArray(self.lower_ty(ty), P(self.lower_expr(e))) + TyKind::Array(ref ty, ref length) => { + let length = self.lower_expr(length); + hir::TyArray(self.lower_ty(ty), + self.record_body(length, None)) } TyKind::Typeof(ref expr) => { - hir::TyTypeof(P(self.lower_expr(expr))) + let expr = self.lower_expr(expr); + hir::TyTypeof(self.record_body(expr, None)) } TyKind::PolyTraitRef(ref bounds) => { hir::TyPolyTraitRef(self.lower_bounds(bounds)) @@ -317,7 +345,10 @@ impl<'a> LoweringContext<'a> { name: v.node.name.name, attrs: self.lower_attrs(&v.node.attrs), 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, None) + }), }, span: v.span, } @@ -505,13 +536,24 @@ impl<'a> LoweringContext<'a> { hir::Arg { id: arg.id, pat: self.lower_pat(&arg.pat), - ty: self.lower_ty(&arg.ty), } } + fn lower_fn_args_to_names(&mut self, decl: &FnDecl) + -> hir::HirVec> { + decl.inputs.iter().map(|arg| { + match arg.pat.node { + PatKind::Ident(_, ident, None) => { + respan(ident.span, ident.node.name) + } + _ => respan(arg.pat.span, keywords::Invalid.name()), + } + }).collect() + } + fn lower_fn_decl(&mut self, decl: &FnDecl) -> P { P(hir::FnDecl { - inputs: decl.inputs.iter().map(|x| self.lower_arg(x)).collect(), + inputs: decl.inputs.iter().map(|arg| self.lower_ty(&arg.ty)).collect(), output: match decl.output { FunctionRetTy::Ty(ref ty) => hir::Return(self.lower_ty(ty)), FunctionRetTy::Default(span) => hir::DefaultReturn(span), @@ -839,17 +881,20 @@ impl<'a> LoweringContext<'a> { hir::ItemUse(path, kind) } ItemKind::Static(ref t, m, ref e) => { + let value = self.lower_expr(e); hir::ItemStatic(self.lower_ty(t), self.lower_mutability(m), - P(self.lower_expr(e))) + self.record_body(value, None)) } 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, None)) } ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { let body = self.lower_block(body); let body = self.expr_block(body, ThinVec::new()); - let body_id = self.record_expr(body); + let body_id = self.record_body(body, Some(decl)); hir::ItemFn(self.lower_fn_decl(decl), self.lower_unsafety(unsafety), self.lower_constness(constness), @@ -897,7 +942,7 @@ impl<'a> LoweringContext<'a> { } ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => { let bounds = self.lower_bounds(bounds); - let items = items.iter().map(|item| self.lower_trait_item(item)).collect(); + let items = items.iter().map(|item| self.lower_trait_item_ref(item)).collect(); hir::ItemTrait(self.lower_unsafety(unsafety), self.lower_generics(generics), bounds, @@ -915,20 +960,27 @@ impl<'a> LoweringContext<'a> { attrs: this.lower_attrs(&i.attrs), node: match i.node { TraitItemKind::Const(ref ty, ref default) => { - hir::ConstTraitItem(this.lower_ty(ty), - default.as_ref().map(|x| P(this.lower_expr(x)))) - } - TraitItemKind::Method(ref sig, ref body) => { - hir::MethodTraitItem(this.lower_method_sig(sig), - body.as_ref().map(|x| { - let body = this.lower_block(x); - let expr = this.expr_block(body, ThinVec::new()); - this.record_expr(expr) + hir::TraitItemKind::Const(this.lower_ty(ty), + default.as_ref().map(|x| { + let value = this.lower_expr(x); + this.record_body(value, None) })) } + TraitItemKind::Method(ref sig, None) => { + let names = this.lower_fn_args_to_names(&sig.decl); + hir::TraitItemKind::Method(this.lower_method_sig(sig), + hir::TraitMethod::Required(names)) + } + TraitItemKind::Method(ref sig, Some(ref body)) => { + let body = this.lower_block(body); + let expr = this.expr_block(body, ThinVec::new()); + let body_id = this.record_body(expr, Some(&sig.decl)); + hir::TraitItemKind::Method(this.lower_method_sig(sig), + hir::TraitMethod::Provided(body_id)) + } TraitItemKind::Type(ref bounds, ref default) => { - hir::TypeTraitItem(this.lower_bounds(bounds), - default.as_ref().map(|x| this.lower_ty(x))) + hir::TraitItemKind::Type(this.lower_bounds(bounds), + default.as_ref().map(|x| this.lower_ty(x))) } TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"), }, @@ -937,6 +989,30 @@ impl<'a> LoweringContext<'a> { }) } + fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef { + let (kind, has_default) = match i.node { + TraitItemKind::Const(_, ref default) => { + (hir::AssociatedItemKind::Const, default.is_some()) + } + TraitItemKind::Type(_, ref default) => { + (hir::AssociatedItemKind::Type, default.is_some()) + } + TraitItemKind::Method(ref sig, ref default) => { + (hir::AssociatedItemKind::Method { + has_self: sig.decl.has_self(), + }, default.is_some()) + } + TraitItemKind::Macro(..) => unimplemented!(), + }; + hir::TraitItemRef { + id: hir::TraitItemId { node_id: i.id }, + name: i.ident.name, + span: i.span, + defaultness: self.lower_defaultness(Defaultness::Default, has_default), + kind: kind, + } + } + fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem { self.with_parent_def(i.id, |this| { hir::ImplItem { @@ -947,13 +1023,15 @@ impl<'a> LoweringContext<'a> { defaultness: this.lower_defaultness(i.defaultness, true /* [1] */), node: match i.node { 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, None); + hir::ImplItemKind::Const(this.lower_ty(ty), body_id) } ImplItemKind::Method(ref sig, ref body) => { let body = this.lower_block(body); let expr = this.expr_block(body, ThinVec::new()); - let expr_id = this.record_expr(expr); - hir::ImplItemKind::Method(this.lower_method_sig(sig), expr_id) + let body_id = this.record_body(expr, Some(&sig.decl)); + hir::ImplItemKind::Method(this.lower_method_sig(sig), body_id) } ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)), ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), @@ -976,7 +1054,7 @@ impl<'a> LoweringContext<'a> { ImplItemKind::Const(..) => hir::AssociatedItemKind::Const, ImplItemKind::Type(..) => hir::AssociatedItemKind::Type, ImplItemKind::Method(ref sig, _) => hir::AssociatedItemKind::Method { - has_self: sig.decl.get_self().is_some(), + has_self: sig.decl.has_self(), }, ImplItemKind::Macro(..) => unimplemented!(), }, @@ -1038,7 +1116,9 @@ impl<'a> LoweringContext<'a> { attrs: this.lower_attrs(&i.attrs), node: match i.node { ForeignItemKind::Fn(ref fdec, ref generics) => { - hir::ForeignItemFn(this.lower_fn_decl(fdec), this.lower_generics(generics)) + hir::ForeignItemFn(this.lower_fn_decl(fdec), + this.lower_fn_args_to_names(fdec), + this.lower_generics(generics)) } ForeignItemKind::Static(ref t, m) => { hir::ForeignItemStatic(this.lower_ty(t), m) @@ -1051,24 +1131,13 @@ impl<'a> LoweringContext<'a> { } fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig { - let hir_sig = hir::MethodSig { + hir::MethodSig { generics: self.lower_generics(&sig.generics), abi: sig.abi, unsafety: self.lower_unsafety(sig.unsafety), constness: self.lower_constness(sig.constness), decl: self.lower_fn_decl(&sig.decl), - }; - // Check for `self: _` and `self: &_` - if let Some(SelfKind::Explicit(..)) = sig.decl.get_self().map(|eself| eself.node) { - match hir_sig.decl.get_self().map(|eself| eself.node) { - Some(hir::SelfKind::Value(..)) | Some(hir::SelfKind::Region(..)) => { - self.diagnostic().span_err(sig.decl.inputs[0].ty.span, - "the type placeholder `_` is not allowed within types on item signatures"); - } - _ => {} - } } - hir_sig } fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety { @@ -1318,8 +1387,8 @@ impl<'a> LoweringContext<'a> { } ExprKind::Repeat(ref expr, ref count) => { let expr = P(self.lower_expr(expr)); - let count = P(self.lower_expr(count)); - hir::ExprRepeat(expr, count) + let count = self.lower_expr(count); + hir::ExprRepeat(expr, self.record_body(count, None)) } ExprKind::Tup(ref elts) => { hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect()) @@ -1402,7 +1471,7 @@ impl<'a> LoweringContext<'a> { let expr = this.lower_expr(body); hir::ExprClosure(this.lower_capture_clause(capture_clause), this.lower_fn_decl(decl), - this.record_expr(expr), + this.record_body(expr, Some(decl)), fn_decl_span) }) } @@ -1686,13 +1755,7 @@ impl<'a> LoweringContext<'a> { // `::std::option::Option::Some() => ` let pat_arm = { let body_block = self.lower_block(body); - let body_span = body_block.span; - let body_expr = P(hir::Expr { - id: self.next_id(), - node: hir::ExprBlock(body_block), - span: body_span, - attrs: ThinVec::new(), - }); + let body_expr = P(self.expr_block(body_block, ThinVec::new())); let pat = self.lower_pat(pat); let some_pat = self.pat_some(e.span, pat); diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 068e7ed8624ed..6e08b52f9a249 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -48,7 +48,7 @@ pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; } /// Components shared by fn-like things (fn items, methods, closures). pub struct FnParts<'a> { pub decl: &'a FnDecl, - pub body: ast::ExprId, + pub body: ast::BodyId, pub kind: FnKind<'a>, pub span: Span, pub id: NodeId, @@ -62,7 +62,10 @@ impl MaybeFnLike for ast::Item { impl MaybeFnLike for ast::TraitItem { fn is_fn_like(&self) -> bool { - match self.node { ast::MethodTraitItem(_, Some(_)) => true, _ => false, } + match self.node { + ast::TraitItemKind::Method(_, ast::TraitMethod::Provided(_)) => true, + _ => false, + } } } @@ -115,7 +118,7 @@ struct ItemFnParts<'a> { abi: abi::Abi, vis: &'a ast::Visibility, generics: &'a ast::Generics, - body: ast::ExprId, + body: ast::BodyId, id: NodeId, span: Span, attrs: &'a [Attribute], @@ -125,14 +128,14 @@ struct ItemFnParts<'a> { /// for use when implementing FnLikeNode operations. struct ClosureParts<'a> { decl: &'a FnDecl, - body: ast::ExprId, + body: ast::BodyId, id: NodeId, span: Span, attrs: &'a [Attribute], } 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 { decl: d, body: b, @@ -172,9 +175,9 @@ impl<'a> FnLikeNode<'a> { } } - pub fn body(self) -> ast::ExprId { + pub fn body(self) -> ast::BodyId { 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) } @@ -227,7 +230,7 @@ impl<'a> FnLikeNode<'a> { Name, &'a ast::MethodSig, Option<&'a ast::Visibility>, - ast::ExprId, + ast::BodyId, Span, &'a [Attribute]) -> A, @@ -252,7 +255,7 @@ impl<'a> FnLikeNode<'a> { _ => bug!("item FnLikeNode that is not fn-like"), }, map::NodeTraitItem(ti) => match ti.node { - ast::MethodTraitItem(ref sig, Some(body)) => { + ast::TraitItemKind::Method(ref sig, ast::TraitMethod::Provided(body)) => { method(ti.id, ti.name, sig, None, body, ti.span, &ti.attrs) } _ => bug!("trait method FnLikeNode that is not fn-like"), diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 45988886a608a..a6ffe7cea5592 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -11,7 +11,6 @@ use super::*; use hir::intravisit::{Visitor, NestedVisitorMap}; -use middle::cstore::InlinedItem; use std::iter::repeat; use syntax::ast::{NodeId, CRATE_NODE_ID}; use syntax_pos::Span; @@ -21,7 +20,7 @@ pub struct NodeCollector<'ast> { /// The crate pub krate: &'ast Crate, /// The node map - pub map: Vec>, + pub(super) map: Vec>, /// The parent of this node pub parent_node: NodeId, /// If true, completely ignore nested items. We set this when loading @@ -43,11 +42,11 @@ impl<'ast> NodeCollector<'ast> { collector } - pub fn extend(krate: &'ast Crate, - parent: &'ast InlinedItem, - parent_node: NodeId, - map: Vec>) - -> NodeCollector<'ast> { + pub(super) fn extend(krate: &'ast Crate, + parent: &'ast InlinedItem, + parent_node: NodeId, + map: Vec>) + -> NodeCollector<'ast> { let mut collector = NodeCollector { krate: krate, map: map, @@ -98,12 +97,22 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { } } + 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)) + } + } + fn visit_nested_impl_item(&mut self, item_id: ImplItemId) { - self.visit_impl_item(self.krate.impl_item(item_id)) + if !self.ignore_nested_items { + self.visit_impl_item(self.krate.impl_item(item_id)) + } } - fn visit_body(&mut self, id: ExprId) { - self.visit_expr(self.krate.expr(id)) + fn visit_nested_body(&mut self, id: BodyId) { + if !self.ignore_nested_items { + self.visit_body(self.krate.body(id)) + } } fn visit_item(&mut self, i: &'ast Item) { @@ -113,11 +122,6 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { self.with_parent(i.id, |this| { 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, _) => { // If this is a tuple-like struct, register the constructor. if !struct_def.is_struct() { @@ -209,7 +213,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { } 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); intravisit::walk_fn(self, fk, fd, b, s, id); } @@ -243,6 +247,14 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { 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) { self.insert(field.id, NodeField(field)); self.with_parent(field.id, |this| { diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 256aee342a3fc..be8780f39b104 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -16,7 +16,7 @@ use syntax::ext::hygiene::Mark; use syntax::visit; 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> { definitions: &'a mut Definitions, parent_def: Option, diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 4f64670f48279..b28c5e80ea3c3 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -220,7 +220,6 @@ impl DefPath { } } - #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum DefPathData { // Root: these should only be used for the root nodes, because @@ -339,7 +338,7 @@ impl Definitions { data, 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 // until we get no match. diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 4546f6d8c27e6..27ebeea9ad91d 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -17,7 +17,6 @@ pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, use dep_graph::{DepGraph, DepNode}; -use middle::cstore::InlinedItem; use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex}; use syntax::abi::Abi; @@ -26,7 +25,8 @@ use syntax::codemap::Spanned; use syntax_pos::Span; use hir::*; -use hir::print as pprust; +use hir::intravisit::Visitor; +use hir::print::Nested; use arena::TypedArena; use std::cell::RefCell; @@ -38,6 +38,15 @@ mod collector; mod def_collector; pub mod definitions; +/// The data we save and restore about an inlined item or method. This is not +/// part of the AST that we parse from a file, but it becomes part of the tree +/// that we trans. +#[derive(Debug)] +struct InlinedItem { + def_id: DefId, + body: Body, +} + #[derive(Copy, Clone, Debug)] pub enum Node<'ast> { NodeItem(&'ast Item), @@ -60,14 +69,12 @@ pub enum Node<'ast> { NodeLifetime(&'ast Lifetime), NodeTyParam(&'ast TyParam), NodeVisibility(&'ast Visibility), - - NodeInlinedItem(&'ast InlinedItem), } /// Represents an entry and its parent NodeID. /// The odd layout is to bring down the total size. #[derive(Copy, Debug)] -pub enum MapEntry<'ast> { +enum MapEntry<'ast> { /// Placeholder for holes in the map. NotPresent, @@ -121,8 +128,6 @@ impl<'ast> MapEntry<'ast> { NodeLifetime(n) => EntryLifetime(p, n), NodeTyParam(n) => EntryTyParam(p, n), NodeVisibility(n) => EntryVisibility(p, n), - - NodeInlinedItem(n) => RootInlinedParent(n), } } @@ -171,10 +176,49 @@ impl<'ast> MapEntry<'ast> { EntryLifetime(_, n) => NodeLifetime(n), EntryTyParam(_, n) => NodeTyParam(n), EntryVisibility(_, n) => NodeVisibility(n), - RootInlinedParent(n) => NodeInlinedItem(n), _ => return None }) } + + fn is_body_owner(self, node_id: NodeId) -> bool { + match self { + EntryItem(_, item) => { + match item.node { + ItemConst(_, body) | + ItemStatic(.., body) | + ItemFn(_, _, _, _, _, body) => body.node_id == node_id, + _ => false + } + } + + EntryTraitItem(_, item) => { + match item.node { + TraitItemKind::Const(_, Some(body)) | + TraitItemKind::Method(_, TraitMethod::Provided(body)) => { + body.node_id == node_id + } + _ => false + } + } + + EntryImplItem(_, item) => { + match item.node { + ImplItemKind::Const(_, body) | + ImplItemKind::Method(_, body) => body.node_id == node_id, + _ => false + } + } + + EntryExpr(_, expr) => { + match expr.node { + ExprClosure(.., body, _) => body.node_id == node_id, + _ => false + } + } + + _ => false + } + } } /// Stores a crate and any number of inlined items from other crates. @@ -250,38 +294,34 @@ impl<'ast> Map<'ast> { if !self.is_inlined_node_id(id) { let mut last_expr = None; loop { - match map[id.as_usize()] { - EntryItem(_, item) => { - assert_eq!(id, item.id); - let def_id = self.local_def_id(id); - + let entry = map[id.as_usize()]; + match entry { + EntryItem(..) | + EntryTraitItem(..) | + EntryImplItem(..) => { if let Some(last_id) = last_expr { - // The body of the item may have a separate dep node - // (Note that trait items don't currently have - // their own dep node, so there's also just one - // HirBody node for all the items) - if self.is_body(last_id, item) { + // The body may have a separate dep node + if entry.is_body_owner(last_id) { + let def_id = self.local_def_id(id); return DepNode::HirBody(def_id); } } - return DepNode::Hir(def_id); + return DepNode::Hir(self.local_def_id(id)); } - EntryImplItem(_, item) => { - let def_id = self.local_def_id(id); + EntryVariant(p, v) => { + id = p; - if let Some(last_id) = last_expr { - // The body of the item may have a separate dep node - if self.is_impl_item_body(last_id, item) { + 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); } } - return DepNode::Hir(def_id); } EntryForeignItem(p, _) | - EntryTraitItem(p, _) | - EntryVariant(p, _) | EntryField(p, _) | EntryStmt(p, _) | EntryTy(p, _) | @@ -308,7 +348,7 @@ impl<'ast> Map<'ast> { bug!("node {} has inlined ancestor but is not inlined", id0), NotPresent => - // Some nodes, notably struct fields, are not + // Some nodes, notably macro definitions, are not // present in the map for whatever reason, but // they *do* have def-ids. So if we encounter an // empty hole, check for that case. @@ -358,29 +398,6 @@ impl<'ast> Map<'ast> { } } - fn is_body(&self, node_id: NodeId, item: &Item) -> bool { - match item.node { - ItemFn(_, _, _, _, _, body) => body.node_id() == node_id, - // Since trait items currently don't get their own dep nodes, - // we check here whether node_id is the body of any of the items. - // If they get their own dep nodes, this can go away - ItemTrait(_, _, _, ref trait_items) => { - trait_items.iter().any(|trait_item| { match trait_item.node { - MethodTraitItem(_, Some(body)) => body.node_id() == node_id, - _ => false - }}) - } - _ => false - } - } - - fn is_impl_item_body(&self, node_id: NodeId, item: &ImplItem) -> bool { - match item.node { - ImplItemKind::Method(_, body) => body.node_id() == node_id, - _ => false - } - } - pub fn num_local_def_ids(&self) -> usize { self.definitions.len() } @@ -436,6 +453,14 @@ impl<'ast> Map<'ast> { self.forest.krate() } + pub fn trait_item(&self, id: TraitItemId) -> &'ast TraitItem { + 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.trait_item(id) + } + pub fn impl_item(&self, id: ImplItemId) -> &'ast ImplItem { self.read(id.node_id); @@ -444,6 +469,31 @@ impl<'ast> Map<'ast> { 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) + } + + /// Returns the `NodeId` that corresponds to the definition of + /// which this is the body of, i.e. a `fn`, `const` or `static` + /// item (possibly associated), or a closure, or the body itself + /// for embedded constant expressions (e.g. `N` in `[T; N]`). + pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId { + let parent = self.get_parent_node(node_id); + if self.map.borrow()[parent.as_usize()].is_body_owner(node_id) { + parent + } else { + node_id + } + } + + pub fn body_owner_def_id(&self, id: BodyId) -> DefId { + self.local_def_id(self.body_owner(id)) + } + /// Get the attributes on the krate. This is preferable to /// invoking `krate.attrs` because it registers a tighter /// dep-graph access. @@ -687,17 +737,13 @@ impl<'ast> Map<'ast> { } } - pub fn expect_inlined_item(&self, id: NodeId) -> &'ast InlinedItem { + pub fn expect_inlined_body(&self, id: NodeId) -> &'ast Body { match self.find_entry(id) { - Some(RootInlinedParent(inlined_item)) => inlined_item, + Some(RootInlinedParent(inlined_item)) => &inlined_item.body, _ => bug!("expected inlined item, found {}", self.node_to_string(id)), } } - pub fn expr(&self, id: ExprId) -> &'ast Expr { - self.expect_expr(id.node_id()) - } - /// Returns the name associated with the given NodeId's AST. pub fn name(&self, id: NodeId) -> Name { match self.get(id) { @@ -778,7 +824,7 @@ impl<'ast> Map<'ast> { Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v), Some(RootCrate) => self.forest.krate.span, - Some(RootInlinedParent(parent)) => parent.body.span, + Some(RootInlinedParent(parent)) => parent.body.value.span, Some(NotPresent) | None => { bug!("hir::map::Map::span: id not in map: {:?}", id) } @@ -796,6 +842,10 @@ impl<'ast> Map<'ast> { pub fn node_to_user_string(&self, id: NodeId) -> String { node_id_to_string(self, id, false) } + + pub fn node_to_pretty_string(&self, id: NodeId) -> String { + print::to_string(self, |s| s.print_node(self.get(id))) + } } pub struct NodesMatchingSuffix<'a, 'ast:'a> { @@ -934,33 +984,47 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest, } } -/// Used for items loaded from external crate that are being inlined into this +/// Used for bodies loaded from external crate that are being inlined into this /// crate. -pub fn map_decoded_item<'ast>(map: &Map<'ast>, - ii: InlinedItem, - ii_parent_id: NodeId) - -> &'ast InlinedItem { +pub fn map_decoded_body<'ast>(map: &Map<'ast>, + def_id: DefId, + body: Body, + parent_id: NodeId) + -> &'ast Body { let _ignore = map.forest.dep_graph.in_ignore(); - let ii = map.forest.inlined_items.alloc(ii); + let ii = map.forest.inlined_items.alloc(InlinedItem { + def_id: def_id, + body: body + }); let mut collector = NodeCollector::extend(map.krate(), ii, - ii_parent_id, + parent_id, mem::replace(&mut *map.map.borrow_mut(), vec![])); - ii.visit(&mut collector); + collector.visit_body(&ii.body); *map.map.borrow_mut() = collector.map; - ii + &ii.body } -pub trait NodePrinter { - fn print_node(&mut self, node: &Node) -> io::Result<()>; +/// Identical to the `PpAnn` implementation for `hir::Crate`, +/// except it avoids creating a dependency on the whole crate. +impl<'ast> print::PpAnn for Map<'ast> { + fn nested(&self, state: &mut print::State, nested: print::Nested) -> io::Result<()> { + match nested { + Nested::Item(id) => state.print_item(self.expect_item(id.id)), + Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)), + Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), + Nested::Body(id) => state.print_expr(&self.body(id).value), + Nested::BodyArgPat(id, i) => state.print_pat(&self.body(id).arguments[i].pat) + } + } } -impl<'a> NodePrinter for pprust::State<'a> { - fn print_node(&mut self, node: &Node) -> io::Result<()> { - match *node { +impl<'a> print::State<'a> { + pub fn print_node(&mut self, node: Node) -> io::Result<()> { + match node { NodeItem(a) => self.print_item(&a), NodeForeignItem(a) => self.print_foreign_item(&a), NodeTraitItem(a) => self.print_trait_item(a), @@ -970,8 +1034,17 @@ impl<'a> NodePrinter for pprust::State<'a> { NodeStmt(a) => self.print_stmt(&a), NodeTy(a) => self.print_type(&a), NodeTraitRef(a) => self.print_trait_ref(&a), + NodeLocal(a) | NodePat(a) => self.print_pat(&a), - NodeBlock(a) => self.print_block(&a), + NodeBlock(a) => { + use syntax::print::pprust::PrintState; + + // containing cbox, will be closed by print-block at } + self.cbox(print::indent_unit)?; + // head-ibox, will be closed by print-block after { + self.ibox(0)?; + self.print_block(&a) + } NodeLifetime(a) => self.print_lifetime(&a), NodeVisibility(a) => self.print_visibility(&a), NodeTyParam(_) => bug!("cannot print TyParam"), @@ -979,10 +1052,7 @@ impl<'a> NodePrinter for pprust::State<'a> { // these cases do not carry enough information in the // ast_map to reconstruct their full structure for pretty // printing. - NodeLocal(_) => bug!("cannot print isolated Local"), NodeStructCtor(_) => bug!("cannot print isolated StructCtor"), - - NodeInlinedItem(_) => bug!("cannot print inlined item"), } } } @@ -1045,9 +1115,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { } Some(NodeTraitItem(ti)) => { let kind = match ti.node { - ConstTraitItem(..) => "assoc constant", - MethodTraitItem(..) => "trait method", - TypeTraitItem(..) => "assoc type", + TraitItemKind::Const(..) => "assoc constant", + TraitItemKind::Method(..) => "trait method", + TraitItemKind::Type(..) => "assoc type", }; format!("{} {} in {}{}", kind, ti.name, path_str(), id_str) @@ -1062,33 +1132,32 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { field.name, path_str(), id_str) } - Some(NodeExpr(ref expr)) => { - format!("expr {}{}", pprust::expr_to_string(&expr), id_str) + Some(NodeExpr(_)) => { + format!("expr {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeStmt(ref stmt)) => { - format!("stmt {}{}", pprust::stmt_to_string(&stmt), id_str) + Some(NodeStmt(_)) => { + format!("stmt {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeTy(ref ty)) => { - format!("type {}{}", pprust::ty_to_string(&ty), id_str) + Some(NodeTy(_)) => { + format!("type {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeTraitRef(ref tr)) => { - format!("trait_ref {}{}", pprust::path_to_string(&tr.path), id_str) + Some(NodeTraitRef(_)) => { + format!("trait_ref {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeLocal(ref pat)) => { - format!("local {}{}", pprust::pat_to_string(&pat), id_str) + Some(NodeLocal(_)) => { + format!("local {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodePat(ref pat)) => { - format!("pat {}{}", pprust::pat_to_string(&pat), id_str) + Some(NodePat(_)) => { + format!("pat {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeBlock(ref block)) => { - format!("block {}{}", pprust::block_to_string(&block), id_str) + Some(NodeBlock(_)) => { + format!("block {}{}", map.node_to_pretty_string(id), id_str) } Some(NodeStructCtor(_)) => { format!("struct_ctor {}{}", path_str(), id_str) } - Some(NodeLifetime(ref l)) => { - format!("lifetime {}{}", - pprust::lifetime_to_string(&l), id_str) + Some(NodeLifetime(_)) => { + format!("lifetime {}{}", map.node_to_pretty_string(id), id_str) } Some(NodeTyParam(ref ty_param)) => { format!("typaram {:?}{}", ty_param, id_str) @@ -1096,9 +1165,6 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { Some(NodeVisibility(ref vis)) => { format!("visibility {:?}{}", vis, id_str) } - Some(NodeInlinedItem(_)) => { - format!("inlined item {}", id_str) - } None => { format!("unknown node{}", id_str) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 4eee76d466ac1..9149da459c26e 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -22,7 +22,6 @@ pub use self::Item_::*; pub use self::Mutability::*; pub use self::PrimTy::*; pub use self::Stmt_::*; -pub use self::TraitItem_::*; pub use self::Ty_::*; pub use self::TyParamBound::*; pub use self::UnOp::*; @@ -32,11 +31,10 @@ pub use self::PathParameters::*; use hir::def::Def; use hir::def_id::DefId; -use util::nodemap::{NodeMap, FxHashSet}; -use rustc_data_structures::fnv::FnvHashMap; +use util::nodemap::{NodeMap, FxHashMap, FxHashSet}; -use syntax_pos::{mk_sp, Span, ExpnId, DUMMY_SP}; -use syntax::codemap::{self, respan, Spanned}; +use syntax_pos::{Span, ExpnId, DUMMY_SP}; +use syntax::codemap::{self, Spanned}; use syntax::abi::Abi; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect}; use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem}; @@ -87,7 +85,7 @@ impl fmt::Debug for Lifetime { write!(f, "lifetime({}: {})", self.id, - print::lifetime_to_string(self)) + print::to_string(print::NO_ANN, |s| s.print_lifetime(self))) } } @@ -119,13 +117,8 @@ impl Path { impl fmt::Debug for Path { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "path({})", print::path_to_string(self)) - } -} - -impl fmt::Display for Path { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", print::path_to_string(self)) + write!(f, "path({})", + print::to_string(print::NO_ANN, |s| s.print_path(self, false))) } } @@ -431,8 +424,9 @@ pub struct Crate { // slightly different results. pub items: BTreeMap, + pub trait_items: BTreeMap, pub impl_items: BTreeMap, - pub exprs: FnvHashMap, + pub bodies: FxHashMap, } impl Crate { @@ -440,6 +434,10 @@ impl Crate { &self.items[&id] } + pub fn trait_item(&self, id: TraitItemId) -> &TraitItem { + &self.trait_items[&id] + } + pub fn impl_item(&self, id: ImplItemId) -> &ImplItem { &self.impl_items[&id] } @@ -459,13 +457,17 @@ impl Crate { visitor.visit_item(item); } + for (_, trait_item) in &self.trait_items { + visitor.visit_trait_item(trait_item); + } + for (_, impl_item) in &self.impl_items { visitor.visit_impl_item(impl_item); } } - pub fn expr(&self, id: ExprId) -> &Expr { - &self.exprs[&id] + pub fn body(&self, id: BodyId) -> &Body { + &self.bodies[&id] } } @@ -503,7 +505,8 @@ pub struct Pat { impl fmt::Debug for Pat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "pat({}: {})", self.id, print::pat_to_string(self)) + write!(f, "pat({}: {})", self.id, + print::to_string(print::NO_ANN, |s| s.print_pat(self))) } } @@ -755,7 +758,7 @@ impl fmt::Debug for Stmt_ { write!(f, "stmt({}: {})", spanned.node.id(), - print::stmt_to_string(&spanned)) + print::to_string(print::NO_ANN, |s| s.print_stmt(&spanned))) } } @@ -853,12 +856,23 @@ pub enum UnsafeSource { UserProvided, } -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct ExprId(NodeId); +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)] +pub struct BodyId { + pub node_id: NodeId, +} -impl ExprId { - pub fn node_id(self) -> NodeId { - self.0 +/// The body of a function or constant value. +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub struct Body { + pub arguments: HirVec, + pub value: Expr +} + +impl Body { + pub fn id(&self) -> BodyId { + BodyId { + node_id: self.value.id + } } } @@ -871,15 +885,10 @@ pub struct Expr { pub attrs: ThinVec, } -impl Expr { - pub fn expr_id(&self) -> ExprId { - ExprId(self.id) - } -} - impl fmt::Debug for Expr { 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::to_string(print::NO_ANN, |s| s.print_expr(self))) } } @@ -936,7 +945,7 @@ pub enum Expr_ { /// A closure (for example, `move |a, b, c| {a + b + c}`). /// /// The final span is the span of the argument block `|...|` - ExprClosure(CaptureClause, P, ExprId, Span), + ExprClosure(CaptureClause, P, BodyId, Span), /// A block (`{ ... }`) ExprBlock(P), @@ -980,7 +989,7 @@ pub enum Expr_ { /// /// For example, `[1; 5]`. The first expression is the element /// to be repeated; the second is the number of times to repeat it. - ExprRepeat(P, P), + ExprRepeat(P, BodyId), } /// Optionally `Self`-qualified value/type path or associated extension. @@ -1003,12 +1012,6 @@ pub enum QPath { TypeRelative(P, P) } -impl fmt::Display for QPath { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", print::qpath_to_string(self)) - } -} - /// Hints at the original code for a `match _ { .. }` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum MatchSource { @@ -1070,6 +1073,14 @@ pub struct MethodSig { pub generics: Generics, } +// The bodies for items are stored "out of line", in a separate +// hashmap in the `Crate`. Here we just record the node-id of the item +// so it can fetched later. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)] +pub struct TraitItemId { + pub node_id: NodeId, +} + /// Represents an item declaration within a trait declaration, /// possibly including a default implementation. A trait item is /// either required (meaning it doesn't have an implementation, just a @@ -1079,21 +1090,31 @@ pub struct TraitItem { pub id: NodeId, pub name: Name, pub attrs: HirVec, - pub node: TraitItem_, + pub node: TraitItemKind, pub span: Span, } +/// A trait method's body (or just argument names). +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum TraitMethod { + /// No default body in the trait, just a signature. + Required(HirVec>), + + /// Both signature and body are provided in the trait. + Provided(BodyId), +} + /// Represents a trait method or associated constant or type #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TraitItem_ { +pub enum TraitItemKind { /// An associated constant with an optional value (otherwise `impl`s /// must contain a value) - ConstTraitItem(P, Option>), + Const(P, Option), /// A method with an optional body - MethodTraitItem(MethodSig, Option), + Method(MethodSig, TraitMethod), /// An associated type with (possibly empty) bounds and optional concrete /// type - TypeTraitItem(TyParamBounds, Option>), + Type(TyParamBounds, Option>), } // The bodies for items are stored "out of line", in a separate @@ -1121,9 +1142,9 @@ pub struct ImplItem { pub enum ImplItemKind { /// An associated constant of the given type, set to the constant result /// of the expression - Const(P, P), + Const(P, BodyId), /// A method implementation with the given signature and body - Method(MethodSig, ExprId), + Method(MethodSig, BodyId), /// An associated type Type(P), } @@ -1147,7 +1168,8 @@ pub struct Ty { impl fmt::Debug for Ty { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "type({})", print::ty_to_string(self)) + write!(f, "type({})", + print::to_string(print::NO_ANN, |s| s.print_type(self))) } } @@ -1176,7 +1198,7 @@ pub enum Ty_ { /// A variable length slice (`[T]`) TySlice(P), /// A fixed length array (`[T; n]`) - TyArray(P, P), + TyArray(P, BodyId), /// A raw pointer (`*const T` or `*mut T`) TyPtr(MutTy), /// A reference (`&'a T` or `&'a mut T`) @@ -1200,7 +1222,7 @@ pub enum Ty_ { /// An `impl TraitA+TraitB` type. TyImplTrait(TyParamBounds), /// Unused for now - TyTypeof(P), + TyTypeof(BodyId), /// TyInfer means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. TyInfer, @@ -1229,67 +1251,18 @@ pub struct InlineAsm { /// represents an argument in a function header #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Arg { - pub ty: P, pub pat: P, pub id: NodeId, } -/// Alternative representation for `Arg`s describing `self` parameter of methods. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum SelfKind { - /// `self`, `mut self` - Value(Mutability), - /// `&'lt self`, `&'lt mut self` - Region(Option, Mutability), - /// `self: TYPE`, `mut self: TYPE` - Explicit(P, Mutability), -} - -pub type ExplicitSelf = Spanned; - -impl Arg { - pub fn to_self(&self) -> Option { - if let PatKind::Binding(BindByValue(mutbl), _, name, _) = self.pat.node { - if name.node == keywords::SelfValue.name() { - return match self.ty.node { - TyInfer => Some(respan(self.pat.span, SelfKind::Value(mutbl))), - TyRptr(lt, MutTy{ref ty, mutbl}) if ty.node == TyInfer => { - Some(respan(self.pat.span, SelfKind::Region(lt, mutbl))) - } - _ => Some(respan(mk_sp(self.pat.span.lo, self.ty.span.hi), - SelfKind::Explicit(self.ty.clone(), mutbl))) - } - } - } - None - } - - pub fn is_self(&self) -> bool { - if let PatKind::Binding(_, _, name, _) = self.pat.node { - name.node == keywords::SelfValue.name() - } else { - false - } - } -} - /// Represents the header (not the body) of a function declaration #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct FnDecl { - pub inputs: HirVec, + pub inputs: HirVec>, pub output: FunctionRetTy, pub variadic: bool, } -impl FnDecl { - pub fn get_self(&self) -> Option { - self.inputs.get(0).and_then(Arg::to_self) - } - pub fn has_self(&self) -> bool { - self.inputs.get(0).map(Arg::is_self).unwrap_or(false) - } -} - #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Unsafety { Unsafe, @@ -1403,7 +1376,7 @@ pub struct Variant_ { pub attrs: HirVec, pub data: VariantData, /// Explicit discriminant, eg `Foo = 1` - pub disr_expr: Option>, + pub disr_expr: Option, } pub type Variant = Spanned; @@ -1562,11 +1535,11 @@ pub enum Item_ { ItemUse(P, UseKind), /// A `static` item - ItemStatic(P, Mutability, P), + ItemStatic(P, Mutability, BodyId), /// A `const` item - ItemConst(P, P), + ItemConst(P, BodyId), /// A function declaration - ItemFn(P, Unsafety, Constness, Abi, Generics, ExprId), + ItemFn(P, Unsafety, Constness, Abi, Generics, BodyId), /// A module ItemMod(Mod), /// An external module @@ -1580,7 +1553,7 @@ pub enum Item_ { /// A union definition, e.g. `union Foo {x: A, y: B}` ItemUnion(VariantData, Generics), /// Represents a Trait Declaration - ItemTrait(Unsafety, Generics, TyParamBounds, HirVec), + ItemTrait(Unsafety, Generics, TyParamBounds, HirVec), // Default trait implementations /// @@ -1616,6 +1589,21 @@ impl Item_ { } } +/// A reference from an trait to one of its associated items. This +/// contains the item's id, naturally, but also the item's name and +/// some other high-level details (like whether it is an associated +/// type or method, and whether it is public). This allows other +/// passes to find the impl they want without loading the id (which +/// means fewer edges in the incremental compilation graph). +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub struct TraitItemRef { + pub id: TraitItemId, + pub name: Name, + pub kind: AssociatedItemKind, + pub span: Span, + pub defaultness: Defaultness, +} + /// A reference from an impl to one of its associated items. This /// contains the item's id, naturally, but also the item's name and /// some other high-level details (like whether it is an associated @@ -1653,7 +1641,7 @@ pub struct ForeignItem { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum ForeignItem_ { /// A foreign function - ForeignItemFn(P, Generics), + ForeignItemFn(P, HirVec>, Generics), /// A foreign static item (`static ext: u8`), with optional mutability /// (the boolean is true when mutable) ForeignItemStatic(P, bool), diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 100e344d94180..18fa6836b5108 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -13,7 +13,6 @@ pub use self::AnnNode::*; use syntax::abi::Abi; use syntax::ast; use syntax::codemap::{CodeMap, Spanned}; -use syntax::parse::token::{self, BinOpToken}; use syntax::parse::lexer::comments; use syntax::print::pp::{self, break_offset, word, space, hardbreak}; use syntax::print::pp::{Breaks, eof}; @@ -25,7 +24,7 @@ use syntax_pos::{self, BytePos}; use errors; use hir; -use hir::{Crate, PatKind, RegionTyParamBound, SelfKind, TraitTyParamBound, TraitBoundModifier}; +use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use std::io::{self, Write, Read}; @@ -38,7 +37,18 @@ pub enum AnnNode<'a> { NodePat(&'a hir::Pat), } +pub enum Nested { + Item(hir::ItemId), + TraitItem(hir::TraitItemId), + ImplItem(hir::ImplItemId), + Body(hir::BodyId), + BodyArgPat(hir::BodyId, usize) +} + pub trait PpAnn { + fn nested(&self, _state: &mut State, _nested: Nested) -> io::Result<()> { + Ok(()) + } fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) } @@ -47,14 +57,23 @@ pub trait PpAnn { } } -#[derive(Copy, Clone)] pub struct NoAnn; - impl PpAnn for NoAnn {} +pub const NO_ANN: &'static PpAnn = &NoAnn; +impl PpAnn for hir::Crate { + fn nested(&self, state: &mut State, nested: Nested) -> io::Result<()> { + match nested { + Nested::Item(id) => state.print_item(self.item(id.id)), + Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)), + Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), + Nested::Body(id) => state.print_expr(&self.body(id).value), + Nested::BodyArgPat(id, i) => state.print_pat(&self.body(id).arguments[i].pat) + } + } +} pub struct State<'a> { - krate: Option<&'a Crate>, pub s: pp::Printer<'a>, cm: Option<&'a CodeMap>, comments: Option>, @@ -86,30 +105,6 @@ impl<'a> PrintState<'a> for State<'a> { } } -pub fn rust_printer<'a>(writer: Box, krate: Option<&'a Crate>) -> State<'a> { - static NO_ANN: NoAnn = NoAnn; - rust_printer_annotated(writer, &NO_ANN, krate) -} - -pub fn rust_printer_annotated<'a>(writer: Box, - ann: &'a PpAnn, - krate: Option<&'a Crate>) - -> State<'a> { - State { - krate: krate, - s: pp::mk_printer(writer, default_columns), - cm: None, - comments: None, - literals: None, - cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral { - cur_cmnt: 0, - cur_lit: 0, - }, - boxes: Vec::new(), - ann: ann, - } -} - #[allow(non_upper_case_globals)] pub const indent_unit: usize = 4; @@ -130,7 +125,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, is_expanded: bool) -> io::Result<()> { let mut s = State::new_from_input(cm, span_diagnostic, filename, input, - out, ann, is_expanded, Some(krate)); + out, ann, is_expanded); // When printing the AST, we sometimes need to inject `#[no_std]` here. // Since you can't compile the HIR, it's not necessary. @@ -147,8 +142,7 @@ impl<'a> State<'a> { input: &mut Read, out: Box, ann: &'a PpAnn, - is_expanded: bool, - krate: Option<&'a Crate>) + is_expanded: bool) -> State<'a> { let (cmnts, lits) = comments::gather_comments_and_literals(span_diagnostic, filename, @@ -165,19 +159,16 @@ impl<'a> State<'a> { None } else { Some(lits) - }, - krate) + }) } pub fn new(cm: &'a CodeMap, out: Box, ann: &'a PpAnn, comments: Option>, - literals: Option>, - krate: Option<&'a Crate>) + literals: Option>) -> State<'a> { State { - krate: krate, s: pp::mk_printer(out, default_columns), cm: Some(cm), comments: comments.clone(), @@ -192,144 +183,36 @@ impl<'a> State<'a> { } } -pub fn to_string(f: F) -> String +pub fn to_string(ann: &PpAnn, f: F) -> String where F: FnOnce(&mut State) -> io::Result<()> { let mut wr = Vec::new(); { - let mut printer = rust_printer(Box::new(&mut wr), None); + let mut printer = State { + s: pp::mk_printer(Box::new(&mut wr), default_columns), + cm: None, + comments: None, + literals: None, + cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral { + cur_cmnt: 0, + cur_lit: 0, + }, + boxes: Vec::new(), + ann: ann, + }; f(&mut printer).unwrap(); eof(&mut printer.s).unwrap(); } String::from_utf8(wr).unwrap() } -pub fn binop_to_string(op: BinOpToken) -> &'static str { - match op { - token::Plus => "+", - token::Minus => "-", - token::Star => "*", - token::Slash => "/", - token::Percent => "%", - token::Caret => "^", - token::And => "&", - token::Or => "|", - token::Shl => "<<", - token::Shr => ">>", - } -} - -pub fn ty_to_string(ty: &hir::Ty) -> String { - to_string(|s| s.print_type(ty)) -} - -pub fn bounds_to_string(bounds: &[hir::TyParamBound]) -> String { - to_string(|s| s.print_bounds("", bounds)) -} - -pub fn pat_to_string(pat: &hir::Pat) -> String { - to_string(|s| s.print_pat(pat)) -} - -pub fn arm_to_string(arm: &hir::Arm) -> String { - to_string(|s| s.print_arm(arm)) -} - -pub fn expr_to_string(e: &hir::Expr) -> String { - to_string(|s| s.print_expr(e)) -} - -pub fn lifetime_to_string(e: &hir::Lifetime) -> String { - to_string(|s| s.print_lifetime(e)) -} - -pub fn stmt_to_string(stmt: &hir::Stmt) -> String { - to_string(|s| s.print_stmt(stmt)) -} - -pub fn item_to_string(i: &hir::Item) -> String { - to_string(|s| s.print_item(i)) -} - -pub fn impl_item_to_string(i: &hir::ImplItem) -> String { - to_string(|s| s.print_impl_item(i)) -} - -pub fn trait_item_to_string(i: &hir::TraitItem) -> String { - to_string(|s| s.print_trait_item(i)) -} - -pub fn generics_to_string(generics: &hir::Generics) -> String { - to_string(|s| s.print_generics(generics)) -} - -pub fn where_clause_to_string(i: &hir::WhereClause) -> String { - to_string(|s| s.print_where_clause(i)) -} - -pub fn fn_block_to_string(p: &hir::FnDecl) -> String { - to_string(|s| s.print_fn_block_args(p)) -} - -pub fn path_to_string(p: &hir::Path) -> String { - to_string(|s| s.print_path(p, false)) -} - -pub fn qpath_to_string(p: &hir::QPath) -> String { - to_string(|s| s.print_qpath(p, false)) -} - -pub fn name_to_string(name: ast::Name) -> String { - to_string(|s| s.print_name(name)) -} - -pub fn fun_to_string(decl: &hir::FnDecl, - unsafety: hir::Unsafety, - constness: hir::Constness, - name: ast::Name, - generics: &hir::Generics) - -> String { - to_string(|s| { - s.head("")?; - s.print_fn(decl, - unsafety, - constness, - Abi::Rust, - Some(name), - generics, - &hir::Inherited)?; - s.end()?; // Close the head box - s.end() // Close the outer box +pub fn visibility_qualified(vis: &hir::Visibility, w: &str) -> String { + to_string(NO_ANN, |s| { + s.print_visibility(vis)?; + word(&mut s.s, w) }) } -pub fn block_to_string(blk: &hir::Block) -> String { - to_string(|s| { - // containing cbox, will be closed by print-block at } - s.cbox(indent_unit)?; - // head-ibox, will be closed by print-block after { - s.ibox(0)?; - s.print_block(blk) - }) -} - -pub fn variant_to_string(var: &hir::Variant) -> String { - to_string(|s| s.print_variant(var)) -} - -pub fn arg_to_string(arg: &hir::Arg) -> String { - to_string(|s| s.print_arg(arg, false)) -} - -pub fn visibility_qualified(vis: &hir::Visibility, s: &str) -> String { - match *vis { - hir::Public => format!("pub {}", s), - hir::Visibility::Crate => format!("pub(crate) {}", s), - hir::Visibility::Restricted { ref path, .. } => format!("pub({}) {}", path, s), - hir::Inherited => s.to_string(), - } -} - fn needs_parentheses(expr: &hir::Expr) -> bool { match expr.node { hir::ExprAssign(..) | @@ -462,8 +345,8 @@ impl<'a> State<'a> { pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> { self.print_inner_attributes(attrs)?; - for item_id in &_mod.item_ids { - self.print_item_id(item_id)?; + for &item_id in &_mod.item_ids { + self.ann.nested(self, Nested::Item(item_id))?; } Ok(()) } @@ -545,16 +428,16 @@ impl<'a> State<'a> { hir::TyImplTrait(ref bounds) => { self.print_bounds("impl ", &bounds[..])?; } - hir::TyArray(ref ty, ref v) => { + hir::TyArray(ref ty, v) => { word(&mut self.s, "[")?; self.print_type(&ty)?; word(&mut self.s, "; ")?; - self.print_expr(&v)?; + self.ann.nested(self, Nested::Body(v))?; word(&mut self.s, "]")?; } - hir::TyTypeof(ref e) => { + hir::TyTypeof(e) => { word(&mut self.s, "typeof(")?; - self.print_expr(&e)?; + self.ann.nested(self, Nested::Body(e))?; word(&mut self.s, ")")?; } hir::TyInfer => { @@ -569,7 +452,7 @@ impl<'a> State<'a> { self.maybe_print_comment(item.span.lo)?; self.print_outer_attributes(&item.attrs)?; match item.node { - hir::ForeignItemFn(ref decl, ref generics) => { + hir::ForeignItemFn(ref decl, ref arg_names, ref generics) => { self.head("")?; self.print_fn(decl, hir::Unsafety::Normal, @@ -577,7 +460,9 @@ impl<'a> State<'a> { Abi::Rust, Some(item.name), generics, - &item.vis)?; + &item.vis, + arg_names, + None)?; self.end()?; // end head-ibox word(&mut self.s, ";")?; self.end() // end the outer fn box @@ -600,7 +485,7 @@ impl<'a> State<'a> { fn print_associated_const(&mut self, name: ast::Name, ty: &hir::Ty, - default: Option<&hir::Expr>, + default: Option, vis: &hir::Visibility) -> io::Result<()> { word(&mut self.s, &visibility_qualified(vis, ""))?; @@ -611,7 +496,7 @@ impl<'a> State<'a> { if let Some(expr) = default { space(&mut self.s)?; self.word_space("=")?; - self.print_expr(expr)?; + self.ann.nested(self, Nested::Body(expr))?; } word(&mut self.s, ";") } @@ -634,25 +519,6 @@ impl<'a> State<'a> { word(&mut self.s, ";") } - pub fn print_item_id(&mut self, item_id: &hir::ItemId) -> io::Result<()> { - if let Some(krate) = self.krate { - // skip nested items if krate context was not provided - let item = &krate.items[&item_id.id]; - self.print_item(item) - } else { - Ok(()) - } - } - - pub fn print_expr_id(&mut self, expr_id: &hir::ExprId) -> io::Result<()> { - if let Some(krate) = self.krate { - let expr = &krate.exprs[expr_id]; - self.print_expr(expr) - } else { - Ok(()) - } - } - /// Pretty-print an item pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> { self.hardbreak_if_not_bol()?; @@ -697,7 +563,7 @@ impl<'a> State<'a> { self.end()?; // end inner 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"))?; if m == hir::MutMutable { self.word_space("mut")?; @@ -709,11 +575,11 @@ impl<'a> State<'a> { self.end()?; // end the head-ibox self.word_space("=")?; - self.print_expr(&expr)?; + self.ann.nested(self, Nested::Body(expr))?; word(&mut self.s, ";")?; 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.print_name(item.name)?; self.word_space(":")?; @@ -722,11 +588,11 @@ impl<'a> State<'a> { self.end()?; // end the head-ibox self.word_space("=")?; - self.print_expr(&expr)?; + self.ann.nested(self, Nested::Body(expr))?; word(&mut self.s, ";")?; 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.print_fn(decl, unsafety, @@ -734,11 +600,13 @@ impl<'a> State<'a> { abi, Some(item.name), typarams, - &item.vis)?; + &item.vis, + &[], + Some(body))?; word(&mut self.s, " ")?; self.end()?; // need to close a box self.end()?; // need to close a box - self.print_expr_id(body)?; + self.ann.nested(self, Nested::Body(body))?; } hir::ItemMod(ref _mod) => { self.head(&visibility_qualified(&item.vis, "mod"))?; @@ -832,7 +700,7 @@ impl<'a> State<'a> { self.bopen()?; self.print_inner_attributes(&item.attrs)?; for impl_item in impl_items { - self.print_impl_item_ref(impl_item)?; + self.ann.nested(self, Nested::ImplItem(impl_item.id))?; } self.bclose(item.span)?; } @@ -858,7 +726,7 @@ impl<'a> State<'a> { word(&mut self.s, " ")?; self.bopen()?; for trait_item in trait_items { - self.print_trait_item(trait_item)?; + self.ann.nested(self, Nested::TraitItem(trait_item.id))?; } self.bclose(item.span)?; } @@ -928,8 +796,11 @@ impl<'a> State<'a> { match *vis { hir::Public => self.word_nbsp("pub"), hir::Visibility::Crate => self.word_nbsp("pub(crate)"), - hir::Visibility::Restricted { ref path, .. } => - self.word_nbsp(&format!("pub({})", path)), + hir::Visibility::Restricted { ref path, .. } => { + word(&mut self.s, "pub(")?; + self.print_path(path, false)?; + self.word_nbsp(")") + } hir::Inherited => Ok(()), } } @@ -985,19 +856,19 @@ impl<'a> State<'a> { self.head("")?; let generics = hir::Generics::empty(); self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?; - match v.node.disr_expr { - Some(ref d) => { - space(&mut self.s)?; - self.word_space("=")?; - self.print_expr(&d) - } - _ => Ok(()), + if let Some(d) = v.node.disr_expr { + space(&mut self.s)?; + self.word_space("=")?; + self.ann.nested(self, Nested::Body(d))?; } + Ok(()) } pub fn print_method_sig(&mut self, name: ast::Name, m: &hir::MethodSig, - vis: &hir::Visibility) + vis: &hir::Visibility, + arg_names: &[Spanned], + body_id: Option) -> io::Result<()> { self.print_fn(&m.decl, m.unsafety, @@ -1005,7 +876,9 @@ impl<'a> State<'a> { m.abi, Some(name), &m.generics, - vis) + vis, + arg_names, + body_id) } pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> { @@ -1014,27 +887,22 @@ impl<'a> State<'a> { self.maybe_print_comment(ti.span.lo)?; self.print_outer_attributes(&ti.attrs)?; match ti.node { - hir::ConstTraitItem(ref ty, ref default) => { - self.print_associated_const(ti.name, - &ty, - default.as_ref().map(|expr| &**expr), - &hir::Inherited)?; - } - hir::MethodTraitItem(ref sig, ref body) => { - if body.is_some() { - self.head("")?; - } - self.print_method_sig(ti.name, sig, &hir::Inherited)?; - if let Some(ref body) = *body { - self.nbsp()?; - self.end()?; // need to close a box - self.end()?; // need to close a box - self.print_expr_id(body)?; - } else { - word(&mut self.s, ";")?; - } + hir::TraitItemKind::Const(ref ty, default) => { + self.print_associated_const(ti.name, &ty, default, &hir::Inherited)?; } - hir::TypeTraitItem(ref bounds, ref default) => { + hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref arg_names)) => { + self.print_method_sig(ti.name, sig, &hir::Inherited, arg_names, None)?; + word(&mut self.s, ";")?; + } + hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { + self.head("")?; + self.print_method_sig(ti.name, sig, &hir::Inherited, &[], Some(body))?; + self.nbsp()?; + self.end()?; // need to close a box + self.end()?; // need to close a box + self.ann.nested(self, Nested::Body(body))?; + } + hir::TraitItemKind::Type(ref bounds, ref default) => { self.print_associated_type(ti.name, Some(bounds), default.as_ref().map(|ty| &**ty))?; @@ -1043,16 +911,6 @@ impl<'a> State<'a> { self.ann.post(self, NodeSubItem(ti.id)) } - pub fn print_impl_item_ref(&mut self, item_ref: &hir::ImplItemRef) -> io::Result<()> { - if let Some(krate) = self.krate { - // skip nested items if krate context was not provided - let item = &krate.impl_item(item_ref.id); - self.print_impl_item(item) - } else { - Ok(()) - } - } - pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> { self.ann.pre(self, NodeSubItem(ii.id))?; self.hardbreak_if_not_bol()?; @@ -1065,16 +923,16 @@ impl<'a> State<'a> { } match ii.node { - hir::ImplItemKind::Const(ref ty, ref expr) => { - self.print_associated_const(ii.name, &ty, Some(&expr), &ii.vis)?; + hir::ImplItemKind::Const(ref ty, expr) => { + 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.print_method_sig(ii.name, sig, &ii.vis)?; + self.print_method_sig(ii.name, sig, &ii.vis, &[], Some(body))?; self.nbsp()?; self.end()?; // need to close a box self.end()?; // need to close a box - self.print_expr_id(body)?; + self.ann.nested(self, Nested::Body(body))?; } hir::ImplItemKind::Type(ref ty) => { self.print_associated_type(ii.name, None, Some(ty))?; @@ -1246,12 +1104,12 @@ impl<'a> State<'a> { 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)?; word(&mut self.s, "[")?; self.print_expr(element)?; self.word_space(";")?; - self.print_expr(count)?; + self.ann.nested(self, Nested::Body(count))?; word(&mut self.s, "]")?; self.end() } @@ -1362,8 +1220,8 @@ impl<'a> State<'a> { hir::ExprArray(ref exprs) => { self.print_expr_vec(exprs)?; } - hir::ExprRepeat(ref element, ref count) => { - self.print_expr_repeat(&element, &count)?; + hir::ExprRepeat(ref element, count) => { + self.print_expr_repeat(&element, count)?; } hir::ExprStruct(ref qpath, ref fields, ref wth) => { self.print_expr_struct(qpath, &fields[..], wth)?; @@ -1434,14 +1292,14 @@ impl<'a> State<'a> { } 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_fn_block_args(&decl)?; + self.print_closure_args(&decl, body)?; space(&mut self.s)?; // this is a bare expression - self.print_expr_id(body)?; + self.ann.nested(self, Nested::Body(body))?; self.end()?; // need to close a box // a box will be closed by print_expr, but we didn't want an overall @@ -1615,8 +1473,8 @@ impl<'a> State<'a> { } self.end() } - hir::DeclItem(ref item) => { - self.print_item_id(item) + hir::DeclItem(item) => { + self.ann.nested(self, Nested::Item(item)) } } } @@ -1637,10 +1495,10 @@ impl<'a> State<'a> { self.print_expr(coll) } - fn print_path(&mut self, - path: &hir::Path, - colons_before_params: bool) - -> io::Result<()> { + pub fn print_path(&mut self, + path: &hir::Path, + colons_before_params: bool) + -> io::Result<()> { self.maybe_print_comment(path.span.lo)?; for (i, segment) in path.segments.iter().enumerate() { @@ -1656,10 +1514,10 @@ impl<'a> State<'a> { Ok(()) } - fn print_qpath(&mut self, - qpath: &hir::QPath, - colons_before_params: bool) - -> io::Result<()> { + pub fn print_qpath(&mut self, + qpath: &hir::QPath, + colons_before_params: bool) + -> io::Result<()> { match *qpath { hir::QPath::Resolved(None, ref path) => { self.print_path(path, colons_before_params) @@ -1954,27 +1812,6 @@ impl<'a> State<'a> { self.end() // close enclosing cbox } - fn print_explicit_self(&mut self, explicit_self: &hir::ExplicitSelf) -> io::Result<()> { - match explicit_self.node { - SelfKind::Value(m) => { - self.print_mutability(m)?; - word(&mut self.s, "self") - } - SelfKind::Region(ref lt, m) => { - word(&mut self.s, "&")?; - self.print_opt_lifetime(lt)?; - self.print_mutability(m)?; - word(&mut self.s, "self") - } - SelfKind::Explicit(ref typ, m) => { - self.print_mutability(m)?; - word(&mut self.s, "self")?; - self.word_space(":")?; - self.print_type(&typ) - } - } - } - pub fn print_fn(&mut self, decl: &hir::FnDecl, unsafety: hir::Unsafety, @@ -1982,7 +1819,9 @@ impl<'a> State<'a> { abi: Abi, name: Option, generics: &hir::Generics, - vis: &hir::Visibility) + vis: &hir::Visibility, + arg_names: &[Spanned], + body_id: Option) -> io::Result<()> { self.print_fn_header_info(unsafety, constness, abi, vis)?; @@ -1991,24 +1830,51 @@ impl<'a> State<'a> { self.print_name(name)?; } self.print_generics(generics)?; - self.print_fn_args_and_ret(decl)?; - self.print_where_clause(&generics.where_clause) - } - pub fn print_fn_args_and_ret(&mut self, decl: &hir::FnDecl) -> io::Result<()> { self.popen()?; - self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?; + let mut i = 0; + // Make sure we aren't supplied *both* `arg_names` and `body_id`. + assert!(arg_names.is_empty() || body_id.is_none()); + self.commasep(Inconsistent, &decl.inputs, |s, ty| { + s.ibox(indent_unit)?; + if let Some(name) = arg_names.get(i) { + word(&mut s.s, &name.node.as_str())?; + word(&mut s.s, ":")?; + space(&mut s.s)?; + } else if let Some(body_id) = body_id { + s.ann.nested(s, Nested::BodyArgPat(body_id, i))?; + word(&mut s.s, ":")?; + space(&mut s.s)?; + } + i += 1; + s.print_type(ty)?; + s.end() + })?; if decl.variadic { word(&mut self.s, ", ...")?; } self.pclose()?; - self.print_fn_output(decl) + self.print_fn_output(decl)?; + self.print_where_clause(&generics.where_clause) } - pub fn print_fn_block_args(&mut self, decl: &hir::FnDecl) -> io::Result<()> { + fn print_closure_args(&mut self, decl: &hir::FnDecl, body_id: hir::BodyId) -> io::Result<()> { word(&mut self.s, "|")?; - self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))?; + let mut i = 0; + self.commasep(Inconsistent, &decl.inputs, |s, ty| { + s.ibox(indent_unit)?; + + s.ann.nested(s, Nested::BodyArgPat(body_id, i))?; + i += 1; + + if ty.node != hir::TyInfer { + word(&mut s.s, ":")?; + space(&mut s.s)?; + s.print_type(ty)?; + } + s.end() + })?; word(&mut self.s, "|")?; if let hir::DefaultReturn(..) = decl.output { @@ -2180,31 +2046,6 @@ impl<'a> State<'a> { self.print_type(&mt.ty) } - pub fn print_arg(&mut self, input: &hir::Arg, is_closure: bool) -> io::Result<()> { - self.ibox(indent_unit)?; - match input.ty.node { - hir::TyInfer if is_closure => self.print_pat(&input.pat)?, - _ => { - if let Some(eself) = input.to_self() { - self.print_explicit_self(&eself)?; - } else { - let invalid = if let PatKind::Binding(_, _, name, _) = input.pat.node { - name.node == keywords::Invalid.name() - } else { - false - }; - if !invalid { - self.print_pat(&input.pat)?; - word(&mut self.s, ":")?; - space(&mut self.s)?; - } - self.print_type(&input.ty)?; - } - } - } - self.end() - } - pub fn print_fn_output(&mut self, decl: &hir::FnDecl) -> io::Result<()> { if let hir::DefaultReturn(..) = decl.output { return Ok(()); @@ -2252,7 +2093,9 @@ impl<'a> State<'a> { abi, name, &generics, - &hir::Inherited)?; + &hir::Inherited, + &[], + None)?; self.end() } diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 9d48fbca53edd..9ff7dcc7d5883 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -75,7 +75,6 @@ use std::collections::HashSet; use hir::map as ast_map; use hir; -use hir::print as pprust; use lint; use hir::def::Def; @@ -1051,8 +1050,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Some(ref node) => match *node { ast_map::NodeItem(ref item) => { match item.node { - hir::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, _) => { - Some((fn_decl, gen, unsafety, constness, item.name, item.span)) + hir::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, body) => { + Some((fn_decl, gen, unsafety, constness, item.name, item.span, body)) } _ => None, } @@ -1066,26 +1065,28 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return; } } - if let hir::ImplItemKind::Method(ref sig, _) = item.node { + if let hir::ImplItemKind::Method(ref sig, body) = item.node { Some((&sig.decl, &sig.generics, sig.unsafety, sig.constness, item.name, - item.span)) + item.span, + body)) } else { None } }, ast_map::NodeTraitItem(item) => { match item.node { - hir::MethodTraitItem(ref sig, Some(_)) => { + hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { Some((&sig.decl, &sig.generics, sig.unsafety, sig.constness, item.name, - item.span)) + item.span, + body)) } _ => None, } @@ -1094,12 +1095,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }, None => None, }; - let (fn_decl, generics, unsafety, constness, name, span) + let (fn_decl, generics, unsafety, constness, name, span, body) = node_inner.expect("expect item fn"); let rebuilder = Rebuilder::new(self.tcx, fn_decl, generics, same_regions, &life_giver); let (fn_decl, generics) = rebuilder.rebuild(); self.give_expl_lifetime_param( - err, &fn_decl, unsafety, constness, name, &generics, span); + err, &fn_decl, unsafety, constness, name, &generics, span, body); } pub fn issue_32330_warnings(&self, span: Span, issue32330s: &[ty::Issue32330]) { @@ -1375,23 +1376,14 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { } fn rebuild_args_ty(&self, - inputs: &[hir::Arg], + inputs: &[P], lifetime: hir::Lifetime, anon_nums: &HashSet, region_names: &HashSet) - -> hir::HirVec { - let mut new_inputs = Vec::new(); - for arg in inputs { - let new_ty = self.rebuild_arg_ty_or_output(&arg.ty, lifetime, - anon_nums, region_names); - let possibly_new_arg = hir::Arg { - ty: new_ty, - pat: arg.pat.clone(), - id: arg.id - }; - new_inputs.push(possibly_new_arg); - } - new_inputs.into() + -> hir::HirVec> { + inputs.iter().map(|arg_ty| { + self.rebuild_arg_ty_or_output(arg_ty, lifetime, anon_nums, region_names) + }).collect() } fn rebuild_output(&self, ty: &hir::FunctionRetTy, @@ -1634,10 +1626,26 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { constness: hir::Constness, name: ast::Name, generics: &hir::Generics, - span: Span) { - let suggested_fn = pprust::fun_to_string(decl, unsafety, constness, name, generics); - let msg = format!("consider using an explicit lifetime \ - parameter as shown: {}", suggested_fn); + span: Span, + body: hir::BodyId) { + let s = hir::print::to_string(&self.tcx.map, |s| { + use syntax::abi::Abi; + use syntax::print::pprust::PrintState; + + s.head("")?; + s.print_fn(decl, + unsafety, + constness, + Abi::Rust, + Some(name), + generics, + &hir::Inherited, + &[], + Some(body))?; + s.end()?; // Close the head box + s.end() // Close the outer box + }); + let msg = format!("consider using an explicit lifetime parameter as shown: {}", s); err.span_help(span, &msg[..]); } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 17cc34fcd8394..ff508d2d8194a 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -33,6 +33,7 @@ #![cfg_attr(stage0, feature(item_like_imports))] #![feature(libc)] #![feature(nonzero)] +#![feature(pub_restricted)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] @@ -80,9 +81,8 @@ pub mod lint; pub mod middle { pub mod astconv_util; - pub mod expr_use_visitor; // STAGE0: increase glitch immunity + pub mod expr_use_visitor; pub mod const_val; - pub mod const_qualif; pub mod cstore; pub mod dataflow; pub mod dead; diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 3ff2abac277b5..cce79820ca8da 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -821,6 +821,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { self.with_lint_attrs(&e.attrs, |cx| { run_lints!(cx, check_expr, late_passes, 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, - body_id: hir::ExprId, span: Span, id: ast::NodeId) { - let body = self.tcx.map.expr(body_id); + body_id: hir::BodyId, span: Span, id: ast::NodeId) { + let body = self.tcx.map.body(body_id); run_lints!(self, check_fn, late_passes, fk, decl, body, 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); @@ -909,10 +910,6 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { 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) { run_lints!(self, check_generics, late_passes, g); hir_visit::walk_generics(self, g); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index ccf53f01cd532..7e0da00694c4a 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -162,14 +162,14 @@ pub trait LateLintPass<'a, 'tcx>: LintPass { _: &LateContext<'a, 'tcx>, _: FnKind<'tcx>, _: &'tcx hir::FnDecl, - _: &'tcx hir::Expr, + _: &'tcx hir::Body, _: Span, _: ast::NodeId) { } fn check_fn_post(&mut self, _: &LateContext<'a, 'tcx>, _: FnKind<'tcx>, _: &'tcx hir::FnDecl, - _: &'tcx hir::Expr, + _: &'tcx hir::Body, _: Span, _: ast::NodeId) { } fn check_trait_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::TraitItem) { } diff --git a/src/librustc/middle/const_qualif.rs b/src/librustc/middle/const_qualif.rs deleted file mode 100644 index ec98637922ee3..0000000000000 --- a/src/librustc/middle/const_qualif.rs +++ /dev/null @@ -1,44 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Const qualification, from partial to completely promotable. -bitflags! { - #[derive(RustcEncodable, RustcDecodable)] - flags ConstQualif: u8 { - // Inner mutability (can not be placed behind a reference) or behind - // &mut in a non-global expression. Can be copied from static memory. - const MUTABLE_MEM = 1 << 0, - // Constant value with a type that implements Drop. Can be copied - // from static memory, similar to MUTABLE_MEM. - const NEEDS_DROP = 1 << 1, - // Even if the value can be placed in static memory, copying it from - // there is more expensive than in-place instantiation, and/or it may - // be too large. This applies to [T; N] and everything containing it. - // N.B.: references need to clear this flag to not end up on the stack. - const PREFER_IN_PLACE = 1 << 2, - // May use more than 0 bytes of memory, doesn't impact the constness - // directly, but is not allowed to be borrowed mutably in a constant. - const NON_ZERO_SIZED = 1 << 3, - // Actually borrowed, has to always be in static memory. Does not - // propagate, and requires the expression to behave like a 'static - // lvalue. The set of expressions with this flag is the minimum - // that have to be promoted. - const HAS_STATIC_BORROWS = 1 << 4, - // Invalid const for miscellaneous reasons (e.g. not implemented). - const NOT_CONST = 1 << 5, - - // Borrowing the expression won't produce &'static T if any of these - // bits are set, though the value could be copied from static memory - // if `NOT_CONST` isn't set. - const NON_STATIC_BORROWS = ConstQualif::MUTABLE_MEM.bits | - ConstQualif::NEEDS_DROP.bits | - ConstQualif::NOT_CONST.bits - } -} diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index d0003693eefe3..7151e5226cab0 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -33,17 +33,17 @@ use mir::Mir; use session::Session; use session::search_paths::PathKind; use util::nodemap::{NodeSet, DefIdMap}; + +use std::collections::BTreeMap; use std::path::PathBuf; use std::rc::Rc; use syntax::ast; use syntax::attr; use syntax::ext::base::SyntaxExtension; -use syntax::ptr::P; use syntax::symbol::Symbol; use syntax_pos::Span; use rustc_back::target::Target; use hir; -use hir::intravisit::Visitor; use rustc_back::PanicStrategy; pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown}; @@ -134,102 +134,6 @@ pub struct NativeLibrary { pub foreign_items: Vec, } -/// The data we save and restore about an inlined item or method. This is not -/// part of the AST that we parse from a file, but it becomes part of the tree -/// that we trans. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct InlinedItem { - pub def_id: DefId, - pub body: P, - pub const_fn_args: Vec>, -} - -/// A borrowed version of `hir::InlinedItem`. This is what's encoded when saving -/// a crate; it then gets read as an InlinedItem. -#[derive(Clone, PartialEq, Eq, RustcEncodable, Hash, Debug)] -pub struct InlinedItemRef<'a> { - pub def_id: DefId, - pub body: &'a hir::Expr, - pub const_fn_args: Vec>, -} - -fn get_fn_args(decl: &hir::FnDecl) -> Vec> { - decl.inputs.iter().map(|arg| match arg.pat.node { - hir::PatKind::Binding(_, def_id, _, _) => Some(def_id), - _ => None - }).collect() -} - -impl<'a> InlinedItemRef<'a> { - pub fn from_item<'b, 'tcx>(def_id: DefId, - item: &'a hir::Item, - tcx: TyCtxt<'b, 'a, 'tcx>) - -> InlinedItemRef<'a> { - let (body, args) = match item.node { - hir::ItemFn(ref decl, _, _, _, _, body_id) => - (tcx.map.expr(body_id), get_fn_args(decl)), - hir::ItemConst(_, ref body) => (&**body, Vec::new()), - _ => bug!("InlinedItemRef::from_item wrong kind") - }; - InlinedItemRef { - def_id: def_id, - body: body, - const_fn_args: args - } - } - - pub fn from_trait_item(def_id: DefId, - item: &'a hir::TraitItem, - _tcx: TyCtxt) - -> InlinedItemRef<'a> { - let (body, args) = match item.node { - hir::ConstTraitItem(_, Some(ref body)) => - (&**body, Vec::new()), - hir::ConstTraitItem(_, None) => { - bug!("InlinedItemRef::from_trait_item called for const without body") - }, - _ => bug!("InlinedItemRef::from_trait_item wrong kind") - }; - InlinedItemRef { - def_id: def_id, - body: body, - const_fn_args: args - } - } - - pub fn from_impl_item<'b, 'tcx>(def_id: DefId, - item: &'a hir::ImplItem, - tcx: TyCtxt<'b, 'a, 'tcx>) - -> InlinedItemRef<'a> { - let (body, args) = match item.node { - hir::ImplItemKind::Method(ref sig, body_id) => - (tcx.map.expr(body_id), get_fn_args(&sig.decl)), - hir::ImplItemKind::Const(_, ref body) => - (&**body, Vec::new()), - _ => bug!("InlinedItemRef::from_impl_item wrong kind") - }; - InlinedItemRef { - def_id: def_id, - body: body, - const_fn_args: args - } - } - - pub fn visit(&self, visitor: &mut V) - where V: Visitor<'a> - { - visitor.visit_expr(&self.body); - } -} - -impl InlinedItem { - pub fn visit<'ast,V>(&'ast self, visitor: &mut V) - where V: Visitor<'ast> - { - visitor.visit_expr(&self.body); - } -} - pub enum LoadedMacro { MacroRules(ast::MacroDef), ProcMacro(Rc), @@ -346,10 +250,10 @@ pub trait CrateStore<'tcx> { fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro; // misc. metadata - fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option<(&'tcx InlinedItem, ast::NodeId)>; - fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option; - fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option; + fn maybe_get_item_body<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + -> Option<&'tcx hir::Body>; + fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap; + fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool; fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx>; fn is_item_mir_available(&self, def: DefId) -> bool; @@ -516,15 +420,15 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") } // misc. metadata - fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option<(&'tcx InlinedItem, ast::NodeId)> { - bug!("maybe_get_item_ast") + fn maybe_get_item_body<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + -> Option<&'tcx hir::Body> { + bug!("maybe_get_item_body") } - fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option { - bug!("local_node_for_inlined_defid") + fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap { + bug!("item_body_nested_bodies") } - fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option { - bug!("defid_for_inlined_node") + fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool { + bug!("const_is_rvalue_promotable_to_static") } fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index f7a34c43cccbd..dfcb5cb7b79fe 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -108,6 +108,9 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { } impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O> { + fn nested(&self, state: &mut pprust::State, nested: pprust::Nested) -> io::Result<()> { + pprust::PpAnn::nested(&self.tcx.map, state, nested) + } fn pre(&self, ps: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { @@ -160,7 +163,7 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O } } -fn build_nodeid_to_index(decl: Option<&hir::FnDecl>, +fn build_nodeid_to_index(body: Option<&hir::Body>, cfg: &cfg::CFG) -> NodeMap> { let mut index = NodeMap(); @@ -168,8 +171,8 @@ fn build_nodeid_to_index(decl: Option<&hir::FnDecl>, // into cfg itself? i.e. introduce a fn-based flow-graph in // addition to the current block-based flow-graph, rather than // have to put traversals like this here? - if let Some(decl) = decl { - add_entries_from_fn_decl(&mut index, decl, cfg.entry); + if let Some(body) = body { + add_entries_from_fn_body(&mut index, body, cfg.entry); } cfg.graph.each_node(|node_idx, node| { @@ -181,20 +184,24 @@ fn build_nodeid_to_index(decl: Option<&hir::FnDecl>, return index; - fn add_entries_from_fn_decl(index: &mut NodeMap>, - decl: &hir::FnDecl, + /// Add mappings from the ast nodes for the formal bindings to + /// the entry-node in the graph. + fn add_entries_from_fn_body(index: &mut NodeMap>, + body: &hir::Body, entry: CFGIndex) { - //! add mappings from the ast nodes for the formal bindings to - //! the entry-node in the graph. + use hir::intravisit::Visitor; + struct Formals<'a> { entry: CFGIndex, index: &'a mut NodeMap>, } let mut formals = Formals { entry: entry, index: index }; - intravisit::walk_fn_decl(&mut formals, decl); - impl<'a, 'v> intravisit::Visitor<'v> for Formals<'a> { + for arg in &body.arguments { + formals.visit_pat(&arg.pat); + } + impl<'a, 'v> Visitor<'v> for Formals<'a> { 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) { @@ -227,7 +234,7 @@ pub enum KillFrom { impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, analysis_name: &'static str, - decl: Option<&hir::FnDecl>, + body: Option<&hir::Body>, cfg: &cfg::CFG, oper: O, id_range: IdRange, @@ -250,7 +257,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { let kills2 = zeroes; let on_entry = vec![entry; num_nodes * words_per_id]; - let nodeid_to_index = build_nodeid_to_index(decl, cfg); + let nodeid_to_index = build_nodeid_to_index(body, cfg); DataFlowContext { tcx: tcx, @@ -502,7 +509,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> { // ^^^^^^^^^^^^^ 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. if self.bits_per_id == 0 { @@ -526,20 +533,11 @@ impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> { } debug!("Dataflow result for {}:", self.analysis_name); - debug!("{}", { - let mut v = Vec::new(); - self.pretty_print_to(box &mut v, body).unwrap(); - String::from_utf8(v).unwrap() - }); - } - - fn pretty_print_to<'b>(&self, wr: Box, - body: &hir::Expr) -> io::Result<()> { - let mut ps = pprust::rust_printer_annotated(wr, self, None); - ps.cbox(pprust::indent_unit)?; - ps.ibox(0)?; - ps.print_expr(body)?; - pp::eof(&mut ps.s) + debug!("{}", pprust::to_string(self, |s| { + s.cbox(pprust::indent_unit)?; + s.ibox(0)?; + s.print_expr(&body.value) + })); } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 1c5dd97b74bd3..76adee4e00c15 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -328,11 +328,12 @@ impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> { self.worklist.extend(enum_def.variants.iter() .map(|variant| variant.node.data.id())); } - hir::ItemTrait(.., ref trait_items) => { - for trait_item in trait_items { + hir::ItemTrait(.., ref trait_item_refs) => { + for trait_item_ref in trait_item_refs { + let trait_item = self.krate.trait_item(trait_item_ref.id); match trait_item.node { - hir::ConstTraitItem(_, Some(_)) | - hir::MethodTraitItem(_, Some(_)) => { + hir::TraitItemKind::Const(_, Some(_)) | + hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => { if has_allow_dead_code_or_lang_attr(&trait_item.attrs) { self.worklist.push(trait_item.id); } @@ -354,6 +355,10 @@ impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> { } } + fn visit_trait_item(&mut self, _item: &hir::TraitItem) { + // ignore: we are handling this in `visit_item` above + } + fn visit_impl_item(&mut self, _item: &hir::ImplItem) { // ignore: we are handling this in `visit_item` above } @@ -546,19 +551,19 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { match impl_item.node { - hir::ImplItemKind::Const(_, ref expr) => { + hir::ImplItemKind::Const(_, body_id) => { if !self.symbol_is_live(impl_item.id, None) { self.warn_dead_code(impl_item.id, impl_item.span, impl_item.name, "associated const"); } - intravisit::walk_expr(self, expr) + self.visit_nested_body(body_id) } hir::ImplItemKind::Method(_, body_id) => { if !self.symbol_is_live(impl_item.id, None) { self.warn_dead_code(impl_item.id, impl_item.span, impl_item.name, "method"); } - self.visit_body(body_id) + self.visit_nested_body(body_id) } hir::ImplItemKind::Type(..) => {} } @@ -567,15 +572,13 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { // Overwrite so that we don't warn the trait item itself. fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { match trait_item.node { - hir::ConstTraitItem(_, Some(ref body)) => { - intravisit::walk_expr(self, body) - } - hir::MethodTraitItem(_, Some(body_id)) => { - self.visit_body(body_id) + hir::TraitItemKind::Const(_, Some(body_id)) | + hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => { + self.visit_nested_body(body_id) } - hir::ConstTraitItem(_, None) | - hir::MethodTraitItem(_, None) | - hir::TypeTraitItem(..) => {} + hir::TraitItemKind::Const(_, None) | + hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) | + hir::TraitItemKind::Type(..) => {} } } } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 2ec7aa4c4d903..38b0b18b0129a 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -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, - 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 { FnKind::ItemFn(_, _, unsafety, ..) => diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index e927843a984b8..f2e46d4cbc96b 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -17,7 +17,7 @@ use syntax::ast::NodeId; use syntax::attr; use syntax::entry::EntryPointType; use syntax_pos::Span; -use hir::{Item, ItemFn, ImplItem}; +use hir::{Item, ItemFn, ImplItem, TraitItem}; use hir::itemlikevisit::ItemLikeVisitor; struct EntryContext<'a, 'tcx: 'a> { @@ -47,6 +47,9 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { find_item(item, self, at_root); } + fn visit_trait_item(&mut self, _trait_item: &'tcx TraitItem) { + // entry fn is never a trait item + } fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem) { // entry fn is never an impl item diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index b3e61f1e57067..a3a49c916338e 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -287,20 +287,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } } - pub fn walk_fn(&mut self, - decl: &hir::FnDecl, - body: &hir::Expr) { - self.walk_arg_patterns(decl, body); - self.consume_expr(body); - } - - fn walk_arg_patterns(&mut self, - decl: &hir::FnDecl, - body: &hir::Expr) { - for arg in &decl.inputs { + pub fn consume_body(&mut self, body: &hir::Body) { + for arg in &body.arguments { let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id)); - let fn_body_scope_r = self.tcx().node_scope_region(body.id); + let fn_body_scope_r = self.tcx().node_scope_region(body.value.id); let arg_cmt = self.mc.cat_rvalue( arg.id, arg.pat.span, @@ -309,6 +300,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.walk_irrefutable_pat(arg_cmt, &arg.pat); } + + self.consume_expr(&body.value); } fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { @@ -537,9 +530,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(&count); } hir::ExprClosure(.., fn_decl_span) => { diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 2357549c82e08..d932061d42d3d 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -34,13 +34,13 @@ struct ItemVisitor<'a, 'tcx: 'a> { } 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); self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| { let mut visitor = ExprVisitor { 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]. - 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| { let mut visitor = ExprVisitor { infcx: &infcx }; - visitor.visit_expr(expr); + visitor.visit_body(body); }); } fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { - if let hir::ConstTraitItem(_, Some(ref expr)) = item.node { - self.visit_const(item.id, expr); + if let hir::TraitItemKind::Const(_, Some(body)) = item.node { + self.visit_const(item.id, body); } else { intravisit::walk_trait_item(self, item); } } fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { - if let hir::ImplItemKind::Const(_, ref expr) = item.node { - self.visit_const(item.id, expr); + if let hir::ImplItemKind::Const(_, body) = item.node { + self.visit_const(item.id, body); } else { intravisit::walk_impl_item(self, item); } } 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 { span_bug!(s, "intrinsicck: closure outside of function") } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 029a1d66add0b..4cae5b370eb7e 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -140,6 +140,10 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> { } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + // at present, lang items are always items, not trait items + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { // at present, lang items are always items, not impl items } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 445aed8f97d60..745a94a5ddba3 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -127,7 +127,6 @@ use syntax_pos::Span; use hir::Expr; use hir; -use hir::print::{expr_to_string, block_to_string}; use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; /// For use with `propagate_through_loop`. @@ -188,7 +187,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IrMaps<'a, 'tcx> { } 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); } fn visit_local(&mut self, l: &'tcx hir::Local) { visit_local(self, l); } @@ -354,13 +353,9 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, '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) { check_local(self, l); } @@ -375,7 +370,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl, - body_id: hir::ExprId, + body_id: hir::BodyId, sp: Span, id: ast::NodeId) { debug!("visit_fn"); @@ -385,7 +380,9 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, debug!("creating fn_maps: {:?}", &fn_maps as *const IrMaps); - for arg in &decl.inputs { + let body = ir.tcx.map.body(body_id); + + for arg in &body.arguments { arg.pat.each_binding(|_bm, arg_id, _x, path1| { debug!("adding argument {}", arg_id); let name = path1.node; @@ -408,16 +405,14 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, clean_exit_var: fn_maps.add_variable(CleanExit) }; - let body = ir.tcx.map.expr(body_id); - // compute liveness 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 - lsets.visit_expr(body); + lsets.visit_body(body); lsets.check_ret(id, sp, fk, entry_ln, body); - lsets.warn_about_unused_args(decl, entry_ln); + lsets.warn_about_unused_args(body, entry_ln); } fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) { @@ -823,7 +818,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // effectively a return---this only occurs in `for` loops, // where the body is really a closure. - debug!("compute: using id for body, {}", expr_to_string(body)); + debug!("compute: using id for body, {}", self.ir.tcx.map.node_to_pretty_string(body.id)); let exit_ln = self.s.exit_ln; let entry_ln: LiveNode = self.with_loop_nodes(body.id, exit_ln, exit_ln, |this| { @@ -916,7 +911,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode) -> LiveNode { - debug!("propagate_through_expr: {}", expr_to_string(expr)); + debug!("propagate_through_expr: {}", self.ir.tcx.map.node_to_pretty_string(expr.id)); match expr.node { // Interesting cases with control flow or which gen/kill @@ -935,14 +930,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprClosure(.., blk_id, _) => { debug!("{} is an ExprClosure", - expr_to_string(expr)); + self.ir.tcx.map.node_to_pretty_string(expr.id)); /* The next-node for a break is the successor of the entire loop. The next-node for a continue is the top of this loop. */ 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, // but we have to consider the closed over variables. @@ -1088,11 +1083,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { 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) => { let succ = self.propagate_through_opt_expr(with_expr.as_ref().map(|e| &**e), succ); fields.iter().rev().fold(succ, |succ, field| { @@ -1149,7 +1139,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprAddrOf(_, ref e) | hir::ExprCast(ref e, _) | hir::ExprType(ref e, _) | - hir::ExprUnary(_, ref e) => { + hir::ExprUnary(_, ref e) | + hir::ExprRepeat(ref e, _) => { self.propagate_through_expr(&e, succ) } @@ -1315,7 +1306,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } } debug!("propagate_through_loop: using id for loop body {} {}", - expr.id, block_to_string(body)); + expr.id, self.ir.tcx.map.node_to_pretty_string(body.id)); let cond_ln = match kind { LoopLoop => ln, @@ -1443,7 +1434,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { sp: Span, fk: FnKind, entry_ln: LiveNode, - body: &hir::Expr) + body: &hir::Body) { let fn_ty = if let FnKind::Closure(_) = fk { self.ir.tcx.tables().node_id_to_type(id) @@ -1460,7 +1451,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // and must outlive the *call-site* of the function. let fn_ret = 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); if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { @@ -1510,8 +1501,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } } - fn warn_about_unused_args(&self, decl: &hir::FnDecl, entry_ln: LiveNode) { - for arg in &decl.inputs { + fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) { + for arg in &body.arguments { arg.pat.each_binding(|_bm, p_id, sp, path1| { let var = self.variable(p_id, sp); // Ignore unused self. diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 4c3b102e54039..2d88567b8b873 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -73,7 +73,6 @@ use self::Aliasability::*; use hir::def_id::DefId; use hir::map as ast_map; use infer::InferCtxt; -use middle::const_qualif::ConstQualif; use hir::def::{Def, CtorKind}; use ty::adjustment; use ty::{self, Ty, TyCtxt}; @@ -705,7 +704,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { }; match fn_expr.node { - hir::ExprClosure(.., body_id, _) => body_id.node_id(), + hir::ExprClosure(.., body_id, _) => body_id.node_id, _ => bug!() } }; @@ -773,23 +772,23 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { span: Span, expr_ty: Ty<'tcx>) -> cmt<'tcx> { - let qualif = self.tcx().const_qualif_map.borrow().get(&id).cloned() - .unwrap_or(ConstQualif::NOT_CONST); + let promotable = self.tcx().rvalue_promotable_to_static.borrow().get(&id).cloned() + .unwrap_or(false); // Only promote `[T; 0]` before an RFC for rvalue promotions // is accepted. - let qualif = match expr_ty.sty { - ty::TyArray(_, 0) => qualif, - _ => ConstQualif::NOT_CONST + let promotable = match expr_ty.sty { + ty::TyArray(_, 0) => true, + _ => promotable & false }; // Compute maximum lifetime of this rvalue. This is 'static if // we can promote to a constant, otherwise equal to enclosing temp // lifetime. - let re = if qualif.intersects(ConstQualif::NON_STATIC_BORROWS) { - self.temporary_scope(id) - } else { + let re = if promotable { self.tcx().mk_region(ty::ReStatic) + } else { + self.temporary_scope(id) }; let ret = self.cat_rvalue(id, span, re, expr_ty); debug!("cat_rvalue_node ret {:?}", ret); diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 2c4710f1e452b..ee841afc02169 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -166,9 +166,10 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } Some(ast_map::NodeTraitItem(trait_method)) => { match trait_method.node { - hir::ConstTraitItem(_, ref default) => default.is_some(), - hir::MethodTraitItem(_, ref body) => body.is_some(), - hir::TypeTraitItem(..) => false, + hir::TraitItemKind::Const(_, ref default) => default.is_some(), + hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true, + hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) | + hir::TraitItemKind::Type(..) => false, } } Some(ast_map::NodeImplItem(impl_item)) => { @@ -250,15 +251,15 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { match item.node { hir::ItemFn(.., body) => { if item_might_be_inlined(&item) { - self.visit_body(body); + self.visit_nested_body(body); } } // Reachable constants will be inlined into other crates // unconditionally, so we need to make sure that their // contents are also reachable. - hir::ItemConst(_, ref init) => { - self.visit_expr(&init); + hir::ItemConst(_, init) => { + self.visit_nested_body(init); } // These are normal, nothing reachable about these @@ -274,28 +275,26 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } ast_map::NodeTraitItem(trait_method) => { match trait_method.node { - hir::ConstTraitItem(_, None) | - hir::MethodTraitItem(_, None) => { + hir::TraitItemKind::Const(_, None) | + hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => { // Keep going, nothing to get exported } - hir::ConstTraitItem(_, Some(ref body)) => { - self.visit_expr(body); + hir::TraitItemKind::Const(_, Some(body_id)) | + hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => { + self.visit_nested_body(body_id); } - hir::MethodTraitItem(_, Some(body_id)) => { - self.visit_body(body_id); - } - hir::TypeTraitItem(..) => {} + hir::TraitItemKind::Type(..) => {} } } ast_map::NodeImplItem(impl_item) => { match impl_item.node { - hir::ImplItemKind::Const(_, ref expr) => { - self.visit_expr(&expr); + hir::ImplItemKind::Const(_, body) => { + self.visit_nested_body(body); } hir::ImplItemKind::Method(ref sig, body) => { let did = self.tcx.map.get_parent_did(search_item); if method_might_be_inlined(self.tcx, sig, impl_item, did) { - self.visit_body(body) + self.visit_nested_body(body) } } hir::ImplItemKind::Type(_) => {} @@ -358,6 +357,8 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {} + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { // processed in visit_item above } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index b1e35e54eb9bb..faf4a448b7a84 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -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>, kind: FnKind<'tcx>, decl: &'tcx hir::FnDecl, - body_id: hir::ExprId, + body_id: hir::BodyId, sp: Span, id: ast::NodeId) { 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.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( - 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 { - 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_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. visitor.cx = Context { - root_id: Some(body_id.node_id()), + root_id: Some(body_id.node_id), parent: ROOT_CODE_EXTENT, 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. visitor.cx = Context { - root_id: Some(body_id.node_id()), + root_id: Some(body_id.node_id), 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. 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, - b: hir::ExprId, s: Span, n: NodeId) { + b: hir::BodyId, s: Span, n: NodeId) { resolve_fn(self, fk, fd, b, s, n); } fn visit_arm(&mut self, a: &'ast Arm) { diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index c5b03a4a32add..c491af972acbc 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -33,7 +33,6 @@ use util::nodemap::NodeMap; use rustc_data_structures::fx::FxHashSet; use hir; -use hir::print::lifetime_to_string; use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] @@ -190,7 +189,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // Items always introduce a new root scope self.with(RootScope, |_, this| { match item.node { - hir::ForeignItemFn(ref decl, ref generics) => { + hir::ForeignItemFn(ref decl, _, ref generics) => { this.visit_early_late(item.id, decl, generics, |this| { intravisit::walk_foreign_item(this, item); }) @@ -206,7 +205,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } 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 { FnKind::ItemFn(_, generics, ..) => { self.visit_early_late(fn_id,decl, generics, |this| { @@ -266,7 +265,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // methods in an impl can reuse label names. let saved = replace(&mut self.labels_in_fn, vec![]); - if let hir::MethodTraitItem(ref sig, None) = trait_item.node { + if let hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(_)) = + trait_item.node { self.visit_early_late( trait_item.id, &sig.decl, &sig.generics, @@ -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 // 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> { sess: &'a Session, scope: Scope<'a>, @@ -419,7 +419,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: hir::ExprId) { scope: ctxt.scope, 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; 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, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, - fb: hir::ExprId, + fb: hir::BodyId, _span: Span, fn_id: ast::NodeId) { match fk { @@ -522,8 +522,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // `self.labels_in_fn`. extract_labels(self, fb); - self.with(FnScope { fn_id: fn_id, body_id: fb.node_id(), s: self.scope }, - |_old_scope, this| this.visit_body(fb)) + self.with(FnScope { fn_id: fn_id, body_id: fb.node_id, s: self.scope }, + |_old_scope, this| this.visit_nested_body(fb)) } // FIXME(#37666) this works around a limitation in the region inferencer @@ -821,9 +821,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { probably a bug in syntax::fold"); } - debug!("lifetime_ref={:?} id={:?} resolved to {:?} span={:?}", - lifetime_to_string(lifetime_ref), - lifetime_ref.id, + debug!("{} resolved to {:?} span={:?}", + self.hir_map.node_to_string(lifetime_ref.id), def, self.sess.codemap().span_to_string(lifetime_ref.span)); self.map.defs.insert(lifetime_ref.id, def); @@ -860,8 +859,8 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap, debug!("insert_late_bound_lifetimes(decl={:?}, generics={:?})", decl, generics); let mut constrained_by_input = ConstrainedCollector { regions: FxHashSet() }; - for arg in &decl.inputs { - constrained_by_input.visit_ty(&arg.ty); + for arg_ty in &decl.inputs { + constrained_by_input.visit_ty(arg_ty); } let mut appears_in_output = AllCollector { diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs index 3576ae662a005..3c5a91f4ff04c 100644 --- a/src/librustc/mir/transform.rs +++ b/src/librustc/mir/transform.rs @@ -48,7 +48,7 @@ impl<'a, 'tcx> MirSource { match tcx.map.get(id) { map::NodeItem(&Item { node: ItemConst(..), .. }) | - map::NodeTraitItem(&TraitItem { node: ConstTraitItem(..), .. }) | + map::NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) | map::NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) => { MirSource::Const(id) } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index f24ff98035532..cb1fc15c5f682 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -508,14 +508,6 @@ pub struct GlobalCtxt<'tcx> { /// FIXME(arielb1): why is this separate from populated_external_types? pub populated_external_primitive_impls: RefCell, - /// Cache used by const_eval when decoding external constants. - /// Contains `None` when the constant has been fetched but doesn't exist. - /// Constains `Some(expr_id, type)` otherwise. - /// `type` is `None` in case it's not a primitive type - pub extern_const_statics: RefCell>)>>>, - /// Cache used by const_eval when decoding extern const fns - pub extern_const_fns: RefCell>, - /// Maps any item's def-id to its stability index. pub stability: RefCell>, @@ -537,8 +529,8 @@ pub struct GlobalCtxt<'tcx> { /// Caches the representation hints for struct definitions. repr_hint_cache: RefCell>>, - /// Maps Expr NodeId's to their constant qualification. - pub const_qualif_map: RefCell>, + /// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime. + pub rvalue_promotable_to_static: RefCell>, /// Caches CoerceUnsized kinds for impls on custom types. pub custom_coerce_unsized_kinds: RefCell>, @@ -787,13 +779,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { used_trait_imports: RefCell::new(NodeSet()), populated_external_types: RefCell::new(DefIdSet()), populated_external_primitive_impls: RefCell::new(DefIdSet()), - extern_const_statics: RefCell::new(DefIdMap()), - extern_const_fns: RefCell::new(DefIdMap()), stability: RefCell::new(stability), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), repr_hint_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - const_qualif_map: RefCell::new(NodeMap()), + rvalue_promotable_to_static: RefCell::new(NodeMap()), custom_coerce_unsized_kinds: RefCell::new(DefIdMap()), cast_kinds: RefCell::new(NodeMap()), fragment_infos: RefCell::new(DefIdMap()), diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2ab10d0446b2a..b03a432de4131 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1206,13 +1206,13 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { tcx.construct_parameter_environment( impl_item.span, 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)) } } } Some(ast_map::NodeTraitItem(trait_item)) => { match trait_item.node { - hir::TypeTraitItem(..) | hir::ConstTraitItem(..) => { + hir::TraitItemKind::Type(..) | hir::TraitItemKind::Const(..) => { // associated types don't have their own entry (for some reason), // so for now just grab environment for the trait let trait_id = tcx.map.get_parent(id); @@ -1221,13 +1221,13 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { trait_def_id, tcx.region_maps.item_extent(id)) } - hir::MethodTraitItem(_, ref body) => { + hir::TraitItemKind::Method(_, ref body) => { // Use call-site for extent (unless this is a // trait method with no default; then fallback // to the method id). - let extent = if let Some(body_id) = *body { + let extent = if let hir::TraitMethod::Provided(body_id) = *body { // 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 { // no default impl: use item extent as free_id_outlive bound. tcx.region_maps.item_extent(id) @@ -1248,7 +1248,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { tcx.construct_parameter_environment( item.span, 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::ItemStruct(..) | @@ -1284,7 +1284,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { tcx.construct_parameter_environment( expr.span, base_def_id, - tcx.region_maps.call_site_extent(id, body.node_id())) + tcx.region_maps.call_site_extent(id, body.node_id)) } else { tcx.empty_parameter_environment() } @@ -2100,10 +2100,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - hir::ItemTrait(.., ref trait_items) => { - for trait_item in trait_items { + hir::ItemTrait(.., ref trait_item_refs) => { + for trait_item_ref in trait_item_refs { let assoc_item = - self.associated_item_from_trait_item_ref(parent_def_id, trait_item); + self.associated_item_from_trait_item_ref(parent_def_id, trait_item_ref); self.associated_items.borrow_mut().insert(assoc_item.def_id, assoc_item); } } @@ -2121,28 +2121,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { fn associated_item_from_trait_item_ref(self, parent_def_id: DefId, - trait_item: &hir::TraitItem) + trait_item_ref: &hir::TraitItemRef) -> AssociatedItem { - let def_id = self.map.local_def_id(trait_item.id); - - let (kind, has_self, has_value) = match trait_item.node { - hir::MethodTraitItem(ref sig, ref body) => { - (AssociatedKind::Method, sig.decl.get_self().is_some(), - body.is_some()) - } - hir::ConstTraitItem(_, ref value) => { - (AssociatedKind::Const, false, value.is_some()) - } - hir::TypeTraitItem(_, ref ty) => { - (AssociatedKind::Type, false, ty.is_some()) + let def_id = self.map.local_def_id(trait_item_ref.id.node_id); + let (kind, has_self) = match trait_item_ref.kind { + hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false), + hir::AssociatedItemKind::Method { has_self } => { + (ty::AssociatedKind::Method, has_self) } + hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false), }; AssociatedItem { - name: trait_item.name, + name: trait_item_ref.name, kind: kind, - vis: Visibility::from_hir(&hir::Inherited, trait_item.id, self), - defaultness: hir::Defaultness::Default { has_value: has_value }, + vis: Visibility::from_hir(&hir::Inherited, trait_item_ref.id.node_id, self), + defaultness: trait_item_ref.defaultness, def_id: def_id, container: TraitContainer(parent_def_id), method_has_self_argument: has_self @@ -2187,11 +2181,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let id = self.map.as_local_node_id(def_id).unwrap(); let item = self.map.expect_item(id); let vec: Vec<_> = match item.node { - hir::ItemTrait(.., ref trait_items) => { - trait_items.iter() - .map(|trait_item| trait_item.id) - .map(|id| self.map.local_def_id(id)) - .collect() + hir::ItemTrait(.., ref trait_item_refs) => { + trait_item_refs.iter() + .map(|trait_item_ref| trait_item_ref.id) + .map(|id| self.map.local_def_id(id.node_id)) + .collect() } hir::ItemImpl(.., ref impl_item_refs) => { impl_item_refs.iter() diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 5ed628d7dcae5..dc2214dd34e72 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -189,9 +189,8 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &move_data::FlowedMoveData<'c, 'tcx>, all_loans: &[Loan<'tcx>], fn_id: ast::NodeId, - decl: &hir::FnDecl, - body: &hir::Expr) { - debug!("check_loans(body id={})", body.id); + body: &hir::Body) { + debug!("check_loans(body id={})", body.value.id); let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env); @@ -202,7 +201,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, all_loans: all_loans, param_env: &infcx.parameter_environment }; - euv::ExprUseVisitor::new(&mut clcx, &infcx).walk_fn(decl, body); + euv::ExprUseVisitor::new(&mut clcx, &infcx).consume_body(body); } #[derive(PartialEq)] diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 5d59b58b847d9..34f1ad57c6211 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -41,21 +41,20 @@ mod move_error; pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, fn_id: NodeId, - decl: &hir::FnDecl, - body: &hir::Expr) + body: &hir::Body) -> (Vec>, move_data::MoveData<'tcx>) { let mut glcx = GatherLoanCtxt { bccx: bccx, 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_error_collector: move_error::MoveErrorCollector::new(), }; let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env); - euv::ExprUseVisitor::new(&mut glcx, &infcx).walk_fn(decl, body); + euv::ExprUseVisitor::new(&mut glcx, &infcx).consume_body(body); glcx.report_potential_errors(); let GatherLoanCtxt { all_loans, move_data, .. } = glcx; @@ -548,14 +547,14 @@ impl<'a, 'tcx> Visitor<'tcx> for StaticInitializerCtxt<'a, 'tcx> { pub fn gather_loans_in_static_initializer<'a, 'tcx>(bccx: &mut BorrowckCtxt<'a, 'tcx>, 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 { bccx: bccx, item_id: item_id }; - sicx.visit_expr(expr); + sicx.visit_nested_body(body); } diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index 9035c2ab3c236..c3ff564121c56 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -11,10 +11,7 @@ use borrowck::BorrowckCtxt; use syntax::ast::{self, MetaItem}; -use syntax_pos::{Span, DUMMY_SP}; - -use rustc::hir; -use rustc::hir::intravisit::{FnKind}; +use syntax_pos::DUMMY_SP; use rustc::mir::{self, BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location}; use rustc::session::Session; @@ -55,27 +52,14 @@ pub struct MoveDataParamEnv<'tcx> { } pub fn borrowck_mir(bcx: &mut BorrowckCtxt, - fk: FnKind, - _decl: &hir::FnDecl, - body: &hir::Expr, - _sp: Span, id: ast::NodeId, 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 param_env = ty::ParameterEnvironment::for_item(tcx, id); - - let mir = &tcx.item_mir(tcx.map.local_def_id(id)); + 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 move_data = MoveData::gather_moves(mir, tcx, ¶m_env); let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; let flow_inits = diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index ecf5c3ef176e5..1ba313015d596 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -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, - b: hir::ExprId, s: Span, id: ast::NodeId) { + b: hir::BodyId, s: Span, id: ast::NodeId) { match fk { FnKind::ItemFn(..) | 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) { - if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node { - gather_loans::gather_loans_in_static_initializer(self, ti.id, &expr); + if let hir::TraitItemKind::Const(_, Some(expr)) = ti.node { + gather_loans::gather_loans_in_static_initializer(self, ti.id, expr); } intravisit::walk_trait_item(self, ti); } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { - if let hir::ImplItemKind::Const(_, ref expr) = ii.node { - gather_loans::gather_loans_in_static_initializer(self, ii.id, &expr); + if let hir::ImplItemKind::Const(_, expr) = ii.node { + gather_loans::gather_loans_in_static_initializer(self, ii.id, expr); } 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 // flow dependent conditions. match item.node { - hir::ItemStatic(.., ref ex) | - hir::ItemConst(_, ref ex) => { - gather_loans::gather_loans_in_static_initializer(this, item.id, &ex); + hir::ItemStatic(.., ex) | + hir::ItemConst(_, ex) => { + gather_loans::gather_loans_in_static_initializer(this, item.id, ex); } _ => { } } @@ -161,25 +161,25 @@ pub struct AnalysisData<'a, 'tcx: 'a> { fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl, - body_id: hir::ExprId, + body_id: hir::BodyId, sp: Span, id: ast::NodeId, attributes: &[ast::Attribute]) { 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")) { 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, loans: loan_dfcx, move_data: flowed_moves } = - build_borrowck_dataflow_data(this, fk, decl, &cfg, body, sp, id); + build_borrowck_dataflow_data(this, &cfg, body, id); move_data::fragments::instrument_move_fragments(&flowed_moves.move_data, this.tcx, @@ -194,31 +194,31 @@ fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, &flowed_moves, &all_loans[..], id, - decl, body); intravisit::walk_fn(this, fk, decl, body_id, sp, id); } fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, - fk: FnKind<'tcx>, - decl: &'tcx hir::FnDecl, cfg: &cfg::CFG, - body: &'tcx hir::Expr, - sp: Span, + body: &'tcx hir::Body, id: ast::NodeId) -> AnalysisData<'a, 'tcx> { // Check the body of fn items. let tcx = this.tcx; - let id_range = intravisit::compute_id_range_for_fn_body(fk, decl, body, sp, id, &tcx.map); + let id_range = { + let mut visitor = intravisit::IdRangeComputingVisitor::new(&tcx.map); + visitor.visit_body(body); + visitor.result() + }; let (all_loans, move_data) = - gather_loans::gather_loans_in_fn(this, id, decl, body); + gather_loans::gather_loans_in_fn(this, id, body); let mut loan_dfcx = DataFlowContext::new(this.tcx, "borrowck", - Some(decl), + Some(body), cfg, LoanDataFlowOperator, id_range, @@ -235,7 +235,6 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, this.tcx, cfg, id_range, - decl, body); AnalysisData { all_loans: all_loans, @@ -263,14 +262,11 @@ 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, - fn_parts.kind, - &fn_parts.decl, cfg, body, - fn_parts.span, fn_parts.id); (bccx, dataflow_data) @@ -416,7 +412,7 @@ pub fn closure_to_block(closure_id: ast::NodeId, match tcx.map.get(closure_id) { hir_map::NodeExpr(expr) => match expr.node { hir::ExprClosure(.., body_id, _) => { - body_id.node_id() + body_id.node_id } _ => { bug!("encountered non-closure id: {}", closure_id) @@ -1121,22 +1117,21 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { if let Categorization::Deref(ref inner_cmt, ..) = err.cmt.cat { if let Categorization::Local(local_id) = inner_cmt.cat { let parent = self.tcx.map.get_parent_node(local_id); - let opt_fn_decl = FnLikeNode::from_node(self.tcx.map.get(parent)) - .map(|fn_like| fn_like.decl()); - if let Some(fn_decl) = opt_fn_decl { - if let Some(ref arg) = fn_decl.inputs.iter() - .find(|ref arg| arg.pat.id == local_id) { + if let Some(fn_like) = FnLikeNode::from_node(self.tcx.map.get(parent)) { + if let Some(i) = self.tcx.map.body(fn_like.body()).arguments.iter() + .position(|arg| arg.pat.id == local_id) { + let arg_ty = &fn_like.decl().inputs[i]; if let hir::TyRptr( opt_lifetime, hir::MutTy{mutbl: hir::Mutability::MutImmutable, ref ty}) = - arg.ty.node { + arg_ty.node { if let Some(lifetime) = opt_lifetime { if let Ok(snippet) = self.tcx.sess.codemap() .span_to_snippet(ty.span) { if let Ok(lifetime_snippet) = self.tcx.sess.codemap() .span_to_snippet(lifetime.span) { - db.span_label(arg.ty.span, + db.span_label(arg_ty.span, &format!("use `&{} mut {}` \ here to make mutable", lifetime_snippet, @@ -1145,9 +1140,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } } else if let Ok(snippet) = self.tcx.sess.codemap() - .span_to_snippet(arg.ty.span) { + .span_to_snippet(arg_ty.span) { if snippet.starts_with("&") { - db.span_label(arg.ty.span, + db.span_label(arg_ty.span, &format!("use `{}` here to make mutable", snippet.replace("&", "&mut "))); } diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index 32bda5e11620a..a02aba7208c7f 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -655,13 +655,12 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { tcx: TyCtxt<'a, 'tcx, 'tcx>, cfg: &cfg::CFG, id_range: IdRange, - decl: &hir::FnDecl, - body: &hir::Expr) + body: &hir::Body) -> FlowedMoveData<'a, 'tcx> { let mut dfcx_moves = DataFlowContext::new(tcx, "flowed_move_data_moves", - Some(decl), + Some(body), cfg, MoveDataFlowOperator, id_range, @@ -669,7 +668,7 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { let mut dfcx_assign = DataFlowContext::new(tcx, "flowed_move_data_assigns", - Some(decl), + Some(body), cfg, AssignDataFlowOperator, id_range, diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 786b59e818da2..01b19e1f53979 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -30,7 +30,6 @@ use rustc_errors::DiagnosticBuilder; use rustc::hir::def::*; use rustc::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; -use rustc::hir::print::pat_to_string; use rustc::hir::{self, Pat, PatKind}; use rustc_back::slice; @@ -43,39 +42,17 @@ struct OuterVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - - fn visit_expr(&mut self, _expr: &'tcx hir::Expr) { - return // const, static and N in [T; N] - shouldn't contain anything - } - - fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { - if let hir::ConstTraitItem(..) = item.node { - return // nothing worth match checking in a constant - } else { - intravisit::walk_trait_item(self, item); - } - } - - fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { - if let hir::ImplItemKind::Const(..) = item.node { - return // nothing worth match checking in a constant - } else { - intravisit::walk_impl_item(self, item); - } + NestedVisitorMap::OnlyBodies(&self.tcx.map) } fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, - b: hir::ExprId, s: Span, id: ast::NodeId) { - if let FnKind::Closure(..) = fk { - span_bug!(s, "check_match: closure outside of function") - } + b: hir::BodyId, s: Span, id: ast::NodeId) { + intravisit::walk_fn(self, fk, fd, b, s, id); MatchVisitor { tcx: self.tcx, param_env: &ty::ParameterEnvironment::for_item(self.tcx, id) - }.visit_fn(fk, fd, b, s, id); + }.visit_body(self.tcx.map.body(b)); } } @@ -96,7 +73,7 @@ struct MatchVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None } fn visit_expr(&mut self, ex: &'tcx hir::Expr) { @@ -119,13 +96,12 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { self.check_patterns(false, slice::ref_slice(&loc.pat)); } - fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, - b: hir::ExprId, s: Span, n: ast::NodeId) { - intravisit::walk_fn(self, fk, fd, b, s, n); + fn visit_body(&mut self, body: &'tcx hir::Body) { + intravisit::walk_body(self, body); - for input in &fd.inputs { - self.check_irrefutable(&input.pat, true); - self.check_patterns(false, slice::ref_slice(&input.pat)); + for arg in &body.arguments { + self.check_irrefutable(&arg.pat, true); + self.check_patterns(false, slice::ref_slice(&arg.pat)); } } } @@ -254,7 +230,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { Useful => bug!() }; - let pattern_string = pat_to_string(witness[0].single_pattern()); + let pattern_string = hir::print::to_string(&self.tcx.map, |s| { + s.print_pat(witness[0].single_pattern()) + }); let mut diag = struct_span_err!( self.tcx.sess, pat.span, E0005, "refutable pattern in {}: `{}` not covered", @@ -405,7 +383,9 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, }, _ => bug!(), }; - let pattern_string = pat_to_string(witness); + let pattern_string = hir::print::to_string(&cx.tcx.map, |s| { + s.print_pat(witness) + }); struct_span_err!(cx.tcx.sess, sp, E0297, "refutable pattern in `for` loop binding: \ `{}` not covered", @@ -415,7 +395,7 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, }, _ => { let pattern_strings: Vec<_> = witnesses.iter().map(|w| { - pat_to_string(w) + hir::print::to_string(&cx.tcx.map, |s| s.print_pat(w)) }).collect(); const LIMIT: usize = 3; let joined_patterns = match pattern_strings.len() { diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs index 83b0d9dec6d90..b24cd261dd584 100644 --- a/src/librustc_const_eval/diagnostics.rs +++ b/src/librustc_const_eval/diagnostics.rs @@ -576,18 +576,18 @@ https://doc.rust-lang.org/reference.html#ffi-attributes 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: ```compile_fail,E0306 -let x = [0i32; true]; // error: expected positive integer for repeat count, - // found boolean +const X: [i32; true] = [0]; // error: expected `usize` for array length, + // found boolean ``` Working example: ``` -let x = [0i32; 2]; +const X: [i32; 1] = [0]; ``` "##, } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 9fcab1239899f..e8e7a2eb7ede0 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -17,7 +17,6 @@ use self::EvalHint::*; use rustc::hir::map as ast_map; use rustc::hir::map::blocks::FnLikeNode; -use rustc::middle::cstore::InlinedItem; use rustc::traits; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::DefId; @@ -56,15 +55,17 @@ macro_rules! math { fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, variant_def: DefId) -> Option<&'tcx Expr> { - fn variant_expr<'a>(variants: &'a [hir::Variant], id: ast::NodeId) - -> Option<&'a Expr> { + let variant_expr = |variants: &'tcx [hir::Variant], id: ast::NodeId | + -> Option<&'tcx Expr> { for variant in variants { 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 - } + }; 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); @@ -96,21 +97,24 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match tcx.map.find(node_id) { None => None, Some(ast_map::NodeItem(it)) => match it.node { - hir::ItemConst(ref ty, ref const_expr) => { - Some((&const_expr, tcx.ast_ty_to_prim_ty(ty))) + hir::ItemConst(ref ty, body) => { + Some((&tcx.map.body(body).value, + tcx.ast_ty_to_prim_ty(ty))) } _ => None }, Some(ast_map::NodeTraitItem(ti)) => match ti.node { - hir::ConstTraitItem(ref ty, ref expr_option) => { + hir::TraitItemKind::Const(ref ty, default) => { if let Some(substs) = substs { // If we have a trait item and the substitutions for it, // `resolve_trait_associated_const` will select an impl // or the default. let trait_id = tcx.map.get_parent(node_id); let trait_id = tcx.map.local_def_id(trait_id); - let default_value = expr_option.as_ref() - .map(|expr| (&**expr, tcx.ast_ty_to_prim_ty(ty))); + let default_value = default.map(|body| { + (&tcx.map.body(body).value, + tcx.ast_ty_to_prim_ty(ty)) + }); resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs) } else { // Technically, without knowing anything about the @@ -125,29 +129,19 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => None }, Some(ast_map::NodeImplItem(ii)) => match ii.node { - hir::ImplItemKind::Const(ref ty, ref expr) => { - Some((&expr, tcx.ast_ty_to_prim_ty(ty))) + hir::ImplItemKind::Const(ref ty, body) => { + Some((&tcx.map.body(body).value, + tcx.ast_ty_to_prim_ty(ty))) } _ => None }, Some(_) => None } } else { - match tcx.extern_const_statics.borrow().get(&def_id) { - Some(&None) => return None, - Some(&Some((expr_id, ty))) => { - return Some((tcx.map.expect_expr(expr_id), ty)); - } - None => {} - } - let mut used_substs = false; - let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) { - Some((&InlinedItem { body: ref const_expr, .. }, _)) => { - Some((&**const_expr, Some(tcx.sess.cstore.item_type(tcx, def_id)))) - } - _ => None - }; - let expr_ty = match tcx.sess.cstore.describe_def(def_id) { + let expr_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { + (&body.value, Some(tcx.sess.cstore.item_type(tcx, def_id))) + }); + match tcx.sess.cstore.describe_def(def_id) { Some(Def::AssociatedConst(_)) => { let trait_id = tcx.sess.cstore.trait_of_item(def_id); // As mentioned in the comments above for in-crate @@ -155,8 +149,6 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // trait-associated const if the caller gives us the // substitutions for the reference to it. if let Some(trait_id) = trait_id { - used_substs = true; - if let Some(substs) = substs { resolve_trait_associated_const(tcx, def_id, expr_ty, trait_id, substs) } else { @@ -168,70 +160,27 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }, Some(Def::Const(..)) => expr_ty, _ => None - }; - // If we used the substitutions, particularly to choose an impl - // of a trait-associated const, don't cache that, because the next - // lookup with the same def_id may yield a different result. - if !used_substs { - tcx.extern_const_statics - .borrow_mut() - .insert(def_id, expr_ty.map(|(e, t)| (e.id, t))); } - expr_ty } } -fn inline_const_fn_from_external_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> Option { - match tcx.extern_const_fns.borrow().get(&def_id) { - Some(&ast::DUMMY_NODE_ID) => return None, - Some(&fn_id) => return Some(fn_id), - None => {} - } - - if !tcx.sess.cstore.is_const_fn(def_id) { - tcx.extern_const_fns.borrow_mut().insert(def_id, ast::DUMMY_NODE_ID); - return None; - } - - let fn_id = tcx.sess.cstore.maybe_get_item_ast(tcx, def_id).map(|t| t.1); - tcx.extern_const_fns.borrow_mut().insert(def_id, - fn_id.unwrap_or(ast::DUMMY_NODE_ID)); - fn_id -} - -pub enum ConstFnNode<'tcx> { - Local(FnLikeNode<'tcx>), - Inlined(&'tcx InlinedItem) -} - -pub fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Option> +fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) + -> Option<&'tcx hir::Body> { - let fn_id = if let Some(node_id) = tcx.map.as_local_node_id(def_id) { - node_id - } else { - if let Some(fn_id) = inline_const_fn_from_external_crate(tcx, def_id) { - if let ast_map::NodeInlinedItem(ii) = tcx.map.get(fn_id) { - return Some(ConstFnNode::Inlined(ii)); + if let Some(node_id) = tcx.map.as_local_node_id(def_id) { + FnLikeNode::from_node(tcx.map.get(node_id)).and_then(|fn_like| { + if fn_like.constness() == hir::Constness::Const { + Some(tcx.map.body(fn_like.body())) } else { - bug!("Got const fn from external crate, but it's not inlined") + None } + }) + } else { + if tcx.sess.cstore.is_const_fn(def_id) { + tcx.sess.cstore.maybe_get_item_body(tcx, def_id) } else { - return None; + None } - }; - - let fn_like = match FnLikeNode::from_node(tcx.map.get(fn_id)) { - Some(fn_like) => fn_like, - None => return None - }; - - if fn_like.constness() == hir::Constness::Const { - Some(ConstFnNode::Local(fn_like)) - } else { - None } } @@ -864,18 +813,15 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Struct(_) => signal!(e, UnimplementedConstVal("tuple struct constructors")), callee => signal!(e, CallOn(callee)), }; - let (arg_defs, body_id) = match lookup_const_fn_by_id(tcx, did) { - Some(ConstFnNode::Inlined(ii)) => (ii.const_fn_args.clone(), ii.body.expr_id()), - Some(ConstFnNode::Local(fn_like)) => - (fn_like.decl().inputs.iter() - .map(|arg| match arg.pat.node { - hir::PatKind::Binding(_, def_id, _, _) => Some(def_id), - _ => None - }).collect(), - fn_like.body()), + let body = match lookup_const_fn_by_id(tcx, did) { + Some(body) => body, None => signal!(e, NonConstPath), }; - let result = tcx.map.expr(body_id); + + let arg_defs = body.arguments.iter().map(|arg| match arg.pat.node { + hir::PatKind::Binding(_, def_id, _, _) => Some(def_id), + _ => None + }).collect::>(); assert_eq!(arg_defs.len(), args.len()); let mut call_args = DefIdMap(); @@ -893,7 +839,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } debug!("const call({:?})", call_args); - eval_const_expr_partial(tcx, &result, ty_hint, Some(&call_args))? + eval_const_expr_partial(tcx, &body.value, ty_hint, Some(&call_args))? }, hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety) { Ok(val) => val, @@ -953,11 +899,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::ExprRepeat(_, ref n) => { + hir::ExprRepeat(_, n) => { let len_hint = ty_hint.checked_or(tcx.types.usize); + let n = &tcx.map.body(n).value; Repeat( 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(_) => signal!(e, RepeatCountNotNatural), _ => signal!(e, RepeatCountNotInt), @@ -1373,7 +1320,8 @@ pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node { if let Def::Local(..) = path.def { - diag.note(&format!("`{}` is a variable", path)); + diag.note(&format!("`{}` is a variable", + tcx.map.node_to_pretty_string(count_expr.id))); } } diff --git a/src/librustc_driver/derive_registrar.rs b/src/librustc_driver/derive_registrar.rs index 4db620b2bec3b..6a884bafce752 100644 --- a/src/librustc_driver/derive_registrar.rs +++ b/src/librustc_driver/derive_registrar.rs @@ -35,6 +35,9 @@ impl<'v> ItemLikeVisitor<'v> for Finder { } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { } } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 74df1e52bde43..5103a55fd71e1 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -47,7 +47,7 @@ use std::path::Path; use std::str::FromStr; use rustc::hir::map as hir_map; -use rustc::hir::map::{blocks, NodePrinter}; +use rustc::hir::map::blocks; use rustc::hir; use rustc::hir::print as pprust_hir; @@ -320,7 +320,16 @@ impl<'ast> HirPrinterSupport<'ast> for NoAnn<'ast> { } impl<'ast> pprust::PpAnn for NoAnn<'ast> {} -impl<'ast> pprust_hir::PpAnn for NoAnn<'ast> {} +impl<'ast> pprust_hir::PpAnn for NoAnn<'ast> { + fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested) + -> io::Result<()> { + if let Some(ref map) = self.ast_map { + pprust_hir::PpAnn::nested(map, state, nested) + } else { + Ok(()) + } + } +} struct IdentifiedAnnotation<'ast> { sess: &'ast Session, @@ -393,6 +402,14 @@ impl<'ast> HirPrinterSupport<'ast> for IdentifiedAnnotation<'ast> { } impl<'ast> pprust_hir::PpAnn for IdentifiedAnnotation<'ast> { + fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested) + -> io::Result<()> { + if let Some(ref map) = self.ast_map { + pprust_hir::PpAnn::nested(map, state, nested) + } else { + Ok(()) + } + } fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { pprust_hir::NodeExpr(_) => s.popen(), @@ -488,6 +505,10 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { } impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { + fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested) + -> io::Result<()> { + pprust_hir::PpAnn::nested(&self.tcx.map, state, nested) + } fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { pprust_hir::NodeExpr(_) => s.popen(), @@ -702,8 +723,8 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, let cfg = match code { blocks::Code::Expr(expr) => cfg::CFG::new(tcx, expr), blocks::Code::FnLike(fn_like) => { - let body = tcx.map.expr(fn_like.body()); - cfg::CFG::new(tcx, body) + let body = tcx.map.body(fn_like.body()); + cfg::CFG::new(tcx, &body.value) }, }; let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges; @@ -909,11 +930,10 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, &mut rdr, box out, annotation.pp_ann(), - true, - Some(ast_map.krate())); + true); for node_id in uii.all_matching_node_ids(ast_map) { let node = ast_map.get(node_id); - pp_state.print_node(&node)?; + pp_state.print_node(node)?; pp::space(&mut pp_state.s)?; let path = annotation.node_path(node_id) .expect("--unpretty missing node paths"); diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 87e6b2befdc32..b5fe158f158ca 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -171,6 +171,10 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for IfThisChanged<'a, 'tcx> { self.process_attrs(item.id, &item.attrs); } + fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { + self.process_attrs(trait_item.id, &trait_item.attrs); + } + fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { self.process_attrs(impl_item.id, &impl_item.attrs); } diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs index 74707865dee4d..49609fbc7984f 100644 --- a/src/librustc_incremental/calculate_svh/mod.rs +++ b/src/librustc_incremental/calculate_svh/mod.rs @@ -234,6 +234,11 @@ impl<'a, 'tcx> Visitor<'tcx> for HashItemsVisitor<'a, 'tcx> { visit::walk_item(self, item); } + fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { + self.calculate_node_id(trait_item.id, |v| v.visit_trait_item(trait_item)); + visit::walk_trait_item(self, trait_item); + } + fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { self.calculate_node_id(impl_item.id, |v| v.visit_impl_item(impl_item)); visit::walk_impl_item(self, impl_item); diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index bb61756694fe5..4bb12667bbc14 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -188,7 +188,7 @@ enum SawAbiComponent<'a> { SawTraitItem(SawTraitOrImplItemComponent), SawImplItem(SawTraitOrImplItemComponent), SawStructField, - SawVariant, + SawVariant(bool), SawQPath, SawPathSegment, SawPathParameters, @@ -473,12 +473,14 @@ enum SawTraitOrImplItemComponent { SawTraitOrImplItemType } -fn saw_trait_item(ti: &TraitItem_) -> SawTraitOrImplItemComponent { +fn saw_trait_item(ti: &TraitItemKind) -> SawTraitOrImplItemComponent { match *ti { - ConstTraitItem(..) => SawTraitOrImplItemConst, - MethodTraitItem(ref sig, ref body) => - SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, body.is_some()), - TypeTraitItem(..) => SawTraitOrImplItemType + TraitItemKind::Const(..) => SawTraitOrImplItemConst, + TraitItemKind::Method(ref sig, TraitMethod::Required(_)) => + SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, false), + TraitItemKind::Method(ref sig, TraitMethod::Provided(_)) => + SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, true), + TraitItemKind::Type(..) => SawTraitOrImplItemType } } @@ -584,7 +586,7 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has g: &'tcx Generics, item_id: NodeId) { 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); visit::walk_variant(self, v, g, item_id) } @@ -616,7 +618,12 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has // implicitly hashing the discriminant of SawExprComponent. hash_span!(self, ex.span, force_span); 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) { @@ -686,7 +693,12 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has debug!("visit_ty: st={:?}", self.st); SawTy(saw_ty(&t.node)).hash(self.st); 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) { @@ -1157,8 +1169,9 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> { // These fields are handled separately: exported_macros: _, items: _, + trait_items: _, impl_items: _, - exprs: _, + bodies: _, } = *krate; visit::Visitor::visit_mod(self, module, span, ast::CRATE_NODE_ID); diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 40873011a7b8d..481462dff86e4 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -185,6 +185,9 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'a, 'tcx> { } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { } } @@ -229,6 +232,9 @@ impl<'a, 'tcx, 'm> ItemLikeVisitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { } } diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index 1d384741d9660..2baef47c214c2 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -243,7 +243,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { cx: &LateContext, fk: FnKind, _: &hir::FnDecl, - _: &hir::Expr, + _: &hir::Body, span: Span, id: ast::NodeId) { match fk { @@ -271,12 +271,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } } - fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) { - if let hir::MethodTraitItem(_, None) = trait_item.node { + fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) { + if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(ref names)) = item.node { self.check_snake_case(cx, "trait method", - &trait_item.name.as_str(), - Some(trait_item.span)); + &item.name.as_str(), + Some(item.span)); + for name in names { + self.check_snake_case(cx, "variable", &name.node.as_str(), Some(name.span)); + } } } @@ -288,14 +291,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) { - // Exclude parameter names from foreign functions - let parent_node = cx.tcx.map.get_parent_node(p.id); - if let hir::map::NodeForeignItem(item) = cx.tcx.map.get(parent_node) { - if let hir::ForeignItemFn(..) = item.node { - return; - } - } - if let &PatKind::Binding(_, _, ref path1, _) = &p.node { self.check_snake_case(cx, "variable", &path1.node.as_str(), Some(p.span)); } @@ -363,7 +358,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals { fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) { match ti.node { - hir::ConstTraitItem(..) => { + hir::TraitItemKind::Const(..) => { NonUpperCaseGlobals::check_upper_case(cx, "associated constant", ti.name, ti.span); } _ => {} diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index cd414846af4fb..c021ffee81899 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -222,7 +222,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode { cx: &LateContext, fk: FnKind<'tcx>, _: &hir::FnDecl, - _: &hir::Expr, + _: &hir::Body, span: Span, _: ast::NodeId) { match fk { @@ -240,11 +240,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode { } } - fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) { - if let hir::MethodTraitItem(ref sig, None) = trait_item.node { + fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) { + if let hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(_)) = item.node { if sig.unsafety == hir::Unsafety::Unsafe { cx.span_lint(UNSAFE_CODE, - trait_item.span, + item.span, "declaration of an `unsafe` method") } } @@ -374,12 +374,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ItemEnum(..) => "an enum", hir::ItemStruct(..) => "a struct", hir::ItemUnion(..) => "a union", - hir::ItemTrait(.., ref items) => { + hir::ItemTrait(.., ref trait_item_refs) => { // Issue #11592, traits are always considered exported, even when private. if it.vis == hir::Visibility::Inherited { self.private_traits.insert(it.id); - for itm in items { - self.private_traits.insert(itm.id); + for trait_item_ref in trait_item_refs { + self.private_traits.insert(trait_item_ref.id.node_id); } return; } @@ -418,9 +418,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } let desc = match trait_item.node { - hir::ConstTraitItem(..) => "an associated constant", - hir::MethodTraitItem(..) => "a trait method", - hir::TypeTraitItem(..) => "an associated type", + hir::TraitItemKind::Const(..) => "an associated constant", + hir::TraitItemKind::Method(..) => "a trait method", + hir::TraitItemKind::Type(..) => "an associated type", }; self.check_missing_docs_attrs(cx, @@ -674,7 +674,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { cx: &LateContext, fn_kind: FnKind, _: &hir::FnDecl, - blk: &hir::Expr, + body: &hir::Body, sp: Span, id: ast::NodeId) { 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 // 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 reached_exit_without_self_call = false; diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 751c9c3440f66..a3aa4af493aaf 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -679,7 +679,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let sig = self.cx.tcx.erase_late_bound_regions(&sig); for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) { - self.check_type_for_ffi_and_report_errors(input_hir.ty.span, input_ty); + self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty); } if let hir::Return(ref ret_hir) = decl.output { @@ -713,7 +713,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes { if nmod.abi != Abi::RustIntrinsic && nmod.abi != Abi::PlatformIntrinsic { for ni in &nmod.items { match ni.node { - hir::ForeignItemFn(ref decl, _) => { + hir::ForeignItemFn(ref decl, _, _) => { vis.check_foreign_fn(ni.id, decl); } hir::ForeignItemStatic(ref ty, _) => { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 429bfb8e3d606..b7ee688117d93 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -97,11 +97,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedMut { fn check_fn(&mut self, cx: &LateContext, _: FnKind, - decl: &hir::FnDecl, - _: &hir::Expr, + _: &hir::FnDecl, + body: &hir::Body, _: Span, _: ast::NodeId) { - for a in &decl.inputs { + for a in &body.arguments { self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat)); } } diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 926c44824ce48..b27b164bd47aa 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -16,8 +16,7 @@ use cstore::CrateMetadata; use encoder::EncodeContext; use schema::*; -use rustc::middle::cstore::{InlinedItem, InlinedItemRef}; -use rustc::middle::const_qualif::ConstQualif; +use rustc::hir; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::ty::{self, TyCtxt, Ty}; @@ -29,8 +28,10 @@ use rustc_serialize::Encodable; #[derive(RustcEncodable, RustcDecodable)] pub struct Ast<'tcx> { id_range: IdRange, - item: Lazy, + body: Lazy, side_tables: LazySeq<(ast::NodeId, TableEntry<'tcx>)>, + pub nested_bodies: LazySeq, + pub rvalue_promotable_to_static: bool, } #[derive(RustcEncodable, RustcDecodable)] @@ -39,16 +40,17 @@ enum TableEntry<'tcx> { NodeType(Ty<'tcx>), ItemSubsts(ty::ItemSubsts<'tcx>), Adjustment(ty::adjustment::Adjustment<'tcx>), - ConstQualif(ConstQualif), } impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - pub fn encode_inlined_item(&mut self, ii: InlinedItemRef<'tcx>) -> Lazy> { + pub fn encode_body(&mut self, body: hir::BodyId) -> Lazy> { + let body = self.tcx.map.body(body); + let mut id_visitor = IdRangeComputingVisitor::new(&self.tcx.map); - ii.visit(&mut id_visitor); + id_visitor.visit_body(body); - let ii_pos = self.position(); - ii.encode(self).unwrap(); + let body_pos = self.position(); + body.encode(self).unwrap(); let tables_pos = self.position(); let tables_count = { @@ -56,14 +58,29 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { ecx: self, count: 0, }; - ii.visit(&mut visitor); + visitor.visit_body(body); visitor.count }; + let nested_pos = self.position(); + let nested_count = { + let mut visitor = NestedBodyEncodingVisitor { + ecx: self, + count: 0, + }; + visitor.visit_body(body); + visitor.count + }; + + let rvalue_promotable_to_static = + self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id]; + self.lazy(&Ast { id_range: id_visitor.result(), - item: Lazy::with_position(ii_pos), + body: Lazy::with_position(body_pos), side_tables: LazySeq::with_position_and_length(tables_pos, tables_count), + nested_bodies: LazySeq::with_position_and_length(nested_pos, nested_count), + rvalue_promotable_to_static: rvalue_promotable_to_static }) } } @@ -94,18 +111,36 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> { encode(tcx.tables().node_types.get(&id).cloned().map(TableEntry::NodeType)); encode(tcx.tables().item_substs.get(&id).cloned().map(TableEntry::ItemSubsts)); encode(tcx.tables().adjustments.get(&id).cloned().map(TableEntry::Adjustment)); - encode(tcx.const_qualif_map.borrow().get(&id).cloned().map(TableEntry::ConstQualif)); } } -/// Decodes an item from its AST in the cdata's metadata and adds it to the +struct NestedBodyEncodingVisitor<'a, 'b: 'a, 'tcx: 'b> { + ecx: &'a mut EncodeContext<'b, 'tcx>, + count: usize, +} + +impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedBodyEncodingVisitor<'a, 'b, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } + + fn visit_nested_body(&mut self, body: hir::BodyId) { + let body = self.ecx.tcx.map.body(body); + body.encode(self.ecx).unwrap(); + self.count += 1; + + self.visit_body(body); + } +} + +/// Decodes an item's body from its AST in the cdata's metadata and adds it to the /// ast-map. -pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - ast: Ast<'tcx>, - orig_did: DefId) - -> &'tcx InlinedItem { - debug!("> Decoding inlined fn: {:?}", tcx.item_path_str(orig_did)); +pub fn decode_body<'a, 'tcx>(cdata: &CrateMetadata, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + ast: Ast<'tcx>) + -> &'tcx hir::Body { + debug!("> Decoding inlined fn: {}", tcx.item_path_str(def_id)); let cnt = ast.id_range.max.as_usize() - ast.id_range.min.as_usize(); let start = tcx.sess.reserve_node_ids(cnt); @@ -115,12 +150,6 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata, max: ast::NodeId::new(start.as_usize() + cnt), }]; - let ii = ast.item.decode((cdata, tcx, id_ranges)); - let item_node_id = tcx.sess.next_node_id(); - let ii = ast_map::map_decoded_item(&tcx.map, - ii, - item_node_id); - for (id, entry) in ast.side_tables.decode((cdata, tcx, id_ranges)) { match entry { TableEntry::TypeRelativeDef(def) => { @@ -135,11 +164,9 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata, TableEntry::Adjustment(adj) => { tcx.tables.borrow_mut().adjustments.insert(id, adj); } - TableEntry::ConstQualif(qualif) => { - tcx.const_qualif_map.borrow_mut().insert(id, qualif); - } } } - ii + let body = ast.body.decode((cdata, tcx, id_ranges)); + ast_map::map_decoded_body(&tcx.map, def_id, body, tcx.sess.next_node_id()) } diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 7ec847d24cfa3..aab4034b7705a 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -88,13 +88,6 @@ pub struct CrateMetadata { pub dllimport_foreign_items: FxHashSet, } -pub struct CachedInlinedItem { - /// The NodeId of the RootInlinedParent HIR map entry - pub inlined_root: ast::NodeId, - /// The local NodeId of the inlined entity - pub item_id: ast::NodeId, -} - pub struct CStore { pub dep_graph: DepGraph, metas: RefCell>>, @@ -104,8 +97,7 @@ pub struct CStore { used_link_args: RefCell>, statically_included_foreign_items: RefCell>, pub dllimport_foreign_items: RefCell>, - pub inlined_item_cache: RefCell>>, - pub defid_for_inlined_node: RefCell>, + pub inlined_item_cache: RefCell>>, pub visible_parent_map: RefCell>, } @@ -121,7 +113,6 @@ impl CStore { dllimport_foreign_items: RefCell::new(FxHashSet()), visible_parent_map: RefCell::new(FxHashMap()), inlined_item_cache: RefCell::new(FxHashMap()), - defid_for_inlined_node: RefCell::new(FxHashMap()), } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 0ac3ffd5cb9ce..64513fa41b219 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -13,7 +13,7 @@ use encoder; use locator; use schema; -use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, LibSource, DepKind, ExternCrate}; +use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, ExternCrate}; use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro}; use rustc::hir::def::{self, Def}; use rustc::middle::lang_items; @@ -36,6 +36,8 @@ use rustc::hir::svh::Svh; use rustc_back::target::Target; use rustc::hir; +use std::collections::BTreeMap; + impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn describe_def(&self, def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def)); @@ -128,7 +130,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn fn_arg_names(&self, did: DefId) -> Vec { - self.dep_graph.read(DepNode::MetaData(did)); + // FIXME(#38501) We've skipped a `read` on the `HirBody` of + // a `fn` when encoding, so the dep-tracking wouldn't work. + // This is only used by rustdoc anyway, which shouldn't have + // incremental recompilation ever enabled. + assert!(!self.dep_graph.is_fully_enabled()); self.get_crate_data(did.krate).get_fn_arg_names(did.index) } @@ -423,94 +429,42 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { }) } - fn maybe_get_item_ast<'a>(&'tcx self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> Option<(&'tcx InlinedItem, ast::NodeId)> + fn maybe_get_item_body<'a>(&'tcx self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> Option<&'tcx hir::Body> { self.dep_graph.read(DepNode::MetaData(def_id)); - match self.inlined_item_cache.borrow().get(&def_id) { - Some(&None) => { - return None; // Not inlinable - } - Some(&Some(ref cached_inlined_item)) => { + if let Some(&cached) = self.inlined_item_cache.borrow().get(&def_id) { + return cached.map(|root_id| { // Already inline - debug!("maybe_get_item_ast({}): already inline as node id {}", - tcx.item_path_str(def_id), cached_inlined_item.item_id); - return Some((tcx.map.expect_inlined_item(cached_inlined_item.inlined_root), - cached_inlined_item.item_id)); - } - None => { - // Not seen yet - } + debug!("maybe_get_item_body({}): already inline", tcx.item_path_str(def_id)); + tcx.map.expect_inlined_body(root_id) + }); } - debug!("maybe_get_item_ast({}): inlining item", tcx.item_path_str(def_id)); + debug!("maybe_get_item_body({}): inlining item", tcx.item_path_str(def_id)); - let inlined = self.get_crate_data(def_id.krate).maybe_get_item_ast(tcx, def_id.index); - - let cache_inlined_item = |original_def_id, inlined_item_id, inlined_root_node_id| { - let cache_entry = cstore::CachedInlinedItem { - inlined_root: inlined_root_node_id, - item_id: inlined_item_id, - }; - self.inlined_item_cache - .borrow_mut() - .insert(original_def_id, Some(cache_entry)); - self.defid_for_inlined_node - .borrow_mut() - .insert(inlined_item_id, original_def_id); - }; - - let find_inlined_item_root = |inlined_item_id| { - let mut node = inlined_item_id; - - // If we can't find the inline root after a thousand hops, we can - // be pretty sure there's something wrong with the HIR map. - for _ in 0 .. 1000 { - let parent_node = tcx.map.get_parent_node(node); - if parent_node == node { - return node; - } - node = parent_node; - } - bug!("cycle in HIR map parent chain") - }; + let inlined = self.get_crate_data(def_id.krate).maybe_get_item_body(tcx, def_id.index); - match inlined { - None => { - self.inlined_item_cache - .borrow_mut() - .insert(def_id, None); - } - Some(&InlinedItem { ref body, .. }) => { - let inlined_root_node_id = find_inlined_item_root(body.id); - cache_inlined_item(def_id, inlined_root_node_id, inlined_root_node_id); - } - } + self.inlined_item_cache.borrow_mut().insert(def_id, inlined.map(|body| { + let root_id = tcx.map.get_parent_node(body.value.id); + assert_eq!(tcx.map.get_parent_node(root_id), root_id); + root_id + })); - // We can be sure to hit the cache now - return self.maybe_get_item_ast(tcx, def_id); + inlined } - fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option { - assert!(!def_id.is_local()); - match self.inlined_item_cache.borrow().get(&def_id) { - Some(&Some(ref cached_inlined_item)) => { - Some(cached_inlined_item.item_id) - } - Some(&None) => { - None - } - _ => { - bug!("Trying to lookup inlined NodeId for unexpected item"); - } - } + fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap { + self.dep_graph.read(DepNode::MetaData(def)); + self.get_crate_data(def.krate).item_body_nested_bodies(def.index) } - fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option { - self.defid_for_inlined_node.borrow().get(&node_id).map(|x| *x) + fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool { + self.dep_graph.read(DepNode::MetaData(def)); + self.get_crate_data(def.krate).const_is_rvalue_promotable_to_static(def.index) } fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx> { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 400a3ac0e3e0d..c27e06c50222b 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -10,7 +10,7 @@ // Decoding metadata from a single crate's metadata -use astencode::decode_inlined_item; +use astencode::decode_body; use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary}; use schema::*; @@ -18,7 +18,7 @@ use rustc::hir::map::{DefKey, DefPath, DefPathData}; use rustc::hir; use rustc::hir::intravisit::IdRange; -use rustc::middle::cstore::{InlinedItem, LinkagePreference}; +use rustc::middle::cstore::LinkagePreference; use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::middle::lang_items; @@ -32,6 +32,7 @@ use rustc::mir::Mir; use std::borrow::Cow; use std::cell::Ref; +use std::collections::BTreeMap; use std::io; use std::mem; use std::str; @@ -819,20 +820,27 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn maybe_get_item_ast(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - id: DefIndex) - -> Option<&'tcx InlinedItem> { - debug!("Looking up item: {:?}", id); + pub fn maybe_get_item_body(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + id: DefIndex) + -> Option<&'tcx hir::Body> { if self.is_proc_macro(id) { return None; } - let item_doc = self.entry(id); - let item_did = self.local_def_id(id); - item_doc.ast.map(|ast| { - let ast = ast.decode(self); - decode_inlined_item(self, tcx, ast, item_did) + self.entry(id).ast.map(|ast| { + decode_body(self, tcx, self.local_def_id(id), ast.decode(self)) }) } + pub fn item_body_nested_bodies(&self, id: DefIndex) -> BTreeMap { + self.entry(id).ast.into_iter().flat_map(|ast| { + ast.decode(self).nested_bodies.decode(self).map(|body| (body.id(), body)) + }).collect() + } + + pub fn const_is_rvalue_promotable_to_static(&self, id: DefIndex) -> bool { + self.entry(id).ast.expect("const item missing `ast`") + .decode(self).rvalue_promotable_to_static + } + pub fn is_item_mir_available(&self, id: DefIndex) -> bool { !self.is_proc_macro(id) && self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some() diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index bc0a64b9a5170..72dcb4ba9a3a8 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -12,8 +12,7 @@ use cstore; use index::Index; use schema::*; -use rustc::middle::cstore::{InlinedItemRef, LinkMeta}; -use rustc::middle::cstore::{LinkagePreference, NativeLibrary}; +use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary}; use rustc::hir::def; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId}; use rustc::hir::map::definitions::DefPathTable; @@ -34,6 +33,7 @@ use std::io::Cursor; use std::rc::Rc; use std::u32; use syntax::ast::{self, CRATE_NODE_ID}; +use syntax::codemap::Spanned; use syntax::attr; use syntax::symbol::Symbol; use syntax_pos; @@ -442,10 +442,18 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let kind = match trait_item.kind { ty::AssociatedKind::Const => EntryKind::AssociatedConst(container), ty::AssociatedKind::Method => { - let fn_data = if let hir::MethodTraitItem(ref sig, _) = ast_item.node { + let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node { + let arg_names = match *m { + hir::TraitMethod::Required(ref names) => { + self.encode_fn_arg_names(names) + } + hir::TraitMethod::Provided(body) => { + self.encode_fn_arg_names_for_body(body) + } + }; FnData { constness: hir::Constness::NotConst, - arg_names: self.encode_fn_arg_names(&sig.decl), + arg_names: arg_names } } else { bug!() @@ -486,13 +494,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), - ast: if let hir::ConstTraitItem(_, Some(_)) = ast_item.node { - // We only save the HIR for associated consts with bodies - // (InlinedItemRef::from_trait_item panics otherwise) - let trait_def_id = trait_item.container.id(); - Some(self.encode_inlined_item( - InlinedItemRef::from_trait_item(trait_def_id, ast_item, tcx) - )) + ast: if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.node { + Some(self.encode_body(body)) } else { None }, @@ -501,12 +504,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { - let tcx = self.tcx; - let node_id = self.tcx.map.as_local_node_id(def_id).unwrap(); let ast_item = self.tcx.map.expect_impl_item(node_id); let impl_item = self.tcx.associated_item(def_id); - let impl_def_id = impl_item.container.id(); let container = match impl_item.defaultness { hir::Defaultness::Default { has_value: true } => AssociatedContainer::ImplDefault, @@ -518,10 +518,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let kind = match impl_item.kind { ty::AssociatedKind::Const => EntryKind::AssociatedConst(container), ty::AssociatedKind::Method => { - let fn_data = if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node { + let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { FnData { constness: sig.constness, - arg_names: self.encode_fn_arg_names(&sig.decl), + arg_names: self.encode_fn_arg_names_for_body(body), } } else { bug!() @@ -535,17 +535,18 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { ty::AssociatedKind::Type => EntryKind::AssociatedType(container) }; - let (ast, mir) = if impl_item.kind == ty::AssociatedKind::Const { - (true, true) - } else if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node { + let (ast, mir) = if let hir::ImplItemKind::Const(_, body) = ast_item.node { + (Some(body), true) + } else if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { let generics = self.tcx.item_generics(def_id); let types = generics.parent_types as usize + generics.types.len(); let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs); let is_const_fn = sig.constness == hir::Constness::Const; + let ast = if is_const_fn { Some(body) } else { None }; let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; - (is_const_fn, needs_inline || is_const_fn || always_encode_mir) + (ast, needs_inline || is_const_fn || always_encode_mir) } else { - (false, false) + (None, false) }; Entry { @@ -563,27 +564,28 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), - ast: if ast { - Some(self.encode_inlined_item( - InlinedItemRef::from_impl_item(impl_def_id, ast_item, tcx) - )) - } else { - None - }, + ast: ast.map(|body| self.encode_body(body)), mir: if mir { self.encode_mir(def_id) } else { None }, } } - fn encode_fn_arg_names(&mut self, decl: &hir::FnDecl) -> LazySeq { - self.lazy_seq(decl.inputs.iter().map(|arg| { - if let PatKind::Binding(_, _, ref path1, _) = arg.pat.node { - path1.node - } else { - Symbol::intern("") + fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId) + -> LazySeq { + let _ignore = self.tcx.dep_graph.in_ignore(); + let body = self.tcx.map.body(body_id); + self.lazy_seq(body.arguments.iter().map(|arg| { + match arg.pat.node { + PatKind::Binding(_, _, name, _) => name.node, + _ => Symbol::intern("") } })) } + fn encode_fn_arg_names(&mut self, names: &[Spanned]) + -> LazySeq { + self.lazy_seq(names.iter().map(|name| name.node)) + } + fn encode_mir(&mut self, def_id: DefId) -> Option>> { self.tcx.mir_map.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow())) } @@ -619,10 +621,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic, hir::ItemStatic(_, hir::MutImmutable, _) => EntryKind::ImmStatic, hir::ItemConst(..) => EntryKind::Const, - hir::ItemFn(ref decl, _, constness, ..) => { + hir::ItemFn(_, _, constness, .., body) => { let data = FnData { constness: constness, - arg_names: self.encode_fn_arg_names(&decl), + arg_names: self.encode_fn_arg_names_for_body(body), }; EntryKind::Fn(self.lazy(&data)) @@ -793,16 +795,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }, ast: match item.node { - hir::ItemConst(..) | - hir::ItemFn(_, _, hir::Constness::Const, ..) => { - Some(self.encode_inlined_item( - InlinedItemRef::from_item(def_id, item, tcx) - )) + hir::ItemConst(_, body) | + hir::ItemFn(_, _, hir::Constness::Const, _, _, body) => { + Some(self.encode_body(body)) } _ => None, }, 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::ItemFn(_, _, constness, _, ref generics, _) => { let tps_len = generics.ty_params.len(); @@ -913,10 +915,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debug!("writing foreign item {}", tcx.node_path_str(nitem.id)); let kind = match nitem.node { - hir::ForeignItemFn(ref fndecl, _) => { + hir::ForeignItemFn(_, ref names, _) => { let data = FnData { constness: hir::Constness::NotConst, - arg_names: self.encode_fn_arg_names(&fndecl), + arg_names: self.encode_fn_arg_names(names), }; EntryKind::ForeignFn(self.lazy(&data)) } @@ -1162,6 +1164,8 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> { } } + fn visit_trait_item(&mut self, _trait_item: &'v hir::TraitItem) {} + fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { // handled in `visit_item` above } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index e06d940de7e58..63bb1bf20c06c 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -729,7 +729,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { name: Some(name), source_info: Some(source_info), }); - let extent = self.extent_of_innermost_scope(); + let extent = self.hir.tcx().region_maps.var_scope(var_id); self.schedule_drop(source_info.span, extent, &Lvalue::Local(var), var_ty); self.var_indices.insert(var_id, var); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 0e4dbb0477716..cfdc1bf27df35 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -126,7 +126,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, arguments: A, abi: Abi, return_ty: Ty<'gcx>, - ast_body: &'gcx hir::Expr) + body: &'gcx hir::Body) -> Mir<'tcx> where A: Iterator, Option<&'gcx hir::Pat>)> { @@ -136,17 +136,16 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let span = tcx.map.span(fn_id); let mut builder = Builder::new(hir, span, arguments.len(), return_ty); - let body_id = ast_body.id; let call_site_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.value.id }); let arg_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.value.id }); let mut block = START_BLOCK; unpack!(block = builder.in_scope(call_site_extent, block, |builder| { unpack!(block = builder.in_scope(arg_extent, block, |builder| { - builder.args_and_body(block, &arguments, arg_extent, ast_body) + builder.args_and_body(block, &arguments, arg_extent, &body.value) })); // Attribute epilogue to function's closing brace let fn_end = Span { lo: span.hi, ..span }; @@ -197,9 +196,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>, item_id: ast::NodeId, - ast_expr: &'tcx hir::Expr) + body_id: hir::BodyId) -> Mir<'tcx> { let tcx = hir.tcx(); + let ast_expr = &tcx.map.body(body_id).value; let ty = tcx.tables().expr_ty_adjusted(ast_expr); let span = tcx.map.span(item_id); let mut builder = Builder::new(hir, span, 0, ty); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index c02a1822d7369..59a11782e0856 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -253,7 +253,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { f: F) where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) { - let extent = self.extent_of_innermost_scope(); + let extent = self.scopes.last().map(|scope| scope.extent).unwrap(); let loop_scope = LoopScope { extent: extent.clone(), continue_block: loop_block, @@ -411,10 +411,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - pub fn extent_of_innermost_scope(&self) -> CodeExtent { - self.scopes.last().map(|scope| scope.extent).unwrap() - } - /// Returns the extent of the scope which should be exited by a /// return. pub fn extent_of_return_scope(&self) -> CodeExtent { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index d579cdb042fb3..cc65fdede092f 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -575,7 +575,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } // 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 { value: v.to_ref(), 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, other => bug!("constant evaluation of repeat count yielded {:?}", other), }, - }, + } } } 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) { Some(map::NodeExpr(expr)) => { 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"); } diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index e2a516edbc835..cbc53ea3c51c7 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -129,16 +129,17 @@ impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> { } 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 // function definition IDs and expression IDs. // Type-checking should not let closures get // this far in an integer constant position. - if let hir::ExprClosure(..) = expr.node { + if let hir::ExprClosure(..) = body.value.node { return; } - self.cx(MirSource::Const(expr.id)).build(|cx| { - build::construct_const(cx, expr.id, expr) + self.cx(MirSource::Const(body.value.id)).build(|cx| { + 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. fn visit_item(&mut self, item: &'tcx hir::Item) { match item.node { - hir::ItemConst(_, ref expr) => { + hir::ItemConst(_, expr) => { self.cx(MirSource::Const(item.id)).build(|cx| { 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| { build::construct_const(cx, item.id, expr) }); @@ -168,7 +169,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { // Trait associated const defaults. fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { - if let hir::ConstTraitItem(_, Some(ref expr)) = item.node { + if let hir::TraitItemKind::Const(_, Some(expr)) = item.node { self.cx(MirSource::Const(item.id)).build(|cx| { build::construct_const(cx, item.id, expr) }); @@ -178,7 +179,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { // Impl associated const. 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| { 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]. 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); } intravisit::walk_expr(self, expr); @@ -196,7 +197,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { // Array lengths, i.e. [T; constant]. 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); } intravisit::walk_ty(self, ty); @@ -205,7 +206,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { // Enum variant discriminant values. fn visit_variant(&mut self, v: &'tcx hir::Variant, 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); } 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, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl, - body_id: hir::ExprId, + body_id: hir::BodyId, span: Span, id: ast::NodeId) { // fetch the fully liberated fn signature (that is, all bound @@ -227,22 +228,21 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { }; 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 { let def_id = self.tcx.map.local_def_id(id); (self.tcx.item_type(def_id).fn_abi(), None) }; + let body = self.tcx.map.body(body_id); let explicit_arguments = - decl.inputs + body.arguments .iter() .enumerate() .map(|(index, arg)| { (fn_sig.inputs()[index], Some(&*arg.pat)) }); - let body = self.tcx.map.expr(body_id); - let arguments = implicit_argument.into_iter().chain(explicit_arguments); self.cx(MirSource::Fn(id)).build(|cx| { build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body) diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 86f56d0035841..d1d9a201567bb 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -26,8 +26,8 @@ use rustc::dep_graph::DepNode; use rustc::ty::cast::CastKind; -use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, compare_lit_exprs}; -use rustc_const_eval::{ConstFnNode, eval_const_expr_partial, lookup_const_by_id}; +use rustc_const_eval::{ConstEvalErr, compare_lit_exprs}; +use rustc_const_eval::{eval_const_expr_partial}; use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll, Math}; use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath}; use rustc_const_eval::ErrKind::UnresolvedPath; @@ -35,80 +35,36 @@ use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_math::{ConstMathErr, Op}; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::DefId; +use rustc::hir::map::blocks::FnLikeNode; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; +use rustc::mir::transform::MirSource; use rustc::ty::{self, Ty, TyCtxt}; use rustc::traits::Reveal; use rustc::util::common::ErrorReported; -use rustc::util::nodemap::NodeMap; -use rustc::middle::const_qualif::ConstQualif; +use rustc::util::nodemap::NodeSet; use rustc::lint::builtin::CONST_ERR; use rustc::hir::{self, PatKind}; use syntax::ast; use syntax_pos::Span; -use rustc::hir::intravisit::{self, FnKind, Visitor, NestedVisitorMap}; +use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use std::collections::hash_map::Entry; use std::cmp::Ordering; - -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -enum Mode { - Const, - ConstFn, - Static, - StaticMut, - - // An expression that occurs outside of any constant context - // (i.e. `const`, `static`, array lengths, etc.). The value - // can be variable at runtime, but will be promotable to - // static memory if we can prove it is actually constant. - Var, -} +use std::mem; struct CheckCrateVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - mode: Mode, - qualif: ConstQualif, - rvalue_borrows: NodeMap, + in_fn: bool, + promotable: bool, + mut_rvalue_borrows: NodeSet, + param_env: ty::ParameterEnvironment<'tcx>, } impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { - fn with_mode(&mut self, mode: Mode, f: F) -> R - where F: FnOnce(&mut CheckCrateVisitor<'a, 'gcx>) -> R - { - let (old_mode, old_qualif) = (self.mode, self.qualif); - self.mode = mode; - self.qualif = ConstQualif::empty(); - let r = f(self); - self.mode = old_mode; - self.qualif = old_qualif; - r - } - - fn with_euv(&mut self, item_id: Option, f: F) -> R - where F: for<'b, 'tcx> FnOnce(&mut euv::ExprUseVisitor<'b, 'gcx, 'tcx>) -> R - { - let param_env = match item_id { - Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id), - None => self.tcx.empty_parameter_environment(), - }; - - self.tcx - .infer_ctxt(None, Some(param_env), Reveal::NotSpecializable) - .enter(|infcx| f(&mut euv::ExprUseVisitor::new(self, &infcx))) - } - - fn global_expr(&mut self, mode: Mode, expr: &'gcx hir::Expr) -> ConstQualif { - assert!(mode != Mode::Var); - match self.tcx.const_qualif_map.borrow_mut().entry(expr.id) { - Entry::Occupied(entry) => return *entry.get(), - Entry::Vacant(entry) => { - // Prevent infinite recursion on re-entry. - entry.insert(ConstQualif::empty()); - } - } + fn check_const_eval(&self, expr: &'gcx hir::Expr) { if let Err(err) = eval_const_expr_partial(self.tcx, expr, ExprTypeChecked, None) { match err.kind { UnimplementedConstVal(_) => {} @@ -124,184 +80,78 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { } } } - self.with_mode(mode, |this| { - this.with_euv(None, |euv| euv.consume_expr(expr)); - this.visit_expr(expr); - this.qualif - }) } - fn fn_like(&mut self, - fk: FnKind<'gcx>, - fd: &'gcx hir::FnDecl, - b: hir::ExprId, - s: Span, - fn_id: ast::NodeId) - -> ConstQualif { - match self.tcx.const_qualif_map.borrow_mut().entry(fn_id) { - Entry::Occupied(entry) => return *entry.get(), - Entry::Vacant(entry) => { - // Prevent infinite recursion on re-entry. - entry.insert(ConstQualif::empty()); - } + // Adds the worst effect out of all the values of one type. + fn add_type(&mut self, ty: Ty<'gcx>) { + if ty.type_contents(self.tcx).interior_unsafe() { + self.promotable = false; } - let mode = match fk { - FnKind::ItemFn(_, _, _, hir::Constness::Const, ..) - => Mode::ConstFn, - FnKind::Method(_, m, ..) => { - if m.constness == hir::Constness::Const { - Mode::ConstFn - } else { - Mode::Var - } - } - _ => Mode::Var, - }; - - let qualif = self.with_mode(mode, |this| { - let body = this.tcx.map.expr(b); - this.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, body)); - intravisit::walk_fn(this, fk, fd, b, s, fn_id); - this.qualif - }); - - // Keep only bits that aren't affected by function body (NON_ZERO_SIZED), - // and bits that don't change semantics, just optimizations (PREFER_IN_PLACE). - let qualif = qualif & (ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE); - - self.tcx.const_qualif_map.borrow_mut().insert(fn_id, qualif); - qualif - } - - fn add_qualif(&mut self, qualif: ConstQualif) { - self.qualif = self.qualif | qualif; - } - - /// Returns true if the call is to a const fn or method. - fn handle_const_fn_call(&mut self, _expr: &hir::Expr, def_id: DefId, ret_ty: Ty<'gcx>) -> bool { - match lookup_const_fn_by_id(self.tcx, def_id) { - Some(ConstFnNode::Local(fn_like)) => { - let qualif = self.fn_like(fn_like.kind(), - fn_like.decl(), - fn_like.body(), - fn_like.span(), - fn_like.id()); - - self.add_qualif(qualif); - - if ret_ty.type_contents(self.tcx).interior_unsafe() { - self.add_qualif(ConstQualif::MUTABLE_MEM); - } - - true - }, - Some(ConstFnNode::Inlined(ii)) => { - let node_id = ii.body.id; - - let qualif = match self.tcx.const_qualif_map.borrow_mut().entry(node_id) { - Entry::Occupied(entry) => *entry.get(), - _ => bug!("const qualif entry missing for inlined item") - }; - - self.add_qualif(qualif); - - if ret_ty.type_contents(self.tcx).interior_unsafe() { - self.add_qualif(ConstQualif::MUTABLE_MEM); - } - - true - }, - None => false + if self.tcx.type_needs_drop_given_env(ty, &self.param_env) { + self.promotable = false; } } - fn record_borrow(&mut self, id: ast::NodeId, mutbl: hir::Mutability) { - match self.rvalue_borrows.entry(id) { - Entry::Occupied(mut entry) => { - // Merge the two borrows, taking the most demanding - // one, mutability-wise. - if mutbl == hir::MutMutable { - entry.insert(mutbl); - } - } - Entry::Vacant(entry) => { - entry.insert(mutbl); - } - } + fn handle_const_fn_call(&mut self, def_id: DefId, ret_ty: Ty<'gcx>) { + self.add_type(ret_ty); + + self.promotable &= if let Some(fn_id) = self.tcx.map.as_local_node_id(def_id) { + FnLikeNode::from_node(self.tcx.map.get(fn_id)).map_or(false, |fn_like| { + fn_like.constness() == hir::Constness::Const + }) + } else { + self.tcx.sess.cstore.is_const_fn(def_id) + }; } } impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None } - fn visit_item(&mut self, i: &'tcx hir::Item) { - debug!("visit_item(item={})", self.tcx.map.node_to_string(i.id)); - assert_eq!(self.mode, Mode::Var); - match i.node { - hir::ItemStatic(_, hir::MutImmutable, ref expr) => { - self.global_expr(Mode::Static, &expr); - } - hir::ItemStatic(_, hir::MutMutable, ref expr) => { - self.global_expr(Mode::StaticMut, &expr); - } - hir::ItemConst(_, ref expr) => { - self.global_expr(Mode::Const, &expr); - } - hir::ItemEnum(ref enum_definition, _) => { - for var in &enum_definition.variants { - if let Some(ref ex) = var.node.disr_expr { - self.global_expr(Mode::Const, &ex); - } - } - } - _ => { - intravisit::walk_item(self, i); + fn visit_nested_body(&mut self, body: hir::BodyId) { + match self.tcx.rvalue_promotable_to_static.borrow_mut().entry(body.node_id) { + Entry::Occupied(_) => return, + Entry::Vacant(entry) => { + // Prevent infinite recursion on re-entry. + entry.insert(false); } } - } - fn visit_trait_item(&mut self, t: &'tcx hir::TraitItem) { - match t.node { - hir::ConstTraitItem(_, ref default) => { - if let Some(ref expr) = *default { - self.global_expr(Mode::Const, &expr); - } else { - intravisit::walk_trait_item(self, t); - } - } - _ => self.with_mode(Mode::Var, |v| intravisit::walk_trait_item(v, t)), - } - } + let item_id = self.tcx.map.body_owner(body); - fn visit_impl_item(&mut self, i: &'tcx hir::ImplItem) { - match i.node { - hir::ImplItemKind::Const(_, ref expr) => { - self.global_expr(Mode::Const, &expr); - } - _ => self.with_mode(Mode::Var, |v| intravisit::walk_impl_item(v, i)), + let outer_in_fn = self.in_fn; + self.in_fn = match MirSource::from_node(self.tcx, item_id) { + MirSource::Fn(_) => true, + _ => false + }; + + let body = self.tcx.map.body(body); + if !self.in_fn { + self.check_const_eval(&body.value); } - } - fn visit_fn(&mut self, - fk: FnKind<'tcx>, - fd: &'tcx hir::FnDecl, - b: hir::ExprId, - s: Span, - fn_id: ast::NodeId) { - self.fn_like(fk, fd, b, s, fn_id); + let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id); + let outer_param_env = mem::replace(&mut self.param_env, param_env); + self.tcx.infer_ctxt(None, Some(self.param_env.clone()), Reveal::NotSpecializable) + .enter(|infcx| euv::ExprUseVisitor::new(self, &infcx).consume_body(body)); + + self.visit_body(body); + + self.param_env = outer_param_env; + self.in_fn = outer_in_fn; } fn visit_pat(&mut self, p: &'tcx hir::Pat) { match p.node { PatKind::Lit(ref lit) => { - self.global_expr(Mode::Const, &lit); + self.check_const_eval(lit); } PatKind::Range(ref start, ref end) => { - self.global_expr(Mode::Const, &start); - self.global_expr(Mode::Const, &end); + self.check_const_eval(start); + self.check_const_eval(end); match compare_lit_exprs(self.tcx, p.span, start, end) { Ok(Ordering::Less) | @@ -315,119 +165,60 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { Err(ErrorReported) => {} } } - _ => intravisit::walk_pat(self, p), + _ => {} } + intravisit::walk_pat(self, p); } - fn visit_block(&mut self, block: &'tcx hir::Block) { - // Check all statements in the block - for stmt in &block.stmts { - match stmt.node { - hir::StmtDecl(ref decl, _) => { - match decl.node { - hir::DeclLocal(_) => {} - // Item statements are allowed - hir::DeclItem(_) => continue, + fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt) { + match stmt.node { + hir::StmtDecl(ref decl, _) => { + match decl.node { + hir::DeclLocal(_) => { + self.promotable = false; } + // Item statements are allowed + hir::DeclItem(_) => {} } - hir::StmtExpr(..) => {} - hir::StmtSemi(..) => {} } - self.add_qualif(ConstQualif::NOT_CONST); + hir::StmtExpr(..) | + hir::StmtSemi(..) => { + self.promotable = false; + } } - intravisit::walk_block(self, block); + intravisit::walk_stmt(self, stmt); } fn visit_expr(&mut self, ex: &'tcx hir::Expr) { - let mut outer = self.qualif; - self.qualif = ConstQualif::empty(); + let outer = self.promotable; + self.promotable = true; let node_ty = self.tcx.tables().node_id_to_type(ex.id); check_expr(self, ex, node_ty); check_adjustments(self, ex); - // Special-case some expressions to avoid certain flags bubbling up. - match ex.node { - hir::ExprCall(ref callee, ref args) => { - for arg in args { - self.visit_expr(&arg) + if let hir::ExprMatch(ref discr, ref arms, _) = ex.node { + // Compute the most demanding borrow from all the arms' + // patterns and set that on the discriminator. + let mut mut_borrow = false; + for pat in arms.iter().flat_map(|arm| &arm.pats) { + if self.mut_rvalue_borrows.remove(&pat.id) { + mut_borrow = true; } - - let inner = self.qualif; - self.visit_expr(&callee); - // The callee's size doesn't count in the call. - let added = self.qualif - inner; - self.qualif = inner | (added - ConstQualif::NON_ZERO_SIZED); } - hir::ExprRepeat(ref element, _) => { - self.visit_expr(&element); - // The count is checked elsewhere (typeck). - let count = match node_ty.sty { - ty::TyArray(_, n) => n, - _ => bug!(), - }; - // [element; 0] is always zero-sized. - if count == 0 { - self.qualif.remove(ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE); - } + if mut_borrow { + self.mut_rvalue_borrows.insert(discr.id); } - hir::ExprMatch(ref discr, ref arms, _) => { - // Compute the most demanding borrow from all the arms' - // patterns and set that on the discriminator. - let mut borrow = None; - for pat in arms.iter().flat_map(|arm| &arm.pats) { - let pat_borrow = self.rvalue_borrows.remove(&pat.id); - match (borrow, pat_borrow) { - (None, _) | - (_, Some(hir::MutMutable)) => { - borrow = pat_borrow; - } - _ => {} - } - } - if let Some(mutbl) = borrow { - self.record_borrow(discr.id, mutbl); - } - intravisit::walk_expr(self, ex); - } - _ => intravisit::walk_expr(self, ex), } + intravisit::walk_expr(self, ex); + // Handle borrows on (or inside the autorefs of) this expression. - match self.rvalue_borrows.remove(&ex.id) { - Some(hir::MutImmutable) => { - // Constants cannot be borrowed if they contain interior mutability as - // it means that our "silent insertion of statics" could change - // initializer values (very bad). - // If the type doesn't have interior mutability, then `ConstQualif::MUTABLE_MEM` has - // propagated from another error, so erroring again would be just noise. - let tc = node_ty.type_contents(self.tcx); - if self.qualif.intersects(ConstQualif::MUTABLE_MEM) && tc.interior_unsafe() { - outer = outer | ConstQualif::NOT_CONST; - } - // If the reference has to be 'static, avoid in-place initialization - // as that will end up pointing to the stack instead. - if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) { - self.qualif = self.qualif - ConstQualif::PREFER_IN_PLACE; - self.add_qualif(ConstQualif::HAS_STATIC_BORROWS); - } - } - Some(hir::MutMutable) => { - // `&mut expr` means expr could be mutated, unless it's zero-sized. - if self.qualif.intersects(ConstQualif::NON_ZERO_SIZED) { - if self.mode == Mode::Var { - outer = outer | ConstQualif::NOT_CONST; - self.add_qualif(ConstQualif::MUTABLE_MEM); - } - } - if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) { - self.add_qualif(ConstQualif::HAS_STATIC_BORROWS); - } - } - None => {} + if self.mut_rvalue_borrows.remove(&ex.id) { + self.promotable = false; } - if self.mode == Mode::Var && !self.qualif.intersects(ConstQualif::NOT_CONST) { + if self.in_fn && self.promotable { match eval_const_expr_partial(self.tcx, ex, ExprTypeChecked, None) { Ok(_) => {} Err(ConstEvalErr { kind: UnimplementedConstVal(_), .. }) | @@ -448,9 +239,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { } } - self.tcx.const_qualif_map.borrow_mut().insert(ex.id, self.qualif); - // Don't propagate certain flags. - self.qualif = outer | (self.qualif - ConstQualif::HAS_STATIC_BORROWS); + self.tcx.rvalue_promotable_to_static.borrow_mut().insert(ex.id, self.promotable); + self.promotable &= outer; } } @@ -463,7 +253,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node_ty: Ty<'tcx>) { match node_ty.sty { ty::TyAdt(def, _) if def.has_dtor() => { - v.add_qualif(ConstQualif::NEEDS_DROP); + v.promotable = false; } _ => {} } @@ -473,17 +263,17 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node hir::ExprUnary(..) | hir::ExprBinary(..) | hir::ExprIndex(..) if v.tcx.tables().method_map.contains_key(&method_call) => { - v.add_qualif(ConstQualif::NOT_CONST); + v.promotable = false; } hir::ExprBox(_) => { - v.add_qualif(ConstQualif::NOT_CONST); + v.promotable = false; } hir::ExprUnary(op, ref inner) => { match v.tcx.tables().node_id_to_type(inner.id).sty { ty::TyRawPtr(_) => { assert!(op == hir::UnDeref); - v.add_qualif(ConstQualif::NOT_CONST); + v.promotable = false; } _ => {} } @@ -495,7 +285,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node op.node == hir::BiLe || op.node == hir::BiLt || op.node == hir::BiGe || op.node == hir::BiGt); - v.add_qualif(ConstQualif::NOT_CONST); + v.promotable = false; } _ => {} } @@ -505,7 +295,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node match v.tcx.cast_kinds.borrow().get(&from.id) { None => span_bug!(e.span, "no kind for cast"), Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => { - v.add_qualif(ConstQualif::NOT_CONST); + v.promotable = false; } _ => {} } @@ -513,33 +303,24 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node hir::ExprPath(ref qpath) => { let def = v.tcx.tables().qpath_def(qpath, e.id); match def { - Def::VariantCtor(_, CtorKind::Const) => { - // Size is determined by the whole enum, may be non-zero. - v.add_qualif(ConstQualif::NON_ZERO_SIZED); - } Def::VariantCtor(..) | Def::StructCtor(..) | Def::Fn(..) | Def::Method(..) => {} - Def::Static(..) => { - match v.mode { - Mode::Static | Mode::StaticMut => {} - Mode::Const | Mode::ConstFn => {} - Mode::Var => v.add_qualif(ConstQualif::NOT_CONST) - } - } - Def::Const(did) | Def::AssociatedConst(did) => { - let substs = Some(v.tcx.tables().node_id_item_substs(e.id) - .unwrap_or_else(|| v.tcx.intern_substs(&[]))); - if let Some((expr, _)) = lookup_const_by_id(v.tcx, did, substs) { - let inner = v.global_expr(Mode::Const, expr); - v.add_qualif(inner); - } - } - Def::Local(..) if v.mode == Mode::ConstFn => { - // Sadly, we can't determine whether the types are zero-sized. - v.add_qualif(ConstQualif::NOT_CONST | ConstQualif::NON_ZERO_SIZED); + Def::AssociatedConst(_) => v.add_type(node_ty), + Def::Const(did) => { + v.promotable &= if let Some(node_id) = v.tcx.map.as_local_node_id(did) { + match v.tcx.map.expect_item(node_id).node { + hir::ItemConst(_, body) => { + v.visit_nested_body(body); + v.tcx.rvalue_promotable_to_static.borrow()[&body.node_id] + } + _ => false + } + } else { + v.tcx.sess.cstore.const_is_rvalue_promotable_to_static(did) + }; } _ => { - v.add_qualif(ConstQualif::NOT_CONST); + v.promotable = false; } } } @@ -560,65 +341,48 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } else { Def::Err }; - let is_const = match def { + match def { Def::StructCtor(_, CtorKind::Fn) | - Def::VariantCtor(_, CtorKind::Fn) => { - // `NON_ZERO_SIZED` is about the call result, not about the ctor itself. - v.add_qualif(ConstQualif::NON_ZERO_SIZED); - true - } + Def::VariantCtor(_, CtorKind::Fn) => {} Def::Fn(did) => { - v.handle_const_fn_call(e, did, node_ty) + v.handle_const_fn_call(did, node_ty) } Def::Method(did) => { match v.tcx.associated_item(did).container { ty::ImplContainer(_) => { - v.handle_const_fn_call(e, did, node_ty) + v.handle_const_fn_call(did, node_ty) } - ty::TraitContainer(_) => false + ty::TraitContainer(_) => v.promotable = false } } - _ => false - }; - if !is_const { - v.add_qualif(ConstQualif::NOT_CONST); + _ => v.promotable = false } } hir::ExprMethodCall(..) => { let method = v.tcx.tables().method_map[&method_call]; - let is_const = match v.tcx.associated_item(method.def_id).container { - ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty), - ty::TraitContainer(_) => false - }; - if !is_const { - v.add_qualif(ConstQualif::NOT_CONST); + match v.tcx.associated_item(method.def_id).container { + ty::ImplContainer(_) => v.handle_const_fn_call(method.def_id, node_ty), + ty::TraitContainer(_) => v.promotable = false } } hir::ExprStruct(..) => { if let ty::TyAdt(adt, ..) = v.tcx.tables().expr_ty(e).sty { // unsafe_cell_type doesn't necessarily exist with no_core if Some(adt.did) == v.tcx.lang_items.unsafe_cell_type() { - v.add_qualif(ConstQualif::MUTABLE_MEM); + v.promotable = false; } } } hir::ExprLit(_) | - hir::ExprAddrOf(..) => { - v.add_qualif(ConstQualif::NON_ZERO_SIZED); - } - - hir::ExprRepeat(..) => { - v.add_qualif(ConstQualif::PREFER_IN_PLACE); - } + hir::ExprAddrOf(..) | + hir::ExprRepeat(..) => {} hir::ExprClosure(..) => { // Paths in constant contexts cannot refer to local variables, // as there are none, and thus closures can't have upvars there. if v.tcx.with_freevars(e.id, |fv| !fv.is_empty()) { - assert!(v.mode == Mode::Var, - "global closures can't capture anything"); - v.add_qualif(ConstQualif::NOT_CONST); + v.promotable = false; } } @@ -647,7 +411,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node hir::ExprAssign(..) | hir::ExprAssignOp(..) | hir::ExprInlineAsm(..) => { - v.add_qualif(ConstQualif::NOT_CONST); + v.promotable = false; } } } @@ -666,7 +430,7 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp Some(Adjust::DerefRef { autoderefs, .. }) => { if (0..autoderefs as u32) .any(|autoderef| v.tcx.tables().is_overloaded_autoderef(e.id, autoderef)) { - v.add_qualif(ConstQualif::NOT_CONST); + v.promotable = false; } } } @@ -676,9 +440,10 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.visit_all_item_likes_in_krate(DepNode::CheckConst, &mut CheckCrateVisitor { tcx: tcx, - mode: Mode::Var, - qualif: ConstQualif::NOT_CONST, - rvalue_borrows: NodeMap(), + in_fn: false, + promotable: false, + mut_rvalue_borrows: NodeSet(), + param_env: tcx.empty_parameter_environment(), }.as_deep_visitor()); tcx.sess.abort_if_errors(); } @@ -687,24 +452,9 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { fn consume(&mut self, _consume_id: ast::NodeId, _consume_span: Span, - cmt: mc::cmt, - _mode: euv::ConsumeMode) { - let mut cur = &cmt; - loop { - match cur.cat { - Categorization::StaticItem => { - break; - } - Categorization::Deref(ref cmt, ..) | - Categorization::Downcast(ref cmt, _) | - Categorization::Interior(ref cmt, _) => cur = cmt, + _cmt: mc::cmt, + _mode: euv::ConsumeMode) {} - Categorization::Rvalue(..) | - Categorization::Upvar(..) | - Categorization::Local(..) => break, - } - } - } fn borrow(&mut self, borrow_id: ast::NodeId, _borrow_span: Span, @@ -731,21 +481,9 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { // Ignore the dummy immutable borrow created by EUV. break; } - let mutbl = bk.to_mutbl_lossy(); - if mutbl == hir::MutMutable && self.mode == Mode::StaticMut { - // Mutable slices are the only `&mut` allowed in - // globals, but only in `static mut`, nowhere else. - // FIXME: This exception is really weird... there isn't - // any fundamental reason to restrict this based on - // type of the expression. `&mut [1]` has exactly the - // same representation as &mut 1. - match cmt.ty.sty { - ty::TyArray(..) | - ty::TySlice(_) => break, - _ => {} - } + if bk.to_mutbl_lossy() == hir::MutMutable { + self.mut_rvalue_borrows.insert(borrow_id); } - self.record_borrow(borrow_id, mutbl); break; } Categorization::StaticItem => { diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index f7e026866e2df..65a60732fc807 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -115,6 +115,11 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { self.visit_item(nested_item) } + fn visit_nested_trait_item(&mut self, trait_item_id: hir::TraitItemId) { + let nested_trait_item = self.krate.unwrap().trait_item(trait_item_id); + self.visit_trait_item(nested_trait_item) + } + fn visit_nested_impl_item(&mut self, impl_item_id: hir::ImplItemId) { let nested_impl_item = self.krate.unwrap().impl_item(impl_item_id); self.visit_impl_item(nested_impl_item) @@ -172,7 +177,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { fn visit_fn(&mut self, fk: hir_visit::FnKind<'v>, fd: &'v hir::FnDecl, - b: hir::ExprId, + b: hir::BodyId, s: Span, id: NodeId) { self.record("FnDecl", Id::None, fd); diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 10f464a9901d0..df9fe00e9a88e 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -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)); } 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) => { if opt_expr.is_some() { diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs index ddb5af1e80c34..3da4f24b6c2fe 100644 --- a/src/librustc_passes/rvalues.rs +++ b/src/librustc_passes/rvalues.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RvalueContext<'a, 'tcx> { fn visit_fn(&mut self, fk: intravisit::FnKind<'tcx>, fd: &'tcx hir::FnDecl, - b: hir::ExprId, + b: hir::BodyId, s: Span, fn_id: ast::NodeId) { // FIXME (@jroesch) change this to be an inference context @@ -50,9 +50,9 @@ impl<'a, 'tcx> Visitor<'tcx> for RvalueContext<'a, 'tcx> { tcx: infcx.tcx, param_env: ¶m_env }; - let body = infcx.tcx.map.expr(b); + let body = infcx.tcx.map.body(b); let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx); - euv.walk_fn(fd, body); + euv.consume_body(body); }); intravisit::walk_fn(self, fk, fd, b, s, fn_id) } diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs index b5be4aa5e64e2..ba4fc57276b2c 100644 --- a/src/librustc_passes/static_recursion.rs +++ b/src/librustc_passes/static_recursion.rs @@ -30,7 +30,7 @@ struct CheckCrateVisitor<'a, 'ast: 'a> { // variant definitions with the discriminant expression that applies to // each one. If the variant uses the default values (starting from `0`), // then `None` is stored. - discriminant_map: NodeMap>, + discriminant_map: NodeMap>, detected_recursive_ids: NodeSet, } @@ -66,7 +66,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> { fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) { match ti.node { - hir::ConstTraitItem(_, ref default) => { + hir::TraitItemKind::Const(_, ref default) => { if let Some(_) = *default { let mut recursion_visitor = CheckItemRecursionVisitor::new(self, &ti.span); recursion_visitor.visit_trait_item(ti); @@ -108,7 +108,7 @@ struct CheckItemRecursionVisitor<'a, 'b: 'a, 'ast: 'b> { root_span: &'b Span, sess: &'b Session, ast_map: &'b ast_map::Map<'ast>, - discriminant_map: &'a mut NodeMap>, + discriminant_map: &'a mut NodeMap>, idstack: Vec, 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()); // When we find an expression, every variant currently on the stack // 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 { 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::NodeId) { let variant_id = variant.node.data.id(); - let maybe_expr; - 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 { + let maybe_expr = *self.discriminant_map.get(&variant_id).unwrap_or_else(|| { span_bug!(variant.span, "`check_static_recursion` attempted to visit \ variant with unknown discriminant") - } + }); // If `maybe_expr` is `None`, that's because no discriminant is // specified that affects this variant. Thus, no risk of recursion. 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); } } diff --git a/src/librustc_plugin/build.rs b/src/librustc_plugin/build.rs index 75046f6aeb874..34ebd12de9c18 100644 --- a/src/librustc_plugin/build.rs +++ b/src/librustc_plugin/build.rs @@ -33,6 +33,9 @@ impl<'v> ItemLikeVisitor<'v> for RegistrarFinder { } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index ca3e4e1c762c7..81863a3fadfd3 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -160,21 +160,19 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } hir::ItemImpl(.., None, _, ref impl_item_refs) => { for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.map.impl_item(impl_item_ref.id); - if impl_item.vis == hir::Public { - self.update(impl_item.id, item_level); + if impl_item_ref.vis == hir::Public { + self.update(impl_item_ref.id.node_id, item_level); } } } hir::ItemImpl(.., Some(_), _, ref impl_item_refs) => { for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.map.impl_item(impl_item_ref.id); - self.update(impl_item.id, item_level); + self.update(impl_item_ref.id.node_id, item_level); } } - hir::ItemTrait(.., ref trait_items) => { - for trait_item in trait_items { - self.update(trait_item.id, item_level); + hir::ItemTrait(.., ref trait_item_refs) => { + for trait_item_ref in trait_item_refs { + self.update(trait_item_ref.id.node_id, item_level); } } hir::ItemStruct(ref def, _) | hir::ItemUnion(ref def, _) => { @@ -214,15 +212,16 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { self.reach(item.id).generics().predicates().item_type(); } } - hir::ItemTrait(.., ref trait_items) => { + hir::ItemTrait(.., ref trait_item_refs) => { if item_level.is_some() { self.reach(item.id).generics().predicates(); - for trait_item in trait_items { - let mut reach = self.reach(trait_item.id); + for trait_item_ref in trait_item_refs { + let mut reach = self.reach(trait_item_ref.id.node_id); reach.generics().predicates(); - if let hir::TypeTraitItem(_, None) = trait_item.node { + if trait_item_ref.kind == hir::AssociatedItemKind::Type && + !trait_item_ref.defaultness.has_value() { // No type to visit. } else { reach.item_type(); @@ -231,12 +230,12 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } // Visit everything except for private impl items - hir::ItemImpl(.., ref trait_ref, _, ref impl_items) => { + hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => { if item_level.is_some() { self.reach(item.id).generics().predicates().impl_trait_ref(); - for impl_item in impl_items { - let id = impl_item.id.node_id; + for impl_item_ref in impl_item_refs { + let id = impl_item_ref.id.node_id; if trait_ref.is_some() || self.get(id).is_some() { self.reach(id).generics().predicates().item_type(); } @@ -789,22 +788,19 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // methods will be visible as `Public::foo`. let mut found_pub_static = false; for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.map.impl_item(impl_item_ref.id); - match impl_item.node { - hir::ImplItemKind::Const(..) => { - if self.item_is_public(&impl_item.id, &impl_item.vis) { + if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) { + let impl_item = self.tcx.map.impl_item(impl_item_ref.id); + match impl_item_ref.kind { + hir::AssociatedItemKind::Const => { found_pub_static = true; intravisit::walk_impl_item(self, impl_item); } - } - hir::ImplItemKind::Method(ref sig, _) => { - if !sig.decl.has_self() && - self.item_is_public(&impl_item.id, &impl_item.vis) { + hir::AssociatedItemKind::Method { has_self: false } => { found_pub_static = true; intravisit::walk_impl_item(self, impl_item); } + _ => {} } - _ => {} } } if found_pub_static { @@ -1092,14 +1088,15 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> self.inner_visibility = item_visibility; intravisit::walk_item(self, item); } - hir::ItemTrait(.., ref trait_items) => { + hir::ItemTrait(.., ref trait_item_refs) => { self.check(item.id, item_visibility).generics().predicates(); - for trait_item in trait_items { - let mut check = self.check(trait_item.id, item_visibility); + for trait_item_ref in trait_item_refs { + let mut check = self.check(trait_item_ref.id.node_id, item_visibility); check.generics().predicates(); - if let hir::TypeTraitItem(_, None) = trait_item.node { + if trait_item_ref.kind == hir::AssociatedItemKind::Type && + !trait_item_ref.defaultness.has_value() { // No type to visit. } else { check.item_type(); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a0af4c4565359..865195d3db488 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -571,6 +571,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { fn visit_ty(&mut self, ty: &'tcx Ty) { if let TyKind::Path(ref qself, ref path) = ty.node { self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type); + } else if let TyKind::ImplicitSelf = ty.node { + let self_ty = keywords::SelfType.ident(); + let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.span)) + .map_or(Def::Err, |d| d.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); } @@ -741,6 +752,13 @@ impl<'a> LexicalScopeBinding<'a> { _ => None, } } + + fn def(self) -> Def { + match self { + LexicalScopeBinding::Item(binding) => binding.def(), + LexicalScopeBinding::Def(def) => def, + } + } } #[derive(Clone)] @@ -2721,6 +2739,13 @@ impl<'a> Resolver<'a> { 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) => { self.resolve_expr(callee, Some(&expr.node)); for argument in arguments { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 491521a323949..43e3b1dd2b50a 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -349,7 +349,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { match item.node { hir::ItemImpl(.., ref ty, _) => { let mut result = String::from("<"); - result.push_str(&rustc::hir::print::ty_to_string(&ty)); + result.push_str(&self.tcx.map.node_to_pretty_string(ty.id)); let trait_id = self.tcx.trait_id_of_impl(impl_id); let mut decl_id = None; diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 84222bfe56eee..2bc42a461528d 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -202,8 +202,6 @@ use rustc::mir::{self, Location}; use rustc::mir::visit as mir_visit; use rustc::mir::visit::Visitor as MirVisitor; -use rustc_const_eval as const_eval; - use syntax::abi::Abi; use syntax_pos::DUMMY_SP; use base::custom_coerce_unsize_info; @@ -344,19 +342,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>, recursion_depth_reset = None; - // Scan the MIR in order to find function calls, closures, and - // drop-glue - let mir = scx.tcx().item_mir(def_id); - - let empty_substs = scx.empty_substs_for_def_id(def_id); - let visitor = MirNeighborCollector { - scx: scx, - mir: &mir, - output: &mut neighbors, - param_substs: empty_substs - }; - - visit_mir_and_promoted(visitor, &mir); + collect_neighbours(scx, Instance::mono(scx, def_id), &mut neighbors); } TransItem::Fn(instance) => { // Keep track of the monomorphization recursion depth @@ -365,18 +351,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>, recursion_depths)); check_type_length_limit(scx.tcx(), instance); - // Scan the MIR in order to find function calls, closures, and - // drop-glue - let mir = scx.tcx().item_mir(instance.def); - - let visitor = MirNeighborCollector { - scx: scx, - mir: &mir, - output: &mut neighbors, - param_substs: instance.substs - }; - - visit_mir_and_promoted(visitor, &mir); + collect_neighbours(scx, instance, &mut neighbors); } } @@ -563,33 +538,12 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { // This is not a callee, but we still have to look for // references to `const` items if let mir::Literal::Item { def_id, substs } = constant.literal { - let tcx = self.scx.tcx(); let substs = monomorphize::apply_param_substs(self.scx, self.param_substs, &substs); - // If the constant referred to here is an associated - // item of a trait, we need to resolve it to the actual - // constant in the corresponding impl. Luckily - // const_eval::lookup_const_by_id() does that for us. - if let Some((expr, _)) = const_eval::lookup_const_by_id(tcx, - def_id, - Some(substs)) { - // The hir::Expr we get here is the initializer of - // the constant, what we really want is the item - // DefId. - let const_node_id = tcx.map.get_parent(expr.id); - let def_id = if tcx.map.is_inlined_node_id(const_node_id) { - tcx.sess.cstore.defid_for_inlined_node(const_node_id).unwrap() - } else { - tcx.map.local_def_id(const_node_id) - }; - - collect_const_item_neighbours(self.scx, - def_id, - substs, - self.output); - } + let instance = Instance::new(def_id, substs).resolve_const(self.scx); + collect_neighbours(self.scx, instance, self.output); } None @@ -1122,6 +1076,11 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { } } + fn visit_trait_item(&mut self, _: &'v hir::TraitItem) { + // Even if there's a default body with no explicit generics, + // it's still generic over some `Self: Trait`, so not a root. + } + fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) { match ii.node { hir::ImplItemKind::Method(hir::MethodSig { @@ -1228,29 +1187,20 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, ' } } -// There are no translation items for constants themselves but their -// initializers might still contain something that produces translation items, -// such as cast that introduce a new vtable. -fn collect_const_item_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, - def_id: DefId, - substs: &'tcx Substs<'tcx>, - output: &mut Vec>) +/// Scan the MIR in order to find function calls, closures, and drop-glue +fn collect_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, + instance: Instance<'tcx>, + output: &mut Vec>) { - // Scan the MIR in order to find function calls, closures, and - // drop-glue - let mir = scx.tcx().item_mir(def_id); + let mir = scx.tcx().item_mir(instance.def); - let visitor = MirNeighborCollector { + let mut visitor = MirNeighborCollector { scx: scx, mir: &mir, output: output, - param_substs: substs + param_substs: instance.substs }; - visit_mir_and_promoted(visitor, &mir); -} - -fn visit_mir_and_promoted<'tcx, V: MirVisitor<'tcx>>(mut visitor: V, mir: &mir::Mir<'tcx>) { visitor.visit_mir(&mir); for promoted in &mir.promoted { visitor.visit_mir(promoted); diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index f292a70965004..d9179d6a6fa73 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -737,14 +737,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.local().drop_glues } - pub fn local_node_for_inlined_defid<'a>(&'a self, def_id: DefId) -> Option { - self.sess().cstore.local_node_for_inlined_defid(def_id) - } - - pub fn defid_for_inlined_node<'a>(&'a self, node_id: ast::NodeId) -> Option { - self.sess().cstore.defid_for_inlined_node(node_id) - } - pub fn instances<'a>(&'a self) -> &'a RefCell, ValueRef>> { &self.local().instances } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 08f68f8d49c78..1cedaa0a4e1a4 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -18,7 +18,6 @@ use rustc::hir::def_id::DefId; use rustc::infer::TransNormalize; use rustc::mir; use rustc::mir::tcx::LvalueTy; -use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::subst::Substs; @@ -36,7 +35,7 @@ use type_::Type; use value::Value; use syntax::ast; -use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::Span; use std::fmt; use std::ptr; @@ -238,24 +237,10 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } fn trans_def(ccx: &'a CrateContext<'a, 'tcx>, - mut instance: Instance<'tcx>, + instance: Instance<'tcx>, args: IndexVec>) -> Result, ConstEvalErr> { - // Try to resolve associated constants. - if let Some(trait_id) = ccx.tcx().trait_of_item(instance.def) { - let trait_ref = ty::TraitRef::new(trait_id, instance.substs); - let trait_ref = ty::Binder(trait_ref); - let vtable = common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref); - if let traits::VtableImpl(vtable_impl) = vtable { - let name = ccx.tcx().item_name(instance.def); - let ac = ccx.tcx().associated_items(vtable_impl.impl_def_id) - .find(|item| item.kind == ty::AssociatedKind::Const && item.name == name); - if let Some(ac) = ac { - instance = Instance::new(ac.def_id, vtable_impl.substs); - } - } - } - + let instance = instance.resolve_const(ccx.shared()); let mir = ccx.tcx().item_mir(instance.def); MirConstContext::new(ccx, &mir, instance.substs, args).trans() } diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 8f05cc793ef22..4b31d5b7f88de 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -11,11 +11,15 @@ use common::*; use rustc::hir::def_id::DefId; use rustc::infer::TransNormalize; +use rustc::traits; use rustc::ty::fold::{TypeFolder, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::ppaux; use rustc::util::common::MemoizationMap; + +use syntax::codemap::DUMMY_SP; + use std::fmt; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] @@ -30,15 +34,35 @@ impl<'tcx> fmt::Display for Instance<'tcx> { } } -impl<'tcx> Instance<'tcx> { +impl<'a, 'tcx> Instance<'tcx> { pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> Instance<'tcx> { assert!(substs.regions().all(|&r| r == ty::ReErased)); Instance { def: def_id, substs: substs } } - pub fn mono<'a>(scx: &SharedCrateContext<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> { + + pub fn mono(scx: &SharedCrateContext<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> { Instance::new(def_id, scx.empty_substs_for_def_id(def_id)) } + + /// For associated constants from traits, return the impl definition. + pub fn resolve_const(&self, scx: &SharedCrateContext<'a, 'tcx>) -> Self { + if let Some(trait_id) = scx.tcx().trait_of_item(self.def) { + let trait_ref = ty::TraitRef::new(trait_id, self.substs); + let trait_ref = ty::Binder(trait_ref); + let vtable = fulfill_obligation(scx, DUMMY_SP, trait_ref); + if let traits::VtableImpl(vtable_impl) = vtable { + let name = scx.tcx().item_name(self.def); + let ac = scx.tcx().associated_items(vtable_impl.impl_def_id) + .find(|item| item.kind == ty::AssociatedKind::Const && item.name == name); + if let Some(ac) = ac { + return Instance::new(ac.def_id, vtable_impl.substs); + } + } + } + + *self + } } /// Monomorphizes a type from the AST by first applying the in-scope diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 598003a392512..75c25a605af25 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -50,10 +50,9 @@ use rustc_const_eval::eval_length; use rustc_data_structures::accumulate_vec::AccumulateVec; -use hir::{self, SelfKind}; +use hir; use hir::def::Def; use hir::def_id::DefId; -use hir::print as pprust; use middle::resolve_lifetime as rl; use rustc::lint; use rustc::ty::subst::{Kind, Subst, Substs}; @@ -227,6 +226,7 @@ pub fn ast_region_to_region<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } fn report_elision_failure( + tcx: TyCtxt, db: &mut DiagnosticBuilder, params: Vec) { @@ -241,13 +241,14 @@ fn report_elision_failure( for (i, info) in elided_params.into_iter().enumerate() { let ElisionFailureInfo { - name, lifetime_count: n, have_bound_regions + parent, index, lifetime_count: n, have_bound_regions } = info; - let help_name = if name.is_empty() { - format!("argument {}", i + 1) + let help_name = if let Some(body) = parent { + let arg = &tcx.map.body(body).arguments[index]; + format!("`{}`", tcx.map.node_to_pretty_string(arg.pat.id)) } else { - format!("`{}`", name) + format!("argument {}", index + 1) }; m.push_str(&(if n == 1 { @@ -315,7 +316,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { err.span_label(ampersand_span, &format!("expected lifetime parameter")); if let Some(params) = params { - report_elision_failure(&mut err, params); + report_elision_failure(self.tcx(), &mut err, params); } err.emit(); ty::ReStatic @@ -540,15 +541,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { /// corresponding to each input type/pattern. fn find_implied_output_region(&self, input_tys: &[Ty<'tcx>], - input_pats: I) -> ElidedLifetime - where I: Iterator + parent: Option, + input_indices: I) -> ElidedLifetime + where I: Iterator { let tcx = self.tcx(); let mut lifetimes_for_params = Vec::with_capacity(input_tys.len()); let mut possible_implied_output_region = None; let mut lifetimes = 0; - for input_type in input_tys.iter() { + for (input_type, index) in input_tys.iter().zip(input_indices) { let mut regions = FxHashSet(); let have_bound_regions = tcx.collect_regions(input_type, &mut regions); @@ -564,11 +566,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { possible_implied_output_region = regions.iter().cloned().next(); } - // Use a placeholder for `name` because computing it can be - // expensive and we don't want to do it until we know it's - // necessary. lifetimes_for_params.push(ElisionFailureInfo { - name: String::new(), + parent: parent, + index: index, lifetime_count: regions.len(), have_bound_regions: have_bound_regions }); @@ -577,11 +577,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { if lifetimes == 1 { Ok(*possible_implied_output_region.unwrap()) } else { - // Fill in the expensive `name` fields now that we know they're - // needed. - for (info, input_pat) in lifetimes_for_params.iter_mut().zip(input_pats) { - info.name = input_pat; - } Err(Some(lifetimes_for_params)) } } @@ -618,8 +613,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let inputs = self.tcx().mk_type_list(data.inputs.iter().map(|a_t| { self.ast_ty_arg_to_ty(&binding_rscope, None, region_substs, a_t) })); - let input_params = iter::repeat(String::new()).take(inputs.len()); - let implied_output_region = self.find_implied_output_region(&inputs, input_params); + let input_params = 0..inputs.len(); + let implied_output_region = self.find_implied_output_region(&inputs, None, input_params); let (output, output_span) = match data.output { Some(ref output_ty) => { @@ -689,7 +684,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } _ => { span_fatal!(self.tcx().sess, path.span, E0245, "`{}` is not a trait", - path); + self.tcx().map.node_to_pretty_string(trait_ref.ref_id)); } } } @@ -976,7 +971,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let mut err = struct_span_err!(tcx.sess, ty.span, E0178, "expected a path on the left-hand side \ of `+`, not `{}`", - pprust::ty_to_string(ty)); + tcx.map.node_to_pretty_string(ty.id)); err.span_label(ty.span, &format!("expected a path")); let hi = bounds.iter().map(|x| match *x { hir::TraitTyParamBound(ref tr, _) => tr.span.hi, @@ -988,22 +983,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { expn_id: ty.span.expn_id, }); match (&ty.node, full_span) { - (&hir::TyRptr(None, ref mut_ty), Some(full_span)) => { - let mutbl_str = if mut_ty.mutbl == hir::MutMutable { "mut " } else { "" }; + (&hir::TyRptr(ref lifetime, ref mut_ty), Some(full_span)) => { + let ty_str = hir::print::to_string(&tcx.map, |s| { + use syntax::print::pp::word; + use syntax::print::pprust::PrintState; + + word(&mut s.s, "&")?; + s.print_opt_lifetime(lifetime)?; + s.print_mutability(mut_ty.mutbl)?; + s.popen()?; + s.print_type(&mut_ty.ty)?; + s.print_bounds(" +", bounds)?; + s.pclose() + }); err.span_suggestion(full_span, "try adding parentheses (per RFC 438):", - format!("&{}({} +{})", - mutbl_str, - pprust::ty_to_string(&mut_ty.ty), - pprust::bounds_to_string(bounds))); - } - (&hir::TyRptr(Some(ref lt), ref mut_ty), Some(full_span)) => { - let mutbl_str = if mut_ty.mutbl == hir::MutMutable { "mut " } else { "" }; - err.span_suggestion(full_span, "try adding parentheses (per RFC 438):", - format!("&{} {}({} +{})", - pprust::lifetime_to_string(lt), - mutbl_str, - pprust::ty_to_string(&mut_ty.ty), - pprust::bounds_to_string(bounds))); + ty_str); } _ => { @@ -1572,6 +1566,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { bf.abi, None, &bf.decl, + None, anon_scope, anon_scope); @@ -1664,8 +1659,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 } - hir::TyArray(ref ty, ref e) => { - if let Ok(length) = eval_length(tcx.global_tcx(), &e, "array length") { + hir::TyArray(ref ty, 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) } else { self.tcx().types.err @@ -1695,26 +1691,28 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { pub fn ty_of_arg(&self, rscope: &RegionScope, - a: &hir::Arg, + ty: &hir::Ty, expected_ty: Option>) -> Ty<'tcx> { - match a.ty.node { + match ty.node { hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(), - hir::TyInfer => self.ty_infer(a.ty.span), - _ => self.ast_ty_to_ty(rscope, &a.ty), + hir::TyInfer => self.ty_infer(ty.span), + _ => self.ast_ty_to_ty(rscope, ty), } } pub fn ty_of_method(&self, sig: &hir::MethodSig, - untransformed_self_ty: Ty<'tcx>, + opt_self_value_ty: Option>, + body: Option, anon_scope: Option) -> &'tcx ty::BareFnTy<'tcx> { self.ty_of_method_or_bare_fn(sig.unsafety, sig.abi, - Some(untransformed_self_ty), + opt_self_value_ty, &sig.decl, + body, None, anon_scope) } @@ -1723,16 +1721,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { unsafety: hir::Unsafety, abi: abi::Abi, decl: &hir::FnDecl, + body: hir::BodyId, anon_scope: Option) -> &'tcx ty::BareFnTy<'tcx> { - self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope) + self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, Some(body), None, anon_scope) } fn ty_of_method_or_bare_fn(&self, unsafety: hir::Unsafety, abi: abi::Abi, - opt_untransformed_self_ty: Option>, + opt_self_value_ty: Option>, decl: &hir::FnDecl, + body: Option, arg_anon_scope: Option, ret_anon_scope: Option) -> &'tcx ty::BareFnTy<'tcx> @@ -1743,38 +1743,29 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // declaration are bound to that function type. let rb = MaybeWithAnonTypes::new(BindingRscope::new(), arg_anon_scope); - // `implied_output_region` is the region that will be assumed for any - // region parameters in the return type. In accordance with the rules for - // lifetime elision, we can determine it in two ways. First (determined - // here), if self is by-reference, then the implied output region is the - // region of the self parameter. - let (self_ty, explicit_self) = match (opt_untransformed_self_ty, decl.get_self()) { - (Some(untransformed_self_ty), Some(explicit_self)) => { - let self_type = self.determine_self_type(&rb, untransformed_self_ty, - &explicit_self); - (Some(self_type), Some(ExplicitSelf::determine(untransformed_self_ty, self_type))) - } - _ => (None, None), - }; + let input_tys: Vec = + decl.inputs.iter().map(|a| self.ty_of_arg(&rb, a, None)).collect(); - // HACK(eddyb) replace the fake self type in the AST with the actual type. - let arg_params = if self_ty.is_some() { - &decl.inputs[1..] - } else { - &decl.inputs[..] - }; - let arg_tys: Vec = - arg_params.iter().map(|a| self.ty_of_arg(&rb, a, None)).collect(); + let has_self = opt_self_value_ty.is_some(); + let explicit_self = opt_self_value_ty.map(|self_value_ty| { + ExplicitSelf::determine(self_value_ty, input_tys[0]) + }); - // Second, if there was exactly one lifetime (either a substitution or a - // reference) in the arguments, then any anonymous regions in the output - // have that lifetime. let implied_output_region = match explicit_self { + // `implied_output_region` is the region that will be assumed for any + // region parameters in the return type. In accordance with the rules for + // lifetime elision, we can determine it in two ways. First (determined + // here), if self is by-reference, then the implied output region is the + // region of the self parameter. Some(ExplicitSelf::ByReference(region, _)) => Ok(*region), + + // Second, if there was exactly one lifetime (either a substitution or a + // reference) in the arguments, then any anonymous regions in the output + // have that lifetime. _ => { - self.find_implied_output_region(&arg_tys, - arg_params.iter() - .map(|a| pprust::pat_to_string(&a.pat))) + let arg_tys = &input_tys[has_self as usize..]; + let arg_params = has_self as usize..input_tys.len(); + self.find_implied_output_region(arg_tys, body, arg_params) } }; @@ -1793,37 +1784,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { unsafety: unsafety, abi: abi, sig: ty::Binder(self.tcx().mk_fn_sig( - self_ty.into_iter().chain(arg_tys), + input_tys.into_iter(), output_ty, decl.variadic )), }) } - fn determine_self_type<'a>(&self, - rscope: &RegionScope, - untransformed_self_ty: Ty<'tcx>, - explicit_self: &hir::ExplicitSelf) - -> Ty<'tcx> - { - match explicit_self.node { - SelfKind::Value(..) => untransformed_self_ty, - SelfKind::Region(ref lifetime, mutability) => { - let region = - self.opt_ast_region_to_region( - rscope, - explicit_self.span, - lifetime); - self.tcx().mk_ref(region, - ty::TypeAndMut { - ty: untransformed_self_ty, - mutbl: mutability - }) - } - SelfKind::Explicit(ref ast_type, _) => self.ast_ty_to_ty(rscope, &ast_type) - } - } - pub fn ty_of_closure(&self, unsafety: hir::Unsafety, decl: &hir::FnDecl, diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index ff50ee11b390e..9b86196b3ece2 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -527,7 +527,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let report_unexpected_def = |def: Def| { span_err!(tcx.sess, pat.span, E0533, "expected unit struct/variant or constant, found {} `{}`", - def.kind_name(), qpath); + def.kind_name(), + hir::print::to_string(&tcx.map, |s| s.print_qpath(qpath, false))); }; // Resolve the path and check the definition for errors. @@ -568,7 +569,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; let report_unexpected_def = |def: Def| { let msg = format!("expected tuple struct/variant, found {} `{}`", - def.kind_name(), qpath); + def.kind_name(), + hir::print::to_string(&tcx.map, |s| s.print_qpath(qpath, false))); struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg) .span_label(pat.span, &format!("not a tuple variant or struct")).emit(); on_error(); diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 4fba29def226c..0b9cf38fa0733 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -13,7 +13,6 @@ use super::{DeferredCallResolution, Expectation, FnCtxt, TupleArgumentsFlag}; use CrateCtxt; use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; -use hir::print; use rustc::{infer, traits}; use rustc::ty::{self, LvaluePreference, Ty}; use syntax::symbol::Symbol; @@ -203,7 +202,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let &ty::TyAdt(adt_def, ..) = t { if adt_def.is_enum() { if let hir::ExprCall(ref expr, _) = call_expr.node { - unit_variant = Some(print::expr_to_string(expr)) + unit_variant = Some(self.tcx.map.node_to_pretty_string(expr.id)) } } } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 1d81ed7d35956..9412c9105c7aa 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -25,7 +25,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expr: &hir::Expr, _capture: hir::CaptureClause, decl: &'gcx hir::FnDecl, - body_id: hir::ExprId, + body_id: hir::BodyId, expected: Expectation<'tcx>) -> Ty<'tcx> { 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), 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) } @@ -47,7 +47,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expr: &hir::Expr, opt_kind: Option, decl: &'gcx hir::FnDecl, - body: &'gcx hir::Expr, + body: &'gcx hir::Body, expected_sig: Option>) -> Ty<'tcx> { 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); - let fn_sig = self.tcx - .liberate_late_bound_regions(self.tcx.region_maps.call_site_extent(expr.id, body.id), - &fn_ty.sig); - let fn_sig = (**self).normalize_associated_types_in(body.span, body.id, &fn_sig); + let extent = self.tcx.region_maps.call_site_extent(expr.id, body.value.id); + let fn_sig = self.tcx.liberate_late_bound_regions(extent, &fn_ty.sig); + let fn_sig = self.inh.normalize_associated_types_in(body.value.span, + body.value.id, &fn_sig); check_fn(self, hir::Unsafety::Normal, @@ -84,7 +84,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { &fn_sig, decl, expr.id, - &body); + body); // Tuple up the arguments and insert the resulting function type into // the `closures` table. diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 478de1673170f..be10b77bd8b90 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -8,14 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::hir; +use rustc::hir::{self, ImplItemKind, TraitItemKind}; use rustc::infer::{self, InferOk}; use rustc::middle::free_region::FreeRegionMap; use rustc::ty; use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc::ty::error::{ExpectedFound, TypeError}; use rustc::ty::subst::{Subst, Substs}; -use rustc::hir::{ImplItemKind, TraitItem_, Ty_}; use rustc::util::common::ErrorReported; use syntax::ast; @@ -450,37 +449,24 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a TypeError::Mutability => { if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m.def_id) { let trait_m_iter = match tcx.map.expect_trait_item(trait_m_node_id).node { - TraitItem_::MethodTraitItem(ref trait_m_sig, _) => { + TraitItemKind::Method(ref trait_m_sig, _) => { trait_m_sig.decl.inputs.iter() } - _ => bug!("{:?} is not a MethodTraitItem", trait_m), + _ => bug!("{:?} is not a TraitItemKind::Method", trait_m), }; - impl_m_iter.zip(trait_m_iter) - .find(|&(ref impl_arg, ref trait_arg)| { - match (&impl_arg.ty.node, &trait_arg.ty.node) { - (&Ty_::TyRptr(_, ref impl_mt), &Ty_::TyRptr(_, ref trait_mt)) | - (&Ty_::TyPtr(ref impl_mt), &Ty_::TyPtr(ref trait_mt)) => { - impl_mt.mutbl != trait_mt.mutbl - } - _ => false, - } - }) - .map(|(ref impl_arg, ref trait_arg)| { - match (impl_arg.to_self(), trait_arg.to_self()) { - (Some(impl_self), Some(trait_self)) => { - (impl_self.span, Some(trait_self.span)) - } - (None, None) => (impl_arg.ty.span, Some(trait_arg.ty.span)), - _ => { - bug!("impl and trait fns have different first args, impl: \ - {:?}, trait: {:?}", - impl_arg, - trait_arg) - } - } - }) - .unwrap_or((cause.span, tcx.map.span_if_local(trait_m.def_id))) + impl_m_iter.zip(trait_m_iter).find(|&(ref impl_arg, ref trait_arg)| { + match (&impl_arg.node, &trait_arg.node) { + (&hir::TyRptr(_, ref impl_mt), &hir::TyRptr(_, ref trait_mt)) | + (&hir::TyPtr(ref impl_mt), &hir::TyPtr(ref trait_mt)) => { + impl_mt.mutbl != trait_mt.mutbl + } + _ => false, + } + }).map(|(ref impl_arg, ref trait_arg)| { + (impl_arg.span, Some(trait_arg.span)) + }) + .unwrap_or_else(|| (cause.span, tcx.map.span_if_local(trait_m.def_id))) } else { (cause.span, tcx.map.span_if_local(trait_m.def_id)) } @@ -489,10 +475,10 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m.def_id) { let (trait_m_output, trait_m_iter) = match tcx.map.expect_trait_item(trait_m_node_id).node { - TraitItem_::MethodTraitItem(ref trait_m_sig, _) => { + TraitItemKind::Method(ref trait_m_sig, _) => { (&trait_m_sig.decl.output, trait_m_sig.decl.inputs.iter()) } - _ => bug!("{:?} is not a MethodTraitItem", trait_m), + _ => bug!("{:?} is not a TraitItemKind::Method", trait_m), }; let impl_iter = impl_sig.inputs().iter(); @@ -503,7 +489,7 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a .filter_map(|(((impl_arg_ty, trait_arg_ty), impl_arg), trait_arg)| { match infcx.sub_types(true, &cause, trait_arg_ty, impl_arg_ty) { Ok(_) => None, - Err(_) => Some((impl_arg.ty.span, Some(trait_arg.ty.span))), + Err(_) => Some((impl_arg.span, Some(trait_arg.span))), } }) .next() @@ -688,13 +674,13 @@ fn compare_number_of_method_arguments<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let trait_m_node_id = tcx.map.as_local_node_id(trait_m.def_id); let trait_span = if let Some(trait_id) = trait_m_node_id { match tcx.map.expect_trait_item(trait_id).node { - TraitItem_::MethodTraitItem(ref trait_m_sig, _) => { + TraitItemKind::Method(ref trait_m_sig, _) => { if let Some(arg) = trait_m_sig.decl.inputs.get(if trait_number_args > 0 { trait_number_args - 1 } else { 0 }) { - Some(arg.pat.span) + Some(arg.span) } else { trait_item_span } @@ -712,7 +698,7 @@ fn compare_number_of_method_arguments<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } else { 0 }) { - arg.pat.span + arg.span } else { impl_m_span } @@ -839,7 +825,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Add a label to the Span containing just the type of the item let trait_c_node_id = tcx.map.as_local_node_id(trait_c.def_id).unwrap(); let trait_c_span = match tcx.map.expect_trait_item(trait_c_node_id).node { - TraitItem_::ConstTraitItem(ref ty, _) => ty.span, + TraitItemKind::Const(ref ty, _) => ty.span, _ => bug!("{:?} is not a trait const", trait_c), }; diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 183a2a48ff523..c733c0856c6da 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -48,7 +48,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let i_n_tps = tcx.item_generics(def_id).types.len(); if i_n_tps != n_tps { let span = match it.node { - hir::ForeignItemFn(_, ref generics) => generics.span, + hir::ForeignItemFn(_, _, ref generics) => generics.span, hir::ForeignItemStatic(..) => it.span }; diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 86bfede87b333..04ec9292d1410 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -26,7 +26,6 @@ use syntax::ast; use errors::DiagnosticBuilder; use syntax_pos::Span; -use rustc::hir::print as pprust; use rustc::hir; use rustc::infer::type_variable::TypeVariableOrigin; @@ -266,7 +265,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let msg = if let Some(callee) = rcvr_expr { format!("{}; use overloaded call notation instead (e.g., `{}()`)", msg, - pprust::expr_to_string(callee)) + self.tcx.map.node_to_pretty_string(callee.id)) } else { msg }; @@ -463,6 +462,9 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> { } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a2dceed8d2653..7275fbd12036b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -122,7 +122,6 @@ use syntax_pos::{self, BytePos, Span, DUMMY_SP}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::{self, PatKind}; -use rustc::hir::print as pprust; use rustc::middle::lang_items; use rustc_back::slice; use rustc_const_eval::eval_length; @@ -550,14 +549,25 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { fn visit_ty(&mut self, t: &'tcx hir::Ty) { match t.node { - hir::TyArray(_, ref expr) => { - check_const_with_type(self.ccx, &expr, self.ccx.tcx.types.usize, expr.id); + hir::TyArray(_, length) => { + check_const_with_type(self.ccx, length, self.ccx.tcx.types.usize, length.node_id); } _ => {} } 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> { @@ -565,6 +575,10 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> { check_item_body(self.ccx, i); } + fn visit_trait_item(&mut self, _item: &'tcx hir::TraitItem) { + // done as part of `visit_item` above + } + fn visit_impl_item(&mut self, _item: &'tcx hir::ImplItem) { // done as part of `visit_item` above } @@ -635,28 +649,28 @@ pub fn check_drop_impls(ccx: &CrateCtxt) -> CompileResult { fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, decl: &'tcx hir::FnDecl, - body_id: hir::ExprId, + body_id: hir::BodyId, fn_id: ast::NodeId, 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 fn_ty = match raw_fty.sty { 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); ccx.inherited(fn_id).enter(|inh| { // 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 = fn_ty.sig.subst(inh.tcx, &inh.parameter_environment.free_substs); let fn_sig = inh.tcx.liberate_late_bound_regions(fn_scope, &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); @@ -666,8 +680,8 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fcx.check_casts(); fcx.select_all_obligations_or_error(); // Casts can introduce new obligations. - fcx.regionck_fn(fn_id, decl, body_id); - fcx.resolve_type_vars_in_fn(decl, body, fn_id); + fcx.regionck_fn(fn_id, body); + fcx.resolve_type_vars_in_body(body, fn_id); }); } @@ -736,32 +750,9 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { 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) { - 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) => { - intravisit::walk_fn_decl_nopat(self, &function_declaration.decl); - walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes); - } - _ => intravisit::walk_ty(self, t) - } - } - // Don't descend into the bodies of nested closures 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 @@ -776,7 +767,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, fn_sig: &ty::FnSig<'tcx>, decl: &'gcx hir::FnDecl, fn_id: ast::NodeId, - body: &'gcx hir::Expr) + body: &'gcx hir::Body) -> FnCtxt<'a, 'gcx, 'tcx> { let mut fn_sig = fn_sig.clone(); @@ -785,7 +776,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // Create the function context. This is either derived from scratch or, // 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(); *fcx.ps.borrow_mut() = UnsafetyState::function(unsafety, unsafety_id); @@ -794,36 +785,26 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, fn_sig = fcx.tcx.mk_fn_sig(fn_sig.inputs().iter().cloned(), &fcx.ret_ty.unwrap(), fn_sig.variadic); - { - let mut visit = GatherLocalsVisitor { fcx: &fcx, }; - - // Add formal parameters. - for (arg_ty, input) in fn_sig.inputs().iter().zip(&decl.inputs) { - // The type of the argument must be well-formed. - // - // NB -- this is now checked in wfcheck, but that - // currently only results in warnings, so we issue an - // old-style WF obligation here so that we still get the - // errors that we used to get. - fcx.register_old_wf_obligation(arg_ty, input.ty.span, traits::MiscObligation); - - // Create type variables for each argument. - input.pat.each_binding(|_bm, pat_id, sp, _path| { - let var_ty = visit.assign(sp, pat_id, None); - fcx.require_type_is_sized(var_ty, sp, traits::VariableType(pat_id)); - }); + GatherLocalsVisitor { fcx: &fcx, }.visit_body(body); - // Check the pattern. - fcx.check_pat(&input.pat, arg_ty); - fcx.write_ty(input.id, arg_ty); - } + // Add formal parameters. + for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { + // The type of the argument must be well-formed. + // + // NB -- this is now checked in wfcheck, but that + // currently only results in warnings, so we issue an + // old-style WF obligation here so that we still get the + // errors that we used to get. + fcx.register_old_wf_obligation(arg_ty, arg.pat.span, traits::MiscObligation); - visit.visit_expr(body); + // Check the pattern. + fcx.check_pat(&arg.pat, arg_ty); + fcx.write_ty(arg.id, arg_ty); } 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 } @@ -848,8 +829,8 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { let _indenter = indenter(); match it.node { // Consts can play a role in type-checking, so they are included here. - hir::ItemStatic(.., ref e) | - hir::ItemConst(_, ref e) => check_const(ccx, &e, it.id), + hir::ItemStatic(.., e) | + hir::ItemConst(_, e) => check_const(ccx, e, it.id), hir::ItemEnum(ref enum_definition, _) => { check_enum_variants(ccx, it.span, @@ -908,7 +889,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { err.emit(); } - if let hir::ForeignItemFn(ref fn_decl, _) = item.node { + if let hir::ForeignItemFn(ref fn_decl, _, _) = item.node { require_c_abi_if_variadic(ccx.tcx, fn_decl, m.abi, item.span); } } @@ -933,8 +914,8 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { for impl_item_ref in impl_item_refs { let impl_item = ccx.tcx.map.impl_item(impl_item_ref.id); match impl_item.node { - hir::ImplItemKind::Const(_, ref expr) => { - check_const(ccx, &expr, impl_item.id) + hir::ImplItemKind::Const(_, expr) => { + check_const(ccx, expr, impl_item.id) } hir::ImplItemKind::Method(ref sig, body_id) => { check_bare_fn(ccx, &sig.decl, body_id, impl_item.id, impl_item.span); @@ -945,18 +926,19 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { } } } - hir::ItemTrait(.., ref trait_items) => { - for trait_item in trait_items { + hir::ItemTrait(.., ref trait_item_refs) => { + for trait_item_ref in trait_item_refs { + let trait_item = ccx.tcx.map.trait_item(trait_item_ref.id); match trait_item.node { - hir::ConstTraitItem(_, Some(ref expr)) => { - check_const(ccx, &expr, trait_item.id) + hir::TraitItemKind::Const(_, Some(expr)) => { + check_const(ccx, expr, trait_item.id) } - hir::MethodTraitItem(ref sig, Some(body_id)) => { + hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body_id)) => { check_bare_fn(ccx, &sig.decl, body_id, trait_item.id, trait_item.span); } - hir::MethodTraitItem(_, None) | - hir::ConstTraitItem(_, None) | - hir::TypeTraitItem(..) => { + hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) | + hir::TraitItemKind::Const(_, None) | + hir::TraitItemKind::Type(..) => { // Nothing to do. } } @@ -1122,7 +1104,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, compare_impl_method(ccx, &ty_impl_item, impl_item.span, - body_id.node_id(), + body_id.node_id, &ty_trait_item, impl_trait_ref, trait_span, @@ -1132,7 +1114,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, compare_impl_method(ccx, &ty_impl_item, impl_item.span, - body_id.node_id(), + body_id.node_id, &ty_trait_item, impl_trait_ref, trait_span, @@ -1243,37 +1225,38 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, /// Checks a constant with a given type. fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, - expr: &'tcx hir::Expr, + body: hir::BodyId, expected_type: Ty<'tcx>, id: ast::NodeId) { + let body = ccx.tcx.map.body(body); ccx.inherited(id).enter(|inh| { - let fcx = FnCtxt::new(&inh, None, expr.id); - fcx.require_type_is_sized(expected_type, expr.span, traits::ConstSized); + let fcx = FnCtxt::new(&inh, None, body.value.id); + fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); // Gather locals in statics (because of block expressions). // This is technically unnecessary because locals in static items are forbidden, // but prevents type checking from blowing up before const checking can properly // 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.closure_analyze(expr); + fcx.closure_analyze(body); fcx.select_obligations_where_possible(); fcx.check_casts(); fcx.select_all_obligations_or_error(); - fcx.regionck_expr(expr); - fcx.resolve_type_vars_in_expr(expr, id); + fcx.regionck_expr(body); + fcx.resolve_type_vars_in_body(body, id); }); } fn check_const<'a, 'tcx>(ccx: &CrateCtxt<'a,'tcx>, - expr: &'tcx hir::Expr, + body: hir::BodyId, id: ast::NodeId) { 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 @@ -1348,8 +1331,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); for v in vs { - if let Some(ref e) = v.node.disr_expr { - check_const_with_type(ccx, e, repr_type_ty, e.id); + if let Some(e) = v.node.disr_expr { + check_const_with_type(ccx, e, repr_type_ty, e.node_id); } } @@ -1365,11 +1348,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 = ccx.tcx.map.expect_variant(variant_i_node_id); 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) }; let span = match v.node.disr_expr { - Some(ref expr) => expr.span, + Some(expr) => ccx.tcx.map.span(expr.node_id), None => v.span }; struct_span_err!(ccx.tcx.sess, span, E0081, @@ -1643,12 +1626,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match self.locals.borrow().get(&nid) { Some(&t) => t, None => { - struct_span_err!(self.tcx.sess, span, E0513, - "no type for local variable {}", - self.tcx.map.node_to_string(nid)) - .span_label(span, &"no type for variable") - .emit(); - self.tcx.types.err + span_bug!(span, "no type for local variable {}", + self.tcx.map.node_to_string(nid)); } } } @@ -3065,7 +3044,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } ty::TyRawPtr(..) => { err.note(&format!("`{0}` is a native pointer; perhaps you need to deref with \ - `(*{0}).{1}`", pprust::expr_to_string(base), field.node)); + `(*{0}).{1}`", + self.tcx.map.node_to_pretty_string(base.id), + field.node)); } _ => {} } @@ -3479,11 +3460,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.diverges.set(self.diverges.get() | old_diverges); self.has_errors.set(self.has_errors.get() | old_has_errors); - debug!("type of expr({}) {} is...", expr.id, - pprust::expr_to_string(expr)); - debug!("... {:?}, expected is {:?}", - ty, - expected); + debug!("type of {} is...", self.tcx.map.node_to_string(expr.id)); + debug!("... {:?}, expected is {:?}", ty, expected); // Add adjustments to !-expressions if ty.is_never() { @@ -3821,10 +3799,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_method_call(expr, name, args, &tps[..], expected, lvalue_pref) } 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, // if appropriate. let t_cast = self.to_ty(t); @@ -3886,9 +3860,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } tcx.mk_array(unified, args.len()) } - hir::ExprRepeat(ref element, ref count_expr) => { - self.check_expr_has_type(&count_expr, tcx.types.usize); - let count = eval_length(self.tcx.global_tcx(), &count_expr, "repeat count") + hir::ExprRepeat(ref element, count) => { + let count_expr = &tcx.map.body(count).value; + let count = eval_length(self.tcx.global_tcx(), count_expr, "repeat count") .unwrap_or(0); let uty = match expected { diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index eb08e70d4c3e4..bd63eb6ad25ef 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -113,12 +113,13 @@ macro_rules! ignore_err { // PUBLIC ENTRY POINTS impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { - pub fn regionck_expr(&self, e: &'gcx hir::Expr) { - let mut rcx = RegionCtxt::new(self, RepeatingScope(e.id), e.id, Subject(e.id)); + pub fn regionck_expr(&self, body: &'gcx hir::Body) { + let id = body.value.id; + let mut rcx = RegionCtxt::new(self, RepeatingScope(id), id, Subject(id)); if self.err_count_since_creation() == 0 { // regionck assumes typeck succeeded - rcx.visit_expr(e); - rcx.visit_region_obligations(e.id); + rcx.visit_body(body); + rcx.visit_region_obligations(id); } rcx.resolve_regions_and_report_errors(); } @@ -140,15 +141,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn regionck_fn(&self, fn_id: ast::NodeId, - decl: &hir::FnDecl, - body_id: hir::ExprId) { + body: &'gcx hir::Body) { 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)); if self.err_count_since_creation() == 0 { // 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, body, self.tcx.map.span(fn_id)); } rcx.free_region_map.relate_free_regions_from_predicates( @@ -267,15 +267,16 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { fn visit_fn_body(&mut self, id: ast::NodeId, // the id of the fn itself - fn_decl: &hir::FnDecl, - body_id: hir::ExprId, + body: &'gcx hir::Body, span: Span) { // When we enter a function, we can derive debug!("visit_fn_body(id={})", id); + let body_id = body.id(); + 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 fn_sig = { @@ -298,20 +299,18 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let fn_sig_tys: Vec<_> = fn_sig.inputs().iter().cloned().chain(Some(fn_sig.output())).collect(); - 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.link_fn_args(self.tcx.region_maps.node_extent(body_id.node_id()), - &fn_decl.inputs[..]); - let body = self.tcx.map.expr(body_id); - self.visit_expr(body); - self.visit_region_obligations(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.link_fn_args(self.tcx.region_maps.node_extent(body_id.node_id), &body.arguments); + self.visit_body(body); + self.visit_region_obligations(body_id.node_id); let call_site_scope = self.call_site_scope.unwrap(); - debug!("visit_fn_body body.id {} call_site_scope: {:?}", - body.id, call_site_scope); + debug!("visit_fn_body body.id {:?} call_site_scope: {:?}", + body.id(), 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), - body_id.node_id(), + body_id.node_id, call_site_region); self.region_bound_pairs.truncate(old_region_bounds_pairs_len); @@ -478,12 +477,13 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { // regions, until regionck, as described in #3238. 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, - b: hir::ExprId, span: Span, id: ast::NodeId) { - self.visit_fn_body(id, fd, b, span) + fn visit_fn(&mut self, _fk: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl, + b: hir::BodyId, span: Span, id: ast::NodeId) { + let body = self.tcx.map.body(b); + self.visit_fn_body(id, body, span) } //visit_pat: visit_pat, // (..) see above @@ -826,8 +826,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { fn check_expr_fn_block(&mut self, expr: &'gcx hir::Expr, - body_id: hir::ExprId) { - let repeating_scope = self.set_repeating_scope(body_id.node_id()); + body_id: hir::BodyId) { + let repeating_scope = self.set_repeating_scope(body_id.node_id); intravisit::walk_expr(self, expr); self.set_repeating_scope(repeating_scope); } @@ -1113,7 +1113,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { for arg in args { let arg_ty = self.node_ty(arg.id); let re_scope = self.tcx.mk_region(ty::ReScope(body_scope)); - let arg_cmt = mc.cat_rvalue(arg.id, arg.ty.span, re_scope, arg_ty); + let arg_cmt = mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty); debug!("arg_ty={:?} arg_cmt={:?} arg={:?}", arg_ty, arg_cmt, diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 63d20416bded5..5d927a503a116 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -57,12 +57,12 @@ use rustc::util::nodemap::NodeMap; // PUBLIC ENTRY POINTS 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); - seed.visit_expr(body); + seed.visit_body(body); 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. 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> { 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) { match expr.node { 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, expr: &hir::Expr, - capture_clause: hir::CaptureClause, - _body_id: hir::ExprId) + capture_clause: hir::CaptureClause) { 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) { @@ -156,23 +157,21 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { fn analyze_closure(&mut self, id: ast::NodeId, span: Span, - decl: &hir::FnDecl, - body_id: hir::ExprId) { + body: &hir::Body) { /*! * 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 = euv::ExprUseVisitor::with_options(self, self.fcx, mc::MemCategorizationOptions { during_closure_kind_inference: true }); - euv.walk_fn(decl, body); + euv.consume_body(body); } // Now that we've analyzed the closure, we know how each @@ -491,18 +490,21 @@ impl<'a, 'gcx, 'tcx> 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> { - NestedVisitorMap::OnlyBodies(&self.fcx.tcx.map) + NestedVisitorMap::None } fn visit_fn(&mut self, fn_kind: intravisit::FnKind<'gcx>, decl: &'gcx hir::FnDecl, - body: hir::ExprId, + body: hir::BodyId, span: Span, id: ast::NodeId) { intravisit::walk_fn(self, fn_kind, decl, body, span, id); - self.analyze_closure(id, span, decl, body); + + let body = self.fcx.tcx.map.body(body); + self.visit_body(body); + self.analyze_closure(id, span, body); } } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index ffdb56753fdc1..c80db7fa4d0e0 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -159,10 +159,10 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { } } - fn check_trait_or_impl_item(&mut self, - item_id: ast::NodeId, - span: Span, - sig_if_method: Option<&hir::MethodSig>) { + fn check_associated_item(&mut self, + item_id: ast::NodeId, + span: Span, + sig_if_method: Option<&hir::MethodSig>) { let code = self.code.clone(); self.for_id(item_id, span).with_fcx(|fcx, this| { let free_substs = &fcx.parameter_environment.free_substs; @@ -337,7 +337,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { fn check_item_fn(&mut self, item: &hir::Item, - body_id: hir::ExprId) + body_id: hir::BodyId) { self.for_item(item).with_fcx(|fcx, this| { 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 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, free_id_outlive, &mut implied_bounds); implied_bounds @@ -478,7 +478,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { return; } - let span = method_sig.decl.inputs[0].pat.span; + let span = method_sig.decl.inputs[0].span; let free_substs = &fcx.parameter_environment.free_substs; let method_ty = fcx.tcx.item_type(method.def_id); @@ -607,10 +607,10 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> { fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) { debug!("visit_trait_item: {:?}", trait_item); let method_sig = match trait_item.node { - hir::TraitItem_::MethodTraitItem(ref sig, _) => Some(sig), + hir::TraitItemKind::Method(ref sig, _) => Some(sig), _ => None }; - self.check_trait_or_impl_item(trait_item.id, trait_item.span, method_sig); + self.check_associated_item(trait_item.id, trait_item.span, method_sig); intravisit::walk_trait_item(self, trait_item) } @@ -620,7 +620,7 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> { hir::ImplItemKind::Method(ref sig, _) => Some(sig), _ => None }; - self.check_trait_or_impl_item(impl_item.id, impl_item.span, method_sig); + self.check_associated_item(impl_item.id, impl_item.span, method_sig); intravisit::walk_impl_item(self, impl_item) } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 56de75995fd2e..9a2bfbf715af9 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -26,42 +26,22 @@ use std::cell::Cell; use syntax::ast; use syntax_pos::Span; -use rustc::hir::print::pat_to_string; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use rustc::hir::{self, PatKind}; +use rustc::hir; /////////////////////////////////////////////////////////////////////////// -// Entry point functions +// Entry point 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_body(&self, + body: &'gcx hir::Body, + item_id: ast::NodeId) { assert_eq!(self.writeback_errors.get(), false); let mut wbcx = WritebackCx::new(self); - wbcx.visit_expr(e); - wbcx.visit_upvar_borrow_map(); - wbcx.visit_closures(); - wbcx.visit_liberated_fn_sigs(); - wbcx.visit_fru_field_types(); - wbcx.visit_deferred_obligations(item_id); - wbcx.visit_type_nodes(); - } - - pub fn resolve_type_vars_in_fn(&self, - decl: &'gcx hir::FnDecl, - body: &'gcx hir::Expr, - item_id: ast::NodeId) { - assert_eq!(self.writeback_errors.get(), false); - let mut wbcx = WritebackCx::new(self); - wbcx.visit_expr(body); - for arg in &decl.inputs { + for arg in &body.arguments { wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id); - wbcx.visit_pat(&arg.pat); - - // Privacy needs the type for the whole pattern, not just each binding - if let PatKind::Binding(..) = arg.pat.node {} else { - wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.pat.id); - } } + wbcx.visit_body(body); wbcx.visit_upvar_borrow_map(); wbcx.visit_closures(); wbcx.visit_liberated_fn_sigs(); @@ -188,7 +168,7 @@ impl<'cx, 'gcx, 'tcx> 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> { - NestedVisitorMap::OnlyBodies(&self.fcx.tcx.map) + NestedVisitorMap::None } fn visit_stmt(&mut self, s: &'gcx hir::Stmt) { @@ -211,10 +191,13 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { self.visit_method_map_entry(ResolvingExpr(e.span), MethodCall::expr(e.id)); - if let hir::ExprClosure(_, ref decl, ..) = e.node { - for input in &decl.inputs { - self.visit_node_id(ResolvingExpr(e.span), input.id); + if let hir::ExprClosure(_, _, body, _) = e.node { + let body = self.fcx.tcx.map.body(body); + for arg in &body.arguments { + self.visit_node_id(ResolvingExpr(e.span), arg.id); } + + self.visit_body(body); } intravisit::walk_expr(self, e); @@ -237,7 +220,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { self.visit_node_id(ResolvingPattern(p.span), p.id); debug!("Type for pattern binding {} (id {}) resolved to {:?}", - pat_to_string(p), + self.tcx().map.node_to_pretty_string(p.id), p.id, self.tcx().tables().node_id_to_type(p.id)); @@ -254,20 +237,6 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { self.write_ty_to_tcx(l.id, var_ty); intravisit::walk_local(self, l); } - - fn visit_ty(&mut self, t: &'gcx hir::Ty) { - 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) => { - intravisit::walk_fn_decl_nopat(self, &function_declaration.decl); - walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes); - } - _ => intravisit::walk_ty(self, t) - } - } } impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 0034a85f8e29e..cd9453770a6ab 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -50,6 +50,9 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for UnusedTraitImportVisitor<'a, 'tcx> { } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { } } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 0e5a16987c12e..3bbe5aa1fef37 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -58,6 +58,9 @@ impl<'a, 'gcx, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCheckVisitor<'a, 'gcx, } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { } } diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 2e8206ec95967..bc1ead07c0ea7 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -67,13 +67,15 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { } } } +} +impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { /// Checks exactly one impl for orphan rules and other such /// restrictions. In this fn, it can happen that multiple errors /// apply to a specific impl, so just return after reporting one /// to prevent inundating the user with a bunch of similar error /// reports. - fn check_item(&self, item: &hir::Item) { + fn visit_item(&mut self, item: &hir::Item) { let def_id = self.tcx.map.local_def_id(item.id); match item.node { hir::ItemImpl(.., None, ref ty, _) => { @@ -368,7 +370,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { the crate they're defined in; define a new trait instead") .span_label(item_trait_ref.path.span, &format!("`{}` trait not defined in this crate", - item_trait_ref.path)) + self.tcx.map.node_to_pretty_string(item_trait_ref.ref_id))) .emit(); return; } @@ -378,11 +380,8 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { } } } -} -impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { - fn visit_item(&mut self, item: &hir::Item) { - self.check_item(item); + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { } fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 815811675a54b..a09bdf0533a15 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -205,6 +205,9 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> { } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { } } diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index 6d5de8f250655..c4c7c699f65f6 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -107,6 +107,9 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for UnsafetyChecker<'cx, 'tcx> { } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index fba77d171797e..fd51b38e1b557 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -82,7 +82,7 @@ use syntax::{abi, ast, attr}; use syntax::symbol::{Symbol, keywords}; use syntax_pos::Span; -use rustc::hir::{self, map as hir_map, print as pprust}; +use rustc::hir::{self, map as hir_map}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::DefId; @@ -204,6 +204,13 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { intravisit::walk_ty(self, ty); } + fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { + self.with_collect_item_sig(trait_item.id, || { + convert_trait_item(self.ccx, trait_item) + }); + intravisit::walk_trait_item(self, trait_item); + } + fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { self.with_collect_item_sig(impl_item.id, || { convert_impl_item(self.ccx, impl_item) @@ -633,7 +640,8 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, id: ast::NodeId, sig: &hir::MethodSig, untransformed_rcvr_ty: Ty<'tcx>, - rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) { + body: Option, + rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,) { let def_id = ccx.tcx.map.local_def_id(id); let ty_generics = generics_of_def_id(ccx, def_id); @@ -644,8 +652,14 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ImplContainer(_) => Some(AnonTypeScope::new(def_id)), TraitContainer(_) => None }; + let assoc_item = ccx.tcx.associated_item(def_id); + let self_value_ty = if assoc_item.method_has_self_argument { + Some(untransformed_rcvr_ty) + } else { + None + }; let fty = AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), - sig, untransformed_rcvr_ty, anon_scope); + sig, self_value_ty, body, anon_scope); let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), ccx.tcx.map.span(id), def_id); @@ -785,56 +799,12 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { tcx.predicates.borrow_mut().insert(def_id, ty_predicates.clone()); }, - hir::ItemTrait(.., ref trait_items) => { + hir::ItemTrait(..) => { generics_of_def_id(ccx, def_id); trait_def_of_item(ccx, it); let _: Result<(), ErrorReported> = // any error is already reported, can ignore ccx.ensure_super_predicates(it.span, def_id); convert_trait_predicates(ccx, it); - let trait_predicates = tcx.item_predicates(def_id); - - debug!("convert: trait_bounds={:?}", trait_predicates); - - // FIXME: is the ordering here important? I think it is. - let container = TraitContainer(def_id); - - // Convert all the associated constants. - for trait_item in trait_items { - if let hir::ConstTraitItem(ref ty, _) = trait_item.node { - let const_def_id = ccx.tcx.map.local_def_id(trait_item.id); - generics_of_def_id(ccx, const_def_id); - let ty = ccx.icx(&trait_predicates) - .to_ty(&ExplicitRscope, ty); - tcx.item_types.borrow_mut().insert(const_def_id, ty); - convert_associated_const(ccx, container, trait_item.id, ty) - } - } - - // Convert all the associated types. - for trait_item in trait_items { - if let hir::TypeTraitItem(_, ref opt_ty) = trait_item.node { - let type_def_id = ccx.tcx.map.local_def_id(trait_item.id); - generics_of_def_id(ccx, type_def_id); - - let typ = opt_ty.as_ref().map({ - |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty) - }); - - convert_associated_type(ccx, container, trait_item.id, typ); - } - } - - // Convert all the methods - for trait_item in trait_items { - if let hir::MethodTraitItem(ref sig, _) = trait_item.node { - convert_method(ccx, - container, - trait_item.id, - sig, - tcx.mk_self_type(), - &trait_predicates); - } - } }, hir::ItemStruct(ref struct_def, _) | hir::ItemUnion(ref struct_def, _) => { @@ -866,6 +836,48 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { } } +fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) { + let tcx = ccx.tcx; + + // we can lookup details about the trait because items are visited + // before trait-items + let trait_def_id = tcx.map.get_parent_did(trait_item.id); + let trait_predicates = tcx.item_predicates(trait_def_id); + + match trait_item.node { + hir::TraitItemKind::Const(ref ty, _) => { + let const_def_id = ccx.tcx.map.local_def_id(trait_item.id); + generics_of_def_id(ccx, const_def_id); + let ty = ccx.icx(&trait_predicates) + .to_ty(&ExplicitRscope, &ty); + tcx.item_types.borrow_mut().insert(const_def_id, ty); + convert_associated_const(ccx, TraitContainer(trait_def_id), + trait_item.id, ty); + } + + hir::TraitItemKind::Type(_, ref opt_ty) => { + let type_def_id = ccx.tcx.map.local_def_id(trait_item.id); + generics_of_def_id(ccx, type_def_id); + + let typ = opt_ty.as_ref().map({ + |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty) + }); + + convert_associated_type(ccx, TraitContainer(trait_def_id), trait_item.id, typ); + } + + hir::TraitItemKind::Method(ref sig, ref method) => { + let body = match *method { + hir::TraitMethod::Required(_) => None, + hir::TraitMethod::Provided(body) => Some(body) + }; + convert_method(ccx, TraitContainer(trait_def_id), + trait_item.id, sig, tcx.mk_self_type(), + body, &trait_predicates); + } + } +} + fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) { let tcx = ccx.tcx; @@ -901,10 +913,10 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) { convert_associated_type(ccx, ImplContainer(impl_def_id), impl_item.id, Some(typ)); } - hir::ImplItemKind::Method(ref sig, _) => { + hir::ImplItemKind::Method(ref sig, body) => { convert_method(ccx, ImplContainer(impl_def_id), impl_item.id, sig, impl_self_ty, - &impl_predicates); + Some(body), &impl_predicates); } } } @@ -1029,7 +1041,7 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, e: &hir::Expr) -> Option { - debug!("disr expr, checking {}", pprust::expr_to_string(e)); + debug!("disr expr, checking {}", ccx.tcx.map.node_to_pretty_string(e.id)); let ty_hint = repr_ty.to_ty(ccx.tcx); let print_err = |cv: ConstVal| { @@ -1088,7 +1100,8 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let mut prev_disr = None::; let variants = def.variants.iter().map(|v| { 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) } else if let Some(disr) = repr_type.disr_incr(tcx, prev_disr) { Some(disr) @@ -1290,12 +1303,13 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) ast_generics: &hir::Generics, trait_predicates: &ty::GenericPredicates<'tcx>, self_trait_ref: ty::TraitRef<'tcx>, - trait_items: &[hir::TraitItem]) + trait_item_refs: &[hir::TraitItemRef]) -> Vec> { - trait_items.iter().flat_map(|trait_item| { + trait_item_refs.iter().flat_map(|trait_item_ref| { + let trait_item = ccx.tcx.map.trait_item(trait_item_ref.id); let bounds = match trait_item.node { - hir::TypeTraitItem(ref bounds, _) => bounds, + hir::TraitItemKind::Type(ref bounds, _) => bounds, _ => { return vec![].into_iter(); } @@ -1363,7 +1377,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let ast_generics = match node { NodeTraitItem(item) => { match item.node { - MethodTraitItem(ref sig, _) => &sig.generics, + TraitItemKind::Method(ref sig, _) => &sig.generics, _ => &no_generics } } @@ -1420,7 +1434,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, NodeForeignItem(item) => { match item.node { ForeignItemStatic(..) => &no_generics, - ForeignItemFn(_, ref generics) => generics + ForeignItemFn(_, _, ref generics) => generics } } @@ -1521,9 +1535,9 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ItemStatic(ref t, ..) | ItemConst(ref t, _) => { ccx.icx(&()).to_ty(&StaticRscope::new(&ccx.tcx), &t) } - ItemFn(ref decl, unsafety, _, abi, ref generics, _) => { + ItemFn(ref decl, unsafety, _, abi, ref generics, body) => { let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl, - Some(AnonTypeScope::new(def_id))); + body, Some(AnonTypeScope::new(def_id))); let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id); ccx.tcx.mk_fn_def(def_id, substs, tofd) } @@ -1563,7 +1577,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let abi = ccx.tcx.map.get_foreign_abi(node_id); match foreign_item.node { - ForeignItemFn(ref fn_decl, ref generics) => { + ForeignItemFn(ref fn_decl, _, ref generics) => { compute_type_of_foreign_fn_decl( ccx, ccx.tcx.map.local_def_id(foreign_item.id), fn_decl, generics, abi) @@ -1628,7 +1642,7 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let no_generics = hir::Generics::empty(); let generics = match it.node { - hir::ForeignItemFn(_, ref generics) => generics, + hir::ForeignItemFn(_, _, ref generics) => generics, hir::ForeignItemStatic(..) => &no_generics }; @@ -2058,13 +2072,13 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>( ccx.tcx.sess.struct_span_err(ast_ty.span, &format!("use of SIMD type `{}` in FFI is highly experimental and \ may result in invalid code", - pprust::ty_to_string(ast_ty))) + ccx.tcx.map.node_to_pretty_string(ast_ty.id))) .help("add #![feature(simd_ffi)] to the crate attributes to enable") .emit(); } }; for (input, ty) in decl.inputs.iter().zip(&input_tys) { - check(&input.ty, ty) + check(&input, ty) } if let hir::Return(ref ty) = decl.output { check(&ty, output) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index cea3ad43a95b8..d3b671f2a4d6e 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -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::(); - mem::transmute_copy::(&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::()]>(&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::(&8_8); - // `u32` is 4 bytes so we replace the `mem::size_of` call with its size -} -``` -"##, - E0516: r##" The `typeof` keyword is currently reserved but unimplemented. Erroneous code example: diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 9f5b73d9b3075..ce495e6fb4cd8 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -87,6 +87,8 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> { } } + fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem) { } + fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { } } diff --git a/src/librustc_typeck/rscope.rs b/src/librustc_typeck/rscope.rs index 131ecfc6e0c78..3f5e443a20a68 100644 --- a/src/librustc_typeck/rscope.rs +++ b/src/librustc_typeck/rscope.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc::hir; use rustc::hir::def_id::DefId; use rustc::ty; use rustc::ty::subst::Substs; @@ -19,7 +20,10 @@ use syntax_pos::Span; #[derive(Clone)] pub struct ElisionFailureInfo { - pub name: String, + /// Where we can find the argument pattern. + pub parent: Option, + /// The index of the argument in the original definition. + pub index: usize, pub lifetime_count: usize, pub have_bound_regions: bool } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 39f996ee62b54..507079a4f874c 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -120,6 +120,9 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { } } diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index 851cfcd87231f..d4d3edbcb126e 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -258,6 +258,9 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { } } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) { + } + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 94e9fdbfc3e2c..cba5e1ba6f318 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -10,6 +10,8 @@ //! Support for inlining external documentation into the current AST. +use std::collections::BTreeMap; +use std::io; use std::iter::once; use syntax::ast; @@ -17,12 +19,9 @@ use rustc::hir; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::DefId; -use rustc::hir::print as pprust; use rustc::ty; use rustc::util::nodemap::FxHashSet; -use rustc_const_eval::lookup_const_by_id; - use core::{DocContext, DocAccessLevels}; use doctree; use clean::{self, GetDefId}; @@ -345,8 +344,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { match item.kind { ty::AssociatedKind::Const => { let default = if item.defaultness.has_value() { - Some(pprust::expr_to_string( - lookup_const_by_id(tcx, item.def_id, None).unwrap().0)) + Some(print_inlined_const(cx, item.def_id)) } else { None }; @@ -476,17 +474,33 @@ fn build_module(cx: &DocContext, did: DefId) -> clean::Module { } } -fn build_const(cx: &DocContext, did: DefId) -> clean::Constant { - let (expr, ty) = lookup_const_by_id(cx.tcx, did, None).unwrap_or_else(|| { - panic!("expected lookup_const_by_id to succeed for {:?}", did); - }); - debug!("converting constant expr {:?} to snippet", expr); - let sn = pprust::expr_to_string(expr); - debug!("got snippet {}", sn); +struct InlinedConst { + nested_bodies: BTreeMap +} + +impl hir::print::PpAnn for InlinedConst { + fn nested(&self, state: &mut hir::print::State, nested: hir::print::Nested) + -> io::Result<()> { + if let hir::print::Nested::Body(body) = nested { + state.print_expr(&self.nested_bodies[&body].value) + } else { + Ok(()) + } + } +} +fn print_inlined_const(cx: &DocContext, did: DefId) -> String { + let body = cx.tcx.sess.cstore.maybe_get_item_body(cx.tcx, did).unwrap(); + let inlined = InlinedConst { + nested_bodies: cx.tcx.sess.cstore.item_body_nested_bodies(did) + }; + hir::print::to_string(&inlined, |s| s.print_expr(&body.value)) +} + +fn build_const(cx: &DocContext, did: DefId) -> clean::Constant { clean::Constant { - type_: ty.map(|t| t.clean(cx)).unwrap_or_else(|| cx.tcx.item_type(did).clean(cx)), - expr: sn + type_: cx.tcx.item_type(did).clean(cx), + expr: print_inlined_const(cx, did) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fdbd2f3647c0c..3b8281980696d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -32,7 +32,6 @@ use rustc::middle::resolve_lifetime::DefRegion::*; use rustc::middle::lang_items; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc::hir::print as pprust; use rustc::ty::subst::Substs; use rustc::ty::{self, AdtKind}; use rustc::middle::stability; @@ -1030,22 +1029,14 @@ pub struct Method { pub abi: Abi, } -impl Clean for hir::MethodSig { +impl<'a> Clean for (&'a hir::MethodSig, hir::BodyId) { fn clean(&self, cx: &DocContext) -> Method { - let decl = FnDecl { - inputs: Arguments { - values: self.decl.inputs.clean(cx), - }, - output: self.decl.output.clean(cx), - variadic: false, - attrs: Attributes::default() - }; Method { - generics: self.generics.clean(cx), - unsafety: self.unsafety, - constness: self.constness, - decl: decl, - abi: self.abi + generics: self.0.generics.clean(cx), + unsafety: self.0.unsafety, + constness: self.0.constness, + decl: (&*self.0.decl, self.1).clean(cx), + abi: self.0.abi } } } @@ -1058,25 +1049,6 @@ pub struct TyMethod { pub abi: Abi, } -impl Clean for hir::MethodSig { - fn clean(&self, cx: &DocContext) -> TyMethod { - let decl = FnDecl { - inputs: Arguments { - values: self.decl.inputs.clean(cx), - }, - output: self.decl.output.clean(cx), - variadic: false, - attrs: Attributes::default() - }; - TyMethod { - unsafety: self.unsafety.clone(), - decl: decl, - generics: self.generics.clean(cx), - abi: self.abi - } - } -} - #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Function { pub decl: FnDecl, @@ -1097,7 +1069,7 @@ impl Clean for doctree::Function { deprecation: self.depr.clean(cx), def_id: cx.tcx.map.local_def_id(self.id), inner: FunctionItem(Function { - decl: self.decl.clean(cx), + decl: (&self.decl, self.body).clean(cx), generics: self.generics.clean(cx), unsafety: self.unsafety, constness: self.constness, @@ -1130,14 +1102,47 @@ pub struct Arguments { pub values: Vec, } -impl Clean for hir::FnDecl { +impl<'a> Clean for (&'a [P], &'a [Spanned]) { + fn clean(&self, cx: &DocContext) -> Arguments { + Arguments { + values: self.0.iter().enumerate().map(|(i, ty)| { + let mut name = self.1.get(i).map(|n| n.node.to_string()) + .unwrap_or(String::new()); + if name.is_empty() { + name = "_".to_string(); + } + Argument { + name: name, + type_: ty.clean(cx), + } + }).collect() + } + } +} + +impl<'a> Clean for (&'a [P], hir::BodyId) { + fn clean(&self, cx: &DocContext) -> Arguments { + let body = cx.tcx.map.body(self.1); + + Arguments { + values: self.0.iter().enumerate().map(|(i, ty)| { + Argument { + name: name_from_pat(&body.arguments[i].pat), + type_: ty.clean(cx), + } + }).collect() + } + } +} + +impl<'a, A: Copy> Clean for (&'a hir::FnDecl, A) + where (&'a [P], A): Clean +{ fn clean(&self, cx: &DocContext) -> FnDecl { FnDecl { - inputs: Arguments { - values: self.inputs.clean(cx), - }, - output: self.output.clean(cx), - variadic: self.variadic, + inputs: (&self.0.inputs[..], self.1).clean(cx), + output: self.0.output.clean(cx), + variadic: self.0.variadic, attrs: Attributes::default() } } @@ -1159,7 +1164,6 @@ impl<'a, 'tcx> Clean for (DefId, &'a ty::PolyFnSig<'tcx>) { values: sig.skip_binder().inputs().iter().map(|t| { Argument { type_: t.clean(cx), - id: ast::CRATE_NODE_ID, name: names.next().map_or("".to_string(), |name| name.to_string()), } }).collect(), @@ -1172,7 +1176,6 @@ impl<'a, 'tcx> Clean for (DefId, &'a ty::PolyFnSig<'tcx>) { pub struct Argument { pub type_: Type, pub name: String, - pub id: ast::NodeId, } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] @@ -1184,26 +1187,17 @@ pub enum SelfTy { impl Argument { pub fn to_self(&self) -> Option { - if self.name == "self" { - match self.type_ { - Infer => Some(SelfValue), - BorrowedRef{ref lifetime, mutability, ref type_} if **type_ == Infer => { - Some(SelfBorrowed(lifetime.clone(), mutability)) - } - _ => Some(SelfExplicit(self.type_.clone())) - } - } else { - None + if self.name != "self" { + return None; } - } -} - -impl Clean for hir::Arg { - fn clean(&self, cx: &DocContext) -> Argument { - Argument { - name: name_from_pat(&*self.pat), - type_: (self.ty.clean(cx)), - id: self.id + if self.type_.is_self_type() { + return Some(SelfValue); + } + match self.type_ { + BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => { + Some(SelfBorrowed(lifetime.clone(), mutability)) + } + _ => Some(SelfExplicit(self.type_.clone())) } } } @@ -1269,17 +1263,22 @@ impl Clean for hir::PolyTraitRef { impl Clean for hir::TraitItem { fn clean(&self, cx: &DocContext) -> Item { let inner = match self.node { - hir::ConstTraitItem(ref ty, ref default) => { + hir::TraitItemKind::Const(ref ty, default) => { AssociatedConstItem(ty.clean(cx), - default.as_ref().map(|e| pprust::expr_to_string(&e))) + default.map(|e| print_const_expr(cx, e))) } - hir::MethodTraitItem(ref sig, Some(_)) => { - MethodItem(sig.clean(cx)) + hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { + MethodItem((sig, body).clean(cx)) } - hir::MethodTraitItem(ref sig, None) => { - TyMethodItem(sig.clean(cx)) + hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => { + TyMethodItem(TyMethod { + unsafety: sig.unsafety.clone(), + decl: (&*sig.decl, &names[..]).clean(cx), + generics: sig.generics.clean(cx), + abi: sig.abi + }) } - hir::TypeTraitItem(ref bounds, ref default) => { + hir::TraitItemKind::Type(ref bounds, ref default) => { AssociatedTypeItem(bounds.clean(cx), default.clean(cx)) } }; @@ -1299,12 +1298,12 @@ impl Clean for hir::TraitItem { impl Clean for hir::ImplItem { fn clean(&self, cx: &DocContext) -> Item { let inner = match self.node { - hir::ImplItemKind::Const(ref ty, ref expr) => { + hir::ImplItemKind::Const(ref ty, expr) => { AssociatedConstItem(ty.clean(cx), - Some(pprust::expr_to_string(expr))) + Some(print_const_expr(cx, expr))) } - hir::ImplItemKind::Method(ref sig, _) => { - MethodItem(sig.clean(cx)) + hir::ImplItemKind::Method(ref sig, body) => { + MethodItem((sig, body).clean(cx)) } hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef { type_: ty.clean(cx), @@ -1353,11 +1352,13 @@ impl<'tcx> Clean for ty::AssociatedItem { }; let self_arg_ty = *fty.sig.input(0).skip_binder(); if self_arg_ty == self_ty { - decl.inputs.values[0].type_ = Infer; + decl.inputs.values[0].type_ = Generic(String::from("Self")); } else if let ty::TyRef(_, mt) = self_arg_ty.sty { if mt.ty == self_ty { match decl.inputs.values[0].type_ { - BorrowedRef{ref mut type_, ..} => **type_ = Infer, + BorrowedRef{ref mut type_, ..} => { + **type_ = Generic(String::from("Self")) + } _ => unreachable!(), } } @@ -1568,6 +1569,13 @@ impl Type { _ => false, } } + + pub fn is_self_type(&self) -> bool { + match *self { + Generic(ref name) => name == "Self", + _ => false + } + } } impl GetDefId for Type { @@ -1677,11 +1685,12 @@ impl Clean for hir::Ty { BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx), type_: box m.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_eval::eval_const_expr; use rustc::middle::const_val::ConstVal; + let e = &cx.tcx.map.body(e).value; let n = match eval_const_expr(cx.tcx, e) { ConstVal::Integral(ConstInt::Usize(u)) => match u { ConstUsize::Us16(u) => u.to_string(), @@ -2332,7 +2341,7 @@ impl Clean for hir::BareFnTy { type_params: Vec::new(), where_predicates: Vec::new() }, - decl: self.decl.clean(cx), + decl: (&*self.decl, &[][..]).clean(cx), abi: self.abi, } } @@ -2362,7 +2371,7 @@ impl Clean for doctree::Static { inner: StaticItem(Static { type_: self.type_.clean(cx), mutability: self.mutability.clean(cx), - expr: pprust::expr_to_string(&self.expr), + expr: print_const_expr(cx, self.expr), }), } } @@ -2386,7 +2395,7 @@ impl Clean for doctree::Constant { deprecation: self.depr.clean(cx), inner: ConstantItem(Constant { type_: self.type_.clean(cx), - expr: pprust::expr_to_string(&self.expr), + expr: print_const_expr(cx, self.expr), }), } } @@ -2630,9 +2639,9 @@ impl Clean> for hir::ForeignMod { impl Clean for hir::ForeignItem { fn clean(&self, cx: &DocContext) -> Item { let inner = match self.node { - hir::ForeignItemFn(ref decl, ref generics) => { + hir::ForeignItemFn(ref decl, ref names, ref generics) => { ForeignFunctionItem(Function { - decl: decl.clean(cx), + decl: (&**decl, &names[..]).clean(cx), generics: generics.clean(cx), unsafety: hir::Unsafety::Unsafe, abi: Abi::Rust, @@ -2714,6 +2723,10 @@ fn name_from_pat(p: &hir::Pat) -> String { } } +fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String { + cx.tcx.map.node_to_pretty_string(body.node_id) +} + /// Given a type Path, resolve it to a Type using the TyCtxt fn resolve_type(cx: &DocContext, path: Path, diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 31e10fbd3b7d3..d819268240bad 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -156,6 +156,7 @@ pub struct Function { pub whence: Span, pub generics: hir::Generics, pub abi: abi::Abi, + pub body: hir::BodyId, } pub struct Typedef { @@ -174,7 +175,7 @@ pub struct Typedef { pub struct Static { pub type_: P, pub mutability: hir::Mutability, - pub expr: P, + pub expr: hir::BodyId, pub name: Name, pub attrs: hir::HirVec, pub vis: hir::Visibility, @@ -186,7 +187,7 @@ pub struct Static { pub struct Constant { pub type_: P, - pub expr: P, + pub expr: hir::BodyId, pub name: Name, pub attrs: hir::HirVec, pub vis: hir::Visibility, diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index b96a737ed0007..bb61a1dedda5d 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -495,7 +495,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { fn visit_item(&mut self, item: &'hir hir::Item) { let name = if let hir::ItemImpl(.., ref ty, _) = item.node { - hir::print::ty_to_string(ty) + self.map.node_to_pretty_string(ty.id) } else { item.name.to_string() }; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index c93112657b96d..b0afc3d63f479 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -157,7 +157,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { unsafety: &hir::Unsafety, constness: hir::Constness, abi: &abi::Abi, - gen: &hir::Generics) -> Function { + gen: &hir::Generics, + body: hir::BodyId) -> Function { debug!("Visiting fn"); Function { id: item.id, @@ -172,6 +173,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { unsafety: *unsafety, constness: constness, abi: *abi, + body: body, } } @@ -410,9 +412,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om.structs.push(self.visit_variant_data(item, name, sd, gen)), hir::ItemUnion(ref sd, ref gen) => om.unions.push(self.visit_union_data(item, name, sd, gen)), - hir::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, _) => + hir::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, body) => om.fns.push(self.visit_fn(item, name, &**fd, unsafety, - constness, abi, gen)), + constness, abi, gen, body)), hir::ItemTy(ref ty, ref gen) => { let t = Typedef { ty: ty.clone(), @@ -456,11 +458,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; om.constants.push(s); }, - hir::ItemTrait(unsafety, ref gen, ref b, ref items) => { + hir::ItemTrait(unsafety, ref gen, ref b, ref item_ids) => { + let items = item_ids.iter() + .map(|ti| self.cx.tcx.map.trait_item(ti.id).clone()) + .collect(); let t = Trait { unsafety: unsafety, name: name, - items: items.clone(), + items: items, generics: gen.clone(), bounds: b.iter().cloned().collect(), id: item.id, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a5abdd922d63f..f72985fd91a3e 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1471,12 +1471,13 @@ impl Arg { } pub fn from_self(eself: ExplicitSelf, eself_ident: SpannedIdent) -> Arg { + let span = mk_sp(eself.span.lo, eself_ident.span.hi); let infer_ty = P(Ty { id: DUMMY_NODE_ID, node: TyKind::ImplicitSelf, - span: DUMMY_SP, + span: span, }); - let arg = |mutbl, ty, span| Arg { + let arg = |mutbl, ty| Arg { pat: P(Pat { id: DUMMY_NODE_ID, node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None), @@ -1486,15 +1487,13 @@ impl Arg { id: DUMMY_NODE_ID, }; match eself.node { - SelfKind::Explicit(ty, mutbl) => { - arg(mutbl, ty, mk_sp(eself.span.lo, eself_ident.span.hi)) - } - SelfKind::Value(mutbl) => arg(mutbl, infer_ty, eself.span), + SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty), + SelfKind::Value(mutbl) => arg(mutbl, infer_ty), SelfKind::Region(lt, mutbl) => arg(Mutability::Immutable, P(Ty { id: DUMMY_NODE_ID, node: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl: mutbl }), - span: DUMMY_SP, - }), eself.span), + span: span, + })), } } } diff --git a/src/test/compile-fail/E0513.rs b/src/test/compile-fail/E0513.rs deleted file mode 100644 index 726e23265241d..0000000000000 --- a/src/test/compile-fail/E0513.rs +++ /dev/null @@ -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 or the MIT license -// , 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::(); - mem::transmute_copy::(&8_8); //~ ERROR E0513 - //~| NOTE no type for variable - } -} diff --git a/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs b/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs index c3fa39659b968..7c3f7a1d574f9 100644 --- a/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs +++ b/src/test/compile-fail/associated-const-type-parameter-arrays-2.rs @@ -25,8 +25,10 @@ impl Foo for Def { } pub fn test() { - let _array = [4; ::Y]; //~ ERROR E0080 - //~| non-constant path in constant + let _array = [4; ::Y]; + //~^ ERROR cannot use an outer type parameter in this context [E0402] + //~| ERROR constant evaluation error [E0080] + //~| non-constant path in constant } fn main() { diff --git a/src/test/compile-fail/associated-const-type-parameter-arrays.rs b/src/test/compile-fail/associated-const-type-parameter-arrays.rs index ddf16a2278e5b..dcf87d5f0fc44 100644 --- a/src/test/compile-fail/associated-const-type-parameter-arrays.rs +++ b/src/test/compile-fail/associated-const-type-parameter-arrays.rs @@ -26,7 +26,9 @@ impl Foo for Def { pub fn test() { let _array: [u32; ::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() { diff --git a/src/test/compile-fail/dep-graph-struct-signature.rs b/src/test/compile-fail/dep-graph-struct-signature.rs index 235fc5051d780..36382e776ce28 100644 --- a/src/test/compile-fail/dep-graph-struct-signature.rs +++ b/src/test/compile-fail/dep-graph-struct-signature.rs @@ -34,9 +34,11 @@ struct WontChange { mod signatures { use WillChange; - #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK - #[rustc_then_this_would_need(CollectItem)] //~ ERROR OK + #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path + #[rustc_then_this_would_need(CollectItem)] //~ ERROR no path trait Bar { + #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK + #[rustc_then_this_would_need(CollectItem)] //~ ERROR OK fn do_something(x: WillChange); } diff --git a/src/test/compile-fail/dep-graph-type-alias.rs b/src/test/compile-fail/dep-graph-type-alias.rs index 2e33f11c04b45..4cc15e8b522ac 100644 --- a/src/test/compile-fail/dep-graph-type-alias.rs +++ b/src/test/compile-fail/dep-graph-type-alias.rs @@ -35,8 +35,9 @@ enum Enum { Variant2(i32) } -#[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK +#[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path trait Trait { + #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK fn method(&self, _: TypeAlias); } diff --git a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs index f8aa1ea95f0f6..eac134ff3cc7d 100644 --- a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs +++ b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs @@ -14,8 +14,8 @@ struct Foo<'a,'b> { } impl<'a,'b> Foo<'a,'b> { - fn bar( - self + fn bar(self: + Foo<'b,'a> //~^ ERROR mismatched method receiver //~| expected type `Foo<'a, 'b>` //~| found type `Foo<'b, 'a>` @@ -24,7 +24,7 @@ impl<'a,'b> Foo<'a,'b> { //~| expected type `Foo<'a, 'b>` //~| found type `Foo<'b, 'a>` //~| lifetime mismatch - : Foo<'b,'a>) {} + ) {} } fn main() {} diff --git a/src/test/compile-fail/issue-27008.rs b/src/test/compile-fail/issue-27008.rs index e89bff025e006..f80135848e0c1 100644 --- a/src/test/compile-fail/issue-27008.rs +++ b/src/test/compile-fail/issue-27008.rs @@ -16,6 +16,4 @@ fn main() { //~| expected type `usize` //~| found type `S` //~| expected usize, found struct `S` - //~| ERROR expected `usize` for repeat count, found struct [E0306] - //~| expected `usize` } diff --git a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs index b5401f7d124e2..691d8d31b412d 100644 --- a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs +++ b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs @@ -12,8 +12,8 @@ fn main() { fn bar(n: isize) { - // FIXME (#24414): This error message needs improvement. 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] } } diff --git a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs index a6f88a57b9125..f4769a7858728 100644 --- a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs +++ b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs @@ -13,8 +13,9 @@ fn main() { fn bar(n: usize) { let _x = [0; n]; - //~^ ERROR constant evaluation error - //~| non-constant path in constant expression - //~| NOTE `n` is a variable + //~^ ERROR attempt to use a non-constant value in a constant [E0435] + //~| NOTE non-constant used with constant + //~| NOTE unresolved path in constant expression + //~| ERROR constant evaluation error [E0080] } } diff --git a/src/test/compile-fail/repeat_count.rs b/src/test/compile-fail/repeat_count.rs index 5d5113ce07c71..a716f3e29d488 100644 --- a/src/test/compile-fail/repeat_count.rs +++ b/src/test/compile-fail/repeat_count.rs @@ -13,43 +13,30 @@ fn main() { let n = 1; let a = [0; n]; - //~^ ERROR constant evaluation error - //~| non-constant path in constant expression + //~^ ERROR attempt to use a non-constant value in a constant [E0435] let b = [0; ()]; //~^ ERROR mismatched types //~| expected type `usize` //~| found type `()` //~| expected usize, found () - //~| ERROR expected `usize` for repeat count, found tuple [E0306] - //~| expected `usize` let c = [0; true]; //~^ ERROR mismatched types //~| expected usize, found bool - //~| ERROR expected `usize` for repeat count, found boolean [E0306] - //~| expected `usize` let d = [0; 0.5]; //~^ ERROR mismatched types //~| expected type `usize` //~| found type `{float}` //~| expected usize, found floating-point variable - //~| ERROR expected `usize` for repeat count, found float [E0306] - //~| expected `usize` let e = [0; "foo"]; //~^ ERROR mismatched types //~| expected type `usize` //~| found type `&'static str` //~| expected usize, found reference - //~| ERROR expected `usize` for repeat count, found string literal [E0306] - //~| expected `usize` let f = [0; -4_isize]; - //~^ ERROR constant evaluation error - //~| expected usize, found isize - //~| ERROR mismatched types + //~^ ERROR mismatched types //~| expected usize, found isize let f = [0_usize; -1_isize]; - //~^ ERROR constant evaluation error - //~| expected usize, found isize - //~| ERROR mismatched types + //~^ ERROR mismatched types //~| expected usize, found isize struct G { g: (), @@ -59,6 +46,4 @@ fn main() { //~| expected type `usize` //~| found type `main::G` //~| expected usize, found struct `main::G` - //~| ERROR expected `usize` for repeat count, found struct [E0306] - //~| expected `usize` } diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs index 10c02d84b385e..28e85c94b664c 100644 --- a/src/test/incremental/hashes/consts.rs +++ b/src/test/incremental/hashes/consts.rs @@ -66,8 +66,10 @@ const CONST_CHANGE_TYPE_2: Option = None; const CONST_CHANGE_VALUE_1: i16 = 1; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[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_clean(cfg="cfail3")] 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; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[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_clean(cfg="cfail3")] 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; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[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_clean(cfg="cfail3")] 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; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[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_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_4: i16 = 1 + 2 * 4; diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index aa17a24be23b6..da3a953d11eaa 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -108,8 +108,10 @@ enum EnumChangeValueCStyleVariant0 { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[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_clean(cfg="cfail3")] enum EnumChangeValueCStyleVariant0 { @@ -126,6 +128,8 @@ enum EnumChangeValueCStyleVariant1 { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[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_clean(cfg="cfail3")] enum EnumChangeValueCStyleVariant1 { diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs index ac67e4349013a..7c6da3ba9fea6 100644 --- a/src/test/incremental/hashes/statics.rs +++ b/src/test/incremental/hashes/statics.rs @@ -119,9 +119,11 @@ static STATIC_CHANGE_TYPE_2: Option = None; static STATIC_CHANGE_VALUE_1: i16 = 1; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[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")] 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; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[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")] 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; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[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")] 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; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[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")] static STATIC_CHANGE_VALUE_4: i16 = 1 + 2 * 4; diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index 391c2e75ba4d5..bc401ae93404f 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -98,11 +98,15 @@ trait TraitAddReturnType { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddReturnType { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method() -> u32; } @@ -115,11 +119,15 @@ trait TraitChangeReturnType { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeReturnType { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method() -> u64; } @@ -132,11 +140,15 @@ trait TraitAddParameterToMethod { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddParameterToMethod { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(a: u32); } @@ -146,15 +158,29 @@ trait TraitAddParameterToMethod { #[cfg(cfail1)] trait TraitChangeMethodParameterName { fn method(a: u32); + fn with_default(x: i32) {} } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeMethodParameterName { + // FIXME(#38501) This should preferably always be clean. + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(b: u32); + + #[rustc_clean(label="Hir", cfg="cfail2")] + #[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_clean(cfg="cfail3")] + fn with_default(y: i32) {} } @@ -166,11 +192,15 @@ trait TraitChangeMethodParameterType { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeMethodParameterType { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(a: i64); } @@ -183,11 +213,15 @@ trait TraitChangeMethodParameterTypeRef { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeMethodParameterTypeRef { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(a: &mut i32); } @@ -200,11 +234,15 @@ trait TraitChangeMethodParametersOrder { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeMethodParametersOrder { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(b: i64, a: i32); } @@ -253,11 +291,15 @@ trait TraitChangeModeSelfRefToMut { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeModeSelfRefToMut { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(&mut self); } @@ -269,11 +311,15 @@ trait TraitChangeModeSelfOwnToMut: Sized { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeModeSelfOwnToMut: Sized { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(mut self) {} } @@ -285,11 +331,15 @@ trait TraitChangeModeSelfOwnToRef { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeModeSelfOwnToRef { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(&self); } @@ -302,11 +352,15 @@ trait TraitAddUnsafeModifier { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddUnsafeModifier { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] unsafe fn method(); } @@ -319,11 +373,15 @@ trait TraitAddExternModifier { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddExternModifier { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] extern fn method(); } @@ -336,11 +394,15 @@ trait TraitChangeExternCToRustIntrinsic { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeExternCToRustIntrinsic { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] extern "rust-intrinsic" fn method(); } @@ -353,11 +415,15 @@ trait TraitAddTypeParameterToMethod { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddTypeParameterToMethod { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(); } @@ -370,11 +436,15 @@ trait TraitAddLifetimeParameterToMethod { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddLifetimeParameterToMethod { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method<'a>(); } @@ -391,11 +461,15 @@ trait TraitAddTraitBoundToMethodTypeParameter { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddTraitBoundToMethodTypeParameter { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(); } @@ -408,11 +482,15 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddBuiltinBoundToMethodTypeParameter { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(); } @@ -425,11 +503,15 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddLifetimeBoundToMethodLifetimeParameter { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method<'a, 'b: 'a>(a: &'a u32, b: &'b u32); } @@ -442,11 +524,15 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddSecondTraitBoundToMethodTypeParameter { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(); } @@ -459,11 +545,15 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(); } @@ -476,11 +566,15 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method<'a, 'b, 'c: 'a + 'b>(a: &'a u32, b: &'b u32, c: &'c u32); } @@ -514,11 +608,15 @@ trait TraitAddTraitBoundToAssociatedType { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddTraitBoundToAssociatedType { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] type Associated: ReferencedTrait0; fn mathod(); @@ -535,11 +633,15 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddLifetimeBoundToAssociatedType<'a> { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] type Associated: 'a; fn mathod(); @@ -617,11 +719,15 @@ trait TraitChangeTypeOfAssociatedConstant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeTypeOfAssociatedConstant { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] const Value: f64; fn mathod(); @@ -1013,11 +1119,15 @@ mod change_return_type_of_method_indirectly_use { #[cfg(not(cfail1))] use super::ReferenceType1 as ReturnType; - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeReturnType { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method() -> ReturnType; } } @@ -1031,11 +1141,15 @@ mod change_method_parameter_type_indirectly_by_use { #[cfg(not(cfail1))] use super::ReferenceType1 as ArgType; - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeArgType { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(a: ArgType); } } @@ -1049,11 +1163,15 @@ mod change_method_parameter_type_bound_indirectly_by_use { #[cfg(not(cfail1))] use super::ReferencedTrait1 as Bound; - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeBoundOfMethodTypeParameter { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(a: T); } } @@ -1068,11 +1186,15 @@ mod change_method_parameter_type_bound_indirectly_by_use_where { #[cfg(not(cfail1))] use super::ReferencedTrait1 as Bound; - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeBoundOfMethodTypeParameterWhere { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method(a: T) where T: Bound; } } diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs index ba8d3cc934bfc..8651a67bae221 100644 --- a/src/test/incremental/string_constant.rs +++ b/src/test/incremental/string_constant.rs @@ -23,14 +23,14 @@ fn main() { } mod x { #[cfg(rpass1)] pub fn x() { - println!("1"); + println!("{}", "1"); } #[cfg(rpass2)] #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] #[rustc_dirty(label="TransCrateItem", cfg="rpass2")] pub fn x() { - println!("2"); + println!("{}", "2"); } } diff --git a/src/test/run-make/graphviz-flowgraph/f18.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f18.dot-expected.dot index c1d6e3023fbc1..b0491fe6e27fd 100644 --- a/src/test/run-make/graphviz-flowgraph/f18.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f18.dot-expected.dot @@ -1,15 +1,15 @@ digraph block { N0[label="entry"]; N1[label="exit"]; - N2[label="stmt "]; + N2[label="stmt fn inner(x: isize) -> isize { x + x }"]; N3[label="expr inner"]; N4[label="expr inner"]; N5[label="expr 18"]; N6[label="expr inner(18)"]; N7[label="expr inner(inner(18))"]; N8[label="stmt inner(inner(18));"]; - N9[label="block { inner(inner(18)); }"]; - N10[label="expr { inner(inner(18)); }"]; + N9[label="block {\l fn inner(x: isize) -> isize { x + x }\l inner(inner(18));\l}\l"]; + N10[label="expr {\l fn inner(x: isize) -> isize { x + x }\l inner(inner(18));\l}\l"]; N0 -> N2; N2 -> N3; N3 -> N4; diff --git a/src/test/run-make/graphviz-flowgraph/f19.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f19.dot-expected.dot index d2f9f41f647be..223978c3d7634 100644 --- a/src/test/run-make/graphviz-flowgraph/f19.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f19.dot-expected.dot @@ -1,8 +1,8 @@ digraph block { N0[label="entry"]; N1[label="exit"]; - N2[label="stmt "]; - N3[label="stmt "]; + N2[label="stmt struct S19 {\l x: isize,\l}\l"]; + N3[label="stmt impl S19 {\l fn inner(self: Self) -> S19 { S19{x: self.x + self.x,} }\l}\l"]; N4[label="expr 19"]; N5[label="expr S19{x: 19,}"]; N6[label="local s"]; @@ -11,8 +11,8 @@ digraph block { N9[label="expr s.inner()"]; N10[label="expr s.inner().inner()"]; N11[label="stmt s.inner().inner();"]; - N12[label="block { let s = S19{x: 19,}; s.inner().inner(); }"]; - N13[label="expr { let s = S19{x: 19,}; s.inner().inner(); }"]; + N12[label="block {\l struct S19 {\l x: isize,\l }\l impl S19 {\l fn inner(self: Self) -> S19 { S19{x: self.x + self.x,} }\l }\l let s = S19{x: 19,};\l s.inner().inner();\l}\l"]; + N13[label="expr {\l struct S19 {\l x: isize,\l }\l impl S19 {\l fn inner(self: Self) -> S19 { S19{x: self.x + self.x,} }\l }\l let s = S19{x: 19,};\l s.inner().inner();\l}\l"]; N0 -> N2; N2 -> N3; N3 -> N4; diff --git a/src/test/run-make/pretty-print-path-suffix/foo_method.pp b/src/test/run-make/pretty-print-path-suffix/foo_method.pp index 696e0544fdc57..fae134986872e 100644 --- a/src/test/run-make/pretty-print-path-suffix/foo_method.pp +++ b/src/test/run-make/pretty-print-path-suffix/foo_method.pp @@ -12,5 +12,6 @@ -fn foo_method(&self) -> &'static str { return "i am very similar to foo."; } -/* nest::{{impl}}::foo_method */ +fn foo_method(self: &Self) + -> &'static str { return "i am very similar to foo."; } /* +nest::{{impl}}::foo_method */ diff --git a/src/test/run-pass-fulldeps/issue-37290/auxiliary/lint.rs b/src/test/run-pass-fulldeps/issue-37290/auxiliary/lint.rs index c6892757c682f..e1b1b441894b7 100644 --- a/src/test/run-pass-fulldeps/issue-37290/auxiliary/lint.rs +++ b/src/test/run-pass-fulldeps/issue-37290/auxiliary/lint.rs @@ -41,12 +41,12 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { 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) { 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) { extent = parent; } diff --git a/src/test/ui/span/mut-arg-hint.stderr b/src/test/ui/span/mut-arg-hint.stderr index 5e9a0b915031e..58f66c1358437 100644 --- a/src/test/ui/span/mut-arg-hint.stderr +++ b/src/test/ui/span/mut-arg-hint.stderr @@ -1,11 +1,3 @@ -error: cannot borrow immutable borrowed content `*a` as mutable - --> $DIR/mut-arg-hint.rs:13:9 - | -12 | fn foo(mut a: &String) { - | ------- use `&mut String` here to make mutable -13 | a.push_str("bar"); - | ^ - error: cannot borrow immutable borrowed content `*a` as mutable --> $DIR/mut-arg-hint.rs:18:5 | @@ -14,6 +6,14 @@ error: cannot borrow immutable borrowed content `*a` as mutable 18 | a.push_str("foo"); | ^ +error: cannot borrow immutable borrowed content `*a` as mutable + --> $DIR/mut-arg-hint.rs:13:9 + | +12 | fn foo(mut a: &String) { + | ------- use `&mut String` here to make mutable +13 | a.push_str("bar"); + | ^ + error: cannot borrow immutable borrowed content `*a` as mutable --> $DIR/mut-arg-hint.rs:25:9 |