]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Error out on unsuffixed self list use declaration
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Tue, 26 Aug 2025 18:07:05 +0000 (20:07 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Thu, 30 Oct 2025 19:58:52 +0000 (20:58 +0100)
gcc/rust/ChangeLog:

* resolve/rust-early-name-resolver-2.0.cc (Early::finalize_rebind_import):
Replace assert with early break and remove early return.
(Early::visit): Check for unsuffixed lower self list.
* resolve/rust-early-name-resolver-2.0.h: Add visit function prototype.

gcc/testsuite/ChangeLog:

* rust/compile/use_self_alone_in_list.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
gcc/rust/resolve/rust-early-name-resolver-2.0.cc
gcc/rust/resolve/rust-early-name-resolver-2.0.h
gcc/testsuite/rust/compile/use_self_alone_in_list.rs [new file with mode: 0644]

index 6036f474afc60a2104873426242172a538d26049..0dff831533117d49b77b7d1c754e8094508deb27 100644 (file)
@@ -438,7 +438,9 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping)
        // We don't want to insert `self` with `use module::self`
        if (path.get_final_segment ().is_lower_self_seg ())
          {
-           rust_assert (segments.size () > 1);
+           // Erroneous `self` or `{self}` use declaration
+           if (segments.size () == 1)
+             break;
            declared_name = segments[segments.size () - 2].as_string ();
          }
        else
@@ -469,7 +471,6 @@ Early::visit (AST::UseDeclaration &decl)
          collect_error (
            Error (decl.get_locus (), ErrorCode::E0429,
                   "%<self%> imports are only allowed within a { } list"));
-         return;
        }
     }
 
@@ -498,5 +499,31 @@ Early::visit (AST::UseDeclaration &decl)
   DefaultResolver::visit (decl);
 }
 
+void
+Early::visit (AST::UseTreeList &use_list)
+{
+  if (!use_list.has_path ())
+    {
+      for (auto &&tree : use_list.get_trees ())
+       {
+         if (tree->get_kind () == AST::UseTree::Kind::Rebind)
+           {
+             auto &rebind = static_cast<AST::UseTreeRebind &> (*tree);
+             auto path_size = rebind.get_path ().get_segments ().size ();
+             if (path_size == 1
+                 && rebind.get_path ()
+                      .get_final_segment ()
+                      .is_lower_self_seg ())
+               {
+                 collect_error (Error (rebind.get_locus (), ErrorCode::E0431,
+                                       "%<self%> import can only appear in an "
+                                       "import list with a non-empty prefix"));
+               }
+           }
+       }
+    }
+  DefaultResolver::visit (use_list);
+}
+
 } // namespace Resolver2_0
 } // namespace Rust
index 960de0e4c791cfd45704f553b3ae1ffd32cbdb65..39403866b832ea52898ed6433fa1a530d712a253 100644 (file)
@@ -61,6 +61,7 @@ public:
   void visit (AST::Function &) override;
   void visit (AST::StructStruct &) override;
   void visit (AST::UseDeclaration &) override;
+  void visit (AST::UseTreeList &) override;
 
   struct ImportData
   {
diff --git a/gcc/testsuite/rust/compile/use_self_alone_in_list.rs b/gcc/testsuite/rust/compile/use_self_alone_in_list.rs
new file mode 100644 (file)
index 0000000..2e87227
--- /dev/null
@@ -0,0 +1,7 @@
+struct B;
+
+use {B as B2, self};
+// { dg-error ".self. import can only appear in an import list with a non-empty prefix" "" { target *-*-* } .-1 }
+
+use {self};
+// { dg-error ".self. import can only appear in an import list with a non-empty prefix" "" { target *-*-* } .-1 }