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 }

Reply via email to