From: Lucas Ly Ba <[email protected]>
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]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/49002a872e07a14ad4e17a0dcdca60096c1ee62b
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4290
.../lints/unused/rust-unused-checker.cc | 25 +++++++++++++++++++
.../checks/lints/unused/rust-unused-checker.h | 1 +
.../lints/unused/rust-unused-collector.cc | 20 +++++++++++++++
.../lints/unused/rust-unused-collector.h | 8 ++++++
.../lints/unused/rust-unused-context.cc | 19 ++++++++++++++
.../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(+)
create mode 100644 gcc/testsuite/rust/compile/unused-mut-identifier_0.rs
create mode 100644 gcc/testsuite/rust/compile/unused-mut-struct-field_0.rs
diff --git a/gcc/rust/checks/lints/unused/rust-unused-checker.cc
b/gcc/rust/checks/lints/unused/rust-unused-checker.cc
index 9f8394ef9..3ec69e22b 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 6f5f8bade..690435ce4 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 530c6b0ce..b07b09e4a 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 7f3ad88fd..ad10677cf 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 d975865ed..29142f483 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 0a9faf53c..832779d7d 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 000000000..58d1b09e2
--- /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 000000000..1662dd3ba
--- /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)
+ }
+ }
+}
+
base-commit: fea14cb5f3af2db6b3336b1b305f2fb9b019ffa8
--
2.52.0