Skip to content

Commit 6616157

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 206d052 commit 6616157

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

171213
void

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,14 @@ class UnusedChecker : public HIR::DefaultHIRVisitor
5050
virtual void visit (HIR::LifetimeParam &lft) override;
5151
virtual void visit (HIR::StructPatternFieldIdentPat &field) override;
5252
virtual void visit (HIR::MatchExpr &expr) override;
53+
virtual void visit (HIR::ImplBlock &impl) override;
54+
virtual void visit (HIR::Trait &trait) override;
55+
virtual void visit (HIR::PathInExpression &path) override;
5356
virtual void visit_loop_label (HIR::LoopLabel &label) override;
57+
58+
bool in_associated_scope = false;
59+
int impl_trait_nesting = 0;
60+
bool self_ctor_from_outer = false;
5461
};
5562
} // namespace Analysis
5663
} // 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)