diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 8cdf6c98331..cfaa355aa4c 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -208,6 +208,9 @@ GRS_OBJS = \
rust/rust-const-checker.o \
rust/rust-lint-marklive.o \
rust/rust-lint-unused-var.o \
+ rust/rust-unused-var-checker.o \
+ rust/rust-unused-var-collector.o \
+ rust/rust-unused-var-context.o \
rust/rust-readonly-check.o \
rust/rust-readonly-check2.o \
rust/rust-hir-type-check-path.o \
@@ -441,6 +444,7 @@ RUST_INCLUDES = -I $(srcdir)/rust \
-I $(srcdir)/rust/typecheck \
-I $(srcdir)/rust/checks/lints \
-I $(srcdir)/rust/checks/errors \
+ -I $(srcdir)/rust/checks/lints/unused-var \
-I $(srcdir)/rust/checks/errors/privacy \
-I $(srcdir)/rust/checks/errors/borrowck \
-I $(srcdir)/rust/util \
@@ -510,6 +514,11 @@ rust/%.o: rust/checks/lints/%.cc
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
$(POSTCOMPILE)
+# build unused variable checking pass files in rust folder
+rust/%.o: rust/checks/lints/unused-var/%.cc
+ $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+ $(POSTCOMPILE)
+
# build rust/checks/errors files in rust folder
rust/%.o: rust/checks/errors/%.cc
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
diff --git a/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.cc b/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.cc
new file mode 100644
index 00000000000..d828bbc5ca1
--- /dev/null
+++ b/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.cc
@@ -0,0 +1,128 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// .
+
+#include "rust-unused-var-checker.h"
+#include "rust-hir-item.h"
+
+#include "options.h"
+
+namespace Rust {
+namespace Analysis {
+UnusedVarChecker::UnusedVarChecker ()
+ : nr_context (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()),
+ mappings (Analysis::Mappings::get ()),
+ unused_var_context (*UnusedVarContext::get ())
+{}
+void
+UnusedVarChecker::go (HIR::Crate &crate)
+{
+ UnusedVarCollector ().go (crate);
+ for (auto &item : crate.get_items ())
+ item->accept_vis (*this);
+}
+void
+UnusedVarChecker::visit (HIR::LetStmt &stmt)
+{
+ HIR::Pattern &pattern = stmt.get_pattern ();
+ check_variable (pattern);
+ walk (stmt);
+}
+void
+UnusedVarChecker::visit_function_param (HIR::FunctionParam ¶m)
+{
+ check_variable (param.get_param_name ());
+}
+
+void
+UnusedVarChecker::visit (HIR::ConstantItem &item)
+{
+ std::string var_name = item.get_identifier ().as_string ();
+ bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
+ auto id = item.get_mappings ().get_hirid ();
+ if (!unused_var_context.is_variable_used (id) && !starts_with_under_score)
+ rust_warning_at (item.get_locus (), OPT_Wunused_variable,
+ "unused name '%s'",
+ item.get_identifier ().as_string ().c_str ());
+}
+
+void
+UnusedVarChecker::visit (HIR::StaticItem &item)
+{
+ std::string var_name = item.get_identifier ().as_string ();
+ bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
+ auto id = item.get_mappings ().get_hirid ();
+ if (!unused_var_context.is_variable_used (id) && !starts_with_under_score)
+ rust_warning_at (item.get_locus (), OPT_Wunused_variable,
+ "unused name '%s'",
+ item.get_identifier ().as_string ().c_str ());
+}
+
+void
+UnusedVarChecker::visit (HIR::TraitItemFunc &item)
+{
+ // TODO: check trait item functions if they are not derived.
+}
+
+void
+UnusedVarChecker::check_variable (HIR::Pattern &pattern)
+{
+ switch (pattern.get_pattern_type ())
+ {
+ case HIR::Pattern::PatternType::IDENTIFIER:
+ check_variable_identifier (
+ static_cast (pattern));
+ break;
+ case HIR::Pattern::PatternType::TUPLE:
+ check_variable_tuple (static_cast (pattern));
+ break;
+ default:
+ break;
+ }
+}
+void
+UnusedVarChecker::check_variable_identifier (HIR::IdentifierPattern &pattern)
+{
+ std::string var_name = pattern.get_identifier ().as_string ();
+ bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
+ auto id = pattern.get_mappings ().get_hirid ();
+ if (!unused_var_context.is_variable_used (id) && var_name != "self"
+ && !starts_with_under_score)
+ rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
+ "unused name '%s'",
+ pattern.get_identifier ().as_string ().c_str ());
+}
+void
+UnusedVarChecker::check_variable_tuple (HIR::TuplePattern &pattern)
+{
+ switch (pattern.get_items ().get_item_type ())
+ {
+ case HIR::TuplePatternItems::ItemType::NO_REST:
+ {
+ auto items
+ = static_cast (pattern.get_items ());
+ for (auto &item : items.get_patterns ())
+ check_variable (*item);
+ }
+ break;
+ default:
+ break;
+ }
+}
+} // namespace Analysis
+} // namespace Rust
\ No newline at end of file
diff --git a/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.h b/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.h
new file mode 100644
index 00000000000..130313c75cc
--- /dev/null
+++ b/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.h
@@ -0,0 +1,48 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// .
+
+#include "rust-hir-item.h"
+#include "rust-hir-visitor.h"
+#include "rust-immutable-name-resolution-context.h"
+#include "rust-unused-var-collector.h"
+
+namespace Rust {
+namespace Analysis {
+class UnusedVarChecker : public HIR::DefaultHIRVisitor
+{
+public:
+ UnusedVarChecker ();
+ void go (HIR::Crate &crate);
+
+private:
+ const Resolver2_0::NameResolutionContext &nr_context;
+ Analysis::Mappings &mappings;
+ UnusedVarContext &unused_var_context;
+
+ using HIR::DefaultHIRVisitor::visit;
+ virtual void visit (HIR::LetStmt &stmt) override;
+ virtual void visit_function_param (HIR::FunctionParam ¶m) override;
+ virtual void visit (HIR::TraitItemFunc &decl) override;
+ virtual void visit (HIR::ConstantItem &item) override;
+ virtual void visit (HIR::StaticItem &item) override;
+ void check_variable_identifier (HIR::IdentifierPattern &identifier);
+ void check_variable_tuple (HIR::TuplePattern &pattern);
+ void check_variable (HIR::Pattern &pattern);
+};
+} // namespace Analysis
+} // namespace Rust
\ No newline at end of file
diff --git a/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.cc b/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.cc
new file mode 100644
index 00000000000..16fa02f4d61
--- /dev/null
+++ b/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.cc
@@ -0,0 +1,130 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// .
+
+#include "rust-unused-var-collector.h"
+#include "rust-hir-full-decls.h"
+#include "rust-hir-item.h"
+#include "rust-hir-path.h"
+#include "rust-immutable-name-resolution-context.h"
+
+namespace Rust {
+namespace Analysis {
+UnusedVarCollector::UnusedVarCollector ()
+ : nr_context (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()),
+ mappings (Analysis::Mappings::get ()),
+ unused_var_context (*UnusedVarContext::get ())
+{}
+void
+UnusedVarCollector::go (HIR::Crate &crate)
+{
+ for (auto &item : crate.get_items ())
+ item->accept_vis (*this);
+}
+void
+UnusedVarCollector::visit (HIR::LetStmt &stmt)
+{
+ HIR::Pattern &pattern = stmt.get_pattern ();
+ collect_variable (pattern);
+ walk (stmt);
+}
+
+void
+UnusedVarCollector::visit (HIR::ConstantItem &item)
+{
+ unused_var_context.add_variable (item.get_mappings ().get_hirid ());
+ walk (item);
+}
+
+void
+UnusedVarCollector::visit (HIR::StaticItem &item)
+{
+ unused_var_context.add_variable (item.get_mappings ().get_hirid ());
+ walk (item);
+}
+
+void
+UnusedVarCollector::visit_function_param (HIR::FunctionParam ¶m)
+{
+ collect_variable (param.get_param_name ());
+}
+
+void
+UnusedVarCollector::visit_closure_param (HIR::ClosureParam ¶m)
+{
+ collect_variable (param.get_pattern ());
+}
+
+void
+UnusedVarCollector::collect_variable (HIR::Pattern &pattern)
+{
+ switch (pattern.get_pattern_type ())
+ {
+ case HIR::Pattern::PatternType::IDENTIFIER:
+ {
+ auto &identifier = static_cast (pattern);
+ auto id = identifier.get_mappings ().get_hirid ();
+ unused_var_context.add_variable (id);
+ }
+ break;
+ case HIR::Pattern::PatternType::TUPLE:
+ {
+ collect_variable_tuple (static_cast (pattern));
+ }
+ break;
+ default:
+ break;
+ }
+}
+void
+UnusedVarCollector::collect_variable_tuple (HIR::TuplePattern &pattern)
+{
+ switch (pattern.get_items ().get_item_type ())
+ {
+ case HIR::TuplePatternItems::ItemType::NO_REST:
+ {
+ auto &items
+ = static_cast (pattern.get_items ());
+ for (auto &sub : items.get_patterns ())
+ collect_variable (*sub);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void
+UnusedVarCollector::visit (HIR::PathInExpression &expr)
+{
+ mark_path_used (expr);
+}
+
+void
+UnusedVarCollector::visit (HIR::QualifiedPathInExpression &expr)
+{
+ mark_path_used (expr);
+}
+
+void
+UnusedVarCollector::visit (HIR::StructExprFieldIdentifier &ident)
+{
+ mark_path_used (ident);
+}
+} // namespace Analysis
+} // namespace Rust
diff --git a/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.h b/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.h
new file mode 100644
index 00000000000..ce1f5d1e7aa
--- /dev/null
+++ b/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.h
@@ -0,0 +1,71 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// .
+
+#include "rust-hir-expr.h"
+#include "rust-hir-item.h"
+#include "rust-hir-path.h"
+#include "rust-hir-visitor.h"
+#include "rust-name-resolution-context.h"
+#include "rust-name-resolver.h"
+#include "rust-unused-var-context.h"
+
+namespace Rust {
+namespace Analysis {
+class UnusedVarCollector : public HIR::DefaultHIRVisitor
+{
+public:
+ UnusedVarCollector ();
+ void go (HIR::Crate &crate);
+
+private:
+ const Resolver2_0::NameResolutionContext &nr_context;
+ Analysis::Mappings &mappings;
+ UnusedVarContext &unused_var_context;
+
+ using HIR::DefaultHIRVisitor::visit;
+ virtual void visit (HIR::LetStmt &stmt) override;
+ virtual void visit (HIR::PathInExpression &expr) override;
+ virtual void visit (HIR::StructExprFieldIdentifier &ident) override;
+ virtual void visit (HIR::ConstantItem &item) override;
+ virtual void visit (HIR::StaticItem &item) override;
+ virtual void visit (HIR::QualifiedPathInExpression &expr) override;
+ virtual void visit_function_param (HIR::FunctionParam ¶m) override;
+ virtual void visit_closure_param (HIR::ClosureParam ¶m) override;
+
+ void collect_variable (HIR::Pattern &pattern);
+ void collect_variable_tuple (HIR::TuplePattern &pattern);
+
+ template void mark_path_used (T &path_expr)
+ {
+ NodeId ast_node_id = path_expr.get_mappings ().get_nodeid ();
+ NodeId def_id;
+
+ if (auto id = nr_context.lookup (ast_node_id))
+ def_id = *id;
+ else
+ return;
+
+ auto hir_id = mappings.lookup_node_to_hir (def_id);
+ if (!hir_id)
+ return;
+
+ unused_var_context.mark_used (hir_id.value ());
+ }
+};
+} // namespace Analysis
+} // namespace Rust
\ No newline at end of file
diff --git a/gcc/rust/checks/lints/unused-var/rust-unused-var-context.cc b/gcc/rust/checks/lints/unused-var/rust-unused-var-context.cc
new file mode 100644
index 00000000000..2271aeeee06
--- /dev/null
+++ b/gcc/rust/checks/lints/unused-var/rust-unused-var-context.cc
@@ -0,0 +1,69 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// .
+
+#include "rust-unused-var-context.h"
+
+namespace Rust {
+namespace Analysis {
+
+UnusedVarContext *
+UnusedVarContext::get ()
+{
+ static UnusedVarContext *instance;
+ if (instance == nullptr)
+ instance = new UnusedVarContext ();
+ return instance;
+}
+
+UnusedVarContext::~UnusedVarContext () {}
+
+void
+UnusedVarContext::add_variable (HirId id)
+{
+ if (is_used.find (id) == is_used.end ())
+ is_used.insert ({id, false});
+}
+
+void
+UnusedVarContext::mark_used (HirId id)
+{
+ is_used[id] = true;
+}
+
+bool
+UnusedVarContext::is_variable_used (HirId id) const
+{
+ auto it = is_used.find (id);
+ return it != is_used.end () && it->second;
+}
+
+std::string
+UnusedVarContext::as_string () const
+{
+ std::stringstream ss;
+ ss << "UnusedVarContext: ";
+ for (const auto &pair : is_used)
+ {
+ ss << "HirId: " << pair.first << " Used: " << (pair.second ? "Yes" : "No")
+ << "\n";
+ }
+ return ss.str ();
+}
+
+} // namespace Analysis
+} // namespace Rust
diff --git a/gcc/rust/checks/lints/unused-var/rust-unused-var-context.h b/gcc/rust/checks/lints/unused-var/rust-unused-var-context.h
new file mode 100644
index 00000000000..2672923b07a
--- /dev/null
+++ b/gcc/rust/checks/lints/unused-var/rust-unused-var-context.h
@@ -0,0 +1,41 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// .
+
+#include "rust-mapping-common.h"
+
+namespace Rust {
+namespace Analysis {
+class UnusedVarContext
+{
+public:
+ static UnusedVarContext *get ();
+ ~UnusedVarContext ();
+
+ void add_variable (HirId id);
+ void mark_used (HirId id);
+
+ bool is_variable_used (HirId id) const;
+
+ std::string as_string () const;
+
+private:
+ UnusedVarContext () = default;
+ std::map is_used;
+};
+} // namespace Analysis
+} // namespace Rust