Skip to content

Commit e683536

Browse files
sakupan102lucasly-ba
authored andcommitted
gccrs : implement unused variable checker on HIR.
This change moves the unused variable checker from the type resolver to HIR. We can now use the HIR Default Visitor, and it will be much more easier to implement other unused lints with this change. gcc/rust/ChangeLog: * Make-lang.in: Add new files rules in Makefile. * lang.opt: Add new flag. * rust-session-manager.cc (Session::compile_crate): Execute new variable checker. * checks/lints/unused-var/rust-unused-var-checker.cc (UnusedVarChecker): Implement unused variable checker. * checks/lints/unused-var/rust-unused-var-checker.h (UnusedVarChecker): Implement unused variable checker. * checks/lints/unused-var/rust-unused-var-collector.cc (UnusedVarCollector): Implement unused variable collector. * checks/lints/unused-var/rust-unused-var-collector.h (UnusedVarCollector): Implement unused variable collector. * checks/lints/unused-var/rust-unused-var-context.cc (UnusedVarContext): Implement unused variable context. * checks/lints/unused-var/rust-unused-var-context.h (UnusedVarContext): Implement unused variable context. gcc/testsuite/ChangeLog: * rust/compile/static_item_0.rs: New test. * rust/compile/template_function_0.rs: New test. Signed-off-by: Lucas Ly Ba <[email protected]>
1 parent f06a3c4 commit e683536

File tree

11 files changed

+392
-1
lines changed

11 files changed

+392
-1
lines changed

gcc/rust/Make-lang.in

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ GRS_OBJS = \
200200
rust/rust-const-checker.o \
201201
rust/rust-lint-marklive.o \
202202
rust/rust-lint-unused-var.o \
203+
rust/rust-unused-var-checker.o \
204+
rust/rust-unused-var-collector.o \
205+
rust/rust-unused-var-context.o \
203206
rust/rust-readonly-check.o \
204207
rust/rust-hir-type-check-path.o \
205208
rust/rust-unsafe-checker.o \
@@ -432,6 +435,7 @@ RUST_INCLUDES = -I $(srcdir)/rust \
432435
-I $(srcdir)/rust/typecheck \
433436
-I $(srcdir)/rust/checks/lints \
434437
-I $(srcdir)/rust/checks/errors \
438+
-I $(srcdir)/rust/checks/lints/unused-var \
435439
-I $(srcdir)/rust/checks/errors/privacy \
436440
-I $(srcdir)/rust/checks/errors/borrowck \
437441
-I $(srcdir)/rust/checks/errors/feature \
@@ -502,6 +506,11 @@ rust/%.o: rust/checks/lints/%.cc
502506
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
503507
$(POSTCOMPILE)
504508

509+
# build unused variable checking pass files in rust folder
510+
rust/%.o: rust/checks/lints/unused-var/%.cc
511+
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
512+
$(POSTCOMPILE)
513+
505514
# build rust/checks/errors files in rust folder
506515
rust/%.o: rust/checks/errors/%.cc
507516
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright (C) 2025 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-unused-var-checker.h"
20+
#include "rust-hir-item.h"
21+
22+
#include "options.h"
23+
24+
namespace Rust {
25+
namespace Analysis {
26+
UnusedVarChecker::UnusedVarChecker ()
27+
: nr_context (
28+
Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()),
29+
mappings (Analysis::Mappings::get ()),
30+
unused_var_context (std::make_unique<UnusedVarContext> ())
31+
{}
32+
void
33+
UnusedVarChecker::go (HIR::Crate &crate)
34+
{
35+
UnusedVarCollector collector (*unused_var_context);
36+
collector.go (crate);
37+
for (auto &item : crate.get_items ())
38+
item->accept_vis (*this);
39+
}
40+
void
41+
UnusedVarChecker::visit (HIR::ConstantItem &item)
42+
{
43+
std::string var_name = item.get_identifier ().as_string ();
44+
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
45+
auto id = item.get_mappings ().get_hirid ();
46+
if (!unused_var_context->is_variable_used (id) && !starts_with_under_score)
47+
rust_warning_at (item.get_locus (), OPT_Wunused_variable,
48+
"unused name '%s'",
49+
item.get_identifier ().as_string ().c_str ());
50+
}
51+
52+
void
53+
UnusedVarChecker::visit (HIR::StaticItem &item)
54+
{
55+
std::string var_name = item.get_identifier ().as_string ();
56+
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
57+
auto id = item.get_mappings ().get_hirid ();
58+
if (!unused_var_context->is_variable_used (id) && !starts_with_under_score)
59+
rust_warning_at (item.get_locus (), OPT_Wunused_variable,
60+
"unused name '%s'",
61+
item.get_identifier ().as_string ().c_str ());
62+
}
63+
64+
void
65+
UnusedVarChecker::visit (HIR::TraitItemFunc &item)
66+
{
67+
// TODO: check trait item functions if they are not derived.
68+
}
69+
void
70+
UnusedVarChecker::visit (HIR::IdentifierPattern &pattern)
71+
{
72+
std::string var_name = pattern.get_identifier ().as_string ();
73+
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
74+
auto id = pattern.get_mappings ().get_hirid ();
75+
if (!unused_var_context->is_variable_used (id) && var_name != "self"
76+
&& !starts_with_under_score)
77+
rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
78+
"unused name '%s'",
79+
pattern.get_identifier ().as_string ().c_str ());
80+
}
81+
} // namespace Analysis
82+
} // namespace Rust
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (C) 2025 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-hir-item.h"
20+
#include "rust-hir-pattern.h"
21+
#include "rust-hir-visitor.h"
22+
#include "rust-immutable-name-resolution-context.h"
23+
#include "rust-unused-var-collector.h"
24+
25+
namespace Rust {
26+
namespace Analysis {
27+
class UnusedVarChecker : public HIR::DefaultHIRVisitor
28+
{
29+
public:
30+
UnusedVarChecker ();
31+
void go (HIR::Crate &crate);
32+
33+
private:
34+
const Resolver2_0::NameResolutionContext &nr_context;
35+
Analysis::Mappings &mappings;
36+
std::unique_ptr<UnusedVarContext> unused_var_context;
37+
38+
using HIR::DefaultHIRVisitor::visit;
39+
virtual void visit (HIR::TraitItemFunc &decl) override;
40+
virtual void visit (HIR::ConstantItem &item) override;
41+
virtual void visit (HIR::StaticItem &item) override;
42+
virtual void visit (HIR::IdentifierPattern &identifier) override;
43+
};
44+
} // namespace Analysis
45+
} // namespace Rust
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright (C) 2025 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-unused-var-collector.h"
20+
#include "rust-hir-full-decls.h"
21+
#include "rust-hir-item.h"
22+
#include "rust-hir-path.h"
23+
#include "rust-hir-pattern.h"
24+
#include "rust-immutable-name-resolution-context.h"
25+
26+
namespace Rust {
27+
namespace Analysis {
28+
UnusedVarCollector::UnusedVarCollector (UnusedVarContext &context)
29+
: nr_context (
30+
Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()),
31+
mappings (Analysis::Mappings::get ()), unused_var_context (context)
32+
{}
33+
void
34+
UnusedVarCollector::go (HIR::Crate &crate)
35+
{
36+
for (auto &item : crate.get_items ())
37+
item->accept_vis (*this);
38+
}
39+
40+
void
41+
UnusedVarCollector::visit (HIR::ConstantItem &item)
42+
{
43+
unused_var_context.add_variable (item.get_mappings ().get_hirid ());
44+
walk (item);
45+
}
46+
47+
void
48+
UnusedVarCollector::visit (HIR::StaticItem &item)
49+
{
50+
unused_var_context.add_variable (item.get_mappings ().get_hirid ());
51+
walk (item);
52+
}
53+
54+
void
55+
UnusedVarCollector::visit (HIR::IdentifierPattern &pattern)
56+
{
57+
auto id = pattern.get_mappings ().get_hirid ();
58+
unused_var_context.add_variable (id);
59+
}
60+
61+
void
62+
UnusedVarCollector::visit (HIR::PathInExpression &expr)
63+
{
64+
mark_path_used (expr);
65+
}
66+
67+
void
68+
UnusedVarCollector::visit (HIR::QualifiedPathInExpression &expr)
69+
{
70+
mark_path_used (expr);
71+
}
72+
73+
void
74+
UnusedVarCollector::visit (HIR::StructExprFieldIdentifier &ident)
75+
{
76+
mark_path_used (ident);
77+
}
78+
} // namespace Analysis
79+
} // namespace Rust
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (C) 2025 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-hir-expr.h"
20+
#include "rust-hir-item.h"
21+
#include "rust-hir-path.h"
22+
#include "rust-hir-pattern.h"
23+
#include "rust-hir-visitor.h"
24+
#include "rust-mapping-common.h"
25+
#include "rust-name-resolution-context.h"
26+
#include "rust-unused-var-context.h"
27+
#include "rust-name-resolver.h"
28+
29+
namespace Rust {
30+
namespace Analysis {
31+
class UnusedVarCollector : public HIR::DefaultHIRVisitor
32+
{
33+
public:
34+
UnusedVarCollector (UnusedVarContext &context);
35+
void go (HIR::Crate &crate);
36+
37+
private:
38+
const Resolver2_0::NameResolutionContext &nr_context;
39+
Analysis::Mappings &mappings;
40+
UnusedVarContext &unused_var_context;
41+
42+
using HIR::DefaultHIRVisitor::visit;
43+
virtual void visit (HIR::PathInExpression &expr) override;
44+
virtual void visit (HIR::StructExprFieldIdentifier &ident) override;
45+
virtual void visit (HIR::ConstantItem &item) override;
46+
virtual void visit (HIR::StaticItem &item) override;
47+
virtual void visit (HIR::IdentifierPattern &pattern) override;
48+
virtual void visit (HIR::QualifiedPathInExpression &expr) override;
49+
50+
template <typename T> void mark_path_used (T &path_expr)
51+
{
52+
NodeId ast_node_id = path_expr.get_mappings ().get_nodeid ();
53+
NodeId def_id = nr_context.lookup (ast_node_id).value ();
54+
HirId hir_id = mappings.lookup_node_to_hir (def_id).value ();
55+
unused_var_context.mark_used (hir_id);
56+
}
57+
};
58+
} // namespace Analysis
59+
} // namespace Rust
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (C) 2025 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-unused-var-context.h"
20+
21+
namespace Rust {
22+
namespace Analysis {
23+
24+
void
25+
UnusedVarContext::add_variable (HirId id)
26+
{
27+
if (is_used.find (id) == is_used.end ())
28+
is_used.insert ({id, false});
29+
}
30+
31+
void
32+
UnusedVarContext::mark_used (HirId id)
33+
{
34+
is_used[id] = true;
35+
}
36+
37+
bool
38+
UnusedVarContext::is_variable_used (HirId id) const
39+
{
40+
auto it = is_used.find (id);
41+
return it != is_used.end () && it->second;
42+
}
43+
44+
std::string
45+
UnusedVarContext::as_string () const
46+
{
47+
std::stringstream ss;
48+
ss << "UnusedVarContext: ";
49+
for (const auto &pair : is_used)
50+
{
51+
ss << "HirId: " << pair.first << " Used: " << (pair.second ? "Yes" : "No")
52+
<< "\n";
53+
}
54+
return ss.str ();
55+
}
56+
57+
} // namespace Analysis
58+
} // namespace Rust

0 commit comments

Comments
 (0)