1
Fork 0

Remove hir::StmtKind::Decl.

It's a level of indirection that hurts far more than it helps. The code
is simpler without it. (This commit cuts more than 120 lines of code.)

In particular, this commit removes some unnecessary `Span`s within
`DeclKind` that were always identical to those in the enclosing `Stmt`,
and some unnecessary allocations via `P`.
This commit is contained in:
Nicholas Nethercote 2019-01-17 10:39:24 +11:00
parent b2ce5a9099
commit afbd004d69
16 changed files with 152 additions and 274 deletions

View file

@ -100,29 +100,20 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
fn stmt(&mut self, stmt: &hir::Stmt, pred: CFGIndex) -> CFGIndex { fn stmt(&mut self, stmt: &hir::Stmt, pred: CFGIndex) -> CFGIndex {
let hir_id = self.tcx.hir().node_to_hir_id(stmt.id); let hir_id = self.tcx.hir().node_to_hir_id(stmt.id);
match stmt.node { let exit = match stmt.node {
hir::StmtKind::Decl(ref decl) => { hir::StmtKind::Local(ref local) => {
let exit = self.decl(&decl, pred);
self.add_ast_node(hir_id.local_id, &[exit])
}
hir::StmtKind::Expr(ref expr) |
hir::StmtKind::Semi(ref expr) => {
let exit = self.expr(&expr, pred);
self.add_ast_node(hir_id.local_id, &[exit])
}
}
}
fn decl(&mut self, decl: &hir::Decl, pred: CFGIndex) -> CFGIndex {
match decl.node {
hir::DeclKind::Local(ref local) => {
let init_exit = self.opt_expr(&local.init, pred); let init_exit = self.opt_expr(&local.init, pred);
self.pat(&local.pat, init_exit) self.pat(&local.pat, init_exit)
} }
hir::StmtKind::Item(_) => {
hir::DeclKind::Item(_) => pred, pred
} }
hir::StmtKind::Expr(ref expr) |
hir::StmtKind::Semi(ref expr) => {
self.expr(&expr, pred)
}
};
self.add_ast_node(hir_id.local_id, &[exit])
} }
fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex { fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex {

View file

@ -298,8 +298,8 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
fn check_stmt_attributes(&self, stmt: &hir::Stmt) { fn check_stmt_attributes(&self, stmt: &hir::Stmt) {
// When checking statements ignore expressions, they will be checked later // When checking statements ignore expressions, they will be checked later
if let hir::StmtKind::Decl(..) = stmt.node { if let hir::StmtKind::Local(ref l) = stmt.node {
for attr in stmt.node.attrs() { for attr in l.attrs.iter() {
if attr.check_name("inline") { if attr.check_name("inline") {
self.check_inline(attr, &stmt.span, Target::Statement); self.check_inline(attr, &stmt.span, Target::Statement);
} }

View file

@ -260,9 +260,6 @@ pub trait Visitor<'v> : Sized {
fn visit_pat(&mut self, p: &'v Pat) { fn visit_pat(&mut self, p: &'v Pat) {
walk_pat(self, p) walk_pat(self, p)
} }
fn visit_decl(&mut self, d: &'v Decl) {
walk_decl(self, d)
}
fn visit_anon_const(&mut self, c: &'v AnonConst) { fn visit_anon_const(&mut self, c: &'v AnonConst) {
walk_anon_const(self, c) walk_anon_const(self, c)
} }
@ -955,9 +952,8 @@ pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) { pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
visitor.visit_id(statement.id); visitor.visit_id(statement.id);
match statement.node { match statement.node {
StmtKind::Decl(ref declaration) => { StmtKind::Local(ref local) => visitor.visit_local(local),
visitor.visit_decl(declaration) StmtKind::Item(ref item) => visitor.visit_nested_item(**item),
}
StmtKind::Expr(ref expression) | StmtKind::Expr(ref expression) |
StmtKind::Semi(ref expression) => { StmtKind::Semi(ref expression) => {
visitor.visit_expr(expression) visitor.visit_expr(expression)
@ -965,13 +961,6 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
} }
} }
pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
match declaration.node {
DeclKind::Local(ref local) => visitor.visit_local(local),
DeclKind::Item(item) => visitor.visit_nested_item(item),
}
}
pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) { pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
visitor.visit_id(constant.id); visitor.visit_id(constant.id);
visitor.visit_nested_body(constant.body); visitor.visit_nested_body(constant.body);

View file

@ -1957,7 +1957,7 @@ impl<'a> LoweringContext<'a> {
) )
} }
fn lower_local(&mut self, l: &Local) -> (P<hir::Local>, SmallVec<[hir::ItemId; 1]>) { fn lower_local(&mut self, l: &Local) -> (hir::Local, SmallVec<[hir::ItemId; 1]>) {
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(l.id); let LoweredNodeId { node_id, hir_id } = self.lower_node_id(l.id);
let mut ids = SmallVec::<[hir::ItemId; 1]>::new(); let mut ids = SmallVec::<[hir::ItemId; 1]>::new();
if self.sess.features_untracked().impl_trait_in_bindings { if self.sess.features_untracked().impl_trait_in_bindings {
@ -1967,7 +1967,7 @@ impl<'a> LoweringContext<'a> {
} }
} }
let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0); let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0);
(P(hir::Local { (hir::Local {
id: node_id, id: node_id,
hir_id, hir_id,
ty: l.ty ty: l.ty
@ -1984,7 +1984,7 @@ impl<'a> LoweringContext<'a> {
span: l.span, span: l.span,
attrs: l.attrs.clone(), attrs: l.attrs.clone(),
source: hir::LocalSource::Normal, source: hir::LocalSource::Normal,
}), ids) }, ids)
} }
fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability { fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
@ -4537,23 +4537,13 @@ impl<'a> LoweringContext<'a> {
.into_iter() .into_iter()
.map(|item_id| hir::Stmt { .map(|item_id| hir::Stmt {
id: self.next_id().node_id, id: self.next_id().node_id,
node: hir::StmtKind::Decl( node: hir::StmtKind::Item(P(item_id)),
P(Spanned {
node: hir::DeclKind::Item(item_id),
span: s.span,
}),
),
span: s.span, span: s.span,
}) })
.collect(); .collect();
ids.push(hir::Stmt { ids.push(hir::Stmt {
id: self.lower_node_id(s.id).node_id, id: self.lower_node_id(s.id).node_id,
node: hir::StmtKind::Decl( node: hir::StmtKind::Local(P(l)),
P(Spanned {
node: hir::DeclKind::Local(l),
span: s.span,
}),
),
span: s.span, span: s.span,
}); });
return ids; return ids;
@ -4567,12 +4557,7 @@ impl<'a> LoweringContext<'a> {
id: id.take() id: id.take()
.map(|id| self.lower_node_id(id).node_id) .map(|id| self.lower_node_id(id).node_id)
.unwrap_or_else(|| self.next_id().node_id), .unwrap_or_else(|| self.next_id().node_id),
node: hir::StmtKind::Decl( node: hir::StmtKind::Item(P(item_id)),
P(Spanned {
node: hir::DeclKind::Item(item_id),
span: s.span,
}),
),
span: s.span, span: s.span,
}) })
.collect(); .collect();
@ -4799,7 +4784,7 @@ impl<'a> LoweringContext<'a> {
) -> hir::Stmt { ) -> hir::Stmt {
let LoweredNodeId { node_id, hir_id } = self.next_id(); let LoweredNodeId { node_id, hir_id } = self.next_id();
let local = P(hir::Local { let local = hir::Local {
pat, pat,
ty: None, ty: None,
init: ex, init: ex,
@ -4808,11 +4793,10 @@ impl<'a> LoweringContext<'a> {
span: sp, span: sp,
attrs: ThinVec::new(), attrs: ThinVec::new(),
source, source,
}); };
let decl = respan(sp, hir::DeclKind::Local(local));
hir::Stmt { hir::Stmt {
id: self.next_id().node_id, id: self.next_id().node_id,
node: hir::StmtKind::Decl(P(decl)), node: hir::StmtKind::Local(P(local)),
span: sp span: sp
} }
} }

View file

@ -1160,8 +1160,10 @@ impl fmt::Debug for Stmt {
#[derive(Clone, RustcEncodable, RustcDecodable)] #[derive(Clone, RustcEncodable, RustcDecodable)]
pub enum StmtKind { pub enum StmtKind {
/// Could be an item or a local (let) binding: /// A local (let) binding:
Decl(P<Decl>), Local(P<Local>),
/// An item binding:
Item(P<ItemId>),
/// Expr without trailing semi-colon (must have unit type): /// Expr without trailing semi-colon (must have unit type):
Expr(P<Expr>), Expr(P<Expr>),
@ -1173,7 +1175,8 @@ pub enum StmtKind {
impl StmtKind { impl StmtKind {
pub fn attrs(&self) -> &[Attribute] { pub fn attrs(&self) -> &[Attribute] {
match *self { match *self {
StmtKind::Decl(ref d) => d.node.attrs(), StmtKind::Local(ref l) => &l.attrs,
StmtKind::Item(_) => &[],
StmtKind::Expr(ref e) | StmtKind::Expr(ref e) |
StmtKind::Semi(ref e) => &e.attrs, StmtKind::Semi(ref e) => &e.attrs,
} }
@ -1194,32 +1197,6 @@ pub struct Local {
pub source: LocalSource, pub source: LocalSource,
} }
pub type Decl = Spanned<DeclKind>;
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub enum DeclKind {
/// A local (let) binding:
Local(P<Local>),
/// An item binding:
Item(ItemId),
}
impl DeclKind {
pub fn attrs(&self) -> &[Attribute] {
match *self {
DeclKind::Local(ref l) => &l.attrs,
DeclKind::Item(_) => &[]
}
}
pub fn is_local(&self) -> bool {
match *self {
DeclKind::Local(_) => true,
_ => false,
}
}
}
/// represents one arm of a 'match' /// represents one arm of a 'match'
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Arm { pub struct Arm {

View file

@ -992,8 +992,23 @@ impl<'a> State<'a> {
pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> { pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
self.maybe_print_comment(st.span.lo())?; self.maybe_print_comment(st.span.lo())?;
match st.node { match st.node {
hir::StmtKind::Decl(ref decl) => { hir::StmtKind::Local(ref loc) => {
self.print_decl(&decl)?; self.space_if_not_bol()?;
self.ibox(indent_unit)?;
self.word_nbsp("let")?;
self.ibox(indent_unit)?;
self.print_local_decl(&loc)?;
self.end()?;
if let Some(ref init) = loc.init {
self.nbsp()?;
self.word_space("=")?;
self.print_expr(&init)?;
}
self.end()?
}
hir::StmtKind::Item(ref item) => {
self.ann.nested(self, Nested::Item(**item))?
} }
hir::StmtKind::Expr(ref expr) => { hir::StmtKind::Expr(ref expr) => {
self.space_if_not_bol()?; self.space_if_not_bol()?;
@ -1562,30 +1577,6 @@ impl<'a> State<'a> {
Ok(()) Ok(())
} }
pub fn print_decl(&mut self, decl: &hir::Decl) -> io::Result<()> {
self.maybe_print_comment(decl.span.lo())?;
match decl.node {
hir::DeclKind::Local(ref loc) => {
self.space_if_not_bol()?;
self.ibox(indent_unit)?;
self.word_nbsp("let")?;
self.ibox(indent_unit)?;
self.print_local_decl(&loc)?;
self.end()?;
if let Some(ref init) = loc.init {
self.nbsp()?;
self.word_space("=")?;
self.print_expr(&init)?;
}
self.end()
}
hir::DeclKind::Item(item) => {
self.ann.nested(self, Nested::Item(item))
}
}
}
pub fn print_usize(&mut self, i: usize) -> io::Result<()> { pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
self.s.word(i.to_string()) self.s.word(i.to_string())
} }
@ -2401,18 +2392,10 @@ fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool {
/// seen the semicolon, and thus don't need another. /// seen the semicolon, and thus don't need another.
fn stmt_ends_with_semi(stmt: &hir::StmtKind) -> bool { fn stmt_ends_with_semi(stmt: &hir::StmtKind) -> bool {
match *stmt { match *stmt {
hir::StmtKind::Decl(ref d) => { hir::StmtKind::Local(_) => true,
match d.node { hir::StmtKind::Item(_) => false,
hir::DeclKind::Local(_) => true, hir::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(&e),
hir::DeclKind::Item(_) => false, hir::StmtKind::Semi(..) => false,
}
}
hir::StmtKind::Expr(ref e) => {
expr_requires_semi_to_be_stmt(&e)
}
hir::StmtKind::Semi(..) => {
false
}
} }
} }

View file

@ -501,12 +501,6 @@ impl_stable_hash_for!(struct hir::Local {
source source
}); });
impl_stable_hash_for_spanned!(hir::DeclKind);
impl_stable_hash_for!(enum hir::DeclKind {
Local(local),
Item(item_id)
});
impl_stable_hash_for!(struct hir::Arm { impl_stable_hash_for!(struct hir::Arm {
attrs, attrs,
pats, pats,
@ -946,7 +940,8 @@ impl_stable_hash_for!(enum hir::ForeignItemKind {
}); });
impl_stable_hash_for!(enum hir::StmtKind { impl_stable_hash_for!(enum hir::StmtKind {
Decl(decl), Local(local),
Item(item_id),
Expr(expr), Expr(expr),
Semi(expr) Semi(expr)
}); });

View file

@ -941,11 +941,6 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
hir_visit::walk_arm(self, a); hir_visit::walk_arm(self, a);
} }
fn visit_decl(&mut self, d: &'tcx hir::Decl) {
run_lints!(self, check_decl, d);
hir_visit::walk_decl(self, d);
}
fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam) { fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam) {
run_lints!(self, check_generic_param, p); run_lints!(self, check_generic_param, p);
hir_visit::walk_generic_param(self, p); hir_visit::walk_generic_param(self, p);

View file

@ -191,7 +191,6 @@ macro_rules! late_lint_methods {
fn check_stmt(a: &$hir hir::Stmt); fn check_stmt(a: &$hir hir::Stmt);
fn check_arm(a: &$hir hir::Arm); fn check_arm(a: &$hir hir::Arm);
fn check_pat(a: &$hir hir::Pat); fn check_pat(a: &$hir hir::Pat);
fn check_decl(a: &$hir hir::Decl);
fn check_expr(a: &$hir hir::Expr); fn check_expr(a: &$hir hir::Expr);
fn check_expr_post(a: &$hir hir::Expr); fn check_expr_post(a: &$hir hir::Expr);
fn check_ty(a: &$hir hir::Ty); fn check_ty(a: &$hir hir::Ty);

View file

@ -589,17 +589,13 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
fn walk_stmt(&mut self, stmt: &hir::Stmt) { fn walk_stmt(&mut self, stmt: &hir::Stmt) {
match stmt.node { match stmt.node {
hir::StmtKind::Decl(ref decl) => { hir::StmtKind::Local(ref local) => {
match decl.node { self.walk_local(&local);
hir::DeclKind::Local(ref local) => { }
self.walk_local(&local);
}
hir::DeclKind::Item(_) => { hir::StmtKind::Item(_) => {
// we don't visit nested items in this visitor, // we don't visit nested items in this visitor,
// only the fn body we were given. // only the fn body we were given.
}
}
} }
hir::StmtKind::Expr(ref expr) | hir::StmtKind::Expr(ref expr) |

View file

@ -956,46 +956,31 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn propagate_through_stmt(&mut self, stmt: &hir::Stmt, succ: LiveNode) fn propagate_through_stmt(&mut self, stmt: &hir::Stmt, succ: LiveNode)
-> LiveNode { -> LiveNode {
match stmt.node { match stmt.node {
hir::StmtKind::Decl(ref decl) => { hir::StmtKind::Local(ref local) => {
self.propagate_through_decl(&decl, succ) // Note: we mark the variable as defined regardless of whether
} // there is an initializer. Initially I had thought to only mark
// the live variable as defined if it was initialized, and then we
// could check for uninit variables just by scanning what is live
// at the start of the function. But that doesn't work so well for
// immutable variables defined in a loop:
// loop { let x; x = 5; }
// because the "assignment" loops back around and generates an error.
//
// So now we just check that variables defined w/o an
// initializer are not live at the point of their
// initialization, which is mildly more complex than checking
// once at the func header but otherwise equivalent.
let succ = self.propagate_through_opt_expr(local.init.as_ref().map(|e| &**e), succ);
self.define_bindings_in_pat(&local.pat, succ)
}
hir::StmtKind::Item(..) => succ,
hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => {
self.propagate_through_expr(&expr, succ) self.propagate_through_expr(&expr, succ)
} }
} }
} }
fn propagate_through_decl(&mut self, decl: &hir::Decl, succ: LiveNode)
-> LiveNode {
match decl.node {
hir::DeclKind::Local(ref local) => {
self.propagate_through_local(&local, succ)
}
hir::DeclKind::Item(_) => succ,
}
}
fn propagate_through_local(&mut self, local: &hir::Local, succ: LiveNode)
-> LiveNode {
// Note: we mark the variable as defined regardless of whether
// there is an initializer. Initially I had thought to only mark
// the live variable as defined if it was initialized, and then we
// could check for uninit variables just by scanning what is live
// at the start of the function. But that doesn't work so well for
// immutable variables defined in a loop:
// loop { let x; x = 5; }
// because the "assignment" loops back around and generates an error.
//
// So now we just check that variables defined w/o an
// initializer are not live at the point of their
// initialization, which is mildly more complex than checking
// once at the func header but otherwise equivalent.
let succ = self.propagate_through_opt_expr(local.init.as_ref().map(|e| &**e), succ);
self.define_bindings_in_pat(&local.pat, succ)
}
fn propagate_through_exprs(&mut self, exprs: &[Expr], succ: LiveNode) fn propagate_through_exprs(&mut self, exprs: &[Expr], succ: LiveNode)
-> LiveNode { -> LiveNode {
exprs.iter().rev().fold(succ, |succ, expr| { exprs.iter().rev().fold(succ, |succ, expr| {

View file

@ -784,20 +784,25 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
// index information.) // index information.)
for (i, statement) in blk.stmts.iter().enumerate() { for (i, statement) in blk.stmts.iter().enumerate() {
if let hir::StmtKind::Decl(..) = statement.node { match statement.node {
// Each StmtKind::Decl introduces a subscope for bindings hir::StmtKind::Local(..) |
// introduced by the declaration; this subscope covers hir::StmtKind::Item(..) => {
// a suffix of the block . Each subscope in a block // Each declaration introduces a subscope for bindings
// has the previous subscope in the block as a parent, // introduced by the declaration; this subscope covers a
// except for the first such subscope, which has the // suffix of the block. Each subscope in a block has the
// block itself as a parent. // previous subscope in the block as a parent, except for
visitor.enter_scope( // the first such subscope, which has the block itself as a
Scope { // parent.
id: blk.hir_id.local_id, visitor.enter_scope(
data: ScopeData::Remainder(FirstStatementIndex::new(i)) Scope {
} id: blk.hir_id.local_id,
); data: ScopeData::Remainder(FirstStatementIndex::new(i))
visitor.cx.var_parent = visitor.cx.parent; }
);
visitor.cx.var_parent = visitor.cx.parent;
}
hir::StmtKind::Expr(..) |
hir::StmtKind::Semi(..) => {}
} }
visitor.visit_stmt(statement) visitor.visit_stmt(statement)
} }

View file

@ -64,52 +64,48 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
span: stmt_span, span: stmt_span,
}))) })))
} }
hir::StmtKind::Decl(ref decl) => { hir::StmtKind::Item(..) => {
match decl.node { // ignore for purposes of the MIR
hir::DeclKind::Item(..) => { }
// ignore for purposes of the MIR hir::StmtKind::Local(ref local) => {
} let remainder_scope = region::Scope {
hir::DeclKind::Local(ref local) => { id: block_id,
let remainder_scope = region::Scope { data: region::ScopeData::Remainder(
id: block_id, region::FirstStatementIndex::new(index)),
data: region::ScopeData::Remainder( };
region::FirstStatementIndex::new(index)),
let mut pattern = cx.pattern_from_hir(&local.pat);
if let Some(ty) = &local.ty {
if let Some(&user_ty) = cx.tables.user_provided_types().get(ty.hir_id) {
debug!("mirror_stmts: user_ty={:?}", user_ty);
pattern = Pattern {
ty: pattern.ty,
span: pattern.span,
kind: Box::new(PatternKind::AscribeUserType {
user_ty: PatternTypeProjection::from_user_type(user_ty),
user_ty_span: ty.span,
subpattern: pattern,
variance: ty::Variance::Covariant,
})
}; };
let mut pattern = cx.pattern_from_hir(&local.pat);
if let Some(ty) = &local.ty {
if let Some(&user_ty) = cx.tables.user_provided_types().get(ty.hir_id) {
debug!("mirror_stmts: user_ty={:?}", user_ty);
pattern = Pattern {
ty: pattern.ty,
span: pattern.span,
kind: Box::new(PatternKind::AscribeUserType {
user_ty: PatternTypeProjection::from_user_type(user_ty),
user_ty_span: ty.span,
subpattern: pattern,
variance: ty::Variance::Covariant,
})
};
}
}
result.push(StmtRef::Mirror(Box::new(Stmt {
kind: StmtKind::Let {
remainder_scope: remainder_scope,
init_scope: region::Scope {
id: hir_id.local_id,
data: region::ScopeData::Node
},
pattern,
initializer: local.init.to_ref(),
lint_level: cx.lint_level_of(local.id),
},
opt_destruction_scope: opt_dxn_ext,
span: stmt_span,
})));
} }
} }
result.push(StmtRef::Mirror(Box::new(Stmt {
kind: StmtKind::Let {
remainder_scope: remainder_scope,
init_scope: region::Scope {
id: hir_id.local_id,
data: region::ScopeData::Node
},
pattern,
initializer: local.init.to_ref(),
lint_level: cx.lint_level_of(local.id),
},
opt_destruction_scope: opt_dxn_ext,
span: stmt_span,
})));
} }
} }
} }

View file

@ -158,11 +158,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
hir_visit::walk_pat(self, p) hir_visit::walk_pat(self, p)
} }
fn visit_decl(&mut self, d: &'v hir::Decl) {
self.record("Decl", Id::None, d);
hir_visit::walk_decl(self, d)
}
fn visit_expr(&mut self, ex: &'v hir::Expr) { fn visit_expr(&mut self, ex: &'v hir::Expr) {
self.record("Expr", Id::Node(ex.id), ex); self.record("Expr", Id::Node(ex.id), ex);
hir_visit::walk_expr(self, ex) hir_visit::walk_expr(self, ex)

View file

@ -220,24 +220,20 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
fn check_stmt(&mut self, stmt: &'tcx hir::Stmt) -> Promotability { fn check_stmt(&mut self, stmt: &'tcx hir::Stmt) -> Promotability {
match stmt.node { match stmt.node {
hir::StmtKind::Decl(ref decl) => { hir::StmtKind::Local(ref local) => {
match &decl.node { if self.remove_mut_rvalue_borrow(&local.pat) {
hir::DeclKind::Local(local) => { if let Some(init) = &local.init {
if self.remove_mut_rvalue_borrow(&local.pat) { self.mut_rvalue_borrows.insert(init.id);
if let Some(init) = &local.init {
self.mut_rvalue_borrows.insert(init.id);
}
}
if let Some(ref expr) = local.init {
let _ = self.check_expr(&expr);
}
NotPromotable
} }
// Item statements are allowed
hir::DeclKind::Item(_) => Promotable
} }
if let Some(ref expr) = local.init {
let _ = self.check_expr(&expr);
}
NotPromotable
} }
// Item statements are allowed
hir::StmtKind::Item(..) => Promotable,
hir::StmtKind::Expr(ref box_expr) | hir::StmtKind::Expr(ref box_expr) |
hir::StmtKind::Semi(ref box_expr) => { hir::StmtKind::Semi(ref box_expr) => {
let _ = self.check_expr(box_expr); let _ = self.check_expr(box_expr);

View file

@ -4840,12 +4840,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) { pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) {
// Don't do all the complex logic below for `DeclItem`. // Don't do all the complex logic below for `DeclItem`.
match stmt.node { match stmt.node {
hir::StmtKind::Decl(ref decl) => { hir::StmtKind::Item(..) => return,
if let hir::DeclKind::Item(_) = decl.node { hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
return
}
}
hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
} }
self.warn_if_unreachable(stmt.id, stmt.span, "statement"); self.warn_if_unreachable(stmt.id, stmt.span, "statement");
@ -4857,15 +4853,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.has_errors.set(false); self.has_errors.set(false);
match stmt.node { match stmt.node {
hir::StmtKind::Decl(ref decl) => { hir::StmtKind::Local(ref l) => {
match decl.node { self.check_decl_local(&l);
hir::DeclKind::Local(ref l) => {
self.check_decl_local(&l);
}
// Ignore for now.
hir::DeclKind::Item(_) => ()
}
} }
// Ignore for now.
hir::StmtKind::Item(_) => {}
hir::StmtKind::Expr(ref expr) => { hir::StmtKind::Expr(ref expr) => {
// Check with expected type of `()`. // Check with expected type of `()`.
self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit()); self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit());