diff options
author | Philip Herron <philip.herron@embecosm.com> | 2022-06-29 15:37:38 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2022-06-29 16:35:52 +0100 |
commit | 18648e7b9f54c0cec4d4d865ff42b453b8de7101 (patch) | |
tree | e81aeb3fa144b3cb85139c2d0eae4092d68db5e8 | |
parent | 81abc8623cb75fa18315c65e94c5965ec36fdb54 (diff) | |
download | gcc-18648e7b9f54c0cec4d4d865ff42b453b8de7101.zip gcc-18648e7b9f54c0cec4d4d865ff42b453b8de7101.tar.gz gcc-18648e7b9f54c0cec4d4d865ff42b453b8de7101.tar.bz2 |
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
-rw-r--r-- | gcc/rust/ast/rust-path.h | 6 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-path.cc | 21 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-type.cc | 28 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/self-path1.rs | 12 | ||||
-rw-r--r-- | 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 d2d925a..367c6d6 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 3c69b65..c3631fd 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 a823543..7d7eac1 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 > : 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 0000000..425ba84 --- /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 0000000..b9b82ca --- /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 } |