From: Pierre-Emmanuel Patry <[email protected]>

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 <[email protected]>
---
 .../resolve/rust-early-name-resolver-2.0.cc   | 31 +++++++++++++++++--
 .../resolve/rust-early-name-resolver-2.0.h    |  1 +
 .../rust/compile/use_self_alone_in_list.rs    |  7 +++++
 3 files changed, 37 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/use_self_alone_in_list.rs

diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 6036f474afc..0dff8315331 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -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
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
index 960de0e4c79..39403866b83 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -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
index 00000000000..2e8722721b2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/use_self_alone_in_list.rs
@@ -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 }
-- 
2.50.1

Reply via email to