rustc: use an Expr instead of a Block for function bodies.
This commit is contained in:
parent
49772fbf5d
commit
ff0830d749
@ -33,16 +33,16 @@ struct LoopScope {
|
||||
}
|
||||
|
||||
pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
blk: &hir::Block) -> CFG {
|
||||
body: &hir::Expr) -> CFG {
|
||||
let mut graph = graph::Graph::new();
|
||||
let entry = graph.add_node(CFGNodeData::Entry);
|
||||
|
||||
// `fn_exit` is target of return exprs, which lies somewhere
|
||||
// outside input `blk`. (Distinguishing `fn_exit` and `block_exit`
|
||||
// outside input `body`. (Distinguishing `fn_exit` and `body_exit`
|
||||
// also resolves chicken-and-egg problem that arises if you try to
|
||||
// have return exprs jump to `block_exit` during construction.)
|
||||
// have return exprs jump to `body_exit` during construction.)
|
||||
let fn_exit = graph.add_node(CFGNodeData::Exit);
|
||||
let block_exit;
|
||||
let body_exit;
|
||||
|
||||
let mut cfg_builder = CFGBuilder {
|
||||
graph: graph,
|
||||
@ -50,8 +50,8 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
tcx: tcx,
|
||||
loop_scopes: Vec::new()
|
||||
};
|
||||
block_exit = cfg_builder.block(blk, entry);
|
||||
cfg_builder.add_contained_edge(block_exit, fn_exit);
|
||||
body_exit = cfg_builder.expr(body, entry);
|
||||
cfg_builder.add_contained_edge(body_exit, fn_exit);
|
||||
let CFGBuilder {graph, ..} = cfg_builder;
|
||||
CFG {graph: graph,
|
||||
entry: entry,
|
||||
|
@ -59,8 +59,8 @@ pub type CFGEdge = graph::Edge<CFGEdgeData>;
|
||||
|
||||
impl CFG {
|
||||
pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
blk: &hir::Block) -> CFG {
|
||||
construct::construct(tcx, blk)
|
||||
body: &hir::Expr) -> CFG {
|
||||
construct::construct(tcx, body)
|
||||
}
|
||||
|
||||
pub fn node_is_reachable(&self, id: ast::NodeId) -> bool {
|
||||
|
@ -672,120 +672,6 @@ extern "C" {
|
||||
```
|
||||
"##,
|
||||
|
||||
E0269: r##"
|
||||
A returned value was expected but not all control paths return one.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0269
|
||||
fn abracada_FAIL() -> String {
|
||||
"this won't work".to_string();
|
||||
// error: not all control paths return a value
|
||||
}
|
||||
```
|
||||
|
||||
In the previous code, the function is supposed to return a `String`, however,
|
||||
the code returns nothing (because of the ';'). Another erroneous code would be:
|
||||
|
||||
```compile_fail
|
||||
fn abracada_FAIL(b: bool) -> u32 {
|
||||
if b {
|
||||
0
|
||||
} else {
|
||||
"a" // It fails because an `u32` was expected and something else is
|
||||
// returned.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It is advisable to find out what the unhandled cases are and check for them,
|
||||
returning an appropriate value or panicking if necessary. Check if you need
|
||||
to remove a semicolon from the last expression, like in the first erroneous
|
||||
code example.
|
||||
"##,
|
||||
|
||||
E0270: r##"
|
||||
Rust lets you define functions which are known to never return, i.e. are
|
||||
'diverging', by marking its return type as `!`.
|
||||
|
||||
For example, the following functions never return:
|
||||
|
||||
```no_run
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn bar() -> ! {
|
||||
foo() // foo() is diverging, so this will diverge too
|
||||
}
|
||||
|
||||
fn baz() -> ! {
|
||||
panic!(); // this macro internally expands to a call to a diverging function
|
||||
}
|
||||
```
|
||||
|
||||
Such functions can be used in a place where a value is expected without
|
||||
returning a value of that type, for instance:
|
||||
|
||||
```no_run
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
let x = 3;
|
||||
|
||||
let y = match x {
|
||||
1 => 1,
|
||||
2 => 4,
|
||||
_ => foo() // diverging function called here
|
||||
};
|
||||
|
||||
println!("{}", y)
|
||||
```
|
||||
|
||||
If the third arm of the match block is reached, since `foo()` doesn't ever
|
||||
return control to the match block, it is fine to use it in a place where an
|
||||
integer was expected. The `match` block will never finish executing, and any
|
||||
point where `y` (like the print statement) is needed will not be reached.
|
||||
|
||||
However, if we had a diverging function that actually does finish execution:
|
||||
|
||||
```ignore
|
||||
fn foo() -> ! {
|
||||
loop {break;}
|
||||
}
|
||||
```
|
||||
|
||||
Then we would have an unknown value for `y` in the following code:
|
||||
|
||||
```no_run
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
let x = 3;
|
||||
|
||||
let y = match x {
|
||||
1 => 1,
|
||||
2 => 4,
|
||||
_ => foo()
|
||||
};
|
||||
|
||||
println!("{}", y);
|
||||
```
|
||||
|
||||
In the previous example, the print statement was never reached when the
|
||||
wildcard match arm was hit, so we were okay with `foo()` not returning an
|
||||
integer that we could set to `y`. But in this example, `foo()` actually does
|
||||
return control, so the print statement will be executed with an uninitialized
|
||||
value.
|
||||
|
||||
Obviously we cannot have functions which are allowed to be used in such
|
||||
positions and yet can return control. So, if you are defining a function that
|
||||
returns `!`, make sure that there is no way for it to actually finish
|
||||
executing.
|
||||
"##,
|
||||
|
||||
E0271: r##"
|
||||
This is because of a type mismatch between the associated type of some
|
||||
trait (e.g. `T::Bar`, where `T` implements `trait Quux { type Bar; }`)
|
||||
|
@ -138,7 +138,7 @@ pub trait Visitor<'v> : Sized {
|
||||
fn visit_where_predicate(&mut self, predicate: &'v WherePredicate) {
|
||||
walk_where_predicate(self, predicate)
|
||||
}
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, id: NodeId) {
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Expr, s: Span, id: NodeId) {
|
||||
walk_fn(self, fk, fd, b, s, id)
|
||||
}
|
||||
fn visit_trait_item(&mut self, ti: &'v TraitItem) {
|
||||
@ -635,13 +635,13 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
|
||||
pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
function_kind: FnKind<'v>,
|
||||
function_declaration: &'v FnDecl,
|
||||
function_body: &'v Block,
|
||||
function_body: &'v Expr,
|
||||
_span: Span,
|
||||
id: NodeId) {
|
||||
visitor.visit_id(id);
|
||||
walk_fn_decl(visitor, function_declaration);
|
||||
walk_fn_kind(visitor, function_kind);
|
||||
visitor.visit_block(function_body)
|
||||
visitor.visit_expr(function_body)
|
||||
}
|
||||
|
||||
pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
|
||||
@ -925,7 +925,7 @@ impl<'v> Visitor<'v> for IdRangeComputingVisitor {
|
||||
/// Computes the id range for a single fn body, ignoring nested items.
|
||||
pub fn compute_id_range_for_fn_body(fk: FnKind,
|
||||
decl: &FnDecl,
|
||||
body: &Block,
|
||||
body: &Expr,
|
||||
sp: Span,
|
||||
id: NodeId)
|
||||
-> IdRange {
|
||||
|
@ -595,12 +595,13 @@ impl<'a> LoweringContext<'a> {
|
||||
hir::ItemConst(self.lower_ty(t), self.lower_expr(e))
|
||||
}
|
||||
ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
|
||||
let body = self.lower_block(body);
|
||||
hir::ItemFn(self.lower_fn_decl(decl),
|
||||
self.lower_unsafety(unsafety),
|
||||
self.lower_constness(constness),
|
||||
abi,
|
||||
self.lower_generics(generics),
|
||||
self.lower_block(body))
|
||||
self.expr_block(body, ThinVec::new()))
|
||||
}
|
||||
ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
|
||||
ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
|
||||
@ -665,7 +666,10 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
TraitItemKind::Method(ref sig, ref body) => {
|
||||
hir::MethodTraitItem(this.lower_method_sig(sig),
|
||||
body.as_ref().map(|x| this.lower_block(x)))
|
||||
body.as_ref().map(|x| {
|
||||
let body = this.lower_block(x);
|
||||
this.expr_block(body, ThinVec::new())
|
||||
}))
|
||||
}
|
||||
TraitItemKind::Type(ref bounds, ref default) => {
|
||||
hir::TypeTraitItem(this.lower_bounds(bounds),
|
||||
@ -691,8 +695,9 @@ impl<'a> LoweringContext<'a> {
|
||||
hir::ImplItemKind::Const(this.lower_ty(ty), this.lower_expr(expr))
|
||||
}
|
||||
ImplItemKind::Method(ref sig, ref body) => {
|
||||
let body = this.lower_block(body);
|
||||
hir::ImplItemKind::Method(this.lower_method_sig(sig),
|
||||
this.lower_block(body))
|
||||
this.expr_block(body, ThinVec::new()))
|
||||
}
|
||||
ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)),
|
||||
ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
|
||||
@ -1110,7 +1115,7 @@ impl<'a> LoweringContext<'a> {
|
||||
self.with_parent_def(e.id, |this| {
|
||||
hir::ExprClosure(this.lower_capture_clause(capture_clause),
|
||||
this.lower_fn_decl(decl),
|
||||
this.lower_block(body),
|
||||
this.lower_expr(body),
|
||||
fn_decl_span)
|
||||
})
|
||||
}
|
||||
|
@ -21,11 +21,9 @@
|
||||
//! nested within a uniquely determined `FnLike`), and users can ask
|
||||
//! for the `Code` associated with a particular NodeId.
|
||||
|
||||
pub use self::Code::*;
|
||||
|
||||
use hir as ast;
|
||||
use hir::map::{self, Node};
|
||||
use hir::{Block, FnDecl};
|
||||
use hir::{Expr, FnDecl};
|
||||
use hir::intravisit::FnKind;
|
||||
use syntax::abi;
|
||||
use syntax::ast::{Attribute, Name, NodeId};
|
||||
@ -50,7 +48,7 @@ pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; }
|
||||
/// Components shared by fn-like things (fn items, methods, closures).
|
||||
pub struct FnParts<'a> {
|
||||
pub decl: &'a FnDecl,
|
||||
pub body: &'a Block,
|
||||
pub body: &'a Expr,
|
||||
pub kind: FnKind<'a>,
|
||||
pub span: Span,
|
||||
pub id: NodeId,
|
||||
@ -77,29 +75,32 @@ impl MaybeFnLike for ast::Expr {
|
||||
}
|
||||
}
|
||||
|
||||
/// Carries either an FnLikeNode or a Block, as these are the two
|
||||
/// Carries either an FnLikeNode or a Expr, as these are the two
|
||||
/// constructs that correspond to "code" (as in, something from which
|
||||
/// we can construct a control-flow graph).
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Code<'a> {
|
||||
FnLikeCode(FnLikeNode<'a>),
|
||||
BlockCode(&'a Block),
|
||||
FnLike(FnLikeNode<'a>),
|
||||
Expr(&'a Expr),
|
||||
}
|
||||
|
||||
impl<'a> Code<'a> {
|
||||
pub fn id(&self) -> NodeId {
|
||||
match *self {
|
||||
FnLikeCode(node) => node.id(),
|
||||
BlockCode(block) => block.id,
|
||||
Code::FnLike(node) => node.id(),
|
||||
Code::Expr(block) => block.id,
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to construct a Code from presumed FnLike or Block node input.
|
||||
pub fn from_node(node: Node) -> Option<Code> {
|
||||
if let map::NodeBlock(block) = node {
|
||||
Some(BlockCode(block))
|
||||
} else {
|
||||
FnLikeNode::from_node(node).map(|fn_like| FnLikeCode(fn_like))
|
||||
/// Attempts to construct a Code from presumed FnLike or Expr node input.
|
||||
pub fn from_node(map: &map::Map<'a>, id: NodeId) -> Option<Code<'a>> {
|
||||
match map.get(id) {
|
||||
map::NodeBlock(_) => {
|
||||
// Use the parent, hopefully an expression node.
|
||||
Code::from_node(map, map.get_parent_node(id))
|
||||
}
|
||||
map::NodeExpr(expr) => Some(Code::Expr(expr)),
|
||||
node => FnLikeNode::from_node(node).map(Code::FnLike)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -114,7 +115,7 @@ struct ItemFnParts<'a> {
|
||||
abi: abi::Abi,
|
||||
vis: &'a ast::Visibility,
|
||||
generics: &'a ast::Generics,
|
||||
body: &'a Block,
|
||||
body: &'a Expr,
|
||||
id: NodeId,
|
||||
span: Span,
|
||||
attrs: &'a [Attribute],
|
||||
@ -124,14 +125,14 @@ struct ItemFnParts<'a> {
|
||||
/// for use when implementing FnLikeNode operations.
|
||||
struct ClosureParts<'a> {
|
||||
decl: &'a FnDecl,
|
||||
body: &'a Block,
|
||||
body: &'a Expr,
|
||||
id: NodeId,
|
||||
span: Span,
|
||||
attrs: &'a [Attribute],
|
||||
}
|
||||
|
||||
impl<'a> ClosureParts<'a> {
|
||||
fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
|
||||
fn new(d: &'a FnDecl, b: &'a Expr, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
|
||||
ClosureParts {
|
||||
decl: d,
|
||||
body: b,
|
||||
@ -171,9 +172,9 @@ impl<'a> FnLikeNode<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn body(self) -> &'a Block {
|
||||
pub fn body(self) -> &'a Expr {
|
||||
self.handle(|i: ItemFnParts<'a>| &*i.body,
|
||||
|_, _, _: &'a ast::MethodSig, _, body: &'a ast::Block, _, _| body,
|
||||
|_, _, _: &'a ast::MethodSig, _, body: &'a ast::Expr, _, _| body,
|
||||
|c: ClosureParts<'a>| c.body)
|
||||
}
|
||||
|
||||
@ -214,7 +215,7 @@ impl<'a> FnLikeNode<'a> {
|
||||
Name,
|
||||
&'a ast::MethodSig,
|
||||
Option<&'a ast::Visibility>,
|
||||
&'a ast::Block,
|
||||
&'a ast::Expr,
|
||||
Span,
|
||||
&'a [Attribute])
|
||||
-> A,
|
||||
|
@ -211,7 +211,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
|
||||
b: &'ast Block, s: Span, id: NodeId) {
|
||||
b: &'ast Expr, s: Span, id: NodeId) {
|
||||
assert_eq!(self.parent_node, id);
|
||||
intravisit::walk_fn(self, fk, fd, b, s, id);
|
||||
}
|
||||
|
@ -904,7 +904,7 @@ pub enum Expr_ {
|
||||
/// A closure (for example, `move |a, b, c| {a + b + c}`).
|
||||
///
|
||||
/// The final span is the span of the argument block `|...|`
|
||||
ExprClosure(CaptureClause, P<FnDecl>, P<Block>, Span),
|
||||
ExprClosure(CaptureClause, P<FnDecl>, P<Expr>, Span),
|
||||
/// A block (`{ ... }`)
|
||||
ExprBlock(P<Block>),
|
||||
|
||||
@ -1035,7 +1035,7 @@ pub enum TraitItem_ {
|
||||
/// must contain a value)
|
||||
ConstTraitItem(P<Ty>, Option<P<Expr>>),
|
||||
/// A method with an optional body
|
||||
MethodTraitItem(MethodSig, Option<P<Block>>),
|
||||
MethodTraitItem(MethodSig, Option<P<Expr>>),
|
||||
/// An associated type with (possibly empty) bounds and optional concrete
|
||||
/// type
|
||||
TypeTraitItem(TyParamBounds, Option<P<Ty>>),
|
||||
@ -1060,7 +1060,7 @@ pub enum ImplItemKind {
|
||||
/// of the expression
|
||||
Const(P<Ty>, P<Expr>),
|
||||
/// A method implementation with the given signature and body
|
||||
Method(MethodSig, P<Block>),
|
||||
Method(MethodSig, P<Expr>),
|
||||
/// An associated type
|
||||
Type(P<Ty>),
|
||||
}
|
||||
@ -1501,7 +1501,7 @@ pub enum Item_ {
|
||||
/// A `const` item
|
||||
ItemConst(P<Ty>, P<Expr>),
|
||||
/// A function declaration
|
||||
ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, P<Block>),
|
||||
ItemFn(P<FnDecl>, Unsafety, Constness, Abi, Generics, P<Expr>),
|
||||
/// A module
|
||||
ItemMod(Mod),
|
||||
/// An external module
|
||||
|
@ -713,7 +713,9 @@ impl<'a> State<'a> {
|
||||
typarams,
|
||||
&item.vis)?;
|
||||
word(&mut self.s, " ")?;
|
||||
self.print_block_with_attrs(&body, &item.attrs)?;
|
||||
self.end()?; // need to close a box
|
||||
self.end()?; // need to close a box
|
||||
self.print_expr(&body)?;
|
||||
}
|
||||
hir::ItemMod(ref _mod) => {
|
||||
self.head(&visibility_qualified(&item.vis, "mod"))?;
|
||||
@ -1002,7 +1004,9 @@ impl<'a> State<'a> {
|
||||
self.print_method_sig(ti.name, sig, &hir::Inherited)?;
|
||||
if let Some(ref body) = *body {
|
||||
self.nbsp()?;
|
||||
self.print_block_with_attrs(body, &ti.attrs)?;
|
||||
self.end()?; // need to close a box
|
||||
self.end()?; // need to close a box
|
||||
self.print_expr(body)?;
|
||||
} else {
|
||||
word(&mut self.s, ";")?;
|
||||
}
|
||||
@ -1034,7 +1038,9 @@ impl<'a> State<'a> {
|
||||
self.head("")?;
|
||||
self.print_method_sig(ii.name, sig, &ii.vis)?;
|
||||
self.nbsp()?;
|
||||
self.print_block_with_attrs(body, &ii.attrs)?;
|
||||
self.end()?; // need to close a box
|
||||
self.end()?; // need to close a box
|
||||
self.print_expr(body)?;
|
||||
}
|
||||
hir::ImplItemKind::Type(ref ty) => {
|
||||
self.print_associated_type(ii.name, None, Some(ty))?;
|
||||
@ -1402,26 +1408,10 @@ impl<'a> State<'a> {
|
||||
self.print_fn_block_args(&decl)?;
|
||||
space(&mut self.s)?;
|
||||
|
||||
let default_return = match decl.output {
|
||||
hir::DefaultReturn(..) => true,
|
||||
_ => false,
|
||||
};
|
||||
// this is a bare expression
|
||||
self.print_expr(body)?;
|
||||
self.end()?; // need to close a box
|
||||
|
||||
if !default_return || !body.stmts.is_empty() || body.expr.is_none() {
|
||||
self.print_block_unclosed(&body)?;
|
||||
} else {
|
||||
// we extract the block, so as not to create another set of boxes
|
||||
match body.expr.as_ref().unwrap().node {
|
||||
hir::ExprBlock(ref blk) => {
|
||||
self.print_block_unclosed(&blk)?;
|
||||
}
|
||||
_ => {
|
||||
// this is a bare expression
|
||||
self.print_expr(body.expr.as_ref().map(|e| &**e).unwrap())?;
|
||||
self.end()?; // need to close a box
|
||||
}
|
||||
}
|
||||
}
|
||||
// a box will be closed by print_expr, but we didn't want an overall
|
||||
// wrapper so we closed the corresponding opening. so create an
|
||||
// empty box to satisfy the close.
|
||||
|
@ -838,7 +838,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: hir_visit::FnKind<'v>, decl: &'v hir::FnDecl,
|
||||
body: &'v hir::Block, span: Span, id: ast::NodeId) {
|
||||
body: &'v hir::Expr, span: Span, id: ast::NodeId) {
|
||||
run_lints!(self, check_fn, late_passes, fk, decl, body, span, id);
|
||||
hir_visit::walk_fn(self, fk, decl, body, span, id);
|
||||
run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id);
|
||||
|
@ -151,9 +151,9 @@ pub trait LateLintPass: LintPass {
|
||||
fn check_ty(&mut self, _: &LateContext, _: &hir::Ty) { }
|
||||
fn check_generics(&mut self, _: &LateContext, _: &hir::Generics) { }
|
||||
fn check_fn(&mut self, _: &LateContext,
|
||||
_: FnKind, _: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) { }
|
||||
_: FnKind, _: &hir::FnDecl, _: &hir::Expr, _: Span, _: ast::NodeId) { }
|
||||
fn check_fn_post(&mut self, _: &LateContext,
|
||||
_: FnKind, _: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) { }
|
||||
_: FnKind, _: &hir::FnDecl, _: &hir::Expr, _: Span, _: ast::NodeId) { }
|
||||
fn check_trait_item(&mut self, _: &LateContext, _: &hir::TraitItem) { }
|
||||
fn check_trait_item_post(&mut self, _: &LateContext, _: &hir::TraitItem) { }
|
||||
fn check_impl_item(&mut self, _: &LateContext, _: &hir::ImplItem) { }
|
||||
|
@ -498,7 +498,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
|
||||
|
||||
impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> {
|
||||
// ^^^^^^^^^^^^^ only needed for pretty printing
|
||||
pub fn propagate(&mut self, cfg: &cfg::CFG, blk: &hir::Block) {
|
||||
pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Expr) {
|
||||
//! Performs the data flow analysis.
|
||||
|
||||
if self.bits_per_id == 0 {
|
||||
@ -524,17 +524,17 @@ impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> {
|
||||
debug!("Dataflow result for {}:", self.analysis_name);
|
||||
debug!("{}", {
|
||||
let mut v = Vec::new();
|
||||
self.pretty_print_to(box &mut v, blk).unwrap();
|
||||
self.pretty_print_to(box &mut v, body).unwrap();
|
||||
String::from_utf8(v).unwrap()
|
||||
});
|
||||
}
|
||||
|
||||
fn pretty_print_to<'b>(&self, wr: Box<io::Write + 'b>,
|
||||
blk: &hir::Block) -> io::Result<()> {
|
||||
body: &hir::Expr) -> io::Result<()> {
|
||||
let mut ps = pprust::rust_printer_annotated(wr, self, None);
|
||||
ps.cbox(pprust::indent_unit)?;
|
||||
ps.ibox(0)?;
|
||||
ps.print_block(blk)?;
|
||||
ps.print_expr(body)?;
|
||||
pp::eof(&mut ps.s)
|
||||
}
|
||||
}
|
||||
|
@ -567,7 +567,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
|
||||
self.warn_dead_code(impl_item.id, impl_item.span,
|
||||
impl_item.name, "method");
|
||||
}
|
||||
intravisit::walk_block(self, body)
|
||||
intravisit::walk_expr(self, body)
|
||||
}
|
||||
hir::ImplItemKind::Type(..) => {}
|
||||
}
|
||||
@ -576,11 +576,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
|
||||
// Overwrite so that we don't warn the trait item itself.
|
||||
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
|
||||
match trait_item.node {
|
||||
hir::ConstTraitItem(_, Some(ref expr)) => {
|
||||
intravisit::walk_expr(self, expr)
|
||||
}
|
||||
hir::ConstTraitItem(_, Some(ref body))|
|
||||
hir::MethodTraitItem(_, Some(ref body)) => {
|
||||
intravisit::walk_block(self, body)
|
||||
intravisit::walk_expr(self, body)
|
||||
}
|
||||
hir::ConstTraitItem(_, None) |
|
||||
hir::MethodTraitItem(_, None) |
|
||||
|
@ -94,7 +94,7 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> {
|
||||
|
||||
impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
|
||||
fn visit_fn(&mut self, fn_kind: FnKind<'v>, fn_decl: &'v hir::FnDecl,
|
||||
block: &'v hir::Block, span: Span, id: ast::NodeId) {
|
||||
block: &'v hir::Expr, span: Span, id: ast::NodeId) {
|
||||
|
||||
let (is_item_fn, is_unsafe_fn) = match fn_kind {
|
||||
FnKind::ItemFn(_, _, unsafety, ..) =>
|
||||
|
@ -290,14 +290,14 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
|
||||
pub fn walk_fn(&mut self,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block) {
|
||||
body: &hir::Expr) {
|
||||
self.walk_arg_patterns(decl, body);
|
||||
self.walk_block(body);
|
||||
self.consume_expr(body);
|
||||
}
|
||||
|
||||
fn walk_arg_patterns(&mut self,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block) {
|
||||
body: &hir::Expr) {
|
||||
for arg in &decl.inputs {
|
||||
let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id));
|
||||
|
||||
|
@ -144,7 +144,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, s: Span, id: ast::NodeId) {
|
||||
b: &'v hir::Expr, s: Span, id: ast::NodeId) {
|
||||
if let FnKind::Closure(..) = fk {
|
||||
span_bug!(s, "intrinsicck: closure outside of function")
|
||||
}
|
||||
|
@ -123,10 +123,9 @@ use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast::{self, NodeId};
|
||||
use syntax::codemap::original_sp;
|
||||
use syntax::parse::token::keywords;
|
||||
use syntax::ptr::P;
|
||||
use syntax_pos::{BytePos, Span};
|
||||
use syntax_pos::Span;
|
||||
|
||||
use hir::Expr;
|
||||
use hir;
|
||||
@ -187,7 +186,7 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt) -> String {
|
||||
|
||||
impl<'a, 'tcx, 'v> Visitor<'v> for IrMaps<'a, 'tcx> {
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, s: Span, id: NodeId) {
|
||||
b: &'v hir::Expr, s: Span, id: NodeId) {
|
||||
visit_fn(self, fk, fd, b, s, id);
|
||||
}
|
||||
fn visit_local(&mut self, l: &hir::Local) { visit_local(self, l); }
|
||||
@ -352,9 +351,9 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'v> Visitor<'v> for Liveness<'a, 'tcx> {
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, s: Span, n: NodeId) {
|
||||
check_fn(self, fk, fd, b, s, n);
|
||||
fn visit_fn(&mut self, _: FnKind<'v>, _: &'v hir::FnDecl,
|
||||
_: &'v hir::Expr, _: Span, _: NodeId) {
|
||||
// do not check contents of nested fns
|
||||
}
|
||||
fn visit_local(&mut self, l: &hir::Local) {
|
||||
check_local(self, l);
|
||||
@ -370,7 +369,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Liveness<'a, 'tcx> {
|
||||
fn visit_fn(ir: &mut IrMaps,
|
||||
fk: FnKind,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
sp: Span,
|
||||
id: ast::NodeId) {
|
||||
debug!("visit_fn");
|
||||
@ -405,10 +404,10 @@ fn visit_fn(ir: &mut IrMaps,
|
||||
|
||||
// compute liveness
|
||||
let mut lsets = Liveness::new(&mut fn_maps, specials);
|
||||
let entry_ln = lsets.compute(decl, body);
|
||||
let entry_ln = lsets.compute(body);
|
||||
|
||||
// check for various error conditions
|
||||
lsets.visit_block(body);
|
||||
lsets.visit_expr(body);
|
||||
lsets.check_ret(id, sp, fk, entry_ln, body);
|
||||
lsets.warn_about_unused_args(decl, entry_ln);
|
||||
}
|
||||
@ -821,17 +820,23 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
|
||||
// _______________________________________________________________________
|
||||
|
||||
fn compute(&mut self, decl: &hir::FnDecl, body: &hir::Block) -> LiveNode {
|
||||
fn compute(&mut self, body: &hir::Expr) -> LiveNode {
|
||||
// if there is a `break` or `again` at the top level, then it's
|
||||
// effectively a return---this only occurs in `for` loops,
|
||||
// where the body is really a closure.
|
||||
|
||||
debug!("compute: using id for block, {}", block_to_string(body));
|
||||
debug!("compute: using id for body, {}", expr_to_string(body));
|
||||
|
||||
let exit_ln = self.s.exit_ln;
|
||||
let entry_ln: LiveNode =
|
||||
self.with_loop_nodes(body.id, exit_ln, exit_ln,
|
||||
|this| this.propagate_through_fn_block(decl, body));
|
||||
let entry_ln: LiveNode = self.with_loop_nodes(body.id, exit_ln, exit_ln, |this| {
|
||||
// the fallthrough exit is only for those cases where we do not
|
||||
// explicitly return:
|
||||
let s = this.s;
|
||||
this.init_from_succ(s.fallthrough_ln, s.exit_ln);
|
||||
this.acc(s.fallthrough_ln, s.clean_exit_var, ACC_READ);
|
||||
|
||||
this.propagate_through_expr(body, s.fallthrough_ln)
|
||||
});
|
||||
|
||||
// hack to skip the loop unless debug! is enabled:
|
||||
debug!("^^ liveness computation results for body {} (entry={:?})",
|
||||
@ -846,20 +851,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
entry_ln
|
||||
}
|
||||
|
||||
fn propagate_through_fn_block(&mut self, _: &hir::FnDecl, blk: &hir::Block)
|
||||
-> LiveNode {
|
||||
// the fallthrough exit is only for those cases where we do not
|
||||
// explicitly return:
|
||||
let s = self.s;
|
||||
self.init_from_succ(s.fallthrough_ln, s.exit_ln);
|
||||
if blk.expr.is_none() {
|
||||
self.acc(s.fallthrough_ln, s.no_ret_var, ACC_READ)
|
||||
}
|
||||
self.acc(s.fallthrough_ln, s.clean_exit_var, ACC_READ);
|
||||
|
||||
self.propagate_through_block(blk, s.fallthrough_ln)
|
||||
}
|
||||
|
||||
fn propagate_through_block(&mut self, blk: &hir::Block, succ: LiveNode)
|
||||
-> LiveNode {
|
||||
let succ = self.propagate_through_opt_expr(blk.expr.as_ref().map(|e| &**e), succ);
|
||||
@ -1448,15 +1439,6 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_fn(_v: &Liveness,
|
||||
_fk: FnKind,
|
||||
_decl: &hir::FnDecl,
|
||||
_body: &hir::Block,
|
||||
_sp: Span,
|
||||
_id: NodeId) {
|
||||
// do not check contents of nested fns
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
fn fn_ret(&self, id: NodeId) -> ty::Binder<Ty<'tcx>> {
|
||||
let fn_ty = self.ir.tcx.tables().node_id_to_type(id);
|
||||
@ -1472,7 +1454,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
sp: Span,
|
||||
_fk: FnKind,
|
||||
entry_ln: LiveNode,
|
||||
body: &hir::Block)
|
||||
body: &hir::Expr)
|
||||
{
|
||||
// within the fn body, late-bound regions are liberated
|
||||
// and must outlive the *call-site* of the function.
|
||||
@ -1481,13 +1463,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
self.ir.tcx.region_maps.call_site_extent(id, body.id),
|
||||
&self.fn_ret(id));
|
||||
|
||||
if fn_ret.is_never() {
|
||||
// FIXME(durka) this rejects code like `fn foo(x: !) -> ! { x }`
|
||||
if self.live_on_entry(entry_ln, self.s.clean_exit_var).is_some() {
|
||||
span_err!(self.ir.tcx.sess, sp, E0270,
|
||||
"computation may converge in a function marked as diverging");
|
||||
}
|
||||
} else if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
|
||||
if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
|
||||
let param_env = ParameterEnvironment::for_item(self.ir.tcx, id);
|
||||
let t_ret_subst = fn_ret.subst(self.ir.tcx, ¶m_env.free_substs);
|
||||
let is_nil = self.ir.tcx.infer_ctxt(None, Some(param_env),
|
||||
@ -1498,32 +1474,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
|
||||
// for nil return types, it is ok to not return a value expl.
|
||||
if !is_nil {
|
||||
let ends_with_stmt = match body.expr {
|
||||
None if !body.stmts.is_empty() =>
|
||||
match body.stmts.last().unwrap().node {
|
||||
hir::StmtSemi(ref e, _) => {
|
||||
self.ir.tcx.tables().expr_ty(&e) == fn_ret
|
||||
},
|
||||
_ => false
|
||||
},
|
||||
_ => false
|
||||
};
|
||||
let mut err = struct_span_err!(self.ir.tcx.sess,
|
||||
sp,
|
||||
E0269,
|
||||
"not all control paths return a value");
|
||||
if ends_with_stmt {
|
||||
let last_stmt = body.stmts.last().unwrap();
|
||||
let original_span = original_sp(self.ir.tcx.sess.codemap(),
|
||||
last_stmt.span, sp);
|
||||
let span_semicolon = Span {
|
||||
lo: original_span.hi - BytePos(1),
|
||||
hi: original_span.hi,
|
||||
expn_id: original_span.expn_id
|
||||
};
|
||||
err.span_help(span_semicolon, "consider removing this semicolon:");
|
||||
}
|
||||
err.emit();
|
||||
span_bug!(sp, "not all control paths return a value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,9 +248,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||
match *node {
|
||||
ast_map::NodeItem(item) => {
|
||||
match item.node {
|
||||
hir::ItemFn(.., ref search_block) => {
|
||||
hir::ItemFn(.., ref body) => {
|
||||
if item_might_be_inlined(&item) {
|
||||
intravisit::walk_block(self, &search_block)
|
||||
self.visit_expr(body);
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,11 +278,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||
hir::MethodTraitItem(_, None) => {
|
||||
// Keep going, nothing to get exported
|
||||
}
|
||||
hir::ConstTraitItem(_, Some(ref expr)) => {
|
||||
self.visit_expr(&expr);
|
||||
}
|
||||
hir::ConstTraitItem(_, Some(ref body)) |
|
||||
hir::MethodTraitItem(_, Some(ref body)) => {
|
||||
intravisit::walk_block(self, body);
|
||||
self.visit_expr(body);
|
||||
}
|
||||
hir::TypeTraitItem(..) => {}
|
||||
}
|
||||
@ -295,7 +293,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||
hir::ImplItemKind::Method(ref sig, ref body) => {
|
||||
let did = self.tcx.map.get_parent_did(search_item);
|
||||
if method_might_be_inlined(self.tcx, sig, impl_item, did) {
|
||||
intravisit::walk_block(self, body)
|
||||
self.visit_expr(body)
|
||||
}
|
||||
}
|
||||
hir::ImplItemKind::Type(_) => {}
|
||||
|
@ -490,12 +490,7 @@ impl RegionMaps {
|
||||
// if there's one. Static items, for instance, won't
|
||||
// have an enclosing scope, hence no scope will be
|
||||
// returned.
|
||||
let expr_extent = self.node_extent(expr_id);
|
||||
// For some reason, the expr's scope itself is skipped here.
|
||||
let mut id = match scope_map[expr_extent.0 as usize].into_option() {
|
||||
Some(i) => i,
|
||||
_ => return None
|
||||
};
|
||||
let mut id = self.node_extent(expr_id);
|
||||
|
||||
while let Some(p) = scope_map[id.0 as usize].into_option() {
|
||||
match code_extents[p.0 as usize] {
|
||||
@ -1086,7 +1081,7 @@ fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &hir::Item) {
|
||||
fn resolve_fn(visitor: &mut RegionResolutionVisitor,
|
||||
kind: FnKind,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
sp: Span,
|
||||
id: ast::NodeId) {
|
||||
debug!("region::resolve_fn(id={:?}, \
|
||||
@ -1128,7 +1123,7 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
|
||||
parent: fn_decl_scope,
|
||||
var_parent: fn_decl_scope
|
||||
};
|
||||
visitor.visit_block(body);
|
||||
visitor.visit_expr(body);
|
||||
|
||||
// Restore context we had at the start.
|
||||
visitor.cx = outer_cx;
|
||||
@ -1191,7 +1186,7 @@ impl<'a, 'v> Visitor<'v> for RegionResolutionVisitor<'a> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl,
|
||||
b: &'v Block, s: Span, n: NodeId) {
|
||||
b: &'v Expr, s: Span, n: NodeId) {
|
||||
resolve_fn(self, fk, fd, b, s, n);
|
||||
}
|
||||
fn visit_arm(&mut self, a: &Arm) {
|
||||
|
@ -202,7 +202,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, decl: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, s: Span, fn_id: ast::NodeId) {
|
||||
b: &'v hir::Expr, s: Span, fn_id: ast::NodeId) {
|
||||
match fk {
|
||||
FnKind::ItemFn(_, generics, ..) => {
|
||||
self.visit_early_late(fn_id,decl, generics, |this| {
|
||||
@ -403,7 +403,7 @@ fn signal_shadowing_problem(sess: &Session, name: ast::Name, orig: Original, sha
|
||||
|
||||
// Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning
|
||||
// if one of the label shadows a lifetime or another label.
|
||||
fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Block) {
|
||||
fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Expr) {
|
||||
struct GatherLabels<'a> {
|
||||
sess: &'a Session,
|
||||
scope: Scope<'a>,
|
||||
@ -415,7 +415,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Block) {
|
||||
scope: ctxt.scope,
|
||||
labels_in_fn: &mut ctxt.labels_in_fn,
|
||||
};
|
||||
gather.visit_block(b);
|
||||
gather.visit_expr(b);
|
||||
return;
|
||||
|
||||
impl<'v, 'a> Visitor<'v> for GatherLabels<'a> {
|
||||
@ -493,7 +493,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
fn add_scope_and_walk_fn<'b>(&mut self,
|
||||
fk: FnKind,
|
||||
fd: &hir::FnDecl,
|
||||
fb: &'b hir::Block,
|
||||
fb: &'b hir::Expr,
|
||||
_span: Span,
|
||||
fn_id: ast::NodeId) {
|
||||
|
||||
@ -516,7 +516,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
extract_labels(self, fb);
|
||||
|
||||
self.with(FnScope { fn_id: fn_id, body_id: fb.id, s: self.scope },
|
||||
|_old_scope, this| this.visit_block(fb))
|
||||
|_old_scope, this| this.visit_expr(fb))
|
||||
}
|
||||
|
||||
fn with<F>(&mut self, wrap_scope: ScopeChain, f: F) where
|
||||
|
@ -190,7 +190,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
all_loans: &[Loan<'tcx>],
|
||||
fn_id: ast::NodeId,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block) {
|
||||
body: &hir::Expr) {
|
||||
debug!("check_loans(body id={})", body.id);
|
||||
|
||||
let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id);
|
||||
|
@ -42,7 +42,7 @@ mod move_error;
|
||||
pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
fn_id: NodeId,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block)
|
||||
body: &hir::Expr)
|
||||
-> (Vec<Loan<'tcx>>,
|
||||
move_data::MoveData<'tcx>) {
|
||||
let mut glcx = GatherLoanCtxt {
|
||||
|
@ -58,7 +58,7 @@ pub struct MoveDataParamEnv<'tcx> {
|
||||
pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
|
||||
fk: FnKind,
|
||||
_decl: &hir::FnDecl,
|
||||
body: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
_sp: Span,
|
||||
id: ast::NodeId,
|
||||
attributes: &[ast::Attribute]) {
|
||||
|
@ -47,9 +47,7 @@ use syntax_pos::{MultiSpan, Span};
|
||||
use errors::DiagnosticBuilder;
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::{FnDecl, Block};
|
||||
use rustc::hir::intravisit;
|
||||
use rustc::hir::intravisit::{Visitor, FnKind};
|
||||
use rustc::hir::intravisit::{self, Visitor, FnKind};
|
||||
|
||||
pub mod check_loans;
|
||||
|
||||
@ -65,8 +63,8 @@ pub struct LoanDataFlowOperator;
|
||||
pub type LoanDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, LoanDataFlowOperator>;
|
||||
|
||||
impl<'a, 'tcx, 'v> Visitor<'v> for BorrowckCtxt<'a, 'tcx> {
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl,
|
||||
b: &'v Block, s: Span, id: ast::NodeId) {
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Expr, s: Span, id: ast::NodeId) {
|
||||
match fk {
|
||||
FnKind::ItemFn(..) |
|
||||
FnKind::Method(..) => {
|
||||
@ -159,7 +157,7 @@ pub struct AnalysisData<'a, 'tcx: 'a> {
|
||||
fn borrowck_fn(this: &mut BorrowckCtxt,
|
||||
fk: FnKind,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
sp: Span,
|
||||
id: ast::NodeId,
|
||||
attributes: &[ast::Attribute]) {
|
||||
@ -200,7 +198,7 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
|
||||
fk: FnKind,
|
||||
decl: &hir::FnDecl,
|
||||
cfg: &cfg::CFG,
|
||||
body: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
sp: Span,
|
||||
id: ast::NodeId)
|
||||
-> AnalysisData<'a, 'tcx>
|
||||
|
@ -656,7 +656,7 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> {
|
||||
cfg: &cfg::CFG,
|
||||
id_range: IdRange,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block)
|
||||
body: &hir::Expr)
|
||||
-> FlowedMoveData<'a, 'tcx> {
|
||||
let mut dfcx_moves =
|
||||
DataFlowContext::new(tcx,
|
||||
|
@ -65,7 +65,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for OuterVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, s: Span, id: ast::NodeId) {
|
||||
b: &'v hir::Expr, s: Span, id: ast::NodeId) {
|
||||
if let FnKind::Closure(..) = fk {
|
||||
span_bug!(s, "check_match: closure outside of function")
|
||||
}
|
||||
@ -113,7 +113,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MatchVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, s: Span, n: ast::NodeId) {
|
||||
b: &'v hir::Expr, s: Span, n: ast::NodeId) {
|
||||
intravisit::walk_fn(self, fk, fd, b, s, n);
|
||||
|
||||
for input in &fd.inputs {
|
||||
|
@ -857,11 +857,10 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
callee => signal!(e, CallOn(callee)),
|
||||
};
|
||||
let (decl, result) = if let Some(fn_like) = lookup_const_fn_by_id(tcx, did) {
|
||||
(fn_like.decl(), &fn_like.body().expr)
|
||||
(fn_like.decl(), fn_like.body())
|
||||
} else {
|
||||
signal!(e, NonConstPath)
|
||||
};
|
||||
let result = result.as_ref().expect("const fn has no result expression");
|
||||
assert_eq!(decl.inputs.len(), args.len());
|
||||
|
||||
let mut call_args = DefIdMap();
|
||||
|
@ -701,8 +701,8 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
|
||||
mut out: W)
|
||||
-> io::Result<()> {
|
||||
let cfg = match code {
|
||||
blocks::BlockCode(block) => cfg::CFG::new(tcx, &block),
|
||||
blocks::FnLikeCode(fn_like) => cfg::CFG::new(tcx, &fn_like.body()),
|
||||
blocks::Code::Expr(expr) => cfg::CFG::new(tcx, expr),
|
||||
blocks::Code::FnLike(fn_like) => cfg::CFG::new(tcx, fn_like.body()),
|
||||
};
|
||||
let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges;
|
||||
let lcfg = LabelledCFG {
|
||||
@ -717,12 +717,12 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
|
||||
let r = dot::render(&lcfg, &mut out);
|
||||
return expand_err_details(r);
|
||||
}
|
||||
blocks::BlockCode(_) => {
|
||||
blocks::Code::Expr(_) => {
|
||||
tcx.sess.err("--pretty flowgraph with -Z flowgraph-print annotations requires \
|
||||
fn-like node id.");
|
||||
return Ok(());
|
||||
}
|
||||
blocks::FnLikeCode(fn_like) => {
|
||||
blocks::Code::FnLike(fn_like) => {
|
||||
let (bccx, analysis_data) =
|
||||
borrowck::build_borrowck_dataflow_data_for_fn(tcx, fn_like.to_fn_parts(), &cfg);
|
||||
|
||||
@ -990,8 +990,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
|
||||
tcx.sess.fatal(&format!("--pretty flowgraph couldn't find id: {}", nodeid))
|
||||
});
|
||||
|
||||
let code = blocks::Code::from_node(node);
|
||||
match code {
|
||||
match blocks::Code::from_node(&tcx.map, nodeid) {
|
||||
Some(code) => {
|
||||
let variants = gather_flowgraph_variants(tcx.sess);
|
||||
|
||||
|
@ -250,7 +250,7 @@ impl LateLintPass for NonSnakeCase {
|
||||
cx: &LateContext,
|
||||
fk: FnKind,
|
||||
_: &hir::FnDecl,
|
||||
_: &hir::Block,
|
||||
_: &hir::Expr,
|
||||
span: Span,
|
||||
id: ast::NodeId) {
|
||||
match fk {
|
||||
|
@ -222,7 +222,7 @@ impl LateLintPass for UnsafeCode {
|
||||
cx: &LateContext,
|
||||
fk: FnKind,
|
||||
_: &hir::FnDecl,
|
||||
_: &hir::Block,
|
||||
_: &hir::Expr,
|
||||
span: Span,
|
||||
_: ast::NodeId) {
|
||||
match fk {
|
||||
@ -812,7 +812,7 @@ impl LateLintPass for UnconditionalRecursion {
|
||||
cx: &LateContext,
|
||||
fn_kind: FnKind,
|
||||
_: &hir::FnDecl,
|
||||
blk: &hir::Block,
|
||||
blk: &hir::Expr,
|
||||
sp: Span,
|
||||
id: ast::NodeId) {
|
||||
let method = match fn_kind {
|
||||
|
@ -99,7 +99,7 @@ impl LateLintPass for UnusedMut {
|
||||
cx: &LateContext,
|
||||
_: FnKind,
|
||||
decl: &hir::FnDecl,
|
||||
_: &hir::Block,
|
||||
_: &hir::Expr,
|
||||
_: Span,
|
||||
_: ast::NodeId) {
|
||||
for a in &decl.inputs {
|
||||
|
@ -156,7 +156,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
fn_id: ast::NodeId,
|
||||
arguments: A,
|
||||
return_ty: Ty<'gcx>,
|
||||
ast_block: &'gcx hir::Block)
|
||||
ast_body: &'gcx hir::Expr)
|
||||
-> (Mir<'tcx>, ScopeAuxiliaryVec)
|
||||
where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
|
||||
{
|
||||
@ -166,7 +166,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
let span = tcx.map.span(fn_id);
|
||||
let mut builder = Builder::new(hir, span, arguments.len(), return_ty);
|
||||
|
||||
let body_id = ast_block.id;
|
||||
let body_id = ast_body.id;
|
||||
let call_site_extent =
|
||||
tcx.region_maps.lookup_code_extent(
|
||||
CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id });
|
||||
@ -176,7 +176,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
let mut block = START_BLOCK;
|
||||
unpack!(block = builder.in_scope(call_site_extent, block, |builder| {
|
||||
unpack!(block = builder.in_scope(arg_extent, block, |builder| {
|
||||
builder.args_and_body(block, return_ty, &arguments, arg_extent, ast_block)
|
||||
builder.args_and_body(block, &arguments, arg_extent, ast_body)
|
||||
}));
|
||||
// Attribute epilogue to function's closing brace
|
||||
let fn_end = Span { lo: span.hi, ..span };
|
||||
@ -310,10 +310,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
fn args_and_body(&mut self,
|
||||
mut block: BasicBlock,
|
||||
return_ty: Ty<'tcx>,
|
||||
arguments: &[(Ty<'gcx>, Option<&'gcx hir::Pat>)],
|
||||
argument_extent: CodeExtent,
|
||||
ast_block: &'gcx hir::Block)
|
||||
ast_body: &'gcx hir::Expr)
|
||||
-> BlockAnd<()>
|
||||
{
|
||||
// Allocate locals for the function arguments
|
||||
@ -342,12 +341,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
if let Some(pattern) = pattern {
|
||||
let pattern = Pattern::from_hir(self.hir.tcx(), pattern);
|
||||
scope = self.declare_bindings(scope, ast_block.span, &pattern);
|
||||
scope = self.declare_bindings(scope, ast_body.span, &pattern);
|
||||
unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
|
||||
}
|
||||
|
||||
// Make sure we drop (parts of) the argument even when not matched on.
|
||||
self.schedule_drop(pattern.as_ref().map_or(ast_block.span, |pat| pat.span),
|
||||
self.schedule_drop(pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
|
||||
argument_extent, &lvalue, ty);
|
||||
|
||||
}
|
||||
@ -357,13 +356,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
self.visibility_scope = visibility_scope;
|
||||
}
|
||||
|
||||
// FIXME(#32959): temporary hack for the issue at hand
|
||||
let return_is_unit = return_ty.is_nil();
|
||||
// start the first basic block and translate the body
|
||||
unpack!(block = self.ast_block(&Lvalue::Local(RETURN_POINTER),
|
||||
return_is_unit, block, ast_block));
|
||||
|
||||
block.unit()
|
||||
let body = self.hir.mirror(ast_body);
|
||||
self.into(&Lvalue::Local(RETURN_POINTER), block, body)
|
||||
}
|
||||
|
||||
fn get_unit_temp(&mut self) -> Lvalue<'tcx> {
|
||||
|
@ -209,7 +209,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
|
||||
fn visit_fn(&mut self,
|
||||
fk: FnKind<'tcx>,
|
||||
decl: &'tcx hir::FnDecl,
|
||||
body: &'tcx hir::Block,
|
||||
body: &'tcx hir::Expr,
|
||||
span: Span,
|
||||
id: ast::NodeId) {
|
||||
// fetch the fully liberated fn signature (that is, all bound
|
||||
|
@ -134,7 +134,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
|
||||
fn fn_like(&mut self,
|
||||
fk: FnKind,
|
||||
fd: &hir::FnDecl,
|
||||
b: &hir::Block,
|
||||
b: &hir::Expr,
|
||||
s: Span,
|
||||
fn_id: ast::NodeId)
|
||||
-> ConstQualif {
|
||||
@ -265,7 +265,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
|
||||
fn visit_fn(&mut self,
|
||||
fk: FnKind<'v>,
|
||||
fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block,
|
||||
b: &'v hir::Expr,
|
||||
s: Span,
|
||||
fn_id: ast::NodeId) {
|
||||
self.fn_like(fk, fd, b, s, fn_id);
|
||||
|
@ -164,7 +164,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
||||
fn visit_fn(&mut self,
|
||||
fk: hir_visit::FnKind<'v>,
|
||||
fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block,
|
||||
b: &'v hir::Expr,
|
||||
s: Span,
|
||||
id: NodeId) {
|
||||
self.record("FnDecl", Id::None, fd);
|
||||
|
@ -54,7 +54,7 @@ impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
|
||||
self.with_context(Loop, |v| v.visit_block(&b));
|
||||
}
|
||||
hir::ExprClosure(.., ref b, _) => {
|
||||
self.with_context(Closure, |v| v.visit_block(&b));
|
||||
self.with_context(Closure, |v| v.visit_expr(&b));
|
||||
}
|
||||
hir::ExprBreak(_) => self.require_loop("break", e.span),
|
||||
hir::ExprAgain(_) => self.require_loop("continue", e.span),
|
||||
|
@ -35,7 +35,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for RvalueContext<'a, 'tcx> {
|
||||
fn visit_fn(&mut self,
|
||||
fk: intravisit::FnKind<'v>,
|
||||
fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block,
|
||||
b: &'v hir::Expr,
|
||||
s: Span,
|
||||
fn_id: ast::NodeId) {
|
||||
// FIXME (@jroesch) change this to be an inference context
|
||||
|
@ -23,7 +23,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
expr: &hir::Expr,
|
||||
_capture: hir::CaptureClause,
|
||||
decl: &'gcx hir::FnDecl,
|
||||
body: &'gcx hir::Block,
|
||||
body: &'gcx hir::Expr,
|
||||
expected: Expectation<'tcx>)
|
||||
-> Ty<'tcx> {
|
||||
debug!("check_expr_closure(expr={:?},expected={:?})",
|
||||
@ -44,7 +44,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
expr: &hir::Expr,
|
||||
opt_kind: Option<ty::ClosureKind>,
|
||||
decl: &'gcx hir::FnDecl,
|
||||
body: &'gcx hir::Block,
|
||||
body: &'gcx hir::Expr,
|
||||
expected_sig: Option<ty::FnSig<'tcx>>)
|
||||
-> Ty<'tcx> {
|
||||
let expr_def_id = self.tcx.map.local_def_id(expr.id);
|
||||
|
@ -534,7 +534,7 @@ pub fn check_drop_impls(ccx: &CrateCtxt) -> CompileResult {
|
||||
|
||||
fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
decl: &'tcx hir::FnDecl,
|
||||
body: &'tcx hir::Block,
|
||||
body: &'tcx hir::Expr,
|
||||
fn_id: ast::NodeId,
|
||||
span: Span) {
|
||||
let raw_fty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(fn_id)).ty;
|
||||
@ -558,7 +558,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
let fcx = check_fn(&inh, fn_ty.unsafety, fn_id, &fn_sig, decl, fn_id, body);
|
||||
|
||||
fcx.select_all_obligations_and_apply_defaults();
|
||||
fcx.closure_analyze_fn(body);
|
||||
fcx.closure_analyze(body);
|
||||
fcx.select_obligations_where_possible();
|
||||
fcx.check_casts();
|
||||
fcx.select_all_obligations_or_error(); // Casts can introduce new obligations.
|
||||
@ -654,7 +654,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
|
||||
|
||||
// Don't descend into the bodies of nested closures
|
||||
fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
|
||||
_: &'gcx hir::Block, _: Span, _: ast::NodeId) { }
|
||||
_: &'gcx hir::Expr, _: Span, _: ast::NodeId) { }
|
||||
}
|
||||
|
||||
/// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
|
||||
@ -669,7 +669,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
|
||||
fn_sig: &ty::FnSig<'tcx>,
|
||||
decl: &'gcx hir::FnDecl,
|
||||
fn_id: ast::NodeId,
|
||||
body: &'gcx hir::Block)
|
||||
body: &'gcx hir::Expr)
|
||||
-> FnCtxt<'a, 'gcx, 'tcx>
|
||||
{
|
||||
let mut fn_sig = fn_sig.clone();
|
||||
@ -709,18 +709,12 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
|
||||
fcx.write_ty(input.id, arg_ty);
|
||||
}
|
||||
|
||||
visit.visit_block(body);
|
||||
visit.visit_expr(body);
|
||||
}
|
||||
|
||||
inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig);
|
||||
|
||||
// FIXME(aburka) do we need this special case? and should it be is_uninhabited?
|
||||
let expected = if fcx.ret_ty.is_never() {
|
||||
NoExpectation
|
||||
} else {
|
||||
ExpectHasType(fcx.ret_ty)
|
||||
};
|
||||
fcx.check_block_with_expected(body, expected);
|
||||
fcx.check_expr_coercable_to_type(body, fcx.ret_ty);
|
||||
|
||||
fcx
|
||||
}
|
||||
@ -1198,7 +1192,7 @@ fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
|
||||
fcx.check_expr_coercable_to_type(expr, expected_type);
|
||||
|
||||
fcx.select_all_obligations_and_apply_defaults();
|
||||
fcx.closure_analyze_const(expr);
|
||||
fcx.closure_analyze(expr);
|
||||
fcx.select_obligations_where_possible();
|
||||
fcx.check_casts();
|
||||
fcx.select_all_obligations_or_error();
|
||||
|
@ -142,13 +142,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn regionck_fn(&self,
|
||||
fn_id: ast::NodeId,
|
||||
decl: &hir::FnDecl,
|
||||
blk: &hir::Block) {
|
||||
body: &hir::Expr) {
|
||||
debug!("regionck_fn(id={})", fn_id);
|
||||
let mut rcx = RegionCtxt::new(self, RepeatingScope(blk.id), blk.id, Subject(fn_id));
|
||||
let mut rcx = RegionCtxt::new(self, RepeatingScope(body.id), body.id, Subject(fn_id));
|
||||
|
||||
if self.err_count_since_creation() == 0 {
|
||||
// regionck assumes typeck succeeded
|
||||
rcx.visit_fn_body(fn_id, decl, blk, self.tcx.map.span(fn_id));
|
||||
rcx.visit_fn_body(fn_id, decl, body, self.tcx.map.span(fn_id));
|
||||
}
|
||||
|
||||
rcx.free_region_map.relate_free_regions_from_predicates(
|
||||
@ -268,7 +268,7 @@ 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: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
span: Span)
|
||||
{
|
||||
// When we enter a function, we can derive
|
||||
@ -305,7 +305,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
self.relate_free_regions(&fn_sig_tys[..], body.id, span);
|
||||
self.link_fn_args(self.tcx.region_maps.node_extent(body.id),
|
||||
&fn_decl.inputs[..]);
|
||||
self.visit_block(body);
|
||||
self.visit_expr(body);
|
||||
self.visit_region_obligations(body.id);
|
||||
|
||||
let call_site_scope = self.call_site_scope.unwrap();
|
||||
@ -480,7 +480,7 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
// regions, until regionck, as described in #3238.
|
||||
|
||||
fn visit_fn(&mut self, _fk: intravisit::FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, span: Span, id: ast::NodeId) {
|
||||
b: &'v hir::Expr, span: Span, id: ast::NodeId) {
|
||||
self.visit_fn_body(id, fd, b, span)
|
||||
}
|
||||
|
||||
@ -825,7 +825,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
fn check_expr_fn_block(&mut self,
|
||||
expr: &hir::Expr,
|
||||
body: &hir::Block) {
|
||||
body: &hir::Expr) {
|
||||
let repeating_scope = self.set_repeating_scope(body.id);
|
||||
intravisit::walk_expr(self, expr);
|
||||
self.set_repeating_scope(repeating_scope);
|
||||
|
@ -57,18 +57,7 @@ use rustc::util::nodemap::NodeMap;
|
||||
// PUBLIC ENTRY POINTS
|
||||
|
||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn closure_analyze_fn(&self, body: &hir::Block) {
|
||||
let mut seed = SeedBorrowKind::new(self);
|
||||
seed.visit_block(body);
|
||||
|
||||
let mut adjust = AdjustBorrowKind::new(self, seed.temp_closure_kinds);
|
||||
adjust.visit_block(body);
|
||||
|
||||
// it's our job to process these.
|
||||
assert!(self.deferred_call_resolutions.borrow().is_empty());
|
||||
}
|
||||
|
||||
pub fn closure_analyze_const(&self, body: &hir::Expr) {
|
||||
pub fn closure_analyze(&self, body: &hir::Expr) {
|
||||
let mut seed = SeedBorrowKind::new(self);
|
||||
seed.visit_expr(body);
|
||||
|
||||
@ -110,7 +99,7 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> {
|
||||
fn check_closure(&mut self,
|
||||
expr: &hir::Expr,
|
||||
capture_clause: hir::CaptureClause,
|
||||
_body: &hir::Block)
|
||||
_body: &hir::Expr)
|
||||
{
|
||||
let closure_def_id = self.fcx.tcx.map.local_def_id(expr.id);
|
||||
if !self.fcx.tables.borrow().closure_kinds.contains_key(&closure_def_id) {
|
||||
@ -164,7 +153,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
id: ast::NodeId,
|
||||
span: Span,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block) {
|
||||
body: &hir::Expr) {
|
||||
/*!
|
||||
* Analysis starting point.
|
||||
*/
|
||||
@ -497,7 +486,7 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||
fn visit_fn(&mut self,
|
||||
fn_kind: intravisit::FnKind<'v>,
|
||||
decl: &'v hir::FnDecl,
|
||||
body: &'v hir::Block,
|
||||
body: &'v hir::Expr,
|
||||
span: Span,
|
||||
id: ast::NodeId)
|
||||
{
|
||||
|
@ -347,7 +347,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
|
||||
|
||||
fn check_item_fn(&mut self,
|
||||
item: &hir::Item,
|
||||
body: &hir::Block)
|
||||
body: &hir::Expr)
|
||||
{
|
||||
self.for_item(item).with_fcx(|fcx, this| {
|
||||
let free_substs = &fcx.parameter_environment.free_substs;
|
||||
|
@ -49,11 +49,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
pub fn resolve_type_vars_in_fn(&self,
|
||||
decl: &hir::FnDecl,
|
||||
blk: &hir::Block,
|
||||
body: &hir::Expr,
|
||||
item_id: ast::NodeId) {
|
||||
assert_eq!(self.writeback_errors.get(), false);
|
||||
let mut wbcx = WritebackCx::new(self);
|
||||
wbcx.visit_block(blk);
|
||||
wbcx.visit_expr(body);
|
||||
for arg in &decl.inputs {
|
||||
wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id);
|
||||
wbcx.visit_pat(&arg.pat);
|
||||
|
Loading…
Reference in New Issue
Block a user