rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
"unused variable %qs",
pattern.get_identifier ().as_string ().c_str ());
+
+ if (pattern.is_mut () && !unused_context.is_mut_used (id)
+ && var_name != Values::Keywords::SELF && var_name[0] != '_')
+ rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
+ "unused mut %qs",
+ pattern.get_identifier ().as_string ().c_str ());
}
void
rust_warning_at (lhs.get_locus (), OPT_Wunused_variable,
"unused assignment %qs", var_name.c_str ());
}
+
+void
+UnusedChecker::visit (HIR::StructPatternFieldIdent &pattern)
+{
+ std::string var_name = pattern.get_identifier ().as_string ();
+ auto id = pattern.get_mappings ().get_hirid ();
+ if (!unused_context.is_variable_used (id)
+ && var_name != Values::Keywords::SELF && var_name[0] != '_')
+ rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
+ "unused variable %qs",
+ pattern.get_identifier ().as_string ().c_str ());
+
+ if (pattern.is_mut () && !unused_context.is_mut_used (id)
+ && var_name != Values::Keywords::SELF && var_name[0] != '_')
+ rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
+ "unused mut %qs",
+ pattern.get_identifier ().as_string ().c_str ());
+}
+
} // namespace Analysis
} // namespace Rust
virtual void visit (HIR::StaticItem &item) override;
virtual void visit (HIR::IdentifierPattern &identifier) override;
virtual void visit (HIR::AssignmentExpr &identifier) override;
+ virtual void visit (HIR::StructPatternFieldIdent &identifier) override;
};
} // namespace Analysis
} // namespace Rust
mark_path_used (ident);
walk (ident);
}
+
void
UnusedCollector::visit (HIR::AssignmentExpr &expr)
{
auto def_id = get_def_id (expr.get_lhs ());
HirId id = expr.get_lhs ().get_mappings ().get_hirid ();
+ unused_context.remove_mut (def_id);
unused_context.add_assign (def_id, id);
visit_outer_attrs (expr);
expr.get_rhs ().accept_vis (*this);
}
+void
+UnusedCollector::visit (HIR::IdentifierPattern &pattern)
+{
+ if (pattern.is_mut ())
+ unused_context.add_mut (pattern.get_mappings ().get_hirid ());
+
+ walk (pattern);
+}
+
+void
+UnusedCollector::visit (HIR::StructPatternFieldIdent &pattern)
+{
+ if (pattern.is_mut ())
+ unused_context.add_mut (pattern.get_mappings ().get_hirid ());
+
+ walk (pattern);
+}
+
} // namespace Analysis
} // namespace Rust
UnusedContext &unused_context;
using HIR::DefaultHIRVisitor::visit;
+
+ // Unused var
virtual void visit (HIR::PathInExpression &expr) override;
virtual void visit (HIR::StructExprFieldIdentifier &ident) override;
virtual void visit (HIR::QualifiedPathInExpression &expr) override;
+
+ // Unused assignments
virtual void visit (HIR::AssignmentExpr &expr) override;
+ // Unused mut
+ virtual void visit (HIR::IdentifierPattern &pattern) override;
+ virtual void visit (HIR::StructPatternFieldIdent &pattern) override;
+
template <typename T> HirId get_def_id (T &path_expr)
{
NodeId ast_node_id = path_expr.get_mappings ().get_nodeid ();
if (assigned_vars.find (id_def) != assigned_vars.end ())
assigned_vars[id_def].pop_back ();
}
+
bool
UnusedContext::is_variable_assigned (HirId id_def, HirId id)
{
!= assigned_vec.end ();
}
+void
+UnusedContext::add_mut (HirId id)
+{
+ mutable_vars.emplace (id);
+}
+
+void
+UnusedContext::remove_mut (HirId id)
+{
+ mutable_vars.erase (id);
+}
+
+bool
+UnusedContext::is_mut_used (HirId id) const
+{
+ return mutable_vars.find (id) == mutable_vars.end ();
+}
+
std::string
UnusedContext::as_string () const
{
class UnusedContext
{
public:
+ // Unused var
void add_variable (HirId id);
bool is_variable_used (HirId id) const;
+
+ // Assigned var
void add_assign (HirId id_def, HirId id);
void remove_assign (HirId id_def);
bool is_variable_assigned (HirId id_def, HirId id);
+ // Mutable var
+ void add_mut (HirId id);
+ void remove_mut (HirId id);
+ bool is_mut_used (HirId id) const;
std::string as_string () const;
private:
std::unordered_set<HirId> used_vars;
+ std::unordered_set<HirId> mutable_vars;
std::map<HirId, std::vector<HirId>> assigned_vars;
};
--- /dev/null
+// { dg-additional-options "-frust-unused-check-2.0" }
+pub fn a() ->i32 {
+ let mut x = 2;
+// { dg-warning "unused mut .x." "" { target *-*-* } .-1 }
+ return x
+}
--- /dev/null
+// { dg-additional-options "-frust-unused-check-2.0" }
+struct Point { x: i32, y: i32 }
+// { dg-warning "field is never read: .x." "" { target *-*-* } .-1 }
+// { dg-warning "field is never read: .y." "" { target *-*-* } .-2 }
+
+pub fn main() -> (i32, i32){
+ let p = Point { x: 1, y: 2 };
+
+ match p {
+ Point { mut x, mut y } => {
+// { dg-warning "unused mut .x." "" { target *-*-* } .-1 }
+// { dg-warning "unused mut .y." "" { target *-*-* } .-2 }
+ return (x,y)
+ }
+ }
+}
+