diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/ast/rust-path.h | 6 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-path.cc | 89 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-type.cc | 90 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/self-path1.rs | 12 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/self-path2.rs | 21 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/issue-1231.rs | 36 |
6 files changed, 188 insertions, 66 deletions
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 36f1c04..c6485c0 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; } @@ -691,6 +693,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..9bd836a 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 ()) { @@ -118,7 +130,43 @@ ResolvePath::resolve_path (AST::PathInExpression *expr) // // can only use old resolution when previous segment is unkown - if (previous_resolved_node_id == module_scope_id) + if (is_first_segment) + { + // name scope first + NodeId resolved_node = UNKNOWN_NODEID; + const CanonicalPath path + = CanonicalPath::new_seg (segment.get_node_id (), + ident_seg.as_string ()); + if (resolver->get_name_scope ().lookup (path, &resolved_node)) + { + resolver->insert_resolved_name (segment.get_node_id (), + resolved_node); + resolved_node_id = resolved_node; + } + // check the type scope + else if (resolver->get_type_scope ().lookup (path, &resolved_node)) + { + resolver->insert_resolved_type (segment.get_node_id (), + resolved_node); + resolved_node_id = resolved_node; + } + 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; + } + else + { + // no error handling here since we might be able to resolve via + // the module hierarchy and handle errors at the end + } + } + + if (resolved_node_id == UNKNOWN_NODEID + && previous_resolved_node_id == module_scope_id) { Optional<CanonicalPath &> resolved_child = mappings->lookup_module_child (module_scope_id, @@ -150,36 +198,8 @@ ResolvePath::resolve_path (AST::PathInExpression *expr) } } - if (resolved_node_id == UNKNOWN_NODEID && is_first_segment) - { - // name scope first - NodeId resolved_node = UNKNOWN_NODEID; - const CanonicalPath path - = CanonicalPath::new_seg (segment.get_node_id (), - ident_seg.as_string ()); - if (resolver->get_name_scope ().lookup (path, &resolved_node)) - { - resolver->insert_resolved_name (segment.get_node_id (), - resolved_node); - } - // check the type scope - else if (resolver->get_type_scope ().lookup (path, &resolved_node)) - { - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - } - else - { - rust_error_at (segment.get_locus (), - "Cannot find path %<%s%> in this scope", - segment.as_string ().c_str ()); - return; - } - - resolved_node_id = resolved_node; - } - - if (resolved_node_id != UNKNOWN_NODEID) + bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID; + if (did_resolve_segment) { if (mappings->node_is_module (resolved_node_id)) { @@ -187,6 +207,13 @@ ResolvePath::resolve_path (AST::PathInExpression *expr) } previous_resolved_node_id = resolved_node_id; } + else if (is_first_segment) + { + rust_error_at (segment.get_locus (), + "Cannot find path %<%s%> in this scope", + segment.as_string ().c_str ()); + return; + } } resolved_node = resolved_node_id; diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc index a823543..d444e37 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; @@ -146,8 +155,39 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) break; } - if (previous_resolved_node_id == module_scope_id - && path.get_segments ().size () > 1) + if (is_first_segment) + { + // name scope first + NodeId resolved_node = UNKNOWN_NODEID; + const CanonicalPath path + = CanonicalPath::new_seg (segment->get_node_id (), + ident_seg.as_string ()); + if (resolver->get_type_scope ().lookup (path, &resolved_node)) + { + resolver->insert_resolved_type (segment->get_node_id (), + resolved_node); + resolved_node_id = resolved_node; + } + else if (resolver->get_name_scope ().lookup (path, &resolved_node)) + { + resolver->insert_resolved_name (segment->get_node_id (), + resolved_node); + resolved_node_id = resolved_node; + } + 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; + } + } + + if (resolved_node_id == UNKNOWN_NODEID + && previous_resolved_node_id == module_scope_id) { Optional<CanonicalPath &> resolved_child = mappings->lookup_module_child (module_scope_id, @@ -179,35 +219,8 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) } } - if (resolved_node_id == UNKNOWN_NODEID && is_first_segment) - { - // name scope first - NodeId resolved_node = UNKNOWN_NODEID; - const CanonicalPath path - = CanonicalPath::new_seg (segment->get_node_id (), - ident_seg.as_string ()); - if (resolver->get_type_scope ().lookup (path, &resolved_node)) - { - resolver->insert_resolved_type (segment->get_node_id (), - resolved_node); - } - else if (resolver->get_name_scope ().lookup (path, &resolved_node)) - { - resolver->insert_resolved_name (segment->get_node_id (), - resolved_node); - } - else - { - rust_error_at (segment->get_locus (), - "failed to resolve TypePath: %s in this scope", - segment->as_string ().c_str ()); - return false; - } - - resolved_node_id = resolved_node; - } - - if (resolved_node_id != UNKNOWN_NODEID) + bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID; + if (did_resolve_segment) { if (mappings->node_is_module (resolved_node_id)) { @@ -215,6 +228,13 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) } previous_resolved_node_id = resolved_node_id; } + else if (is_first_segment) + { + rust_error_at (segment->get_locus (), + "failed to resolve TypePath: %s in this scope", + segment->as_string ().c_str ()); + return false; + } } if (resolved_node_id != UNKNOWN_NODEID) 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 } diff --git a/gcc/testsuite/rust/execute/torture/issue-1231.rs b/gcc/testsuite/rust/execute/torture/issue-1231.rs new file mode 100644 index 0000000..970e86f --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-1231.rs @@ -0,0 +1,36 @@ +// { dg-additional-options "-w" } +// { dg-output "outer\ninner\n" } +extern "C" { + fn printf(s: *const i8, ...); +} + +fn machin() { + unsafe { + let a = "outer\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, 123); + } +} + +fn bidule() { + fn machin() { + unsafe { + let a = "inner\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, 123); + } + } + + self::machin(); + machin(); +} + +fn main() -> i32 { + bidule(); + + 0 +} |