diff options
author | Arthur Cohen <arthur.cohen@embecosm.com> | 2022-04-27 16:34:37 +0200 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2022-04-27 16:34:37 +0200 |
commit | 10b01c305ff73a9da40fb81b7f90312d1f79f037 (patch) | |
tree | 07689ae1cbd6c05fb9923ebb2f1de5e06a40674c /gcc | |
parent | d69dd650367fa7fcfac38001b6406c1bff2601e1 (diff) | |
download | gcc-10b01c305ff73a9da40fb81b7f90312d1f79f037.zip gcc-10b01c305ff73a9da40fb81b7f90312d1f79f037.tar.gz gcc-10b01c305ff73a9da40fb81b7f90312d1f79f037.tar.bz2 |
ast: ResolvePath: Move into its own source file
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/Make-lang.in | 1 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.cc | 1 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.h | 29 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-path.cc | 276 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-path.h | 49 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-pattern.cc | 1 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve.cc | 237 |
7 files changed, 328 insertions, 266 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 5fa93a0..f59deb8 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -91,6 +91,7 @@ GRS_OBJS = \ rust/rust-ast-resolve-pattern.o \ rust/rust-ast-resolve-expr.o \ rust/rust-ast-resolve-type.o \ + rust/rust-ast-resolve-path.o \ rust/rust-hir-type-check.o \ rust/rust-privacy-check.o \ rust/rust-privacy-ctx.o \ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc index e551802..71af8c2 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc @@ -22,6 +22,7 @@ #include "rust-ast-verify-assignee.h" #include "rust-ast-resolve-type.h" #include "rust-ast-resolve-pattern.h" +#include "rust-ast-resolve-path.h" namespace Rust { namespace Resolver { diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index a049ba1..34a318d 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -25,35 +25,6 @@ namespace Rust { namespace Resolver { -class ResolvePath : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::PathInExpression *expr, NodeId parent) - { - ResolvePath resolver (parent); - resolver.resolve_path (expr); - } - - static void go (AST::QualifiedPathInExpression *expr, NodeId parent) - { - ResolvePath resolver (parent); - resolver.resolve_path (expr); - } - -private: - ResolvePath (NodeId parent) : ResolverBase (parent) {} - - void resolve_path (AST::PathInExpression *expr); - - void resolve_path (AST::QualifiedPathInExpression *expr); - - void resolve_segments (CanonicalPath prefix, size_t offs, - std::vector<AST::PathExprSegment> &segs, - NodeId expr_node_id, Location expr_locus); -}; - class ResolveExpr : public ResolverBase { using Rust::Resolver::ResolverBase::visit; diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc new file mode 100644 index 0000000..7aec4f8 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-path.cc @@ -0,0 +1,276 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-ast-resolve-path.h" +#include "rust-ast-resolve-type.h" +#include "rust-path.h" + +namespace Rust { +namespace Resolver { + +void +ResolvePath::go (AST::PathInExpression *expr, NodeId parent) +{ + ResolvePath resolver (parent); + resolver.resolve_path (expr); +} + +void +ResolvePath::go (AST::QualifiedPathInExpression *expr, NodeId parent) +{ + ResolvePath resolver (parent); + resolver.resolve_path (expr); +} + +void +ResolvePath::resolve_path (AST::PathInExpression *expr) +{ + // resolve root segment first then apply segments in turn + std::vector<AST::PathExprSegment> &segs = expr->get_segments (); + AST::PathExprSegment &root_segment = segs.at (0); + AST::PathIdentSegment &root_ident_seg = root_segment.get_ident_segment (); + + bool segment_is_type = false; + CanonicalPath root_seg_path + = CanonicalPath::new_seg (root_segment.get_node_id (), + root_ident_seg.as_string ()); + + // name scope first + if (resolver->get_name_scope ().lookup (root_seg_path, &resolved_node)) + { + segment_is_type = false; + resolver->insert_resolved_name (root_segment.get_node_id (), + resolved_node); + resolver->insert_new_definition (root_segment.get_node_id (), + Definition{expr->get_node_id (), + parent}); + } + // check the type scope + else if (resolver->get_type_scope ().lookup (root_seg_path, &resolved_node)) + { + segment_is_type = true; + resolver->insert_resolved_type (root_segment.get_node_id (), + resolved_node); + resolver->insert_new_definition (root_segment.get_node_id (), + Definition{expr->get_node_id (), + parent}); + } + else + { + rust_error_at (expr->get_locus (), + "Cannot find path %<%s%> in this scope", + root_segment.as_string ().c_str ()); + return; + } + + if (root_segment.has_generic_args ()) + { + bool ok = ResolveTypeToCanonicalPath::type_resolve_generic_args ( + root_segment.get_generic_args ()); + if (!ok) + { + rust_error_at (root_segment.get_locus (), + "failed to resolve generic arguments"); + return; + } + } + + bool is_single_segment = segs.size () == 1; + if (is_single_segment) + { + if (segment_is_type) + resolver->insert_resolved_type (expr->get_node_id (), resolved_node); + else + resolver->insert_resolved_name (expr->get_node_id (), resolved_node); + + resolver->insert_new_definition (expr->get_node_id (), + Definition{expr->get_node_id (), + parent}); + return; + } + + resolve_segments (root_seg_path, 1, expr->get_segments (), + expr->get_node_id (), expr->get_locus ()); +} + +void +ResolvePath::resolve_path (AST::QualifiedPathInExpression *expr) +{ + AST::QualifiedPathType &root_segment = expr->get_qualified_path_type (); + + bool canonicalize_type_with_generics = false; + ResolveType::go (&root_segment.get_as_type_path (), + root_segment.get_node_id (), + canonicalize_type_with_generics); + + ResolveType::go (root_segment.get_type ().get (), root_segment.get_node_id (), + canonicalize_type_with_generics); + + bool type_resolve_generic_args = true; + CanonicalPath impl_type_seg + = ResolveTypeToCanonicalPath::resolve (*root_segment.get_type ().get (), + canonicalize_type_with_generics, + type_resolve_generic_args); + + CanonicalPath trait_type_seg + = ResolveTypeToCanonicalPath::resolve (root_segment.get_as_type_path (), + canonicalize_type_with_generics, + type_resolve_generic_args); + CanonicalPath root_seg_path + = TraitImplProjection::resolve (root_segment.get_node_id (), trait_type_seg, + impl_type_seg); + bool segment_is_type = false; + + // name scope first + if (resolver->get_name_scope ().lookup (root_seg_path, &resolved_node)) + { + segment_is_type = false; + resolver->insert_resolved_name (root_segment.get_node_id (), + resolved_node); + resolver->insert_new_definition (root_segment.get_node_id (), + Definition{expr->get_node_id (), + parent}); + } + // check the type scope + else if (resolver->get_type_scope ().lookup (root_seg_path, &resolved_node)) + { + segment_is_type = true; + resolver->insert_resolved_type (root_segment.get_node_id (), + resolved_node); + resolver->insert_new_definition (root_segment.get_node_id (), + Definition{expr->get_node_id (), + parent}); + } + else + { + rust_error_at (expr->get_locus (), + "Cannot find path %<%s%> in this scope", + root_segment.as_string ().c_str ()); + return; + } + + bool is_single_segment = expr->get_segments ().empty (); + if (is_single_segment) + { + if (segment_is_type) + resolver->insert_resolved_type (expr->get_node_id (), resolved_node); + else + resolver->insert_resolved_name (expr->get_node_id (), resolved_node); + + resolver->insert_new_definition (expr->get_node_id (), + Definition{expr->get_node_id (), + parent}); + return; + } + + resolve_segments (root_seg_path, 0, expr->get_segments (), + expr->get_node_id (), expr->get_locus ()); +} + +void +ResolvePath::resolve_segments (CanonicalPath prefix, size_t offs, + std::vector<AST::PathExprSegment> &segs, + NodeId expr_node_id, Location expr_locus) +{ + // we can attempt to resolve this path fully + CanonicalPath path = prefix; + bool segment_is_type = false; + for (size_t i = offs; i < segs.size (); i++) + { + AST::PathExprSegment &seg = segs.at (i); + auto s = ResolvePathSegmentToCanonicalPath::resolve (seg); + path = path.append (s); + + // reset state + segment_is_type = false; + resolved_node = UNKNOWN_NODEID; + + if (resolver->get_name_scope ().lookup (path, &resolved_node)) + { + resolver->insert_resolved_name (seg.get_node_id (), resolved_node); + resolver->insert_new_definition (seg.get_node_id (), + Definition{expr_node_id, parent}); + } + // check the type scope + else if (resolver->get_type_scope ().lookup (path, &resolved_node)) + { + segment_is_type = true; + resolver->insert_resolved_type (seg.get_node_id (), resolved_node); + resolver->insert_new_definition (seg.get_node_id (), + Definition{expr_node_id, parent}); + } + else + { + // attempt to fully resolve the path which is allowed to fail given + // the following scenario + // + // https://github.com/Rust-GCC/gccrs/issues/355 Paths are + // resolved fully here, there are limitations though imagine: + // + // struct Foo<A> (A); + // + // impl Foo<isize> { + // fn test() -> ... + // + // impl Foo<f32> { + // fn test() -> ... + // + // fn main() { + // let a:i32 = Foo::test(); + // + // there are multiple paths that test can resolve to Foo::<?>::test + // here so we cannot resolve this case + // + // canonical names: + // + // struct Foo<A> -> Foo + // impl Foo<isize>::fn test -> Foo::isize::test + // impl Foo<f32>::fn test -> Foo::f32::test + // + // Since there is the case we have the following paths for test: + // + // Foo::isize::test + // Foo::f32::test + // vs + // Foo::test + // + // but the lookup was simply Foo::test we must rely on type resolution + // to figure this type out in a similar fashion to method resolution + // with a probe phase + + // nothing more we can do we need the type resolver to try and resolve + // this + return; + } + } + + // its fully resolved lets mark it as such + if (resolved_node != UNKNOWN_NODEID) + { + if (segment_is_type) + resolver->insert_resolved_type (expr_node_id, resolved_node); + else + resolver->insert_resolved_name (expr_node_id, resolved_node); + + resolver->insert_new_definition (expr_node_id, + Definition{expr_node_id, parent}); + } +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-path.h b/gcc/rust/resolve/rust-ast-resolve-path.h new file mode 100644 index 0000000..7a4413b --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-path.h @@ -0,0 +1,49 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_PATH_H +#define RUST_AST_RESOLVE_PATH_H + +#include "rust-ast-resolve-base.h" + +namespace Rust { +namespace Resolver { + +class ResolvePath : public ResolverBase +{ + using Rust::Resolver::ResolverBase::visit; + +public: + static void go (AST::PathInExpression *expr, NodeId parent); + static void go (AST::QualifiedPathInExpression *expr, NodeId parent); + +private: + ResolvePath (NodeId parent) : ResolverBase (parent) {} + + void resolve_path (AST::PathInExpression *expr); + void resolve_path (AST::QualifiedPathInExpression *expr); + + void resolve_segments (CanonicalPath prefix, size_t offs, + std::vector<AST::PathExprSegment> &segs, + NodeId expr_node_id, Location expr_locus); +}; + +} // namespace Resolver +} // namespace Rust + +#endif // !RUST_AST_RESOLVE_PATH_H diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc index 24cd171..bac5521 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc @@ -17,6 +17,7 @@ // <http://www.gnu.org/licenses/>. #include "rust-ast-resolve-pattern.h" +#include "rust-ast-resolve-path.h" #include "rust-ast-resolve-expr.h" namespace Rust { diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 723c460..6da5609 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -122,243 +122,6 @@ ResolveStructExprField::visit (AST::StructExprFieldIdentifier &field) ResolveExpr::go (&expr, field.get_node_id (), prefix, canonical_prefix); } -// rust-ast-resolve-expr.h - -void -ResolvePath::resolve_path (AST::PathInExpression *expr) -{ - // resolve root segment first then apply segments in turn - std::vector<AST::PathExprSegment> &segs = expr->get_segments (); - AST::PathExprSegment &root_segment = segs.at (0); - AST::PathIdentSegment &root_ident_seg = root_segment.get_ident_segment (); - - bool segment_is_type = false; - CanonicalPath root_seg_path - = CanonicalPath::new_seg (root_segment.get_node_id (), - root_ident_seg.as_string ()); - - // name scope first - if (resolver->get_name_scope ().lookup (root_seg_path, &resolved_node)) - { - segment_is_type = false; - resolver->insert_resolved_name (root_segment.get_node_id (), - resolved_node); - resolver->insert_new_definition (root_segment.get_node_id (), - Definition{expr->get_node_id (), - parent}); - } - // check the type scope - else if (resolver->get_type_scope ().lookup (root_seg_path, &resolved_node)) - { - segment_is_type = true; - resolver->insert_resolved_type (root_segment.get_node_id (), - resolved_node); - resolver->insert_new_definition (root_segment.get_node_id (), - Definition{expr->get_node_id (), - parent}); - } - else - { - rust_error_at (expr->get_locus (), - "Cannot find path %<%s%> in this scope", - root_segment.as_string ().c_str ()); - return; - } - - if (root_segment.has_generic_args ()) - { - bool ok = ResolveTypeToCanonicalPath::type_resolve_generic_args ( - root_segment.get_generic_args ()); - if (!ok) - { - rust_error_at (root_segment.get_locus (), - "failed to resolve generic arguments"); - return; - } - } - - bool is_single_segment = segs.size () == 1; - if (is_single_segment) - { - if (segment_is_type) - resolver->insert_resolved_type (expr->get_node_id (), resolved_node); - else - resolver->insert_resolved_name (expr->get_node_id (), resolved_node); - - resolver->insert_new_definition (expr->get_node_id (), - Definition{expr->get_node_id (), - parent}); - return; - } - - resolve_segments (root_seg_path, 1, expr->get_segments (), - expr->get_node_id (), expr->get_locus ()); -} - -void -ResolvePath::resolve_path (AST::QualifiedPathInExpression *expr) -{ - AST::QualifiedPathType &root_segment = expr->get_qualified_path_type (); - - bool canonicalize_type_with_generics = false; - ResolveType::go (&root_segment.get_as_type_path (), - root_segment.get_node_id (), - canonicalize_type_with_generics); - - ResolveType::go (root_segment.get_type ().get (), root_segment.get_node_id (), - canonicalize_type_with_generics); - - bool type_resolve_generic_args = true; - CanonicalPath impl_type_seg - = ResolveTypeToCanonicalPath::resolve (*root_segment.get_type ().get (), - canonicalize_type_with_generics, - type_resolve_generic_args); - - CanonicalPath trait_type_seg - = ResolveTypeToCanonicalPath::resolve (root_segment.get_as_type_path (), - canonicalize_type_with_generics, - type_resolve_generic_args); - CanonicalPath root_seg_path - = TraitImplProjection::resolve (root_segment.get_node_id (), trait_type_seg, - impl_type_seg); - bool segment_is_type = false; - - // name scope first - if (resolver->get_name_scope ().lookup (root_seg_path, &resolved_node)) - { - segment_is_type = false; - resolver->insert_resolved_name (root_segment.get_node_id (), - resolved_node); - resolver->insert_new_definition (root_segment.get_node_id (), - Definition{expr->get_node_id (), - parent}); - } - // check the type scope - else if (resolver->get_type_scope ().lookup (root_seg_path, &resolved_node)) - { - segment_is_type = true; - resolver->insert_resolved_type (root_segment.get_node_id (), - resolved_node); - resolver->insert_new_definition (root_segment.get_node_id (), - Definition{expr->get_node_id (), - parent}); - } - else - { - rust_error_at (expr->get_locus (), - "Cannot find path %<%s%> in this scope", - root_segment.as_string ().c_str ()); - return; - } - - bool is_single_segment = expr->get_segments ().empty (); - if (is_single_segment) - { - if (segment_is_type) - resolver->insert_resolved_type (expr->get_node_id (), resolved_node); - else - resolver->insert_resolved_name (expr->get_node_id (), resolved_node); - - resolver->insert_new_definition (expr->get_node_id (), - Definition{expr->get_node_id (), - parent}); - return; - } - - resolve_segments (root_seg_path, 0, expr->get_segments (), - expr->get_node_id (), expr->get_locus ()); -} - -void -ResolvePath::resolve_segments (CanonicalPath prefix, size_t offs, - std::vector<AST::PathExprSegment> &segs, - NodeId expr_node_id, Location expr_locus) -{ - // we can attempt to resolve this path fully - CanonicalPath path = prefix; - bool segment_is_type = false; - for (size_t i = offs; i < segs.size (); i++) - { - AST::PathExprSegment &seg = segs.at (i); - auto s = ResolvePathSegmentToCanonicalPath::resolve (seg); - path = path.append (s); - - // reset state - segment_is_type = false; - resolved_node = UNKNOWN_NODEID; - - if (resolver->get_name_scope ().lookup (path, &resolved_node)) - { - resolver->insert_resolved_name (seg.get_node_id (), resolved_node); - resolver->insert_new_definition (seg.get_node_id (), - Definition{expr_node_id, parent}); - } - // check the type scope - else if (resolver->get_type_scope ().lookup (path, &resolved_node)) - { - segment_is_type = true; - resolver->insert_resolved_type (seg.get_node_id (), resolved_node); - resolver->insert_new_definition (seg.get_node_id (), - Definition{expr_node_id, parent}); - } - else - { - // attempt to fully resolve the path which is allowed to fail given - // the following scenario - // - // https://github.com/Rust-GCC/gccrs/issues/355 Paths are - // resolved fully here, there are limitations though imagine: - // - // struct Foo<A> (A); - // - // impl Foo<isize> { - // fn test() -> ... - // - // impl Foo<f32> { - // fn test() -> ... - // - // fn main() { - // let a:i32 = Foo::test(); - // - // there are multiple paths that test can resolve to Foo::<?>::test - // here so we cannot resolve this case - // - // canonical names: - // - // struct Foo<A> -> Foo - // impl Foo<isize>::fn test -> Foo::isize::test - // impl Foo<f32>::fn test -> Foo::f32::test - // - // Since there is the case we have the following paths for test: - // - // Foo::isize::test - // Foo::f32::test - // vs - // Foo::test - // - // but the lookup was simply Foo::test we must rely on type resolution - // to figure this type out in a similar fashion to method resolution - // with a probe phase - - // nothing more we can do we need the type resolver to try and resolve - // this - return; - } - } - - // its fully resolved lets mark it as such - if (resolved_node != UNKNOWN_NODEID) - { - if (segment_is_type) - resolver->insert_resolved_type (expr_node_id, resolved_node); - else - resolver->insert_resolved_name (expr_node_id, resolved_node); - - resolver->insert_new_definition (expr_node_id, - Definition{expr_node_id, parent}); - } -} - // rust-ast-resolve-item.h void |