https://gcc.gnu.org/g:af13b316e2f146c760f829f790d0b6238482067d
commit r16-2836-gaf13b316e2f146c760f829f790d0b6238482067d Author: Owen Avery <powerboat9.ga...@gmail.com> Date: Thu May 15 22:04:34 2025 -0400 gccrs: nr2.0: Catch Self in impl block self types gcc/rust/ChangeLog: * resolve/rust-default-resolver.cc (DefaultResolver::visit): Use visit_impl_type to visit the self types of impl blocks. * resolve/rust-default-resolver.h (DefaultResolver::visit_impl_type): New member function declaration. * resolve/rust-late-name-resolver-2.0.cc (Late::Late): Initialize member variable block_big_self. (Late::visit_impl_type): New member function definition. (Late::visit): Check for Self while inside impl block self types. * resolve/rust-late-name-resolver-2.0.h (Late::visit_impl_type): New member function. (Late::block_big_self): New member variable. gcc/testsuite/ChangeLog: * rust/compile/issue-3671.rs: Remove usage of Self. * rust/compile/nr2/exclude: Remove issue-3671.rs. * rust/compile/self-in-impl.rs: New test. Signed-off-by: Owen Avery <powerboat9.ga...@gmail.com> Diff: --- gcc/rust/resolve/rust-default-resolver.cc | 4 ++-- gcc/rust/resolve/rust-default-resolver.h | 1 + gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 22 +++++++++++++++++++++- gcc/rust/resolve/rust-late-name-resolver-2.0.h | 4 ++++ gcc/testsuite/rust/compile/issue-3671.rs | 2 +- gcc/testsuite/rust/compile/nr2/exclude | 1 - gcc/testsuite/rust/compile/self-in-impl.rs | 17 +++++++++++++++++ 7 files changed, 46 insertions(+), 5 deletions(-) diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index 12f6e1c83349..a4793c048708 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -109,7 +109,7 @@ DefaultResolver::visit (AST::InherentImpl &impl) visit (generic); if (impl.has_where_clause ()) visit (impl.get_where_clause ()); - visit (impl.get_type ()); + visit_impl_type (impl.get_type ()); ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_inner); }; @@ -135,7 +135,7 @@ DefaultResolver::visit (AST::TraitImpl &impl) visit (generic); if (impl.has_where_clause ()) visit (impl.get_where_clause ()); - visit (impl.get_type ()); + visit_impl_type (impl.get_type ()); visit (impl.get_trait_path ()); ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_inner); diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index 639e87113d4b..f500d9018f2e 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -51,6 +51,7 @@ public: void visit (AST::Trait &) override; // used to handle Self insertion in TopLevel virtual void maybe_insert_big_self (AST::Impl &) {} + virtual void visit_impl_type (AST::Type &type) { visit (type); } void visit (AST::InherentImpl &) override; void visit (AST::TraitImpl &) override; diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 062c6f2d0b1c..99e798682464 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -34,7 +34,7 @@ namespace Rust { namespace Resolver2_0 { Late::Late (NameResolutionContext &ctx) - : DefaultResolver (ctx), funny_error (false) + : DefaultResolver (ctx), funny_error (false), block_big_self (false) {} static NodeId @@ -473,6 +473,16 @@ Late::visit (AST::PathInExpression &expr) Definition (resolved->get_node_id ())); } +void +Late::visit_impl_type (AST::Type &type) +{ + // TODO: does this have to handle reentrancy? + rust_assert (!block_big_self); + block_big_self = true; + visit (type); + block_big_self = false; +} + void Late::visit (AST::TypePath &type) { @@ -483,6 +493,16 @@ Late::visit (AST::TypePath &type) DefaultResolver::visit (type); + // prevent "impl Self {}" and similar + if (type.get_segments ().size () == 1 + && !type.get_segments ().front ()->is_lang_item () + && type.get_segments ().front ()->is_big_self_seg () && block_big_self) + { + rust_error_at (type.get_locus (), + "%<Self%> is not valid in the self type of an impl block"); + return; + } + // this *should* mostly work // TODO: make sure typepath-like path resolution (?) is working auto resolved = ctx.resolve_path (type, Namespace::Types); diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index 5b5637d48a91..ddf14ff49409 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -59,6 +59,7 @@ public: void visit (AST::ContinueExpr &) override; void visit (AST::LoopLabel &) override; void visit (AST::PathInExpression &) override; + void visit_impl_type (AST::Type &) override; void visit (AST::TypePath &) override; void visit (AST::Visibility &) override; void visit (AST::Trait &) override; @@ -78,6 +79,9 @@ private: void setup_builtin_types (); bool funny_error; + + /* used to prevent "impl Self {}", "impl (Self, i32) {}", etc */ + bool block_big_self; }; // TODO: Add missing mappings and data structures diff --git a/gcc/testsuite/rust/compile/issue-3671.rs b/gcc/testsuite/rust/compile/issue-3671.rs index e800d536e02c..8015653c0bc5 100644 --- a/gcc/testsuite/rust/compile/issue-3671.rs +++ b/gcc/testsuite/rust/compile/issue-3671.rs @@ -1,2 +1,2 @@ -impl Self<0> {} +impl Foo<0> {} // { dg-error "could not resolve type path" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index 70c59f9abdd4..dc8d5fbcc089 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -6,7 +6,6 @@ pub_restricted_2.rs issue-2905-2.rs torture/alt_patterns1.rs torture/name_resolve1.rs -issue-3671.rs issue-3652.rs issue-1487.rs issue-2015.rs diff --git a/gcc/testsuite/rust/compile/self-in-impl.rs b/gcc/testsuite/rust/compile/self-in-impl.rs new file mode 100644 index 000000000000..f888162a9f06 --- /dev/null +++ b/gcc/testsuite/rust/compile/self-in-impl.rs @@ -0,0 +1,17 @@ +// { dg-additional-options "-frust-name-resolution-2.0" } + +// the error message here is what rustc >=1.66 emits +// rustc <1.66 emits a "cycle detected" error when +// trying to calculate the impl type +// +// since we aren't trying to match error messages too closely +// and the >=1.66 error message is nicer +// we may as well mimic that + +impl ((Self, i32)) {} +// { dg-error ".Self. is not valid in the self" "" { target *-*-* } .-1 } + +trait Foo {} + +impl Foo for ((Self, i32)) {} +// { dg-error ".Self. is not valid in the self" "" { target *-*-* } .-1 }