// Copyright (C) 2020-2023 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 // . #ifndef RUST_HIR_TYPE_CHECK #define RUST_HIR_TYPE_CHECK #include "rust-type-util.h" #include "rust-hir-full-decls.h" #include "rust-hir-map.h" #include "rust-tyty.h" #include "rust-hir-trait-reference.h" #include "rust-autoderef.h" namespace Rust { namespace Resolver { class TypeCheckContextItem { public: enum ItemType { ITEM, IMPL_ITEM, TRAIT_ITEM, }; TypeCheckContextItem (HIR::Function *item); TypeCheckContextItem (HIR::ImplBlock *impl_block, HIR::Function *item); TypeCheckContextItem (HIR::TraitItemFunc *trait_item); ItemType get_type () const; HIR::Function *get_item (); std::pair &get_impl_item (); HIR::TraitItemFunc *get_trait_item (); TyTy::FnType *get_context_type (); private: union Item { HIR::Function *item; std::pair impl_item; HIR::TraitItemFunc *trait_item; Item (HIR::Function *item); Item (HIR::ImplBlock *impl_block, HIR::Function *item); Item (HIR::TraitItemFunc *trait_item); }; ItemType type; Item item; }; class TypeCheckContext { public: static TypeCheckContext *get (); ~TypeCheckContext (); bool lookup_builtin (NodeId id, TyTy::BaseType **type); bool lookup_builtin (std::string name, TyTy::BaseType **type); void insert_builtin (HirId id, NodeId ref, TyTy::BaseType *type); void insert_type (const Analysis::NodeMapping &mappings, TyTy::BaseType *type); void insert_implicit_type (TyTy::BaseType *type); bool lookup_type (HirId id, TyTy::BaseType **type) const; void insert_implicit_type (HirId id, TyTy::BaseType *type); void insert_type_by_node_id (NodeId ref, HirId id); bool lookup_type_by_node_id (NodeId ref, HirId *id); TyTy::BaseType *peek_return_type (); TypeCheckContextItem &peek_context (); void push_return_type (TypeCheckContextItem item, TyTy::BaseType *return_type); void pop_return_type (); void iterate (std::function cb); bool have_loop_context () const; void push_new_loop_context (HirId id, Location locus); void push_new_while_loop_context (HirId id); TyTy::BaseType *peek_loop_context (); TyTy::BaseType *pop_loop_context (); void swap_head_loop_context (TyTy::BaseType *val); void insert_trait_reference (DefId id, TraitReference &&ref); bool lookup_trait_reference (DefId id, TraitReference **ref); void insert_receiver (HirId id, TyTy::BaseType *t); bool lookup_receiver (HirId id, TyTy::BaseType **ref); void insert_associated_trait_impl (HirId id, AssociatedImplTrait &&associated); bool lookup_associated_trait_impl (HirId id, AssociatedImplTrait **associated); void insert_associated_type_mapping (HirId id, HirId mapping); void clear_associated_type_mapping (HirId id); // lookup any associated type mappings, the out parameter of mapping is // allowed to be nullptr which allows this interface to do a simple does exist // check bool lookup_associated_type_mapping (HirId id, HirId *mapping); void insert_associated_impl_mapping (HirId trait_id, const TyTy::BaseType *impl_type, HirId impl_id); bool lookup_associated_impl_mapping_for_self (HirId trait_id, const TyTy::BaseType *self, HirId *mapping); void insert_autoderef_mappings (HirId id, std::vector &&adjustments); bool lookup_autoderef_mappings (HirId id, std::vector **adjustments); void insert_cast_autoderef_mappings (HirId id, std::vector &&adjustments); bool lookup_cast_autoderef_mappings (HirId id, std::vector **adjustments); void insert_variant_definition (HirId id, HirId variant); bool lookup_variant_definition (HirId id, HirId *variant); void insert_operator_overload (HirId id, TyTy::FnType *call_site); bool lookup_operator_overload (HirId id, TyTy::FnType **call); void insert_unconstrained_check_marker (HirId id, bool status); bool have_checked_for_unconstrained (HirId id, bool *result); void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate); bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result); void insert_query (HirId id); void query_completed (HirId id); bool query_in_progress (HirId id) const; void insert_trait_query (DefId id); void trait_query_completed (DefId id); bool trait_query_in_progress (DefId id) const; private: TypeCheckContext (); std::map node_id_refs; std::map resolved; std::vector> builtins; std::vector> return_type_stack; std::vector loop_type_stack; std::map trait_context; std::map receiver_context; std::map associated_impl_traits; // trait-id -> list of < self-tyty:impl-id> std::map>> associated_traits_to_impls; std::map associated_type_mappings; // adjustment mappings std::map> autoderef_mappings; std::map> cast_autoderef_mappings; // operator overloads std::map operator_overloads; // variants std::map variants; // unconstrained type-params check std::map unconstrained; // predicates std::map predicates; // query context lookups std::set querys_in_progress; std::set trait_queries_in_progress; }; class TypeResolution { public: static void Resolve (HIR::Crate &crate); }; class TraitQueryGuard { public: TraitQueryGuard (DefId id) : id (id), ctx (*TypeCheckContext::get ()) { ctx.insert_trait_query (id); } ~TraitQueryGuard () { ctx.trait_query_completed (id); } private: DefId id; TypeCheckContext &ctx; }; } // namespace Resolver } // namespace Rust #endif // RUST_HIR_TYPE_CHECK