| // Copyright (C) 2020-2024 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_TYPE_H |
| #define RUST_AST_RESOLVE_TYPE_H |
| |
| #include "rust-ast-resolve-base.h" |
| #include "rust-ast-resolve-expr.h" |
| |
| namespace Rust { |
| namespace Resolver { |
| |
| class ResolveRelativeTypePath |
| { |
| public: |
| static bool go (AST::TypePath &path, NodeId &resolved_node_id); |
| }; |
| |
| class ResolveRelativeQualTypePath : public ResolverBase |
| { |
| using ResolverBase::visit; |
| |
| public: |
| static bool go (AST::QualifiedPathInType &path); |
| |
| void visit (AST::TypePathSegmentGeneric &seg) override; |
| |
| void visit (AST::TypePathSegment &seg) override; |
| |
| protected: |
| bool resolve_qual_seg (AST::QualifiedPathType &seg); |
| |
| private: |
| ResolveRelativeQualTypePath (); |
| |
| bool failure_flag; |
| }; |
| |
| class ResolveType : public ResolverBase |
| { |
| using Rust::Resolver::ResolverBase::visit; |
| |
| public: |
| static NodeId go (AST::Type *type) |
| { |
| ResolveType resolver; |
| type->accept_vis (resolver); |
| return resolver.resolved_node; |
| } |
| |
| void visit (AST::BareFunctionType &fntype) override |
| { |
| for (auto ¶m : fntype.get_function_params ()) |
| ResolveType::go (param.get_type ().get ()); |
| |
| if (fntype.has_return_type ()) |
| ResolveType::go (fntype.get_return_type ().get ()); |
| } |
| |
| void visit (AST::TupleType &tuple) override |
| { |
| if (tuple.is_unit_type ()) |
| { |
| resolved_node = resolver->get_unit_type_node_id (); |
| return; |
| } |
| |
| for (auto &elem : tuple.get_elems ()) |
| ResolveType::go (elem.get ()); |
| } |
| |
| void visit (AST::TypePath &path) override |
| { |
| ResolveRelativeTypePath::go (path, resolved_node); |
| } |
| |
| void visit (AST::QualifiedPathInType &path) override |
| { |
| ResolveRelativeQualTypePath::go (path); |
| } |
| |
| void visit (AST::ArrayType &type) override; |
| |
| void visit (AST::ReferenceType &type) override; |
| |
| void visit (AST::InferredType &type) override; |
| |
| void visit (AST::NeverType &type) override; |
| |
| void visit (AST::RawPointerType &type) override; |
| |
| void visit (AST::TraitObjectTypeOneBound &type) override; |
| |
| void visit (AST::TraitObjectType &type) override; |
| |
| void visit (AST::SliceType &type) override; |
| |
| private: |
| ResolveType () : ResolverBase () {} |
| }; |
| |
| class ResolveTypeBound : public ResolverBase |
| { |
| using Rust::Resolver::ResolverBase::visit; |
| |
| public: |
| static NodeId go (AST::TypeParamBound *type) |
| { |
| ResolveTypeBound resolver; |
| type->accept_vis (resolver); |
| return resolver.resolved_node; |
| }; |
| |
| void visit (AST::TraitBound &bound) override |
| { |
| resolved_node = ResolveType::go (&bound.get_type_path ()); |
| } |
| |
| private: |
| ResolveTypeBound () : ResolverBase () {} |
| }; |
| |
| class ResolveGenericParam : public ResolverBase |
| { |
| using Rust::Resolver::ResolverBase::visit; |
| |
| public: |
| static NodeId go (AST::GenericParam *param, const CanonicalPath &prefix, |
| const CanonicalPath &canonical_prefix) |
| { |
| ResolveGenericParam resolver (prefix, canonical_prefix); |
| param->accept_vis (resolver); |
| return resolver.resolved_node; |
| } |
| |
| void visit (AST::ConstGenericParam ¶m) override |
| { |
| ResolveType::go (param.get_type ().get ()); |
| |
| if (param.has_default_value ()) |
| ResolveExpr::go (param.get_default_value ().get_expression ().get (), |
| prefix, canonical_prefix); |
| |
| ok = true; |
| } |
| |
| void visit (AST::TypeParam ¶m) override |
| { |
| // if it has a type lets resolve it |
| if (param.has_type ()) |
| ResolveType::go (param.get_type ().get ()); |
| |
| if (param.has_type_param_bounds ()) |
| { |
| for (auto &bound : param.get_type_param_bounds ()) |
| { |
| ResolveTypeBound::go (bound.get ()); |
| } |
| } |
| |
| auto seg |
| = CanonicalPath::new_seg (param.get_node_id (), |
| param.get_type_representation ().as_string ()); |
| resolver->get_type_scope ().insert ( |
| seg, param.get_node_id (), param.get_locus (), false, Rib::ItemType::Type, |
| [&] (const CanonicalPath &, NodeId, location_t locus) -> void { |
| rust_error_at (param.get_locus (), |
| "generic param redefined multiple times"); |
| rust_error_at (locus, "was defined here"); |
| }); |
| |
| mappings->insert_canonical_path (param.get_node_id (), seg); |
| } |
| |
| private: |
| ResolveGenericParam (const CanonicalPath &prefix, |
| const CanonicalPath &canonical_prefix) |
| : ResolverBase (), ok (false), prefix (prefix), |
| canonical_prefix (canonical_prefix) |
| {} |
| |
| bool ok; |
| const CanonicalPath &prefix; |
| const CanonicalPath &canonical_prefix; |
| }; |
| |
| class ResolveWhereClause : public ResolverBase |
| { |
| using Rust::Resolver::ResolverBase::visit; |
| |
| public: |
| static void Resolve (AST::WhereClause &where_clause) |
| { |
| ResolveWhereClause r; |
| for (auto &clause : where_clause.get_items ()) |
| clause->accept_vis (r); |
| } |
| |
| void visit (AST::TypeBoundWhereClauseItem &item) override |
| { |
| ResolveType::go (item.get_type ().get ()); |
| if (item.has_type_param_bounds ()) |
| { |
| for (auto &bound : item.get_type_param_bounds ()) |
| { |
| ResolveTypeBound::go (bound.get ()); |
| } |
| } |
| } |
| |
| private: |
| ResolveWhereClause () : ResolverBase () {} |
| }; |
| |
| class ResolveTypeToCanonicalPath : public ResolverBase |
| { |
| using Rust::Resolver::ResolverBase::visit; |
| |
| public: |
| static bool go (AST::Type *type, CanonicalPath &result); |
| |
| void visit (AST::TypePath &path) override; |
| |
| void visit (AST::ReferenceType &type) override; |
| |
| void visit (AST::RawPointerType &type) override; |
| |
| void visit (AST::SliceType &type) override; |
| |
| void visit (AST::TraitObjectTypeOneBound &type) override; |
| |
| void visit (AST::TraitObjectType &type) override; |
| |
| private: |
| ResolveTypeToCanonicalPath (); |
| |
| CanonicalPath result; |
| }; |
| |
| class ResolveGenericArgs : public ResolverBase |
| { |
| using Rust::Resolver::ResolverBase::visit; |
| |
| public: |
| static void go (AST::GenericArgs &generic_args); |
| static void go (AST::GenericArgs &generic_args, const CanonicalPath &prefix, |
| const CanonicalPath &canonical_prefix); |
| |
| private: |
| ResolveGenericArgs (const CanonicalPath &prefix, |
| const CanonicalPath &canonical_prefix) |
| : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) |
| {} |
| |
| bool is_type_name (const CanonicalPath &path); |
| bool is_const_value_name (const CanonicalPath &path); |
| |
| /** |
| * Resolve a disambiguated generic arg |
| */ |
| void disambiguate (AST::GenericArg &arg); |
| |
| /** |
| * Resolve a disambiguated generic arg |
| */ |
| void resolve_disambiguated_generic (AST::GenericArg &arg); |
| |
| const CanonicalPath &prefix; |
| const CanonicalPath &canonical_prefix; |
| }; |
| |
| } // namespace Resolver |
| } // namespace Rust |
| |
| #endif // RUST_AST_RESOLVE_TYPE_H |