]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: nr2.0: Catch Self in impl block self types
authorOwen Avery <powerboat9.gamer@gmail.com>
Fri, 16 May 2025 02:04:34 +0000 (22:04 -0400)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 5 Aug 2025 14:36:45 +0000 (16:36 +0200)
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.gamer@gmail.com>
gcc/rust/resolve/rust-default-resolver.cc
gcc/rust/resolve/rust-default-resolver.h
gcc/rust/resolve/rust-late-name-resolver-2.0.cc
gcc/rust/resolve/rust-late-name-resolver-2.0.h
gcc/testsuite/rust/compile/issue-3671.rs
gcc/testsuite/rust/compile/nr2/exclude
gcc/testsuite/rust/compile/self-in-impl.rs [new file with mode: 0644]

index 12f6e1c83349017aebca5c80de758dbd63037b4c..a4793c0487081a38825c3bafff8ab11688f2196d 100644 (file)
@@ -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);
index 639e87113d4b5673fd6c47a2d7f39762fbb1992f..f500d9018f2eca991aadbeed441ea7046f0e7d1c 100644 (file)
@@ -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;
 
index 062c6f2d0b1c167966cb455052f6a8f7e6f398c8..99e798682464715ab65141034f74d1bc938409d4 100644 (file)
@@ -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);
index 5b5637d48a913283b5504ac9d8a3fbf44cd73a61..ddf14ff494099dec5b6ba107f9c98fa39264cf00 100644 (file)
@@ -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
index e800d536e02cdfee3bda1478ff3f0a54e817484f..8015653c0bc51788990c1cea5456dd018c8c6cf1 100644 (file)
@@ -1,2 +1,2 @@
-impl Self<0> {}
+impl Foo<0> {}
 // { dg-error "could not resolve type path" "" { target *-*-* } .-1 }
index 70c59f9abdd4927531b49d8108e978d98647161c..dc8d5fbcc0892af4b8da75f1344bf0a4b8efe059 100644 (file)
@@ -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 (file)
index 0000000..f888162
--- /dev/null
@@ -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 }