Fix the unused struct field lint for struct variants

Fixes #14837.
This commit is contained in:
Jakub Wieczorek 2014-06-12 08:38:30 +02:00 committed by Alex Crichton
parent c17af5d7fd
commit 42d538e615
2 changed files with 59 additions and 21 deletions

View File

@ -55,6 +55,11 @@ struct MarkSymbolVisitor<'a> {
live_symbols: Box<HashSet<ast::NodeId>>,
}
#[deriving(Clone)]
struct MarkSymbolVisitorContext {
struct_has_extern_repr: bool
}
impl<'a> MarkSymbolVisitor<'a> {
fn new(tcx: &'a ty::ctxt,
worklist: Vec<ast::NodeId>) -> MarkSymbolVisitor<'a> {
@ -170,48 +175,61 @@ impl<'a> MarkSymbolVisitor<'a> {
}
fn visit_node(&mut self, node: &ast_map::Node) {
let ctxt = MarkSymbolVisitorContext {
struct_has_extern_repr: false
};
match *node {
ast_map::NodeItem(item) => {
match item.node {
ast::ItemStruct(struct_def, _) => {
ast::ItemStruct(..) => {
let has_extern_repr = item.attrs.iter().fold(attr::ReprAny, |acc, attr| {
attr::find_repr_attr(self.tcx.sess.diagnostic(), attr, acc)
}) == attr::ReprExtern;
let live_fields = struct_def.fields.iter().filter(|f| {
has_extern_repr || match f.node.kind {
ast::NamedField(_, ast::Public) => true,
_ => false
}
visit::walk_item(self, &*item, MarkSymbolVisitorContext {
struct_has_extern_repr: has_extern_repr,
..(ctxt)
});
self.live_symbols.extend(live_fields.map(|f| f.node.id));
visit::walk_item(self, &*item, ());
}
ast::ItemFn(..)
| ast::ItemTy(..)
| ast::ItemEnum(..)
| ast::ItemTy(..)
| ast::ItemStatic(..) => {
visit::walk_item(self, &*item, ());
visit::walk_item(self, &*item, ctxt);
}
_ => ()
}
}
ast_map::NodeTraitMethod(trait_method) => {
visit::walk_trait_method(self, &*trait_method, ());
visit::walk_trait_method(self, &*trait_method, ctxt);
}
ast_map::NodeMethod(method) => {
visit::walk_block(self, &*method.body, ());
visit::walk_block(self, &*method.body, ctxt);
}
ast_map::NodeForeignItem(foreign_item) => {
visit::walk_foreign_item(self, &*foreign_item, ());
visit::walk_foreign_item(self, &*foreign_item, ctxt);
}
_ => ()
}
}
}
impl<'a> Visitor<()> for MarkSymbolVisitor<'a> {
impl<'a> Visitor<MarkSymbolVisitorContext> for MarkSymbolVisitor<'a> {
fn visit_expr(&mut self, expr: &ast::Expr, _: ()) {
fn visit_struct_def(&mut self, def: &ast::StructDef, _: ast::Ident, _: &ast::Generics,
_: ast::NodeId, ctxt: MarkSymbolVisitorContext) {
let live_fields = def.fields.iter().filter(|f| {
ctxt.struct_has_extern_repr || match f.node.kind {
ast::NamedField(_, ast::Public) => true,
_ => false
}
});
self.live_symbols.extend(live_fields.map(|f| f.node.id));
visit::walk_struct_def(self, def, ctxt);
}
fn visit_expr(&mut self, expr: &ast::Expr, ctxt: MarkSymbolVisitorContext) {
match expr.node {
ast::ExprMethodCall(..) => {
self.lookup_and_handle_method(expr.id, expr.span);
@ -222,10 +240,10 @@ impl<'a> Visitor<()> for MarkSymbolVisitor<'a> {
_ => ()
}
visit::walk_expr(self, expr, ())
visit::walk_expr(self, expr, ctxt);
}
fn visit_pat(&mut self, pat: &ast::Pat, _: ()) {
fn visit_pat(&mut self, pat: &ast::Pat, ctxt: MarkSymbolVisitorContext) {
match pat.node {
ast::PatStruct(_, ref fields, _) => {
self.handle_field_pattern_match(pat, fields.as_slice());
@ -233,15 +251,15 @@ impl<'a> Visitor<()> for MarkSymbolVisitor<'a> {
_ => ()
}
visit::walk_pat(self, pat, ())
visit::walk_pat(self, pat, ctxt);
}
fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId, _: ()) {
fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId, ctxt: MarkSymbolVisitorContext) {
self.lookup_and_handle_definition(&id);
visit::walk_path(self, path, ());
visit::walk_path(self, path, ctxt);
}
fn visit_item(&mut self, _: &ast::Item, _: ()) {
fn visit_item(&mut self, _: &ast::Item, _: MarkSymbolVisitorContext) {
// Do not recurse into items. These items will be added to the
// worklist and recursed into manually if necessary.
}

View File

@ -0,0 +1,20 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(struct_variant)]
#![deny(warnings)]
pub enum Foo {
Bar {
pub baz: int
}
}
fn main() { }