diff options
| author | bors <bors@rust-lang.org> | 2016-12-28 20:19:39 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2016-12-28 20:19:39 +0000 |
| commit | 4ecc85beb339aa8089d936e450b0d800bdf580ae (patch) | |
| tree | 361b71fea58b9738649230009fe54f4643c9f188 /src | |
| parent | 02b22ec7bd8fa542dd3b08a8497ad5cd3a20c417 (diff) | |
| parent | ee0ea9534317466307c85e6a855e13370d37260d (diff) | |
| download | rust-4ecc85beb339aa8089d936e450b0d800bdf580ae.tar.gz rust-4ecc85beb339aa8089d936e450b0d800bdf580ae.zip | |
Auto merge of #38449 - eddyb:lazy-10, r=nikomatsakis
[10/n] Split constants and functions' arguments into disjoint bodies. _This is part of a series ([prev](https://github.com/rust-lang/rust/pull/38053) | [next]()) of patches designed to rework rustc into an out-of-order on-demand pipeline model for both better feature support (e.g. [MIR-based](https://github.com/solson/miri) early constant evaluation) and incremental execution of compiler passes (e.g. type-checking), with beneficial consequences to IDE support as well. If any motivation is unclear, please ask for additional PR description clarifications or code comments._ <hr> Finishes the signature-body split started in #37918, namely: * `trait` items are separated just like `impl` items were, for uniformity, closing #37712 * `static`s, `const`s (including associated ones), `enum` discriminants and array lengths get bodies * even the count in "repeat expressions", i.e. `n` in `[x; n]`, which fixes #24414 * arguments' patterns are moved to the bodies, with the types staying in `FnDecl` * `&self` now desugars to `self: &Self` instead of `self: &_` (similarly for other `self` forms) * `astconv`'s and metadata's (for rustdoc) informative uses are explicitly ignored for the purposes of the dep graph. this could be fixed in the future by hashing the exact information being extracted about the arguments as opposed to generating a dependency on *the whole body*
Diffstat (limited to 'src')
124 files changed, 2280 insertions, 2757 deletions
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index f21d98a0fc7..4d66bba9f07 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 2637d34c5c5..26e1dc7e049 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<DefId> { self.data.thread.query() } diff --git a/src/librustc/dep_graph/visit.rs b/src/librustc/dep_graph/visit.rs index f6a22e47cf2..1990574ca9a 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 474d7d508c4..4b171193b4a 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 71ef7131440..f359ca20163 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 1cf5e35a095..9a2658f48f3 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<DefIndex>, - exprs: FnvHashMap<hir::ExprId, hir::Expr>, resolver: &'a mut Resolver, /// The items being lowered are collected here. items: BTreeMap<NodeId, hir::Item>, + trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>, impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>, + bodies: FxHashMap<hir::BodyId, hir::Body>, } 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<Spanned<Name>> { + 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<hir::FnDecl> { 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(<pat>) => <body>` let pat_arm = { let body_block = self.lower_block(body); - let body_span = body_block.span; - let body_expr = P(hir::Expr { - id: self.next_id(), - node: hir::ExprBlock(body_block), - span: body_span, - 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 068e7ed8624..6e08b52f9a2 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 45988886a60..a6ffe7cea55 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<MapEntry<'ast>>, + pub(super) map: Vec<MapEntry<'ast>>, /// 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<MapEntry<'ast>>) - -> NodeCollector<'ast> { + pub(super) fn extend(krate: &'ast Crate, + parent: &'ast InlinedItem, + parent_node: NodeId, + map: Vec<MapEntry<'ast>>) + -> 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 256aee342a3..be8780f39b1 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<DefIndex>, diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 4f64670f482..b28c5e80ea3 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 4546f6d8c27..27ebeea9ad9 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 4eee76d466a..9149da459c2 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<NodeId, Item>, + pub trait_items: BTreeMap<TraitItemId, TraitItem>, pub impl_items: BTreeMap<ImplItemId, ImplItem>, - pub exprs: FnvHashMap<ExprId, Expr>, + pub bodies: FxHashMap<BodyId, Body>, } 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<Arg>, + 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<Attribute>, } -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<FnDecl>, ExprId, Span), + ExprClosure(CaptureClause, P<FnDecl>, BodyId, Span), /// A block (`{ ... }`) ExprBlock(P<Block>), @@ -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<Expr>, P<Expr>), + ExprRepeat(P<Expr>, BodyId), } /// Optionally `Self`-qualified value/type path or associated extension. @@ -1003,12 +1012,6 @@ pub enum QPath { TypeRelative(P<Ty>, P<PathSegment>) } -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<Attribute>, - 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<Spanned<Name>>), + + /// 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<Ty>, Option<P<Expr>>), + Const(P<Ty>, Option<BodyId>), /// A method with an optional body - MethodTraitItem(MethodSig, Option<ExprId>), + Method(MethodSig, TraitMethod), /// An associated type with (possibly empty) bounds and optional concrete /// type - TypeTraitItem(TyParamBounds, Option<P<Ty>>), + Type(TyParamBounds, Option<P<Ty>>), } // 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<Ty>, P<Expr>), + Const(P<Ty>, BodyId), /// A method implementation with the given signature and body - Method(MethodSig, ExprId), + Method(MethodSig, BodyId), /// An associated type Type(P<Ty>), } @@ -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<Ty>), /// A fixed length array (`[T; n]`) - TyArray(P<Ty>, P<Expr>), + TyArray(P<Ty>, 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<Expr>), + 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<Ty>, pub pat: P<Pat>, 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<Lifetime>, Mutability), - /// `self: TYPE`, `mut self: TYPE` - Explicit(P<Ty>, Mutability), -} - -pub type ExplicitSelf = Spanned<SelfKind>; - -impl Arg { - pub fn to_self(&self) -> Option<ExplicitSelf> { - 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<Arg>, + pub inputs: HirVec<P<Ty>>, pub output: FunctionRetTy, pub variadic: bool, } -impl FnDecl { - pub fn get_self(&self) -> Option<ExplicitSelf> { - 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<Attribute>, pub data: VariantData, /// Explicit discriminant, eg `Foo = 1` - pub disr_expr: Option<P<Expr>>, + pub disr_expr: Option<BodyId>, } pub type Variant = Spanned<Variant_>; @@ -1562,11 +1535,11 @@ pub enum Item_ { ItemUse(P<Path>, UseKind), /// A `static` item - ItemStatic(P<Ty>, Mutability, P<Expr>), + ItemStatic(P<Ty>, Mutability, BodyId), /// A `const` item - ItemConst(P<Ty>, P<Expr>), + ItemConst(P<Ty>, BodyId), /// A function declaration - ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, ExprId), + ItemFn(P<FnDecl>, 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<A, B> {x: A, y: B}` ItemUnion(VariantData, Generics), /// Represents a Trait Declaration - ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItem>), + ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>), // 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<FnDecl>, Generics), + ForeignItemFn(P<FnDecl>, HirVec<Spanned<Name>>, Generics), /// A foreign static item (`static ext: u8`), with optional mutability /// (the boolean is true when mutable) ForeignItemStatic(P<Ty>, bool), diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 100e344d941..18fa6836b51 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<Vec<comments::Comment>>, @@ -86,30 +105,6 @@ impl<'a> PrintState<'a> for State<'a> { } } -pub fn rust_printer<'a>(writer: Box<Write + 'a>, 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<Write + 'a>, - 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<Write + 'a>, 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<Write + 'a>, ann: &'a PpAnn, comments: Option<Vec<comments::Comment>>, - literals: Option<Vec<comments::Literal>>, - krate: Option<&'a Crate>) + literals: Option<Vec<comments::Literal>>) -> 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: F) -> String +pub fn to_string<F>(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<hir::BodyId>, 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<ast::Name>], + body_id: Option<hir::BodyId>) -> 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<ast::Name>, generics: &hir::Generics, - vis: &hir::Visibility) + vis: &hir::Visibility, + arg_names: &[Spanned<ast::Name>], + body_id: Option<hir::BodyId>) -> 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 9d48fbca53e..9ff7dcc7d58 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<hir::Ty>], lifetime: hir::Lifetime, anon_nums: &HashSet<u32>, region_names: &HashSet<ast::Name>) - -> hir::HirVec<hir::Arg> { - 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<P<hir::Ty>> { + 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 17cc34fcd83..ff508d2d819 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 3ff2abac277..cce79820ca8 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 ccf53f01cd5..7e0da00694c 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 ec98637922e..00000000000 --- 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// 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 d0003693eef..7151e5226ca 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<DefIndex>, } -/// 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<hir::Expr>, - pub const_fn_args: Vec<Option<DefId>>, -} - -/// 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<Option<DefId>>, -} - -fn get_fn_args(decl: &hir::FnDecl) -> Vec<Option<DefId>> { - 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<V>(&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<SyntaxExtension>), @@ -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<ast::NodeId>; - fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId>; + 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<hir::BodyId, hir::Body>; + 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<ast::NodeId> { - bug!("local_node_for_inlined_defid") + fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body> { + bug!("item_body_nested_bodies") } - fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId> { - 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 f7a34c43ccc..dfcb5cb7b79 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<Vec<CFGIndex>> { 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<Vec<CFGIndex>>, - 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<Vec<CFGIndex>>, + 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<Vec<CFGIndex>>, } 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<io::Write + 'b>, - 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 1c5dd97b74b..76adee4e00c 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 2ec7aa4c4d9..38b0b18b012 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 e927843a984..f2e46d4cbc9 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 b3e61f1e570..a3a49c91633 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 2357549c82e..d932061d42d 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 029a1d66add..4cae5b370eb 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 445aed8f97d..745a94a5ddb 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 4c3b102e540..2d88567b8b8 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 2c4710f1e45..ee841afc021 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 b1e35e54eb9..faf4a448b7a 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 c5b03a4a32a..c491af972ac 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 3576ae662a0..3c5a91f4ff0 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 f24ff980355..cb1fc15c5f6 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<DefIdSet>, - /// 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<DefIdMap<Option<(NodeId, Option<Ty<'tcx>>)>>>, - /// Cache used by const_eval when decoding extern const fns - pub extern_const_fns: RefCell<DefIdMap<NodeId>>, - /// Maps any item's def-id to its stability index. pub stability: RefCell<stability::Index<'tcx>>, @@ -537,8 +529,8 @@ pub struct GlobalCtxt<'tcx> { /// Caches the representation hints for struct definitions. repr_hint_cache: RefCell<DepTrackingMap<maps::ReprHints<'tcx>>>, - /// Maps Expr NodeId's to their constant qualification. - pub const_qualif_map: RefCell<NodeMap<middle::const_qualif::ConstQualif>>, + /// Maps Expr NodeId's to `true` iff `&expr` can have 'static lifetime. + pub rvalue_promotable_to_static: RefCell<NodeMap<bool>>, /// Caches CoerceUnsized kinds for impls on custom types. pub custom_coerce_unsized_kinds: RefCell<DefIdMap<ty::adjustment::CustomCoerceUnsized>>, @@ -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 2ab10d0446b..b03a432de41 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 5ed628d7dca..dc2214dd34e 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 5d59b58b847..34f1ad57c62 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<Loan<'tcx>>, 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 68929cd4e85..c7bd5b7ed04 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; @@ -57,27 +54,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 ecf5c3ef176..1ba313015d5 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 32bda5e1162..a02aba7208c 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 786b59e818d..01b19e1f539 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 83b0d9dec6d..b24cd261dd5 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 9fcab123989..e8e7a2eb7ed 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<ast::NodeId> { - 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<ConstFnNode<'tcx>> +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::<Vec<_>>(); 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 4db620b2bec..6a884bafce7 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 74df1e52bde..5103a55fd71 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<borrowck_dot::Variant>, 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 87e6b2befdc..b5fe158f158 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 74707865dee..49609fbc798 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 bb61756694f..4bb12667bbc 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 40873011a7b..481462dff86 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 1d384741d96..2baef47c214 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 cd414846af4..c021ffee818 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 751c9c3440f..a3aa4af493a 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 429bfb8e3d6..b7ee688117d 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 926c44824ce..b27b164bd47 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<InlinedItem>, + body: Lazy<hir::Body>, side_tables: LazySeq<(ast::NodeId, TableEntry<'tcx>)>, + pub nested_bodies: LazySeq<hir::Body>, + 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<Ast<'tcx>> { + pub fn encode_body(&mut self, body: hir::BodyId) -> Lazy<Ast<'tcx>> { + 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 7ec847d24cf..aab4034b770 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<DefIndex>, } -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<FxHashMap<CrateNum, Rc<CrateMetadata>>>, @@ -104,8 +97,7 @@ pub struct CStore { used_link_args: RefCell<Vec<String>>, statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>, pub dllimport_foreign_items: RefCell<FxHashSet<DefIndex>>, - pub inlined_item_cache: RefCell<DefIdMap<Option<CachedInlinedItem>>>, - pub defid_for_inlined_node: RefCell<NodeMap<DefId>>, + pub inlined_item_cache: RefCell<DefIdMap<Option<ast::NodeId>>>, pub visible_parent_map: RefCell<DefIdMap<DefId>>, } @@ -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 0ac3ffd5cb9..64513fa41b2 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<Def> { 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<ast::Name> { - 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<ast::NodeId> { - 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<hir::BodyId, hir::Body> { + 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<DefId> { - 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 400a3ac0e3e..c27e06c5022 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<hir::BodyId, hir::Body> { + 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 bc0a64b9a51..72dcb4ba9a3 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<ast::Name> { - 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<ast::Name> { + 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<ast::Name>]) + -> LazySeq<ast::Name> { + self.lazy_seq(names.iter().map(|name| name.node)) + } + fn encode_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> { 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 e06d940de7e..63bb1bf20c0 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 0e4dbb04777..cfdc1bf27df 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<Item=(Ty<'gcx>, 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 c02a1822d73..59a11782e08 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 d579cdb042f..cc65fdede09 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 e2a516edbc8..cbc53ea3c51 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 86f56d00358..d1d9a201567 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<hir::Mutability>, + in_fn: bool, + promotable: bool, + mut_rvalue_borrows: NodeSet, + param_env: ty::ParameterEnvironment<'tcx>, } impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { - fn with_mode<F, R>(&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<F, R>(&mut self, item_id: Option<ast::NodeId>, 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 f7e026866e2..65a60732fc8 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 10f464a9901..df9fe00e9a8 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 ddb5af1e80c..3da4f24b6c2 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 b5be4aa5e64..ba4fc57276b 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<Option<&'ast hir::Expr>>, + discriminant_map: NodeMap<Option<hir::BodyId>>, 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<Option<&'ast hir::Expr>>, + discriminant_map: &'a mut NodeMap<Option<hir::BodyId>>, idstack: Vec<ast::NodeId>, 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 75046f6aeb8..34ebd12de9c 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 ca3e4e1c762..81863a3fadf 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 a0af4c45653..865195d3db4 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 491521a3239..43e3b1dd2b5 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 84222bfe56e..2bc42a46152 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<TransItem<'tcx>>) +/// 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<TransItem<'tcx>>) { - // 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 f292a709650..d9179d6a6fa 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<ast::NodeId> { - self.sess().cstore.local_node_for_inlined_defid(def_id) - } - - pub fn defid_for_inlined_node<'a>(&'a self, node_id: ast::NodeId) -> Option<DefId> { - self.sess().cstore.defid_for_inlined_node(node_id) - } - pub fn instances<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef>> { &self.local().instances } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 08f68f8d49c..1cedaa0a4e1 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<mir::Local, Const<'tcx>>) -> Result<Const<'tcx>, 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 8f05cc793ef..4b31d5b7f88 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 598003a3925..75c25a605af 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<ElisionFailureInfo>) { @@ -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<I>(&self, input_tys: &[Ty<'tcx>], - input_pats: I) -> ElidedLifetime - where I: Iterator<Item=String> + parent: Option<hir::BodyId>, + input_indices: I) -> ElidedLifetime + where I: Iterator<Item=usize> { 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>>) -> 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<Ty<'tcx>>, + body: Option<hir::BodyId>, anon_scope: Option<AnonTypeScope>) -> &'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<AnonTypeScope>) -> &'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<Ty<'tcx>>, + opt_self_value_ty: Option<Ty<'tcx>>, decl: &hir::FnDecl, + body: Option<hir::BodyId>, arg_anon_scope: Option<AnonTypeScope>, ret_anon_scope: Option<AnonTypeScope>) -> &'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<Ty> = + 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<Ty> = - 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 ff50ee11b39..9b86196b3ec 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 4fba29def22..0b9cf38fa07 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 1d81ed7d359..9412c9105c7 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<ty::ClosureKind>, decl: &'gcx hir::FnDecl, - body: &'gcx hir::Expr, + body: &'gcx hir::Body, expected_sig: Option<ty::FnSig<'tcx>>) -> 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 478de167317..be10b77bd8b 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 183a2a48ff5..c733c0856c6 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 86bfede87b3..04ec9292d14 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 a2dceed8d26..7275fbd1203 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 eb08e70d4c3..bd63eb6ad25 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 63d20416bde..5d927a503a1 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 ffdb56753fd..c80db7fa4d0 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 56de75995fd..9a2bfbf715a 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 0034a85f8e2..cd9453770a6 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 0e5a16987c1..3bbe5aa1fef 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 2e8206ec959..bc1ead07c0e 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 815811675a5..a09bdf0533a 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 6d5de8f2506..c4c7c699f65 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 fba77d17179..fd51b38e1b5 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<hir::BodyId>, + 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<ty::Disr> { - 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::<ty::Disr>; 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<ty::Predicate<'tcx>> { - 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 cea3ad43a95..d3b671f2a4d 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::<u32>(); - mem::transmute_copy::<u32, [u8; size]>(&8_8); - // error: no type for local variable -} -``` - -To fix this error, please use a constant size instead of `size`. To make -this error more obvious, you could run: - -```compile_fail,E0080 -use std::mem; - -unsafe { - mem::transmute_copy::<u32, [u8; mem::size_of::<u32>()]>(&8_8); - // error: constant evaluation error -} -``` - -So now, you can fix your code by setting the size directly: - -``` -use std::mem; - -unsafe { - mem::transmute_copy::<u32, [u8; 4]>(&8_8); - // `u32` is 4 bytes so we replace the `mem::size_of` call with its size -} -``` -"##, - E0516: r##" 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 9f5b73d9b30..ce495e6fb4c 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 131ecfc6e0c..3f5e443a20a 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<hir::BodyId>, + /// 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 39f996ee62b..507079a4f87 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 851cfcd8723..d4d3edbcb12 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 94e9fdbfc3e..cba5e1ba6f3 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<clean::Item>) { 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<hir::BodyId, hir::Body> +} + +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 fdbd2f3647c..3b828198069 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<Method> for hir::MethodSig { +impl<'a> Clean<Method> 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<TyMethod> 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<Item> 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<Argument>, } -impl Clean<FnDecl> for hir::FnDecl { +impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], &'a [Spanned<ast::Name>]) { + 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<Arguments> for (&'a [P<hir::Ty>], 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<FnDecl> for (&'a hir::FnDecl, A) + where (&'a [P<hir::Ty>], A): Clean<Arguments> +{ 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<FnDecl> 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<FnDecl> 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<SelfTy> { - 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<Argument> 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<PolyTrait> for hir::PolyTraitRef { impl Clean<Item> 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<Item> for hir::TraitItem { impl Clean<Item> 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<Item> 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<Type> 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<BareFunctionDecl> 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<Item> 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<Item> 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<Vec<Item>> for hir::ForeignMod { impl Clean<Item> 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 31e10fbd3b7..d819268240b 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<hir::Ty>, pub mutability: hir::Mutability, - pub expr: P<hir::Expr>, + pub expr: hir::BodyId, pub name: Name, pub attrs: hir::HirVec<ast::Attribute>, pub vis: hir::Visibility, @@ -186,7 +187,7 @@ pub struct Static { pub struct Constant { pub type_: P<hir::Ty>, - pub expr: P<hir::Expr>, + pub expr: hir::BodyId, pub name: Name, pub attrs: hir::HirVec<ast::Attribute>, pub vis: hir::Visibility, diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index d81165ba00f..c242eea2362 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -502,7 +502,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 c93112657b9..b0afc3d63f4 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 a5abdd922d6..f72985fd91a 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 726e2326524..00000000000 --- 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::mem; - -fn main() { - unsafe { - let size = mem::size_of::<u32>(); - mem::transmute_copy::<u32, [u8; size]>(&8_8); //~ ERROR E0513 - //~| NOTE no type for variable - } -} 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 c3fa39659b9..7c3f7a1d574 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<A: Foo, B: Foo>() { - let _array = [4; <A as Foo>::Y]; //~ ERROR E0080 - //~| non-constant path in constant + let _array = [4; <A as Foo>::Y]; + //~^ ERROR cannot use an outer type parameter in this context [E0402] + //~| ERROR constant evaluation error [E0080] + //~| non-constant path in constant } 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 ddf16a2278e..dcf87d5f0fc 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<A: Foo, B: Foo>() { let _array: [u32; <A as Foo>::Y]; - //~^ ERROR the trait bound `A: Foo` is not satisfied + //~^ ERROR cannot use an outer type parameter in this context [E0402] + //~| ERROR constant evaluation error [E0080] + //~| non-constant path in constant } fn main() { diff --git a/src/test/compile-fail/dep-graph-struct-signature.rs b/src/test/compile-fail/dep-graph-struct-signature.rs index 235fc5051d7..36382e776ce 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 2e33f11c04b..4cc15e8b522 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 f8aa1ea95f0..eac134ff3cc 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 e89bff025e0..f80135848e0 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 b5401f7d124..691d8d31b41 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 a6f88a57b91..f4769a78587 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 5d5113ce07c..a716f3e29d4 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 10c02d84b38..28e85c94b66 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<u64> = 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 aa17a24be23..da3a953d11e 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 ac67e434901..7c6da3ba9fe 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<u16> = 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 391c2e75ba4..bc401ae9340 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<T>(); } @@ -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<T: ReferencedTrait0>(); } @@ -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<T: Sized>(); } @@ -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<T: ReferencedTrait0 + ReferencedTrait1>(); } @@ -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<T: Sized + Sync>(); } @@ -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<T: Bound>(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<T>(a: T) where T: Bound; } } diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs index ba8d3cc934b..8651a67bae2 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 c1d6e3023fb..b0491fe6e27 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 d2f9f41f647..223978c3d76 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 696e0544fdc..fae13498687 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 c6892757c68..e1b1b441894 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 5e9a0b91503..58f66c13584 100644 --- a/src/test/ui/span/mut-arg-hint.stderr +++ b/src/test/ui/span/mut-arg-hint.stderr @@ -1,12 +1,4 @@ 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 | 17 | pub fn foo<'a>(mut a: &'a String) { @@ -15,6 +7,14 @@ error: cannot borrow immutable borrowed content `*a` as mutable | ^ 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 | 24 | pub fn foo(mut a: &String) { |
