Skip to content

Commit 7e9b048

Browse files
committed
gccrs: add self_constructor_from_outer_item lint
Warn when the `Self` constructor is used from an item nested inside an impl or trait, such as a function defined in a method body. gcc/rust/ChangeLog: * checks/lints/unused/rust-unused-checker.cc (UnusedChecker::visit): New. * checks/lints/unused/rust-unused-checker.h (UnusedChecker::visit): New. gcc/testsuite/ChangeLog: * rust/compile/self-constructor-from-outer-item_0.rs: New test. Signed-off-by: Lucas Ly Ba <lucas.ly-ba@outlook.com>
1 parent 76397e8 commit 7e9b048

3 files changed

Lines changed: 68 additions & 0 deletions

File tree

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "rust-hir-generic-param.h"
2222
#include "rust-hir-item.h"
2323
#include "rust-hir-pattern.h"
24+
#include "rust-hir-path.h"
2425

2526
#include "options.h"
2627
#include "rust-keyword-values.h"
@@ -166,7 +167,48 @@ UnusedChecker::visit (HIR::Function &fct)
166167
rust_warning_at (fct.get_locus (), OPT_Wunused_variable,
167168
"function %qs should have a snake case name",
168169
fct.get_function_name ().as_string ().c_str ());
170+
171+
bool is_associated = in_associated_scope;
172+
bool saved_associated = in_associated_scope;
173+
bool saved_self_ctor = self_ctor_from_outer;
174+
in_associated_scope = false;
175+
self_ctor_from_outer = impl_trait_nesting > 0 && !is_associated;
169176
walk (fct);
177+
in_associated_scope = saved_associated;
178+
self_ctor_from_outer = saved_self_ctor;
179+
}
180+
181+
void
182+
UnusedChecker::visit (HIR::ImplBlock &impl)
183+
{
184+
impl_trait_nesting++;
185+
bool saved_associated = in_associated_scope;
186+
in_associated_scope = true;
187+
walk (impl);
188+
in_associated_scope = saved_associated;
189+
impl_trait_nesting--;
190+
}
191+
192+
void
193+
UnusedChecker::visit (HIR::Trait &trait)
194+
{
195+
impl_trait_nesting++;
196+
bool saved_associated = in_associated_scope;
197+
in_associated_scope = true;
198+
walk (trait);
199+
in_associated_scope = saved_associated;
200+
impl_trait_nesting--;
201+
}
202+
203+
void
204+
UnusedChecker::visit (HIR::PathInExpression &path)
205+
{
206+
if (self_ctor_from_outer && path.get_segments ().size () == 1
207+
&& path.get_segments ()[0].get_segment ().to_string ()
208+
== Values::Keywords::SELF_ALIAS)
209+
rust_warning_at (path.get_locus (), OPT_Wunused_variable,
210+
"cannot reference %<Self%> constructor from outer item");
211+
walk (path);
170212
}
171213

172214
void

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,14 @@ class UnusedChecker : public HIR::DefaultHIRVisitor
5252
virtual void visit (HIR::MatchExpr &expr) override;
5353
virtual void visit (HIR::ExternBlock &block) override;
5454
virtual void visit (HIR::LetStmt &stmt) override;
55+
virtual void visit (HIR::ImplBlock &impl) override;
56+
virtual void visit (HIR::Trait &trait) override;
57+
virtual void visit (HIR::PathInExpression &path) override;
5558
virtual void visit_loop_label (HIR::LoopLabel &label) override;
59+
60+
bool in_associated_scope = false;
61+
int impl_trait_nesting = 0;
62+
bool self_ctor_from_outer = false;
5663
};
5764
} // namespace Analysis
5865
} // namespace Rust
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// { dg-additional-options "-frust-unused-check-2.0" }
2+
#![feature(no_core)]
3+
#![no_core]
4+
5+
pub struct S0(usize);
6+
7+
impl S0 {
8+
pub fn foo() -> S0 {
9+
fn bar() -> S0 {
10+
Self(0)
11+
// { dg-warning "cannot reference .Self. constructor from outer item" "" { target *-*-* } .-1 }
12+
}
13+
bar()
14+
}
15+
16+
pub fn direct() -> S0 {
17+
Self(0)
18+
}
19+
}

0 commit comments

Comments
 (0)