diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-08-31 12:22:18 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-08-31 12:22:18 +0100 |
commit | 2ab6f9ee9f294bcd38378905d94fe7b280524414 (patch) | |
tree | b0047c7b6d3a1717d3f592ab5ed13447dab04e57 | |
parent | 0e3030707bfcd196fd678a25bf28fbdb925914c4 (diff) | |
download | gcc-2ab6f9ee9f294bcd38378905d94fe7b280524414.zip gcc-2ab6f9ee9f294bcd38378905d94fe7b280524414.tar.gz gcc-2ab6f9ee9f294bcd38378905d94fe7b280524414.tar.bz2 |
Add name resolution for QualifiedPathInType
Qualified path types allow for TypePaths qualified with a paticular
associated impl and type;
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-type.h | 74 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve.cc | 44 |
2 files changed, 116 insertions, 2 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 97c0311..9ad465a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -97,6 +97,7 @@ public: class ResolveTypeToCanonicalPath : public ResolverBase { +protected: using Rust::Resolver::ResolverBase::visit; public: @@ -128,7 +129,7 @@ public: static bool type_resolve_generic_args (AST::GenericArgs &args); -private: +protected: ResolveTypeToCanonicalPath (bool include_generic_args, bool type_resolve_generic_args) : ResolverBase (UNKNOWN_NODEID), result (CanonicalPath::create_empty ()), @@ -182,8 +183,10 @@ public: } }; -class ResolveRelativeTypePath +class ResolveRelativeTypePath : public ResolveTypeToCanonicalPath { + using ResolveTypeToCanonicalPath::visit; + public: static NodeId go (AST::TypePath &path, NodeId parent, const CanonicalPath &prefix, @@ -218,6 +221,64 @@ public: return resolved_node; } + + static NodeId go (AST::QualifiedPathInType &path, NodeId parent, + const CanonicalPath &prefix, + bool canonicalize_type_with_generics) + { + auto &qualified_path = path.get_qualified_path_type (); + CanonicalPath result = prefix; + if (!resolve_qual_seg (qualified_path, result)) + return UNKNOWN_NODEID; + + // resolve the associated impl + auto resolver = Resolver::get (); + NodeId projection_resolved_id = UNKNOWN_NODEID; + if (!resolver->get_name_scope ().lookup (result, &projection_resolved_id)) + { + rust_error_at (path.get_locus (), + "failed to resolve associated path: %s", + result.get ().c_str ()); + + return UNKNOWN_NODEID; + } + // mark the resolution for this + resolver->insert_resolved_name (qualified_path.get_node_id (), + projection_resolved_id); + + // qualified types are similar to other paths in that we cannot guarantee + // that we can resolve the path at name resolution. We must look up + // associated types and type information to figure this out properly + + ResolveRelativeTypePath o (result); + std::unique_ptr<AST::TypePathSegment> &associated + = path.get_associated_segment (); + + associated->accept_vis (o); + if (o.failure_flag) + return UNKNOWN_NODEID; + + for (auto &seg : path.get_segments ()) + { + seg->accept_vis (o); + if (o.failure_flag) + return UNKNOWN_NODEID; + } + + // we only return the projection id for now since we need the type system to + // resolve the associated types in this path + return projection_resolved_id; + } + +private: + ResolveRelativeTypePath (CanonicalPath qualified_path) + : ResolveTypeToCanonicalPath (true, true) + { + result = qualified_path; + } + + static bool resolve_qual_seg (AST::QualifiedPathType &seg, + CanonicalPath &result); }; class ResolveType : public ResolverBase @@ -275,6 +336,15 @@ public: } } + void visit (AST::QualifiedPathInType &path) override + { + resolved_node + = ResolveRelativeTypePath::go (path, parent, + CanonicalPath::create_empty (), + canonicalize_type_with_generics); + ok = resolved_node != UNKNOWN_NODEID; + } + void visit (AST::ArrayType &type) override; void visit (AST::ReferenceType &type) override diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 9d79b36..1f90181 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -744,5 +744,49 @@ ResolveItem::resolve_extern_item (AST::ExternalItem *item) ResolveExternItem::go (item); } +// qualified path in type + +bool +ResolveRelativeTypePath::resolve_qual_seg (AST::QualifiedPathType &seg, + CanonicalPath &result) +{ + if (seg.is_error ()) + { + rust_error_at (seg.get_locus (), "segment has error: %s", + seg.as_string ().c_str ()); + return false; + } + + bool canonicalize_type_with_generics = true; + NodeId type_resolved_node + = ResolveType::go (seg.get_type ().get (), seg.get_node_id (), + canonicalize_type_with_generics); + if (type_resolved_node == UNKNOWN_NODEID) + return false; + + CanonicalPath impl_type_seg + = ResolveTypeToCanonicalPath::resolve (*seg.get_type ().get ()); + if (!seg.has_as_clause ()) + { + result = result.append (impl_type_seg); + return true; + } + + NodeId trait_resolved_node + = ResolveType::go (&seg.get_as_type_path (), seg.get_node_id (), + canonicalize_type_with_generics); + + if (trait_resolved_node == UNKNOWN_NODEID) + return false; + + CanonicalPath trait_type_seg + = ResolveTypeToCanonicalPath::resolve (seg.get_as_type_path ()); + CanonicalPath projection + = TraitImplProjection::resolve (seg.get_node_id (), trait_type_seg, + impl_type_seg); + result = result.append (projection); + return true; +} + } // namespace Resolver } // namespace Rust |