Skip to content

Commit c01321f

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 2c7b222 commit c01321f

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
@@ -20,6 +20,7 @@
2020
#include "rust-hir-expr.h"
2121
#include "rust-hir-generic-param.h"
2222
#include "rust-hir-item.h"
23+
#include "rust-hir-path.h"
2324

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

170212
void

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

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