Skip to content

Commit 85f2a83

Browse files
committed
gccrs: add unused mut lint
gcc/rust/ChangeLog: * checks/lints/unused/rust-unused-checker.cc (UnusedChecker::UnusedChecker): Add warning for identifier pattern and field ident pattern in struct (UnusedChecker::visit): Add methods. * checks/lints/unused/rust-unused-checker.h: Same here. * checks/lints/unused/rust-unused-collector.cc (UnusedCollector::UnusedCollector): Collect unused mut variables (UnusedCollector::visit): Add methods. * checks/lints/unused/rust-unused-collector.h: Same here. * checks/lints/unused/rust-unused-context.cc (UnusedContext::remove_assign): Add methods for unused mut set. (UnusedContext::add_mut): Same here. (UnusedContext::remove_mut): Same here. (UnusedContext::is_mut_used): Same here. * checks/lints/unused/rust-unused-context.h: Same here. gcc/testsuite/ChangeLog: * rust/compile/unused-mut-identifier_0.rs: New test. * rust/compile/unused-mut-struct-field_0.rs: New test. Signed-off-by: Lucas Ly Ba <[email protected]>
1 parent 9353bdf commit 85f2a83

File tree

8 files changed

+105
-0
lines changed

8 files changed

+105
-0
lines changed

gcc/rust/checks/lints/unused/rust-unused-checker.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ UnusedChecker::visit (HIR::IdentifierPattern &pattern)
7777
rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
7878
"unused variable %qs",
7979
pattern.get_identifier ().as_string ().c_str ());
80+
81+
if (pattern.is_mut () && !unused_context.is_mut_used (id)
82+
&& var_name != "self" && !starts_with_under_score)
83+
rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
84+
"unused mut %qs",
85+
pattern.get_identifier ().as_string ().c_str ());
8086
}
8187
void
8288

@@ -95,5 +101,25 @@ UnusedChecker::visit (HIR::AssignmentExpr &expr)
95101
rust_warning_at (lhs.get_locus (), OPT_Wunused_variable,
96102
"unused assignment %qs", var_name.c_str ());
97103
}
104+
105+
void
106+
UnusedChecker::visit (HIR::StructPatternFieldIdent &pattern)
107+
{
108+
std::string var_name = pattern.get_identifier ().as_string ();
109+
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
110+
auto id = pattern.get_mappings ().get_hirid ();
111+
if (!unused_context.is_variable_used (id) && var_name != "self"
112+
&& !starts_with_under_score)
113+
rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
114+
"unused variable %qs",
115+
pattern.get_identifier ().as_string ().c_str ());
116+
117+
if (pattern.is_mut () && !unused_context.is_mut_used (id)
118+
&& var_name != "self" && !starts_with_under_score)
119+
rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
120+
"unused mut %qs",
121+
pattern.get_identifier ().as_string ().c_str ());
122+
}
123+
98124
} // namespace Analysis
99125
} // namespace Rust

gcc/rust/checks/lints/unused/rust-unused-checker.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class UnusedChecker : public HIR::DefaultHIRVisitor
4242
virtual void visit (HIR::StaticItem &item) override;
4343
virtual void visit (HIR::IdentifierPattern &identifier) override;
4444
virtual void visit (HIR::AssignmentExpr &identifier) override;
45+
virtual void visit (HIR::StructPatternFieldIdent &identifier) override;
4546
};
4647
} // namespace Analysis
4748
} // namespace Rust

gcc/rust/checks/lints/unused/rust-unused-collector.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,35 @@ UnusedCollector::visit (HIR::StructExprFieldIdentifier &ident)
5858
mark_path_used (ident);
5959
walk (ident);
6060
}
61+
6162
void
6263
UnusedCollector::visit (HIR::AssignmentExpr &expr)
6364
{
6465
auto def_id = get_def_id (expr.get_lhs ());
6566
HirId id = expr.get_lhs ().get_mappings ().get_hirid ();
67+
unused_context.remove_mut (def_id);
6668
unused_context.add_assign (def_id, id);
6769
visit_outer_attrs (expr);
6870
expr.get_rhs ().accept_vis (*this);
6971
}
7072

73+
void
74+
UnusedCollector::visit (HIR::IdentifierPattern &pattern)
75+
{
76+
if (pattern.is_mut ())
77+
unused_context.add_mut (pattern.get_mappings ().get_hirid ());
78+
79+
walk (pattern);
80+
}
81+
82+
void
83+
UnusedCollector::visit (HIR::StructPatternFieldIdent &pattern)
84+
{
85+
if (pattern.is_mut ())
86+
unused_context.add_mut (pattern.get_mappings ().get_hirid ());
87+
88+
walk (pattern);
89+
}
90+
7191
} // namespace Analysis
7292
} // namespace Rust

gcc/rust/checks/lints/unused/rust-unused-collector.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,19 @@ class UnusedCollector : public HIR::DefaultHIRVisitor
3838
UnusedContext &unused_context;
3939

4040
using HIR::DefaultHIRVisitor::visit;
41+
42+
// Unused var
4143
virtual void visit (HIR::PathInExpression &expr) override;
4244
virtual void visit (HIR::StructExprFieldIdentifier &ident) override;
4345
virtual void visit (HIR::QualifiedPathInExpression &expr) override;
46+
47+
// Unused assignments
4448
virtual void visit (HIR::AssignmentExpr &expr) override;
4549

50+
// Unused mut
51+
virtual void visit (HIR::IdentifierPattern &pattern) override;
52+
virtual void visit (HIR::StructPatternFieldIdent &pattern) override;
53+
4654
template <typename T> HirId get_def_id (T &path_expr)
4755
{
4856
NodeId ast_node_id = path_expr.get_mappings ().get_nodeid ();

gcc/rust/checks/lints/unused/rust-unused-context.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ UnusedContext::remove_assign (HirId id_def)
4646
if (assigned_vars.find (id_def) != assigned_vars.end ())
4747
assigned_vars[id_def].pop_back ();
4848
}
49+
4950
bool
5051
UnusedContext::is_variable_assigned (HirId id_def, HirId id)
5152
{
@@ -54,6 +55,24 @@ UnusedContext::is_variable_assigned (HirId id_def, HirId id)
5455
!= assigned_vec.end ();
5556
}
5657

58+
void
59+
UnusedContext::add_mut (HirId id)
60+
{
61+
mutable_vars.emplace (id);
62+
}
63+
64+
void
65+
UnusedContext::remove_mut (HirId id)
66+
{
67+
mutable_vars.erase (id);
68+
}
69+
70+
bool
71+
UnusedContext::is_mut_used (HirId id) const
72+
{
73+
return mutable_vars.find (id) == mutable_vars.end ();
74+
}
75+
5776
std::string
5877
UnusedContext::as_string () const
5978
{

gcc/rust/checks/lints/unused/rust-unused-context.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,24 @@ namespace Analysis {
2424
class UnusedContext
2525
{
2626
public:
27+
// Unused var
2728
void add_variable (HirId id);
2829
bool is_variable_used (HirId id) const;
30+
31+
// Assigned var
2932
void add_assign (HirId id_def, HirId id);
3033
void remove_assign (HirId id_def);
3134
bool is_variable_assigned (HirId id_def, HirId id);
3235

36+
// Mutable var
37+
void add_mut (HirId id);
38+
void remove_mut (HirId id);
39+
bool is_mut_used (HirId id) const;
3340
std::string as_string () const;
3441

3542
private:
3643
std::unordered_set<HirId> used_vars;
44+
std::unordered_set<HirId> mutable_vars;
3745
std::map<HirId, std::vector<HirId>> assigned_vars;
3846
};
3947

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// { dg-additional-options "-frust-unused-check-2.0" }
2+
pub fn a() ->i32 {
3+
let mut x = 2;
4+
// { dg-warning "unused mut .x." "" { target *-*-* } .-1 }
5+
return x
6+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// { dg-additional-options "-frust-unused-check-2.0" }
2+
struct Point { x: i32, y: i32 }
3+
// { dg-warning "field is never read: .x." "" { target *-*-* } .-1 }
4+
// { dg-warning "field is never read: .y." "" { target *-*-* } .-2 }
5+
6+
pub fn main() -> (i32, i32){
7+
let p = Point { x: 1, y: 2 };
8+
9+
match p {
10+
Point { mut x, mut y } => {
11+
// { dg-warning "unused mut .x." "" { target *-*-* } .-1 }
12+
// { dg-warning "unused mut .y." "" { target *-*-* } .-2 }
13+
return (x,y)
14+
}
15+
}
16+
}
17+

0 commit comments

Comments
 (0)