From f89856be6ccd1f63ef72d343587cd5d7932cfe8b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 20 Dec 2016 22:46:11 +0200 Subject: [PATCH] rustc: move function arguments into hir::Body. --- src/librustc/dep_graph/graph.rs | 6 + src/librustc/hir/intravisit.rs | 45 ++-- src/librustc/hir/lowering.rs | 71 ++++--- src/librustc/hir/map/blocks.rs | 7 +- src/librustc/hir/map/mod.rs | 4 +- src/librustc/hir/mod.rs | 18 +- src/librustc/hir/print.rs | 194 ++++++++++-------- src/librustc/infer/error_reporting.rs | 51 +++-- src/librustc/middle/cstore.rs | 32 +-- src/librustc/middle/dataflow.rs | 26 ++- src/librustc/middle/dead.rs | 6 +- src/librustc/middle/expr_use_visitor.rs | 17 +- src/librustc/middle/liveness.rs | 12 +- src/librustc/middle/reachable.rs | 7 +- src/librustc/middle/resolve_lifetime.rs | 9 +- src/librustc/ty/mod.rs | 2 +- src/librustc_borrowck/borrowck/check_loans.rs | 3 +- .../borrowck/gather_loans/mod.rs | 3 +- src/librustc_borrowck/borrowck/mod.rs | 37 ++-- src/librustc_borrowck/borrowck/move_data.rs | 5 +- src/librustc_const_eval/check_match.rs | 41 +--- src/librustc_const_eval/eval.rs | 20 +- .../calculate_svh/svh_visitor.rs | 6 +- src/librustc_lint/bad_style.rs | 19 +- src/librustc_lint/builtin.rs | 6 +- src/librustc_lint/types.rs | 4 +- src/librustc_lint/unused.rs | 6 +- src/librustc_metadata/cstore_impl.rs | 6 +- src/librustc_metadata/encoder.rs | 44 ++-- src/librustc_mir/build/matches/mod.rs | 2 +- src/librustc_mir/build/mod.rs | 9 +- src/librustc_mir/build/scope.rs | 6 +- src/librustc_mir/mir_map.rs | 5 +- src/librustc_passes/consts.rs | 2 +- src/librustc_passes/rvalues.rs | 2 +- src/librustc_typeck/astconv.rs | 56 +++-- src/librustc_typeck/check/compare_method.rs | 10 +- src/librustc_typeck/check/intrinsic.rs | 2 +- src/librustc_typeck/check/mod.rs | 58 ++---- src/librustc_typeck/check/regionck.rs | 13 +- src/librustc_typeck/check/upvar.rs | 5 +- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/check/writeback.rs | 51 +---- src/librustc_typeck/collect.rs | 29 +-- src/librustc_typeck/rscope.rs | 6 +- src/librustdoc/clean/mod.rs | 121 ++++++----- src/librustdoc/doctree.rs | 1 + src/librustdoc/visit_ast.rs | 8 +- .../explicit-self-lifetime-mismatch.rs | 6 +- src/test/incremental/hashes/trait_defs.rs | 12 +- 50 files changed, 545 insertions(+), 568 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 2637d34c5c56..26e1dc7e0490 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -51,6 +51,12 @@ impl DepGraph { } } + /// True if we are actually building the full dep-graph. + #[inline] + pub fn is_fully_enabled(&self) -> bool { + self.data.thread.is_fully_enabled() + } + pub fn query(&self) -> DepGraphQuery { self.data.thread.query() } diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 845b6473259d..4b171193b4af 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -395,6 +395,10 @@ pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_node_i } pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) { + for argument in &body.arguments { + visitor.visit_id(argument.id); + visitor.visit_pat(&argument.pat); + } visitor.visit_expr(&body.value); } @@ -680,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), } @@ -750,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) } @@ -799,12 +796,15 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai visitor.visit_ty(ty); walk_list!(visitor, visit_nested_body, default); } - TraitItemKind::Method(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); + } } - TraitItemKind::Method(ref sig, Some(body_id)) => { + TraitItemKind::Method(ref sig, TraitMethod::Provided(body_id)) => { visitor.visit_fn(FnKind::Method(trait_item.name, sig, None, @@ -1113,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: BodyId, - sp: Span, - id: NodeId, - map: &map::Map<'v>) - -> IdRange { - let mut visitor = IdRangeComputingVisitor::new(map); - visitor.visit_fn(fk, decl, body, sp, id); - visitor.result() -} diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index c858436e7fc4..9a2658f48f3d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -170,8 +170,12 @@ impl<'a> LoweringContext<'a> { visit::walk_crate(&mut item_lowerer, c); } - fn record_body(&mut self, value: hir::Expr) -> hir::BodyId { + 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(); @@ -310,11 +314,11 @@ impl<'a> LoweringContext<'a> { TyKind::Array(ref ty, ref length) => { let length = self.lower_expr(length); hir::TyArray(self.lower_ty(ty), - self.record_body(length)) + self.record_body(length, None)) } TyKind::Typeof(ref expr) => { let expr = self.lower_expr(expr); - hir::TyTypeof(self.record_body(expr)) + hir::TyTypeof(self.record_body(expr, None)) } TyKind::PolyTraitRef(ref bounds) => { hir::TyPolyTraitRef(self.lower_bounds(bounds)) @@ -343,7 +347,7 @@ impl<'a> LoweringContext<'a> { data: self.lower_variant_data(&v.node.data), disr_expr: v.node.disr_expr.as_ref().map(|e| { let e = self.lower_expr(e); - self.record_body(e) + self.record_body(e, None) }), }, span: v.span, @@ -532,13 +536,24 @@ impl<'a> LoweringContext<'a> { hir::Arg { id: arg.id, pat: self.lower_pat(&arg.pat), - ty: self.lower_ty(&arg.ty), } } + fn lower_fn_args_to_names(&mut self, decl: &FnDecl) + -> hir::HirVec> { + decl.inputs.iter().map(|arg| { + match arg.pat.node { + PatKind::Ident(_, ident, None) => { + respan(ident.span, ident.node.name) + } + _ => respan(arg.pat.span, keywords::Invalid.name()), + } + }).collect() + } + fn lower_fn_decl(&mut self, decl: &FnDecl) -> P { P(hir::FnDecl { - inputs: decl.inputs.iter().map(|x| self.lower_arg(x)).collect(), + inputs: decl.inputs.iter().map(|arg| self.lower_ty(&arg.ty)).collect(), output: match decl.output { FunctionRetTy::Ty(ref ty) => hir::Return(self.lower_ty(ty)), FunctionRetTy::Default(span) => hir::DefaultReturn(span), @@ -869,17 +884,17 @@ impl<'a> LoweringContext<'a> { let value = self.lower_expr(e); hir::ItemStatic(self.lower_ty(t), self.lower_mutability(m), - self.record_body(value)) + self.record_body(value, None)) } ItemKind::Const(ref t, ref e) => { let value = self.lower_expr(e); hir::ItemConst(self.lower_ty(t), - self.record_body(value)) + 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_body(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), @@ -948,16 +963,20 @@ impl<'a> LoweringContext<'a> { hir::TraitItemKind::Const(this.lower_ty(ty), default.as_ref().map(|x| { let value = this.lower_expr(x); - this.record_body(value) + this.record_body(value, None) })) } - TraitItemKind::Method(ref sig, ref body) => { + TraitItemKind::Method(ref sig, None) => { + let names = this.lower_fn_args_to_names(&sig.decl); hir::TraitItemKind::Method(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_body(expr) - })) + 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::TraitItemKind::Type(this.lower_bounds(bounds), @@ -1005,13 +1024,13 @@ impl<'a> LoweringContext<'a> { node: match i.node { ImplItemKind::Const(ref ty, ref expr) => { let value = this.lower_expr(expr); - let body_id = this.record_body(value); + 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 body_id = this.record_body(expr); + 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)), @@ -1097,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) @@ -1367,7 +1388,7 @@ impl<'a> LoweringContext<'a> { ExprKind::Repeat(ref expr, ref count) => { let expr = P(self.lower_expr(expr)); let count = self.lower_expr(count); - hir::ExprRepeat(expr, self.record_body(count)) + hir::ExprRepeat(expr, self.record_body(count, None)) } ExprKind::Tup(ref elts) => { hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect()) @@ -1450,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_body(expr), + this.record_body(expr, Some(decl)), fn_decl_span) }) } @@ -1734,13 +1755,7 @@ impl<'a> LoweringContext<'a> { // `::std::option::Option::Some() => ` let pat_arm = { let body_block = self.lower_block(body); - let body_span = body_block.span; - let body_expr = P(hir::Expr { - id: self.next_id(), - node: hir::ExprBlock(body_block), - span: body_span, - attrs: ThinVec::new(), - }); + let body_expr = P(self.expr_block(body_block, ThinVec::new())); let pat = self.lower_pat(pat); let some_pat = self.pat_some(e.span, pat); diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 001a4d1526dd..6e08b52f9a24 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -62,7 +62,10 @@ impl MaybeFnLike for ast::Item { impl MaybeFnLike for ast::TraitItem { fn is_fn_like(&self) -> bool { - match self.node { ast::TraitItemKind::Method(_, Some(_)) => true, _ => false, } + match self.node { + ast::TraitItemKind::Method(_, ast::TraitMethod::Provided(_)) => true, + _ => false, + } } } @@ -252,7 +255,7 @@ impl<'a> FnLikeNode<'a> { _ => bug!("item FnLikeNode that is not fn-like"), }, map::NodeTraitItem(ti) => match ti.node { - ast::TraitItemKind::Method(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/mod.rs b/src/librustc/hir/map/mod.rs index ff9d12bb4f12..330583c0d886 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -389,7 +389,9 @@ impl<'ast> Map<'ast> { fn is_trait_item_body(&self, node_id: NodeId, item: &TraitItem) -> bool { match item.node { TraitItemKind::Const(_, Some(body)) | - TraitItemKind::Method(_, Some(body)) => body.node_id == node_id, + TraitItemKind::Method(_, TraitMethod::Provided(body)) => { + body.node_id == node_id + } _ => false } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index b4a42711e4d2..73097389c189 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -868,6 +868,7 @@ pub struct BodyId { /// The body of a function or constant value. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Body { + pub arguments: HirVec, pub value: Expr } @@ -1102,6 +1103,16 @@ pub struct TraitItem { pub span: Span, } +/// A trait method's body (or just argument names). +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum TraitMethod { + /// No default body in the trait, just a signature. + Required(HirVec>), + + /// Both signature and body are provided in the trait. + Provided(BodyId), +} + /// Represents a trait method or associated constant or type #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum TraitItemKind { @@ -1109,7 +1120,7 @@ pub enum TraitItemKind { /// must contain a value) Const(P, Option), /// A method with an optional body - Method(MethodSig, Option), + Method(MethodSig, TraitMethod), /// An associated type with (possibly empty) bounds and optional concrete /// type Type(TyParamBounds, Option>), @@ -1248,7 +1259,6 @@ pub struct InlineAsm { /// represents an argument in a function header #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Arg { - pub ty: P, pub pat: P, pub id: NodeId, } @@ -1256,7 +1266,7 @@ pub struct Arg { /// Represents the header (not the body) of a function declaration #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct FnDecl { - pub inputs: HirVec, + pub inputs: HirVec>, pub output: FunctionRetTy, pub variadic: bool, } @@ -1639,7 +1649,7 @@ pub struct ForeignItem { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum ForeignItem_ { /// A foreign function - ForeignItemFn(P, Generics), + ForeignItemFn(P, HirVec>, Generics), /// A foreign static item (`static ext: u8`), with optional mutability /// (the boolean is true when mutable) ForeignItemStatic(P, bool), diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 9518113b5a09..a7ffce37ee44 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -20,7 +20,6 @@ use syntax::print::pp::{Breaks, eof}; use syntax::print::pp::Breaks::{Consistent, Inconsistent}; use syntax::print::pprust::{self as ast_pp, PrintState}; use syntax::ptr::P; -use syntax::symbol::keywords; use syntax_pos::{self, BytePos}; use errors; @@ -267,10 +266,6 @@ 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)) } @@ -283,24 +278,35 @@ 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 fn_decl_in_crate_to_string(krate: &hir::Crate, + decl: &hir::FnDecl, + unsafety: hir::Unsafety, + constness: hir::Constness, + name: ast::Name, + generics: &hir::Generics, + body_id: hir::BodyId) + -> String { + + let mut wr = Vec::new(); + { + let mut s = rust_printer(Box::new(&mut wr), Some(krate)); + (|s: &mut State| { + s.head("")?; + s.print_fn(decl, + unsafety, + constness, + Abi::Rust, + Some(name), + generics, + &hir::Inherited, + &[], + Some(body_id))?; + s.end()?; // Close the head box + s.end()?; // Close the outer box + eof(&mut s.s) + })(&mut s).unwrap(); + } + String::from_utf8(wr).unwrap() } pub fn block_to_string(blk: &hir::Block) -> String { @@ -317,10 +323,6 @@ 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), @@ -569,7 +571,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 +579,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 @@ -644,13 +648,14 @@ impl<'a> State<'a> { } } + fn maybe_body(&mut self, body_id: hir::BodyId) -> Option<&'a hir::Body> { + self.krate.map(|krate| krate.body(body_id)) + } + fn print_body_id(&mut self, body_id: hir::BodyId) -> io::Result<()> { - if let Some(krate) = self.krate { - let expr = &krate.body(body_id).value; - self.print_expr(expr) - } else { - Ok(()) - } + self.maybe_body(body_id).map_or(Ok(()), |body| { + self.print_expr(&body.value) + }) } /// Pretty-print an item @@ -734,7 +739,9 @@ 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 @@ -995,7 +1002,9 @@ impl<'a> State<'a> { pub fn print_method_sig(&mut self, name: ast::Name, m: &hir::MethodSig, - vis: &hir::Visibility) + vis: &hir::Visibility, + arg_names: &[Spanned], + body_id: Option) -> io::Result<()> { self.print_fn(&m.decl, m.unsafety, @@ -1003,7 +1012,9 @@ impl<'a> State<'a> { m.abi, Some(name), &m.generics, - vis) + vis, + arg_names, + body_id) } pub fn print_trait_item_ref(&mut self, item_ref: &hir::TraitItemRef) -> io::Result<()> { @@ -1025,19 +1036,17 @@ impl<'a> State<'a> { hir::TraitItemKind::Const(ref ty, default) => { self.print_associated_const(ti.name, &ty, default, &hir::Inherited)?; } - hir::TraitItemKind::Method(ref sig, body) => { - if body.is_some() { - self.head("")?; - } - self.print_method_sig(ti.name, sig, &hir::Inherited)?; - if let Some(body) = body { - self.nbsp()?; - self.end()?; // need to close a box - self.end()?; // need to close a box - self.print_body_id(body)?; - } else { - word(&mut self.s, ";")?; - } + 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.print_body_id(body)?; } hir::TraitItemKind::Type(ref bounds, ref default) => { self.print_associated_type(ti.name, @@ -1075,7 +1084,7 @@ impl<'a> State<'a> { } 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 @@ -1442,7 +1451,7 @@ impl<'a> State<'a> { 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 @@ -1966,7 +1975,9 @@ impl<'a> State<'a> { abi: Abi, name: Option, generics: &hir::Generics, - vis: &hir::Visibility) + vis: &hir::Visibility, + arg_names: &[Spanned], + body_id: Option) -> io::Result<()> { self.print_fn_header_info(unsafety, constness, abi, vis)?; @@ -1975,24 +1986,58 @@ 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()); + let args = body_id.and_then(|body_id| self.maybe_body(body_id)) + .map_or(&[][..], |body| &body.arguments[..]); + 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(arg) = args.get(i) { + s.print_pat(&arg.pat)?; + 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; + let args = self.maybe_body(body_id).map_or(&[][..], |body| &body.arguments[..]); + self.commasep(Inconsistent, &decl.inputs, |s, ty| { + s.ibox(indent_unit)?; + + if let Some(arg) = args.get(i) { + s.print_pat(&arg.pat)?; + } else { + word(&mut s.s, "_")?; + } + 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 { @@ -2164,27 +2209,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)?, - _ => { - 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(()); @@ -2232,7 +2256,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 026f4b187e23..7d8ee33b4bed 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -1051,8 +1051,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 +1066,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::TraitItemKind::Method(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 +1096,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 +1377,14 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { } fn rebuild_args_ty(&self, - inputs: &[hir::Arg], + inputs: &[P], lifetime: hir::Lifetime, anon_nums: &HashSet, region_names: &HashSet) - -> hir::HirVec { - let mut new_inputs = Vec::new(); - for arg in inputs { - let new_ty = self.rebuild_arg_ty_or_output(&arg.ty, lifetime, - anon_nums, region_names); - let possibly_new_arg = hir::Arg { - ty: new_ty, - pat: arg.pat.clone(), - id: arg.id - }; - new_inputs.push(possibly_new_arg); - } - new_inputs.into() + -> hir::HirVec> { + inputs.iter().map(|arg_ty| { + self.rebuild_arg_ty_or_output(arg_ty, lifetime, anon_nums, region_names) + }).collect() } fn rebuild_output(&self, ty: &hir::FunctionRetTy, @@ -1634,10 +1627,16 @@ 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 = pprust::fn_decl_in_crate_to_string(self.tcx.map.krate(), + decl, + unsafety, + constness, + name, + generics, + body); + let msg = format!("consider using an explicit lifetime parameter as shown: {}", s); err.span_help(span, &msg[..]); } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 4c2e43f8e225..7dcc5aae8e73 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -140,7 +140,6 @@ pub struct NativeLibrary { pub struct InlinedItem { pub def_id: DefId, pub body: hir::Body, - pub const_fn_args: Vec>, } /// A borrowed version of `hir::InlinedItem`. This is what's encoded when saving @@ -149,14 +148,6 @@ pub struct InlinedItem { pub struct InlinedItemRef<'a> { pub def_id: DefId, pub body: &'a hir::Body, - pub const_fn_args: Vec>, -} - -fn get_fn_args(decl: &hir::FnDecl) -> Vec> { - decl.inputs.iter().map(|arg| match arg.pat.node { - hir::PatKind::Binding(_, def_id, _, _) => Some(def_id), - _ => None - }).collect() } impl<'a, 'tcx> InlinedItemRef<'tcx> { @@ -164,16 +155,14 @@ impl<'a, 'tcx> InlinedItemRef<'tcx> { item: &hir::Item, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> InlinedItemRef<'tcx> { - let (body_id, args) = match item.node { - hir::ItemFn(ref decl, _, _, _, _, body_id) => - (body_id, get_fn_args(decl)), - hir::ItemConst(_, body_id) => (body_id, vec![]), + let body_id = match item.node { + hir::ItemFn(.., body_id) | + hir::ItemConst(_, body_id) => body_id, _ => bug!("InlinedItemRef::from_item wrong kind") }; InlinedItemRef { def_id: def_id, body: tcx.map.body(body_id), - const_fn_args: args } } @@ -181,9 +170,8 @@ impl<'a, 'tcx> InlinedItemRef<'tcx> { item: &hir::TraitItem, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> InlinedItemRef<'tcx> { - let (body_id, args) = match item.node { - hir::TraitItemKind::Const(_, Some(body_id)) => - (body_id, vec![]), + let body_id = match item.node { + hir::TraitItemKind::Const(_, Some(body_id)) => body_id, hir::TraitItemKind::Const(_, None) => { bug!("InlinedItemRef::from_trait_item called for const without body") }, @@ -192,7 +180,6 @@ impl<'a, 'tcx> InlinedItemRef<'tcx> { InlinedItemRef { def_id: def_id, body: tcx.map.body(body_id), - const_fn_args: args } } @@ -200,17 +187,14 @@ impl<'a, 'tcx> InlinedItemRef<'tcx> { item: &hir::ImplItem, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> InlinedItemRef<'tcx> { - let (body_id, args) = match item.node { - hir::ImplItemKind::Method(ref sig, body_id) => - (body_id, get_fn_args(&sig.decl)), - hir::ImplItemKind::Const(_, body_id) => - (body_id, vec![]), + let body_id = match item.node { + hir::ImplItemKind::Method(_, body_id) | + hir::ImplItemKind::Const(_, body_id) => body_id, _ => bug!("InlinedItemRef::from_impl_item wrong kind") }; InlinedItemRef { def_id: def_id, body: tcx.map.body(body_id), - const_fn_args: args } } diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 8705393849ae..3f2893a9e24a 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -160,7 +160,7 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O } } -fn build_nodeid_to_index(decl: Option<&hir::FnDecl>, +fn build_nodeid_to_index(body: Option<&hir::Body>, cfg: &cfg::CFG) -> NodeMap> { let mut index = NodeMap(); @@ -168,8 +168,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,18 +181,22 @@ fn build_nodeid_to_index(decl: Option<&hir::FnDecl>, return index; - fn add_entries_from_fn_decl(index: &mut NodeMap>, - decl: &hir::FnDecl, + /// Add mappings from the ast nodes for the formal bindings to + /// the entry-node in the graph. + fn add_entries_from_fn_body(index: &mut NodeMap>, + body: &hir::Body, entry: CFGIndex) { - //! add mappings from the ast nodes for the formal bindings to - //! the entry-node in the graph. + use hir::intravisit::Visitor; + struct Formals<'a> { entry: CFGIndex, index: &'a mut NodeMap>, } let mut formals = Formals { entry: entry, index: index }; - intravisit::walk_fn_decl(&mut formals, decl); - impl<'a, 'v> intravisit::Visitor<'v> for Formals<'a> { + for arg in &body.arguments { + formals.visit_pat(&arg.pat); + } + impl<'a, 'v> Visitor<'v> for Formals<'a> { fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> { intravisit::NestedVisitorMap::None } @@ -227,7 +231,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 +254,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, diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 926975d1423b..76adee4e00c1 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -333,7 +333,7 @@ impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> { let trait_item = self.krate.trait_item(trait_item_ref.id); match trait_item.node { hir::TraitItemKind::Const(_, Some(_)) | - hir::TraitItemKind::Method(_, Some(_)) => { + hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => { if has_allow_dead_code_or_lang_attr(&trait_item.attrs) { self.worklist.push(trait_item.id); } @@ -573,11 +573,11 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { match trait_item.node { hir::TraitItemKind::Const(_, Some(body_id)) | - hir::TraitItemKind::Method(_, Some(body_id)) => { + hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => { self.visit_nested_body(body_id) } hir::TraitItemKind::Const(_, None) | - hir::TraitItemKind::Method(_, None) | + hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) | hir::TraitItemKind::Type(..) => {} } } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 1efc4b37ed5a..9ba26a0bf1de 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::Body) { - self.walk_arg_patterns(decl, &body.value); - self.consume_expr(&body.value); - } - - fn walk_arg_patterns(&mut self, - decl: &hir::FnDecl, - body: &hir::Expr) { - for arg in &decl.inputs { + pub fn walk_fn(&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> { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index ea1c897708b5..021cb9bb72d5 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -381,7 +381,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; @@ -404,8 +406,6 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, clean_exit_var: fn_maps.add_variable(CleanExit) }; - let body = ir.tcx.map.body(body_id); - // compute liveness let mut lsets = Liveness::new(&mut fn_maps, specials); let entry_ln = lsets.compute(&body.value); @@ -413,7 +413,7 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, // check for various error conditions 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) { @@ -1502,8 +1502,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/reachable.rs b/src/librustc/middle/reachable.rs index 34a42dede758..ee841afc0216 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -167,7 +167,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { Some(ast_map::NodeTraitItem(trait_method)) => { match trait_method.node { hir::TraitItemKind::Const(_, ref default) => default.is_some(), - hir::TraitItemKind::Method(_, ref body) => body.is_some(), + hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true, + hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) | hir::TraitItemKind::Type(..) => false, } } @@ -275,11 +276,11 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { ast_map::NodeTraitItem(trait_method) => { match trait_method.node { hir::TraitItemKind::Const(_, None) | - hir::TraitItemKind::Method(_, None) => { + hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => { // Keep going, nothing to get exported } hir::TraitItemKind::Const(_, Some(body_id)) | - hir::TraitItemKind::Method(_, Some(body_id)) => { + hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => { self.visit_nested_body(body_id); } hir::TraitItemKind::Type(..) => {} diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 9b70c522362d..140beefb020b 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -190,7 +190,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); }) @@ -266,7 +266,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::TraitItemKind::Method(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, @@ -860,8 +861,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/ty/mod.rs b/src/librustc/ty/mod.rs index 28192cd1873d..b03a432de413 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1225,7 +1225,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { // 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) } else { diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index e5b764be8799..f7249784dba4 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -189,7 +189,6 @@ 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::Body) { debug!("check_loans(body id={})", body.value.id); @@ -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).walk_fn(body); } #[derive(PartialEq)] diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 50b276ce6941..c9e526202fa6 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -41,7 +41,6 @@ mod move_error; pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, fn_id: NodeId, - decl: &hir::FnDecl, body: &hir::Body) -> (Vec>, move_data::MoveData<'tcx>) { @@ -55,7 +54,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, 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).walk_fn(body); glcx.report_potential_errors(); let GatherLoanCtxt { all_loans, move_data, .. } = glcx; diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 93c12fed1de2..1ba313015d59 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -179,7 +179,7 @@ fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, 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::Body, - sp: Span, 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.id(), 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, @@ -266,11 +265,8 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>( 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) @@ -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 6a5ee13bb845..a02aba7208c7 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::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 cb1d67d01c77..4c1fb90e54c7 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -43,39 +43,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::TraitItemKind::Const(..) = 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::BodyId, s: Span, id: ast::NodeId) { - if let FnKind::Closure(..) = fk { - span_bug!(s, "check_match: closure outside of function") - } + 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 +74,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 +97,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::BodyId, 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)); } } } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index c42b558830fc..e27a04766357 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -870,18 +870,16 @@ 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) = match lookup_const_fn_by_id(tcx, did) { - Some(ConstFnNode::Inlined(ii)) => (ii.const_fn_args.clone(), &ii.body), - 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(), - tcx.map.body(fn_like.body())), + let body = match lookup_const_fn_by_id(tcx, did) { + Some(ConstFnNode::Inlined(ii)) => &ii.body, + Some(ConstFnNode::Local(fn_like)) => tcx.map.body(fn_like.body()), None => signal!(e, NonConstPath), }; - let result = &body.value; + + let arg_defs = body.arguments.iter().map(|arg| match arg.pat.node { + hir::PatKind::Binding(_, def_id, _, _) => Some(def_id), + _ => None + }).collect::>(); assert_eq!(arg_defs.len(), args.len()); let mut call_args = DefIdMap(); @@ -899,7 +897,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, diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index 11ade150d1c6..4bb12667bbc1 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -476,8 +476,10 @@ enum SawTraitOrImplItemComponent { fn saw_trait_item(ti: &TraitItemKind) -> SawTraitOrImplItemComponent { match *ti { TraitItemKind::Const(..) => SawTraitOrImplItemConst, - TraitItemKind::Method(ref sig, ref body) => - SawTraitOrImplItemMethod(sig.unsafety, sig.constness, sig.abi, body.is_some()), + 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 } } diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index 5354233e57c4..2baef47c214c 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -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::TraitItemKind::Method(_, 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)); } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 501da6807280..c021ffee8189 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -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::TraitItemKind::Method(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") } } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 751c9c3440f6..a3aa4af493aa 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 b4c9a0672b03..b7ee688117d9 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::Body, + _: &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/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 6132b23c720b..6a626e9942cb 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -128,7 +128,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn fn_arg_names(&self, did: DefId) -> Vec { - self.dep_graph.read(DepNode::MetaData(did)); + // FIXME(#38501) We've skipped a `read` on the `HirBody` of + // a `fn` when encoding, so the dep-tracking wouldn't work. + // This is only used by rustdoc anyway, which shouldn't have + // incremental recompilation ever enabled. + assert!(!self.dep_graph.is_fully_enabled()); self.get_crate_data(did.krate).get_fn_arg_names(did.index) } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 1c4225817a9e..732887620cfa 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -34,6 +34,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 +443,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::TraitItemKind::Method(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!() @@ -518,10 +527,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!() @@ -574,16 +583,23 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } - fn encode_fn_arg_names(&mut self, decl: &hir::FnDecl) -> LazySeq { - self.lazy_seq(decl.inputs.iter().map(|arg| { - if let PatKind::Binding(_, _, ref path1, _) = arg.pat.node { - path1.node - } else { - Symbol::intern("") + fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId) + -> LazySeq { + let _ignore = self.tcx.dep_graph.in_ignore(); + let body = self.tcx.map.body(body_id); + self.lazy_seq(body.arguments.iter().map(|arg| { + match arg.pat.node { + PatKind::Binding(_, _, name, _) => name.node, + _ => Symbol::intern("") } })) } + fn encode_fn_arg_names(&mut self, names: &[Spanned]) + -> LazySeq { + self.lazy_seq(names.iter().map(|name| name.node)) + } + fn encode_mir(&mut self, def_id: DefId) -> Option>> { self.tcx.mir_map.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow())) } @@ -619,10 +635,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)) @@ -915,10 +931,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)) } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index e06d940de7e5..63bb1bf20c06 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 7eefcdb15d08..cfdc1bf27df3 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>, - body_id: hir::BodyId) + body: &'gcx hir::Body) -> Mir<'tcx> where A: Iterator, Option<&'gcx hir::Pat>)> { @@ -138,15 +138,14 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let call_site_extent = tcx.region_maps.lookup_code_extent( - CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id.node_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.node_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| { - let ast_expr = &tcx.map.body(body_id).value; - builder.args_and_body(block, &arguments, arg_extent, ast_expr) + 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 }; diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index c02a1822d736..59a11782e085 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/mir_map.rs b/src/librustc_mir/mir_map.rs index 607411684e70..cbc53ea3c51c 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -234,8 +234,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { (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)| { @@ -244,7 +245,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { 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_id) + build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body) }); intravisit::walk_fn(self, fk, decl, body_id, span, id); diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 10983aab309f..11f39a8fdf86 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -166,7 +166,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { let qualif = self.with_mode(mode, |this| { let body = this.tcx.map.body(b); - this.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, body)); + this.with_euv(Some(fn_id), |euv| euv.walk_fn(body)); intravisit::walk_fn(this, fk, fd, b, s, fn_id); this.qualif }); diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs index e845115cf4fd..e4151a66c313 100644 --- a/src/librustc_passes/rvalues.rs +++ b/src/librustc_passes/rvalues.rs @@ -52,7 +52,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RvalueContext<'a, 'tcx> { }; let body = infcx.tcx.map.body(b); let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx); - euv.walk_fn(fd, body); + euv.walk_fn(body); }); intravisit::walk_fn(self, fk, fd, b, s, fn_id) } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 3b2520308c70..5c49ace4917c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -227,6 +227,7 @@ pub fn ast_region_to_region<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } fn report_elision_failure( + tcx: TyCtxt, db: &mut DiagnosticBuilder, params: Vec) { @@ -241,13 +242,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!("`{}`", pprust::pat_to_string(&arg.pat)) } else { - format!("`{}`", name) + format!("argument {}", index + 1) }; m.push_str(&(if n == 1 { @@ -315,7 +317,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 +542,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { /// corresponding to each input type/pattern. fn find_implied_output_region(&self, input_tys: &[Ty<'tcx>], - input_pats: I) -> ElidedLifetime - where I: Iterator + parent: Option, + input_indices: I) -> ElidedLifetime + where I: Iterator { let tcx = self.tcx(); let mut lifetimes_for_params = Vec::with_capacity(input_tys.len()); let mut possible_implied_output_region = None; let mut lifetimes = 0; - for input_type in input_tys.iter() { + for (input_type, index) in input_tys.iter().zip(input_indices) { let mut regions = FxHashSet(); let have_bound_regions = tcx.collect_regions(input_type, &mut regions); @@ -564,11 +567,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 +578,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 +614,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) => { @@ -1572,6 +1568,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { bf.abi, None, &bf.decl, + None, anon_scope, anon_scope); @@ -1696,26 +1693,28 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { pub fn ty_of_arg(&self, rscope: &RegionScope, - a: &hir::Arg, + ty: &hir::Ty, expected_ty: Option>) -> Ty<'tcx> { - match a.ty.node { + match ty.node { hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(), - hir::TyInfer => self.ty_infer(a.ty.span), - _ => self.ast_ty_to_ty(rscope, &a.ty), + hir::TyInfer => self.ty_infer(ty.span), + _ => self.ast_ty_to_ty(rscope, ty), } } pub fn ty_of_method(&self, sig: &hir::MethodSig, opt_self_value_ty: Option>, + body: Option, anon_scope: Option) -> &'tcx ty::BareFnTy<'tcx> { self.ty_of_method_or_bare_fn(sig.unsafety, sig.abi, opt_self_value_ty, &sig.decl, + body, None, anon_scope) } @@ -1724,9 +1723,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { unsafety: hir::Unsafety, abi: abi::Abi, decl: &hir::FnDecl, + body: hir::BodyId, anon_scope: Option) -> &'tcx ty::BareFnTy<'tcx> { - self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope) + self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, Some(body), None, anon_scope) } fn ty_of_method_or_bare_fn(&self, @@ -1734,6 +1734,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { abi: abi::Abi, opt_self_value_ty: Option>, decl: &hir::FnDecl, + body: Option, arg_anon_scope: Option, ret_anon_scope: Option) -> &'tcx ty::BareFnTy<'tcx> @@ -1764,12 +1765,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // reference) in the arguments, then any anonymous regions in the output // have that lifetime. _ => { - let arg_params = &decl.inputs[has_self as usize..]; let arg_tys = &input_tys[has_self as usize..]; - - self.find_implied_output_region(arg_tys, - arg_params.iter() - .map(|a| pprust::pat_to_string(&a.pat))) + let arg_params = has_self as usize..input_tys.len(); + self.find_implied_output_region(arg_tys, body, arg_params) } }; diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 0a18aad2712b..be10b77bd8b9 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -456,7 +456,7 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a }; impl_m_iter.zip(trait_m_iter).find(|&(ref impl_arg, ref trait_arg)| { - match (&impl_arg.ty.node, &trait_arg.ty.node) { + 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 @@ -464,7 +464,7 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a _ => false, } }).map(|(ref impl_arg, ref trait_arg)| { - (impl_arg.ty.span, Some(trait_arg.ty.span)) + (impl_arg.span, Some(trait_arg.span)) }) .unwrap_or_else(|| (cause.span, tcx.map.span_if_local(trait_m.def_id))) } else { @@ -489,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() @@ -680,7 +680,7 @@ fn compare_number_of_method_arguments<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } else { 0 }) { - Some(arg.pat.span) + Some(arg.span) } else { trait_item_span } @@ -698,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 } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 183a2a48ff52..c733c0856c6d 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/mod.rs b/src/librustc_typeck/check/mod.rs index 021aeec47f02..e919075bc8f3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -681,8 +681,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); - 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); }); } @@ -751,16 +751,6 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { intravisit::walk_pat(self, p); } - fn visit_ty(&mut self, t: &'gcx hir::Ty) { - match t.node { - 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::BodyId, _: Span, _: ast::NodeId) { } @@ -796,31 +786,21 @@ 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, }; + GatherLocalsVisitor { fcx: &fcx, }.visit_body(body); - // 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); + // 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); - // 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)); - }); - - // Check the pattern. - fcx.check_pat(&input.pat, arg_ty); - fcx.write_ty(input.id, arg_ty); - } - - visit.visit_body(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); @@ -910,7 +890,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); } } @@ -954,10 +934,10 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { hir::TraitItemKind::Const(_, Some(expr)) => { check_const(ccx, expr, trait_item.id) } - hir::TraitItemKind::Method(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::TraitItemKind::Method(_, None) | + hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) | hir::TraitItemKind::Const(_, None) | hir::TraitItemKind::Type(..) => { // Nothing to do. @@ -1269,7 +1249,7 @@ fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, fcx.select_all_obligations_or_error(); fcx.regionck_expr(body); - fcx.resolve_type_vars_in_expr(body, id); + fcx.resolve_type_vars_in_body(body, id); }); } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 80b967210f98..bd63eb6ad25e 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -141,7 +141,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn regionck_fn(&self, fn_id: ast::NodeId, - decl: &hir::FnDecl, body: &'gcx hir::Body) { debug!("regionck_fn(id={})", fn_id); let node_id = body.value.id; @@ -149,7 +148,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if self.err_count_since_creation() == 0 { // regionck assumes typeck succeeded - rcx.visit_fn_body(fn_id, decl, body, 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( @@ -268,7 +267,6 @@ 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: &'gcx hir::Body, span: Span) { @@ -303,8 +301,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { 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[..]); + 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); @@ -483,10 +480,10 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { NestedVisitorMap::None } - fn visit_fn(&mut self, _fk: intravisit::FnKind<'gcx>, fd: &'gcx hir::FnDecl, + 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, fd, body, span) + self.visit_fn_body(id, body, span) } //visit_pat: visit_pat, // (..) see above @@ -1116,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 0ad01a0e00d6..af4fe2dc41b4 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -157,7 +157,6 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { fn analyze_closure(&mut self, id: ast::NodeId, span: Span, - decl: &hir::FnDecl, body: &hir::Body) { /*! * Analysis starting point. @@ -172,7 +171,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { mc::MemCategorizationOptions { during_closure_kind_inference: true }); - euv.walk_fn(decl, body); + euv.walk_fn(body); } // Now that we've analyzed the closure, we know how each @@ -505,7 +504,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for AdjustBorrowKind<'a, 'gcx, 'tcx> { let body = self.fcx.tcx.map.body(body); self.visit_body(body); - self.analyze_closure(id, span, decl, body); + self.analyze_closure(id, span, body); } } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 4955322963a1..c80db7fa4d0e 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -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); diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index beed85297fd8..479d595ee737 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -28,40 +28,21 @@ 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, body: &'gcx hir::Body, 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_body(body); - 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::Body, - item_id: ast::NodeId) { - assert_eq!(self.writeback_errors.get(), false); - let mut wbcx = WritebackCx::new(self); - wbcx.visit_body(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(); @@ -211,12 +192,12 @@ 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, body, _) = 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); } - let body = self.fcx.tcx.map.body(body); self.visit_body(body); } @@ -257,16 +238,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::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/collect.rs b/src/librustc_typeck/collect.rs index cb9e1c989e36..bbaf1b651109 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -640,7 +640,8 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, id: ast::NodeId, sig: &hir::MethodSig, untransformed_rcvr_ty: Ty<'tcx>, - rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) { + body: Option, + rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,) { let def_id = ccx.tcx.map.local_def_id(id); let ty_generics = generics_of_def_id(ccx, def_id); @@ -658,7 +659,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, None }; let fty = AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), - sig, self_value_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); @@ -865,10 +866,14 @@ fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) { convert_associated_type(ccx, TraitContainer(trait_def_id), trait_item.id, typ); } - hir::TraitItemKind::Method(ref sig, _) => { + 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(), - &trait_predicates); + body, &trait_predicates); } } } @@ -908,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); } } } @@ -1429,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 } } @@ -1530,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) } @@ -1572,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) @@ -1637,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 }; @@ -2073,7 +2078,7 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>( } }; 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/rscope.rs b/src/librustc_typeck/rscope.rs index 131ecfc6e0c7..3f5e443a20a6 100644 --- a/src/librustc_typeck/rscope.rs +++ b/src/librustc_typeck/rscope.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc::hir; use rustc::hir::def_id::DefId; use rustc::ty; use rustc::ty::subst::Substs; @@ -19,7 +20,10 @@ use syntax_pos::Span; #[derive(Clone)] pub struct ElisionFailureInfo { - pub name: String, + /// Where we can find the argument pattern. + pub parent: Option, + /// The index of the argument in the original definition. + pub index: usize, pub lifetime_count: usize, pub have_bound_regions: bool } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 40f005fecbd0..7516faab5196 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1030,22 +1030,14 @@ pub struct Method { pub abi: Abi, } -impl Clean for hir::MethodSig { +impl<'a> Clean for (&'a hir::MethodSig, hir::BodyId) { fn clean(&self, cx: &DocContext) -> Method { - let decl = FnDecl { - inputs: Arguments { - values: self.decl.inputs.clean(cx), - }, - output: self.decl.output.clean(cx), - variadic: false, - attrs: Attributes::default() - }; Method { - generics: self.generics.clean(cx), - unsafety: self.unsafety, - constness: self.constness, - decl: decl, - abi: self.abi + generics: self.0.generics.clean(cx), + unsafety: self.0.unsafety, + constness: self.0.constness, + decl: (&*self.0.decl, self.1).clean(cx), + abi: self.0.abi } } } @@ -1058,25 +1050,6 @@ pub struct TyMethod { pub abi: Abi, } -impl Clean for hir::MethodSig { - fn clean(&self, cx: &DocContext) -> TyMethod { - let decl = FnDecl { - inputs: Arguments { - values: self.decl.inputs.clean(cx), - }, - output: self.decl.output.clean(cx), - variadic: false, - attrs: Attributes::default() - }; - TyMethod { - unsafety: self.unsafety.clone(), - decl: decl, - generics: self.generics.clean(cx), - abi: self.abi - } - } -} - #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Function { pub decl: FnDecl, @@ -1097,7 +1070,7 @@ impl Clean for doctree::Function { deprecation: self.depr.clean(cx), def_id: cx.tcx.map.local_def_id(self.id), inner: FunctionItem(Function { - decl: self.decl.clean(cx), + decl: (&self.decl, self.body).clean(cx), generics: self.generics.clean(cx), unsafety: self.unsafety, constness: self.constness, @@ -1130,14 +1103,47 @@ pub struct Arguments { pub values: Vec, } -impl Clean for hir::FnDecl { +impl<'a> Clean for (&'a [P], &'a [Spanned]) { + fn clean(&self, cx: &DocContext) -> Arguments { + Arguments { + values: self.0.iter().enumerate().map(|(i, ty)| { + let mut name = self.1.get(i).map(|n| n.node.to_string()) + .unwrap_or(String::new()); + if name.is_empty() { + name = "_".to_string(); + } + Argument { + name: name, + type_: ty.clean(cx), + } + }).collect() + } + } +} + +impl<'a> Clean for (&'a [P], hir::BodyId) { + fn clean(&self, cx: &DocContext) -> Arguments { + let body = cx.tcx.map.body(self.1); + + Arguments { + values: self.0.iter().enumerate().map(|(i, ty)| { + Argument { + name: name_from_pat(&body.arguments[i].pat), + type_: ty.clean(cx), + } + }).collect() + } + } +} + +impl<'a, A: Copy> Clean for (&'a hir::FnDecl, A) + where (&'a [P], A): Clean +{ fn clean(&self, cx: &DocContext) -> FnDecl { FnDecl { - inputs: Arguments { - values: self.inputs.clean(cx), - }, - output: self.output.clean(cx), - variadic: self.variadic, + inputs: (&self.0.inputs[..], self.1).clean(cx), + output: self.0.output.clean(cx), + variadic: self.0.variadic, attrs: Attributes::default() } } @@ -1159,7 +1165,6 @@ impl<'a, 'tcx> Clean for (DefId, &'a ty::PolyFnSig<'tcx>) { values: sig.skip_binder().inputs().iter().map(|t| { Argument { type_: t.clean(cx), - id: ast::CRATE_NODE_ID, name: names.next().map_or("".to_string(), |name| name.to_string()), } }).collect(), @@ -1172,7 +1177,6 @@ impl<'a, 'tcx> Clean for (DefId, &'a ty::PolyFnSig<'tcx>) { pub struct Argument { pub type_: Type, pub name: String, - pub id: ast::NodeId, } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] @@ -1199,16 +1203,6 @@ impl Argument { } } -impl Clean for hir::Arg { - fn clean(&self, cx: &DocContext) -> Argument { - Argument { - name: name_from_pat(&*self.pat), - type_: (self.ty.clean(cx)), - id: self.id - } - } -} - #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] pub enum FunctionRetTy { Return(Type), @@ -1274,11 +1268,16 @@ impl Clean for hir::TraitItem { AssociatedConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx, e))) } - hir::TraitItemKind::Method(ref sig, Some(_)) => { - MethodItem(sig.clean(cx)) + hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { + MethodItem((sig, body).clean(cx)) } - hir::TraitItemKind::Method(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::TraitItemKind::Type(ref bounds, ref default) => { AssociatedTypeItem(bounds.clean(cx), default.clean(cx)) @@ -1304,8 +1303,8 @@ impl Clean for hir::ImplItem { AssociatedConstItem(ty.clean(cx), 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), @@ -2343,7 +2342,7 @@ impl Clean for hir::BareFnTy { type_params: Vec::new(), where_predicates: Vec::new() }, - decl: self.decl.clean(cx), + decl: (&*self.decl, &[][..]).clean(cx), abi: self.abi, } } @@ -2641,9 +2640,9 @@ impl Clean> for hir::ForeignMod { impl Clean for hir::ForeignItem { fn clean(&self, cx: &DocContext) -> Item { let inner = match self.node { - hir::ForeignItemFn(ref decl, ref generics) => { + hir::ForeignItemFn(ref decl, ref names, ref generics) => { ForeignFunctionItem(Function { - decl: decl.clean(cx), + decl: (&**decl, &names[..]).clean(cx), generics: generics.clean(cx), unsafety: hir::Unsafety::Unsafe, abi: Abi::Rust, diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 46b1ed2aa24d..d819268240ba 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 { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 5a90a739de4e..b0afc3d63f47 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(), diff --git a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs index f8aa1ea95f0f..eac134ff3cc7 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/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index d3793d6cdd8d..bc401ae93404 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -158,6 +158,7 @@ trait TraitAddParameterToMethod { #[cfg(cfail1)] trait TraitChangeMethodParameterName { fn method(a: u32); + fn with_default(x: i32) {} } #[cfg(not(cfail1))] @@ -166,11 +167,20 @@ trait TraitChangeMethodParameterName { #[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) {} } @@ -303,7 +313,7 @@ trait TraitChangeModeSelfOwnToMut: Sized { #[cfg(not(cfail1))] #[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")]