https://gcc.gnu.org/g:fe65006e77a434872ffbae3c0343dff4e7c31013
commit r16-6362-gfe65006e77a434872ffbae3c0343dff4e7c31013 Author: Lucas Ly Ba <[email protected]> Date: Mon Nov 17 16:13:33 2025 +0000 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]> Diff: --- .../checks/lints/unused/rust-unused-checker.cc | 25 ++++++++++++++++++++++ gcc/rust/checks/lints/unused/rust-unused-checker.h | 1 + .../checks/lints/unused/rust-unused-collector.cc | 20 +++++++++++++++++ .../checks/lints/unused/rust-unused-collector.h | 8 +++++++ .../checks/lints/unused/rust-unused-context.cc | 19 ++++++++++++++++ gcc/rust/checks/lints/unused/rust-unused-context.h | 8 +++++++ .../rust/compile/unused-mut-identifier_0.rs | 6 ++++++ .../rust/compile/unused-mut-struct-field_0.rs | 17 +++++++++++++++ 8 files changed, 104 insertions(+) diff --git a/gcc/rust/checks/lints/unused/rust-unused-checker.cc b/gcc/rust/checks/lints/unused/rust-unused-checker.cc index 9f8394ef90e8..3ec69e22b46a 100644 --- a/gcc/rust/checks/lints/unused/rust-unused-checker.cc +++ b/gcc/rust/checks/lints/unused/rust-unused-checker.cc @@ -76,6 +76,12 @@ UnusedChecker::visit (HIR::IdentifierPattern &pattern) 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 @@ -92,5 +98,24 @@ UnusedChecker::visit (HIR::AssignmentExpr &expr) 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 diff --git a/gcc/rust/checks/lints/unused/rust-unused-checker.h b/gcc/rust/checks/lints/unused/rust-unused-checker.h index 6f5f8badefeb..690435ce455e 100644 --- a/gcc/rust/checks/lints/unused/rust-unused-checker.h +++ b/gcc/rust/checks/lints/unused/rust-unused-checker.h @@ -42,6 +42,7 @@ private: 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 diff --git a/gcc/rust/checks/lints/unused/rust-unused-collector.cc b/gcc/rust/checks/lints/unused/rust-unused-collector.cc index 530c6b0ce9c4..b07b09e4a362 100644 --- a/gcc/rust/checks/lints/unused/rust-unused-collector.cc +++ b/gcc/rust/checks/lints/unused/rust-unused-collector.cc @@ -58,15 +58,35 @@ UnusedCollector::visit (HIR::StructExprFieldIdentifier &ident) 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 diff --git a/gcc/rust/checks/lints/unused/rust-unused-collector.h b/gcc/rust/checks/lints/unused/rust-unused-collector.h index 7f3ad88fdca6..ad10677cf879 100644 --- a/gcc/rust/checks/lints/unused/rust-unused-collector.h +++ b/gcc/rust/checks/lints/unused/rust-unused-collector.h @@ -38,11 +38,19 @@ private: 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 (); diff --git a/gcc/rust/checks/lints/unused/rust-unused-context.cc b/gcc/rust/checks/lints/unused/rust-unused-context.cc index d975865ed588..29142f4838ed 100644 --- a/gcc/rust/checks/lints/unused/rust-unused-context.cc +++ b/gcc/rust/checks/lints/unused/rust-unused-context.cc @@ -46,6 +46,7 @@ UnusedContext::remove_assign (HirId id_def) 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) { @@ -54,6 +55,24 @@ 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 { diff --git a/gcc/rust/checks/lints/unused/rust-unused-context.h b/gcc/rust/checks/lints/unused/rust-unused-context.h index 0a9faf53c8c3..832779d7dbf8 100644 --- a/gcc/rust/checks/lints/unused/rust-unused-context.h +++ b/gcc/rust/checks/lints/unused/rust-unused-context.h @@ -24,16 +24,24 @@ namespace Analysis { 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; }; diff --git a/gcc/testsuite/rust/compile/unused-mut-identifier_0.rs b/gcc/testsuite/rust/compile/unused-mut-identifier_0.rs new file mode 100644 index 000000000000..58d1b09e2267 --- /dev/null +++ b/gcc/testsuite/rust/compile/unused-mut-identifier_0.rs @@ -0,0 +1,6 @@ +// { 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 +} diff --git a/gcc/testsuite/rust/compile/unused-mut-struct-field_0.rs b/gcc/testsuite/rust/compile/unused-mut-struct-field_0.rs new file mode 100644 index 000000000000..1662dd3ba1c4 --- /dev/null +++ b/gcc/testsuite/rust/compile/unused-mut-struct-field_0.rs @@ -0,0 +1,17 @@ +// { 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) + } + } +} +
