[gcc/devel/rust/master] Add support for the self path

Thomas Schwinge tschwinge@gcc.gnu.org
Wed Jul 6 12:50:55 GMT 2022


https://gcc.gnu.org/g:18648e7b9f54c0cec4d4d865ff42b453b8de7101

commit 18648e7b9f54c0cec4d4d865ff42b453b8de7101
Author: Philip Herron <philip.herron@embecosm.com>
Date:   Wed Jun 29 15:37:38 2022 +0100

    Add support for the self path
    
    This keyword is described in
    https://doc.rust-lang.org/std/keyword.self.html
    
    Which allows it to refer to the current module when used as the first
    segment. If the keyword is used as any other segment it leads to a
    confusion between self the local parameter keyword in methods. Rustc
    emits a generic unresolved segment error in that senario which I have
    adopted here.
    
    Fixes #1227

Diff:
---
 gcc/rust/ast/rust-path.h                  |  6 ++++++
 gcc/rust/resolve/rust-ast-resolve-path.cc | 21 +++++++++++++++++++++
 gcc/rust/resolve/rust-ast-resolve-type.cc | 28 ++++++++++++++++++++++++----
 gcc/testsuite/rust/compile/self-path1.rs  | 12 ++++++++++++
 gcc/testsuite/rust/compile/self-path2.rs  | 21 +++++++++++++++++++++
 5 files changed, 84 insertions(+), 4 deletions(-)

diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index d2d925a01ce..367c6d611e3 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -50,6 +50,8 @@ public:
 
   std::string as_string () const { return segment_name; }
 
+  Location get_locus () const { return locus; }
+
   bool is_super_segment () const { return as_string ().compare ("super") == 0; }
   bool is_crate_segment () const { return as_string ().compare ("crate") == 0; }
   bool is_lower_self () const { return as_string ().compare ("self") == 0; }
@@ -616,6 +618,10 @@ public:
     return get_ident_segment ().is_super_segment ();
   }
   bool is_big_self_seg () const { return get_ident_segment ().is_big_self (); }
+  bool is_lower_self_seg () const
+  {
+    return get_ident_segment ().is_lower_self ();
+  }
 };
 
 // Segment used in type path with generic args
diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc
index 3c69b65f0e0..c3631fd57ec 100644
--- a/gcc/rust/resolve/rust-ast-resolve-path.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-path.cc
@@ -59,6 +59,18 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
       bool is_first_segment = i == 0;
       resolved_node_id = UNKNOWN_NODEID;
 
+      bool in_middle_of_path = i > 0;
+      if (in_middle_of_path && segment.is_lower_self_seg ())
+	{
+	  // error[E0433]: failed to resolve: `self` in paths can only be used
+	  // in start position
+	  rust_error_at (segment.get_locus (),
+			 "failed to resolve: %<%s%> in paths can only be used "
+			 "in start position",
+			 segment.as_string ().c_str ());
+	  return;
+	}
+
       NodeId crate_scope_id = resolver->peek_crate_module_scope ();
       if (segment.is_crate_path_seg ())
 	{
@@ -170,6 +182,15 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
 	    }
 	  else
 	    {
+	      if (segment.is_lower_self_seg ())
+		{
+		  module_scope_id = crate_scope_id;
+		  previous_resolved_node_id = module_scope_id;
+		  resolver->insert_resolved_name (segment.get_node_id (),
+						  module_scope_id);
+		  continue;
+		}
+
 	      rust_error_at (segment.get_locus (),
 			     "Cannot find path %<%s%> in this scope",
 			     segment.as_string ().c_str ());
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc
index a823543e18d..7d7eac17311 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -95,6 +95,18 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
       bool is_first_segment = i == 0;
       resolved_node_id = UNKNOWN_NODEID;
 
+      bool in_middle_of_path = i > 0;
+      if (in_middle_of_path && segment->is_lower_self_seg ())
+	{
+	  // error[E0433]: failed to resolve: `self` in paths can only be used
+	  // in start position
+	  rust_error_at (segment->get_locus (),
+			 "failed to resolve: %<%s%> in paths can only be used "
+			 "in start position",
+			 segment->as_string ().c_str ());
+	  return false;
+	}
+
       NodeId crate_scope_id = resolver->peek_crate_module_scope ();
       if (segment->is_crate_path_seg ())
 	{
@@ -129,10 +141,7 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
 	      = static_cast<AST::TypePathSegmentGeneric *> (segment.get ());
 	    if (s->has_generic_args ())
 	      {
-		for (auto &gt : s->get_generic_args ().get_type_args ())
-		  {
-		    ResolveType::go (gt.get ());
-		  }
+		ResolveType::type_resolve_generic_args (s->get_generic_args ());
 	      }
 	  }
 	  break;
@@ -198,6 +207,17 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
 	    }
 	  else
 	    {
+	      if (segment->is_lower_self_seg ())
+		{
+		  // what is the current crate scope node id?
+		  module_scope_id = crate_scope_id;
+		  previous_resolved_node_id = module_scope_id;
+		  resolver->insert_resolved_name (segment->get_node_id (),
+						  module_scope_id);
+
+		  continue;
+		}
+
 	      rust_error_at (segment->get_locus (),
 			     "failed to resolve TypePath: %s in this scope",
 			     segment->as_string ().c_str ());
diff --git a/gcc/testsuite/rust/compile/self-path1.rs b/gcc/testsuite/rust/compile/self-path1.rs
new file mode 100644
index 00000000000..425ba848fc0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self-path1.rs
@@ -0,0 +1,12 @@
+// { dg-additional-options "-w" }
+struct foo;
+
+fn bar() -> self::foo {
+    crate::foo
+}
+
+fn baz() {
+    let a: foo = self::bar();
+
+    crate::bar();
+}
diff --git a/gcc/testsuite/rust/compile/self-path2.rs b/gcc/testsuite/rust/compile/self-path2.rs
new file mode 100644
index 00000000000..b9b82cae5a6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self-path2.rs
@@ -0,0 +1,21 @@
+// { dg-additional-options "-w" }
+struct foo;
+
+fn bar() -> self::foo {
+    crate::foo
+}
+
+fn baz() {
+    let a: foo = self::bar();
+
+    crate::bar();
+
+    crate::self::foo();
+    // { dg-error "failed to resolve: .self. in paths can only be used in start position" "" { target *-*-* } .-1 }
+}
+
+type a = foo;
+type b = crate::foo;
+type c = self::foo;
+type d = crate::self::foo;
+// { dg-error "failed to resolve: .self. in paths can only be used in start position" "" { target *-*-* } .-1 }


More information about the Gcc-cvs mailing list