From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by sourceware.org (Postfix) with ESMTPS id BF277383F0B1 for ; Tue, 31 Jan 2023 13:23:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BF277383F0B1 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com Received: by mail-wm1-x333.google.com with SMTP id k16so10335078wms.2 for ; Tue, 31 Jan 2023 05:23:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=eoIAkFAhCbOaLjYsLLW7SgHd22W8iA8BpYzDbACm0lc=; b=TpRVrjbQ3D4cm1YXMvh/2MjQTcqJuuhCSGTkg7EckuHkAgfThQAgeyvtKVUpva24dl HZHpMSzC3YPvMS2J2n4GXMgn0BJS/9gLtoclZFo71PEVcDYpajmH5ewFyU4wgMPPQCsO Debu8GGUH44EI3xqw+XNpaE3WweOQT6mWyFS54B/oWSXHYxAG9Yo4nXP8jVtjNjJE/pf NwYy2sW7/BsYaebQEjiTejuDVchgJJDZsmoNwomqm/IMa/SdArI/9c0kkcjWxwhpVkhT rMZJcFbEYFfvnXJzFKkpo3xjN17L9iUZVPqs9pOh5y7TfCtVJZCmeyOIOeK9sD9EQgLx SEsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=eoIAkFAhCbOaLjYsLLW7SgHd22W8iA8BpYzDbACm0lc=; b=kEM1De2Y5y7qs9cB3ogUb+2ostqczY5AtU9UACSBtXoDz06BglvI+A3S4N7oe+SAx6 4KrLOxxJkT//HfXFVLSbsYWlSexB23X6I/slQA9n5DGSz1C0NkLPrReHlkJaG/lJuy+I izfKfW9e++NquyOEMAWRwcW/xtyJ8D3jixY2JalD/EV2/zMSxHnZa/dNdln80gtWrJo7 Hfbxz+VGMuROAFvjD56ovKzgUdMBQz9HNDtghtCuXlttn/qZeOsIYLkKo5dzy1Ds43PS h4Fzaee3fdvgT8yPeX9o2+0kAFvYO9ftr6dGPclmwPUZK527ukwg5bR3dfByAqFJOvBI HwTA== X-Gm-Message-State: AO0yUKWJ8PgwsbGlwLooPIzgrssK/ArRi/k4QWf+9xDXANRKg+SxzoMd FXAkNaYRxBy2uIckyQIuA+anBJJAKIYIwXpeSg== X-Google-Smtp-Source: AK7set8Xvx73OtQww8LqvXLfoqkQN3acd7bNgmdmlRnu+5ujWL88l19eyb4CfdLhlUQGhjaDfSDDgA== X-Received: by 2002:a05:600c:4e88:b0:3da:f5d1:c677 with SMTP id f8-20020a05600c4e8800b003daf5d1c677mr3479601wmq.35.1675171424038; Tue, 31 Jan 2023 05:23:44 -0800 (PST) Received: from platypus.lan ([2001:861:5e4c:3bb0:6424:328a:1734:3249]) by smtp.gmail.com with ESMTPSA id v14-20020a1cf70e000000b003db0b0cc2afsm19882480wmh.30.2023.01.31.05.23.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 31 Jan 2023 05:23:43 -0800 (PST) From: Arthur Cohen To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org, Philip Herron Subject: [COMMITTED] gccrs: Refactor TypeResolution to be a simple query based system Date: Tue, 31 Jan 2023 14:27:29 +0100 Message-Id: <20230131132729.664059-1-arthur.cohen@embecosm.com> X-Mailer: git-send-email 2.39.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-15.2 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FILL_THIS_FORM,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Philip Herron This patch refactors the type resolution system to introduce a new interface bool query_type (HirId, TyTy::BaseType** result) This is needed in order to properly support forward declared items. Our name resolution system has two parts: 1. Toplevel scan 2. Item resolution The toplevel scan gathers all the nesseacry 'names' into their respective namespace by doing a full toplevel scan and generate canonical paths for each item. The second pass is responsible for drilling down into each structure or function to resolve each field or variable etc. This means our name resolution system supports forward decalred items but our type resolution system did not. This patch removes the toplevel scan from our type resolution pass which is not able to handle all cases such as a function with return type and the type is decalred after the fact or a type alias to a type declared after the fact. The name resolution mappings are resolved so when errors occured here we got errors such as unable to lookup HirId 1234, which meant yes we have 'resolved' this reference to this HirId but we are unable to find any type information for it. This means we needed a new way to figure out the type in a query based way. This is where the new query_type inferface comes in so when we have an HirId we want to resolve the mappings class allows us to figure out what item this is such as: 1. HIR::Item (normal HIR::Function, Struct, TypeAlias, ...) 2. HIR::ImplItem (function, constant, ... within an impl-block) 3. HIR::ImplBlock (Self type on an impl-block) 4. HIR::ExternalItem (extern-block item) The mappings class allows us to simply lookup these HIR nodes and then call the relevant resolver class to compute the type. This patch does not add support for self-referencial types but is the starting point to be able to support such types. Fixes #1455 gcc/rust/ChangeLog: * Make-lang.in: Remove `rust-hir-typecheck-toplevel` object and add `rust-hir-path-probe` one. * typecheck/rust-hir-dot-operator.cc (MethodResolver::MethodResolver): Remove no longer used `context` and `mapping` fields, and use new `query_type` API. (MethodResolver::MethodResolver): Likewise. (MethodResolver::select): Use new `query_type` API. * typecheck/rust-hir-path-probe.h: New header. * typecheck/rust-hir-path-probe.cc: New file. * typecheck/rust-hir-dot-operator.h (class MethodResolver): Remove no longer used `context` and `mapping` fields, and use new `query_type` API. * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::query_type): New function. * typecheck/rust-hir-type-check-base.h: Declare `query_type` function. * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Add debug print. * typecheck/rust-hir-type-check-implitem.cc (TypeCheckTopLevelExternItem::Resolve): Refactor and make use of new query system. (TypeCheckTopLevelExternItem::Resolve): Likewise. (TypeCheckTopLevelExternItem::visit): Likewise. (TypeCheckTopLevelImplItem::visit): Likewise. (TypeCheckImplItem::visit): Likewise. (TypeCheckImplItem::TypeCheckImplItem): Likewise. (TypeCheckImplItem::Resolve): Likewise. (TypeCheckImplItemWithTrait::visit): Likewise. * typecheck/rust-hir-type-check-implitem.h (class TypeCheckTopLevelImplItem): Likewise. (class TypeCheckImplItemWithTrait): Likewise. * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::TypeCheckItem): Likewise. (TypeCheckItem::Resolve): Likewise. (TypeCheckItem::ResolveImplItem): Likewise. (TypeCheckItem::ResolveImplBlockSelf): Likewise. (TypeCheckItem::visit): Likewise. (TypeCheckItem::resolve_impl_item): Likewise. (TypeCheckItem::resolve_impl_block_substitutions): Likewise. (TypeCheckItem::resolve_impl_block_self): Likewise. * typecheck/rust-hir-type-check-item.h: Likewise. * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_root_path): Likewise. (TypeCheckExpr::resolve_segments): Likewise. * typecheck/rust-hir-type-check-stmt.cc (TypeCheckStmt::visit): Likewise. * typecheck/rust-hir-type-check-stmt.h: Likewise. * typecheck/rust-hir-type-check-type.cc (TypeCheckType::Resolve): Likewise. (TypeCheckType::visit): Likewise. (TypeCheckType::resolve_root_path): Likewise. * typecheck/rust-hir-type-check.cc (TypeResolution::Resolve): Likewise. * typecheck/rust-hir-type-check.h: Likewise. * typecheck/rust-substitution-mapper.h: Likewise. * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::scan): Likewise. (TypeCheckBase::get_predicate_from_bound): Likewise. (TypeBoundsMappings::add_bound): Likewise. * typecheck/rust-tyty-cmp.h: Likewise. * typecheck/rust-tyty.h: Likewise. * typecheck/rust-tyty.cc (SubstitutionRef::infer_substitions): Likewise. (ParamType::resolve): Do not infinite loop anymore. * util/rust-hir-map.h: Add new `hirImplBlockTypeMappings` and declare `lookup_impl_block_type`. * util/rust-hir-map.cc (Mappings::insert_hir_impl_block): Use new `hirImplBlockTypeMappings` (Mappings::lookup_impl_block_type): New function. gcc/testsuite/ChangeLog: * rust/compile/const_generics_5.rs: Fix assertions. * rust/compile/unconstrained_type_param.rs: Add more assertions. Tested on x86_64-pc-linux-gnu, committed on master. --- gcc/rust/Make-lang.in | 2 +- gcc/rust/typecheck/rust-hir-dot-operator.cc | 8 +- gcc/rust/typecheck/rust-hir-dot-operator.h | 6 +- gcc/rust/typecheck/rust-hir-path-probe.cc | 46 ++ gcc/rust/typecheck/rust-hir-path-probe.h | 24 +- .../typecheck/rust-hir-type-check-base.cc | 76 +++ gcc/rust/typecheck/rust-hir-type-check-base.h | 2 + .../typecheck/rust-hir-type-check-expr.cc | 3 + .../typecheck/rust-hir-type-check-implitem.cc | 181 +++--- .../typecheck/rust-hir-type-check-implitem.h | 42 +- .../typecheck/rust-hir-type-check-item.cc | 554 +++++++++++++++--- gcc/rust/typecheck/rust-hir-type-check-item.h | 47 +- .../typecheck/rust-hir-type-check-path.cc | 4 +- .../typecheck/rust-hir-type-check-stmt.cc | 387 ++---------- gcc/rust/typecheck/rust-hir-type-check-stmt.h | 62 +- .../typecheck/rust-hir-type-check-type.cc | 110 ++-- gcc/rust/typecheck/rust-hir-type-check.cc | 9 +- gcc/rust/typecheck/rust-hir-type-check.h | 41 ++ gcc/rust/typecheck/rust-substitution-mapper.h | 2 +- gcc/rust/typecheck/rust-tyty-bounds.cc | 24 +- gcc/rust/typecheck/rust-tyty-cmp.h | 2 + gcc/rust/typecheck/rust-tyty.cc | 45 +- gcc/rust/typecheck/rust-tyty.h | 34 +- gcc/rust/util/rust-hir-map.cc | 13 + gcc/rust/util/rust-hir-map.h | 2 + .../rust/compile/const_generics_5.rs | 13 +- .../rust/compile/unconstrained_type_param.rs | 2 + 27 files changed, 952 insertions(+), 789 deletions(-) create mode 100644 gcc/rust/typecheck/rust-hir-path-probe.cc diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index f73ada4c8ac..7dad27a5dcd 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -116,7 +116,6 @@ GRS_OBJS = \ rust/rust-tyty-bounds.o \ rust/rust-hir-type-check-util.o \ rust/rust-hir-trait-resolve.o \ - rust/rust-hir-type-check-toplevel.o \ rust/rust-hir-type-check-item.o \ rust/rust-hir-type-check-type.o \ rust/rust-hir-type-check-struct.o \ @@ -126,6 +125,7 @@ GRS_OBJS = \ rust/rust-hir-type-check-enumitem.o \ rust/rust-hir-type-check-implitem.o \ rust/rust-hir-dot-operator.o \ + rust/rust-hir-path-probe.o \ rust/rust-coercion.o \ rust/rust-casts.o \ rust/rust-hir-type-check-base.o \ diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc index 985e61b83f0..ed2df11da45 100644 --- a/gcc/rust/typecheck/rust-hir-dot-operator.cc +++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc @@ -25,8 +25,7 @@ namespace Resolver { MethodResolver::MethodResolver (bool autoderef_flag, const HIR::PathIdentSegment &segment_name) - : AutoderefCycle (autoderef_flag), mappings (Analysis::Mappings::get ()), - context (TypeCheckContext::get ()), segment_name (segment_name), + : AutoderefCycle (autoderef_flag), segment_name (segment_name), try_result (MethodCandidate::get_error ()) {} @@ -80,8 +79,9 @@ MethodResolver::select (const TyTy::BaseType &receiver) return true; TyTy::BaseType *ty = nullptr; - if (!context->lookup_type (func->get_mappings ().get_hirid (), &ty)) + if (!query_type (func->get_mappings ().get_hirid (), &ty)) return true; + rust_assert (ty != nullptr); if (ty->get_kind () == TyTy::TypeKind::ERROR) return true; @@ -127,7 +127,7 @@ MethodResolver::select (const TyTy::BaseType &receiver) continue; TyTy::BaseType *ty = nullptr; - if (!context->lookup_type (func->get_mappings ().get_hirid (), &ty)) + if (!query_type (func->get_mappings ().get_hirid (), &ty)) continue; if (ty->get_kind () == TyTy::TypeKind::ERROR) continue; diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h index 8bb49f6da74..8341173a061 100644 --- a/gcc/rust/typecheck/rust-hir-dot-operator.h +++ b/gcc/rust/typecheck/rust-hir-dot-operator.h @@ -37,7 +37,7 @@ struct MethodCandidate bool is_error () const { return candidate.is_error (); } }; -class MethodResolver : protected AutoderefCycle +class MethodResolver : private TypeCheckBase, protected AutoderefCycle { public: struct predicate_candidate @@ -63,10 +63,6 @@ protected: bool select (const TyTy::BaseType &receiver) override; private: - // context info - Analysis::Mappings *mappings; - TypeCheckContext *context; - // search const HIR::PathIdentSegment &segment_name; std::vector predicate_items; diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc new file mode 100644 index 00000000000..cb3270d3623 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-path-probe.cc @@ -0,0 +1,46 @@ +// 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 +// . + +#include "rust-hir-path-probe.h" +#include "rust-hir-type-check-item.h" + +namespace Rust { +namespace Resolver { + +void +PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item, + HIR::ImplBlock *impl) +{ + current_impl = impl; + HirId impl_ty_id = impl->get_type ()->get_mappings ().get_hirid (); + TyTy::BaseType *impl_block_ty = nullptr; + if (!query_type (impl_ty_id, &impl_block_ty)) + return; + + if (!receiver->can_eq (impl_block_ty, false)) + { + if (!impl_block_ty->can_eq (receiver, false)) + return; + } + + // lets visit the impl_item + item->accept_vis (*this); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h index 5e85f4e2a16..c957487dd2a 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -195,7 +195,7 @@ public: { HirId tyid = alias.get_mappings ().get_hirid (); TyTy::BaseType *ty = nullptr; - bool ok = context->lookup_type (tyid, &ty); + bool ok = query_type (tyid, &ty); rust_assert (ok); PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias, @@ -214,7 +214,7 @@ public: { HirId tyid = constant.get_mappings ().get_hirid (); TyTy::BaseType *ty = nullptr; - bool ok = context->lookup_type (tyid, &ty); + bool ok = query_type (tyid, &ty); rust_assert (ok); PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant, @@ -233,7 +233,7 @@ public: { HirId tyid = function.get_mappings ().get_hirid (); TyTy::BaseType *ty = nullptr; - bool ok = context->lookup_type (tyid, &ty); + bool ok = query_type (tyid, &ty); rust_assert (ok); PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function, @@ -272,23 +272,7 @@ protected: } void process_impl_item_candidate (HirId id, HIR::ImplItem *item, - HIR::ImplBlock *impl) - { - current_impl = impl; - HirId impl_ty_id = impl->get_type ()->get_mappings ().get_hirid (); - TyTy::BaseType *impl_block_ty = nullptr; - if (!context->lookup_type (impl_ty_id, &impl_block_ty)) - return; - - if (!receiver->can_eq (impl_block_ty, false)) - { - if (!impl_block_ty->can_eq (receiver, false)) - return; - } - - // lets visit the impl_item - item->accept_vis (*this); - } + HIR::ImplBlock *impl); void process_associated_trait_for_candidates (const TraitReference *trait_ref, diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index d5121e7a7bc..cf496d3eb19 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -17,8 +17,10 @@ // . #include "rust-hir-type-check-base.h" +#include "rust-hir-type-check-item.h" #include "rust-hir-type-check-type.h" #include "rust-hir-type-check-expr.h" +#include "rust-hir-type-check-implitem.h" #include "rust-coercion.h" #include "rust-casts.h" @@ -37,6 +39,13 @@ TypeCheckBase::check_for_unconstrained ( const TyTy::SubstitutionArgumentMappings &constraint_b, const TyTy::BaseType *reference) { + bool check_result = false; + bool check_completed + = context->have_checked_for_unconstrained (reference->get_ref (), + &check_result); + if (check_completed) + return check_result; + std::set symbols_to_constrain; std::map symbol_to_location; for (const auto &p : params_to_constrain) @@ -86,6 +95,10 @@ TypeCheckBase::check_for_unconstrained ( unconstrained = true; } } + + context->insert_unconstrained_check_marker (reference->get_ref (), + unconstrained); + return unconstrained; } @@ -479,5 +492,68 @@ TypeCheckBase::resolve_generic_params ( } } +bool +TypeCheckBase::query_type (HirId reference, TyTy::BaseType **result) +{ + if (context->lookup_type (reference, result)) + return true; + + HIR::Item *item = mappings->lookup_hir_item (reference); + if (item != nullptr) + { + rust_debug_loc (item->get_locus (), "resolved item {%u} to", reference); + *result = TypeCheckItem::Resolve (*item); + return true; + } + + HirId parent_impl_id = UNKNOWN_HIRID; + HIR::ImplItem *impl_item + = mappings->lookup_hir_implitem (reference, &parent_impl_id); + if (impl_item != nullptr) + { + HIR::ImplBlock *impl_block + = mappings->lookup_hir_impl_block (parent_impl_id); + rust_assert (impl_block != nullptr); + + // found an impl item + rust_debug_loc (impl_item->get_locus (), "resolved impl-item {%u} to", + reference); + + *result = TypeCheckItem::ResolveImplItem (*impl_block, *impl_item); + return true; + } + + // is it an impl_type? + HIR::ImplBlock *impl_block_by_type = nullptr; + bool found_impl_block_type + = mappings->lookup_impl_block_type (reference, &impl_block_by_type); + if (found_impl_block_type) + { + *result = TypeCheckItem::ResolveImplBlockSelf (*impl_block_by_type); + return true; + } + + // is it an extern item? + HirId parent_extern_block_id = UNKNOWN_HIRID; + HIR::ExternalItem *extern_item + = mappings->lookup_hir_extern_item (reference, &parent_extern_block_id); + if (extern_item != nullptr) + { + HIR::ExternBlock *block + = mappings->lookup_hir_extern_block (parent_extern_block_id); + rust_assert (block != nullptr); + + *result = TypeCheckTopLevelExternItem::Resolve (extern_item, *block); + return true; + } + + // more? + Location possible_locus = mappings->lookup_location (reference); + rust_debug_loc (possible_locus, "query system failed to resolve: [%u]", + reference); + + return false; +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h index b8ff2cf6dc9..335014339f3 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.h +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -69,6 +69,8 @@ protected: const std::vector> &generic_params, std::vector &substitutions); + bool query_type (HirId reference, TyTy::BaseType **result); + Analysis::Mappings *mappings; Resolver *resolver; TypeCheckContext *context; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index bea5eb8cb0b..2f22c82f063 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -188,6 +188,9 @@ TypeCheckExpr::visit (HIR::CallExpr &expr) return; } + rust_debug_loc (expr.get_locus (), "resolved_call_expr to: {%s}", + function_tyty->get_name ().c_str ()); + TyTy::VariantDef &variant = TyTy::VariantDef::get_error_node (); if (function_tyty->get_kind () == TyTy::TypeKind::ADT) { diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc index f1f56d28ae2..e29b8d776b2 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc @@ -32,12 +32,21 @@ TypeCheckTopLevelExternItem::TypeCheckTopLevelExternItem ( : TypeCheckBase (), parent (parent) {} -void +TyTy::BaseType * TypeCheckTopLevelExternItem::Resolve (HIR::ExternalItem *item, const HIR::ExternBlock &parent) { + // is it already resolved? + auto context = TypeCheckContext::get (); + TyTy::BaseType *resolved = nullptr; + bool already_resolved + = context->lookup_type (item->get_mappings ().get_hirid (), &resolved); + if (already_resolved) + return resolved; + TypeCheckTopLevelExternItem resolver (parent); item->accept_vis (resolver); + return resolver.resolved; } void @@ -47,6 +56,7 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalStaticItem &item) = TypeCheckType::Resolve (item.get_item_type ().get ()); context->insert_type (item.get_mappings (), actual_type); + resolved = actual_type; } void @@ -142,79 +152,40 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function) ret_type, std::move (substitutions)); context->insert_type (function.get_mappings (), fnType); + resolved = fnType; } -TypeCheckTopLevelImplItem::TypeCheckTopLevelImplItem ( - TyTy::BaseType *self, +TypeCheckImplItem::TypeCheckImplItem ( + HIR::ImplBlock *parent, TyTy::BaseType *self, std::vector substitutions) - : TypeCheckBase (), self (self), substitutions (substitutions) + : TypeCheckBase (), parent (parent), self (self), + substitutions (substitutions) {} -void -TypeCheckTopLevelImplItem::Resolve ( - HIR::ImplItem *item, TyTy::BaseType *self, +TyTy::BaseType * +TypeCheckImplItem::Resolve ( + HIR::ImplBlock *parent, HIR::ImplItem *item, TyTy::BaseType *self, std::vector substitutions) { - TypeCheckTopLevelImplItem resolver (self, substitutions); + // is it already resolved? + auto context = TypeCheckContext::get (); + TyTy::BaseType *resolved = nullptr; + bool already_resolved + = context->lookup_type (item->get_impl_mappings ().get_hirid (), &resolved); + if (already_resolved) + return resolved; + + // resolve + TypeCheckImplItem resolver (parent, self, substitutions); item->accept_vis (resolver); + return resolver.result; } void -TypeCheckTopLevelImplItem::visit (HIR::TypeAlias &alias) -{ - TyTy::BaseType *actual_type - = TypeCheckType::Resolve (alias.get_type_aliased ().get ()); - - context->insert_type (alias.get_mappings (), actual_type); - - for (auto &where_clause_item : alias.get_where_clause ().get_items ()) - { - ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); - } -} - -void -TypeCheckTopLevelImplItem::visit (HIR::ConstantItem &constant) -{ - TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ()); - TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); - - TyTy::BaseType *unified = unify_site ( - constant.get_mappings ().get_hirid (), - TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()), - TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()), - constant.get_locus ()); - context->insert_type (constant.get_mappings (), unified); -} - -void -TypeCheckTopLevelImplItem::visit (HIR::Function &function) +TypeCheckImplItem::visit (HIR::Function &function) { if (function.has_generics ()) - { - for (auto &generic_param : function.get_generic_params ()) - { - switch (generic_param.get ()->get_kind ()) - { - case HIR::GenericParam::GenericKind::LIFETIME: - case HIR::GenericParam::GenericKind::CONST: - // FIXME: Skipping Lifetime and Const completely until better - // handling. - break; - - case HIR::GenericParam::GenericKind::TYPE: { - auto param_type - = TypeResolveGenericParam::Resolve (generic_param.get ()); - context->insert_type (generic_param->get_mappings (), - param_type); - - substitutions.push_back (TyTy::SubstitutionParamMapping ( - static_cast (*generic_param), param_type)); - } - break; - } - } - } + resolve_generic_params (function.get_generic_params (), substitutions); for (auto &where_clause_item : function.get_where_clause ().get_items ()) { @@ -328,41 +299,10 @@ TypeCheckTopLevelImplItem::visit (HIR::Function &function) std::move (substitutions)); context->insert_type (function.get_mappings (), fnType); -} - -TypeCheckImplItem::TypeCheckImplItem (HIR::ImplBlock *parent, - TyTy::BaseType *self) - : TypeCheckBase (), parent (parent), self (self) -{} - -void -TypeCheckImplItem::Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item, - TyTy::BaseType *self) -{ - TypeCheckImplItem resolver (parent, self); - item->accept_vis (resolver); -} - -void -TypeCheckImplItem::visit (HIR::Function &function) -{ - TyTy::BaseType *lookup; - if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup)) - { - rust_error_at (function.get_locus (), "failed to lookup function type"); - return; - } - - if (lookup->get_kind () != TyTy::TypeKind::FNDEF) - { - rust_error_at (function.get_locus (), - "found invalid type for function [%s]", - lookup->as_string ().c_str ()); - return; - } + result = fnType; // need to get the return type from this - TyTy::FnType *resolve_fn_type = static_cast (lookup); + TyTy::FnType *resolve_fn_type = fnType; auto expected_ret_tyty = resolve_fn_type->get_return_type (); context->push_return_type (TypeCheckContextItem (parent, &function), expected_ret_tyty); @@ -383,20 +323,41 @@ TypeCheckImplItem::visit (HIR::Function &function) } void -TypeCheckImplItem::visit (HIR::ConstantItem &const_item) -{} +TypeCheckImplItem::visit (HIR::ConstantItem &constant) +{ + TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ()); + TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); + + TyTy::BaseType *unified = unify_site ( + constant.get_mappings ().get_hirid (), + TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()), + TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()), + constant.get_locus ()); + context->insert_type (constant.get_mappings (), unified); + result = unified; +} void -TypeCheckImplItem::visit (HIR::TypeAlias &type_alias) -{} +TypeCheckImplItem::visit (HIR::TypeAlias &alias) +{ + TyTy::BaseType *actual_type + = TypeCheckType::Resolve (alias.get_type_aliased ().get ()); + + context->insert_type (alias.get_mappings (), actual_type); + result = actual_type; + for (auto &where_clause_item : alias.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } +} TypeCheckImplItemWithTrait::TypeCheckImplItemWithTrait ( HIR::ImplBlock *parent, TyTy::BaseType *self, TyTy::TypeBoundPredicate &trait_reference, std::vector substitutions) - : TypeCheckImplItem (parent, self), trait_reference (trait_reference), + : TypeCheckBase (), trait_reference (trait_reference), resolved_trait_item (TyTy::TypeBoundPredicateItem::error ()), - substitutions (substitutions) + parent (parent), self (self), substitutions (substitutions) { rust_assert (is_trait_impl_block ()); } @@ -417,10 +378,8 @@ void TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant) { // normal resolution of the item - TypeCheckImplItem::visit (constant); - TyTy::BaseType *lookup; - if (!context->lookup_type (constant.get_mappings ().get_hirid (), &lookup)) - return; + TyTy::BaseType *lookup + = TypeCheckImplItem::Resolve (parent, &constant, self, substitutions); // map the impl item to the associated trait item const auto tref = trait_reference.get (); @@ -468,10 +427,8 @@ void TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type) { // normal resolution of the item - TypeCheckImplItem::visit (type); - TyTy::BaseType *lookup; - if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup)) - return; + TyTy::BaseType *lookup + = TypeCheckImplItem::Resolve (parent, &type, self, substitutions); // map the impl item to the associated trait item const auto tref = trait_reference.get (); @@ -528,11 +485,9 @@ TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type) void TypeCheckImplItemWithTrait::visit (HIR::Function &function) { - // we get the error checking from the base method here - TypeCheckImplItem::visit (function); - TyTy::BaseType *lookup; - if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup)) - return; + // normal resolution of the item + TyTy::BaseType *lookup + = TypeCheckImplItem::Resolve (parent, &function, self, substitutions); // map the impl item to the associated trait item const auto tref = trait_reference.get (); diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index 768588d2671..0e5f16d6762 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -28,7 +28,8 @@ class TypeCheckTopLevelExternItem : public TypeCheckBase, public HIR::HIRExternalItemVisitor { public: - static void Resolve (HIR::ExternalItem *item, const HIR::ExternBlock &parent); + static TyTy::BaseType *Resolve (HIR::ExternalItem *item, + const HIR::ExternBlock &parent); void visit (HIR::ExternalStaticItem &item) override; void visit (HIR::ExternalFunctionItem &function) override; @@ -37,47 +38,33 @@ private: TypeCheckTopLevelExternItem (const HIR::ExternBlock &parent); const HIR::ExternBlock &parent; -}; - -class TypeCheckTopLevelImplItem : public TypeCheckBase, - public HIR::HIRImplVisitor -{ -public: - static void - Resolve (HIR::ImplItem *item, TyTy::BaseType *self, - std::vector substitutions); - - void visit (HIR::TypeAlias &alias) override; - void visit (HIR::ConstantItem &constant) override; - void visit (HIR::Function &function) override; - -private: - TypeCheckTopLevelImplItem ( - TyTy::BaseType *self, - std::vector substitutions); - - TyTy::BaseType *self; - std::vector substitutions; + TyTy::BaseType *resolved; }; class TypeCheckImplItem : public TypeCheckBase, public HIR::HIRImplVisitor { public: - static void Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item, - TyTy::BaseType *self); + static TyTy::BaseType * + Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item, TyTy::BaseType *self, + std::vector substitutions); void visit (HIR::Function &function) override; void visit (HIR::ConstantItem &const_item) override; void visit (HIR::TypeAlias &type_alias) override; protected: - TypeCheckImplItem (HIR::ImplBlock *parent, TyTy::BaseType *self); + TypeCheckImplItem (HIR::ImplBlock *parent, TyTy::BaseType *self, + std::vector substitutions); HIR::ImplBlock *parent; TyTy::BaseType *self; + std::vector substitutions; + + TyTy::BaseType *result; }; -class TypeCheckImplItemWithTrait : public TypeCheckImplItem +class TypeCheckImplItemWithTrait : public TypeCheckBase, + public HIR::HIRImplVisitor { public: static TyTy::TypeBoundPredicateItem @@ -105,6 +92,9 @@ private: TyTy::TypeBoundPredicate &trait_reference; TyTy::TypeBoundPredicateItem resolved_trait_item; + + HIR::ImplBlock *parent; + TyTy::BaseType *self; std::vector substitutions; }; diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 0aa26072efc..e39dd537d6e 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -16,59 +16,466 @@ // along with GCC; see the file COPYING3. If not see // . -#include "rust-hir-type-check-item.h" #include "rust-hir-full.h" +#include "rust-hir-type-check-item.h" +#include "rust-hir-type-check-enumitem.h" #include "rust-hir-type-check-implitem.h" #include "rust-hir-type-check-type.h" #include "rust-hir-type-check-stmt.h" #include "rust-hir-type-check-expr.h" +#include "rust-hir-type-check-pattern.h" #include "rust-hir-trait-resolve.h" namespace Rust { namespace Resolver { -TypeCheckItem::TypeCheckItem () : TypeCheckBase () {} +TypeCheckItem::TypeCheckItem () : TypeCheckBase (), infered (nullptr) {} -void +TyTy::BaseType * TypeCheckItem::Resolve (HIR::Item &item) { + // is it already resolved? + auto context = TypeCheckContext::get (); + TyTy::BaseType *resolved = nullptr; + bool already_resolved + = context->lookup_type (item.get_mappings ().get_hirid (), &resolved); + if (already_resolved) + return resolved; + rust_assert (item.get_hir_kind () == HIR::Node::BaseKind::VIS_ITEM); HIR::VisItem &vis_item = static_cast (item); TypeCheckItem resolver; vis_item.accept_vis (resolver); + return resolver.infered; +} + +TyTy::BaseType * +TypeCheckItem::ResolveImplItem (HIR::ImplBlock &impl_block, HIR::ImplItem &item) +{ + TypeCheckItem resolver; + return resolver.resolve_impl_item (impl_block, item); +} + +TyTy::BaseType * +TypeCheckItem::ResolveImplBlockSelf (HIR::ImplBlock &impl_block) +{ + TypeCheckItem resolver; + + bool failed_flag = false; + std::vector substitutions + = resolver.resolve_impl_block_substitutions (impl_block, failed_flag); + if (failed_flag) + { + return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ()); + } + + return resolver.resolve_impl_block_self (impl_block); +} + +void +TypeCheckItem::visit (HIR::TypeAlias &alias) +{ + TyTy::BaseType *actual_type + = TypeCheckType::Resolve (alias.get_type_aliased ().get ()); + + context->insert_type (alias.get_mappings (), actual_type); + + for (auto &where_clause_item : alias.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + infered = actual_type; +} + +void +TypeCheckItem::visit (HIR::TupleStruct &struct_decl) +{ + std::vector substitutions; + if (struct_decl.has_generics ()) + resolve_generic_params (struct_decl.get_generic_params (), substitutions); + + for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + + std::vector fields; + size_t idx = 0; + for (auto &field : struct_decl.get_fields ()) + { + TyTy::BaseType *field_type + = TypeCheckType::Resolve (field.get_field_type ().get ()); + TyTy::StructFieldType *ty_field + = new TyTy::StructFieldType (field.get_mappings ().get_hirid (), + std::to_string (idx), field_type, + field.get_locus ()); + fields.push_back (ty_field); + context->insert_type (field.get_mappings (), ty_field->get_field_type ()); + idx++; + } + + // get the path + const CanonicalPath *canonical_path = nullptr; + bool ok = mappings->lookup_canonical_path ( + struct_decl.get_mappings ().get_nodeid (), &canonical_path); + rust_assert (ok); + RustIdent ident{*canonical_path, struct_decl.get_locus ()}; + + // its a single variant ADT + std::vector variants; + variants.push_back (new TyTy::VariantDef ( + struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (), + ident, TyTy::VariantDef::VariantType::TUPLE, nullptr, std::move (fields))); + + // Process #[repr(X)] attribute, if any + const AST::AttrVec &attrs = struct_decl.get_outer_attrs (); + TyTy::ADTType::ReprOptions repr + = parse_repr_options (attrs, struct_decl.get_locus ()); + + TyTy::BaseType *type + = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), + mappings->get_next_hir_id (), + struct_decl.get_identifier (), ident, + TyTy::ADTType::ADTKind::TUPLE_STRUCT, + std::move (variants), std::move (substitutions), repr); + + context->insert_type (struct_decl.get_mappings (), type); + infered = type; +} + +void +TypeCheckItem::visit (HIR::StructStruct &struct_decl) +{ + std::vector substitutions; + if (struct_decl.has_generics ()) + resolve_generic_params (struct_decl.get_generic_params (), substitutions); + + for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + + std::vector fields; + for (auto &field : struct_decl.get_fields ()) + { + TyTy::BaseType *field_type + = TypeCheckType::Resolve (field.get_field_type ().get ()); + TyTy::StructFieldType *ty_field + = new TyTy::StructFieldType (field.get_mappings ().get_hirid (), + field.get_field_name (), field_type, + field.get_locus ()); + fields.push_back (ty_field); + context->insert_type (field.get_mappings (), ty_field->get_field_type ()); + } + + // get the path + const CanonicalPath *canonical_path = nullptr; + bool ok = mappings->lookup_canonical_path ( + struct_decl.get_mappings ().get_nodeid (), &canonical_path); + rust_assert (ok); + RustIdent ident{*canonical_path, struct_decl.get_locus ()}; + + // its a single variant ADT + std::vector variants; + variants.push_back (new TyTy::VariantDef ( + struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (), + ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields))); + + // Process #[repr(X)] attribute, if any + const AST::AttrVec &attrs = struct_decl.get_outer_attrs (); + TyTy::ADTType::ReprOptions repr + = parse_repr_options (attrs, struct_decl.get_locus ()); + + TyTy::BaseType *type + = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), + mappings->get_next_hir_id (), + struct_decl.get_identifier (), ident, + TyTy::ADTType::ADTKind::STRUCT_STRUCT, + std::move (variants), std::move (substitutions), repr); + + context->insert_type (struct_decl.get_mappings (), type); + infered = type; +} + +void +TypeCheckItem::visit (HIR::Enum &enum_decl) +{ + std::vector substitutions; + if (enum_decl.has_generics ()) + resolve_generic_params (enum_decl.get_generic_params (), substitutions); + + std::vector variants; + int64_t discriminant_value = 0; + for (auto &variant : enum_decl.get_variants ()) + { + TyTy::VariantDef *field_type + = TypeCheckEnumItem::Resolve (variant.get (), discriminant_value); + + discriminant_value++; + variants.push_back (field_type); + } + + // get the path + const CanonicalPath *canonical_path = nullptr; + bool ok + = mappings->lookup_canonical_path (enum_decl.get_mappings ().get_nodeid (), + &canonical_path); + rust_assert (ok); + RustIdent ident{*canonical_path, enum_decl.get_locus ()}; + + // multi variant ADT + TyTy::BaseType *type + = new TyTy::ADTType (enum_decl.get_mappings ().get_hirid (), + mappings->get_next_hir_id (), + enum_decl.get_identifier (), ident, + TyTy::ADTType::ADTKind::ENUM, std::move (variants), + std::move (substitutions)); + + context->insert_type (enum_decl.get_mappings (), type); + infered = type; +} + +void +TypeCheckItem::visit (HIR::Union &union_decl) +{ + std::vector substitutions; + if (union_decl.has_generics ()) + resolve_generic_params (union_decl.get_generic_params (), substitutions); + + for (auto &where_clause_item : union_decl.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + + std::vector fields; + for (auto &variant : union_decl.get_variants ()) + { + TyTy::BaseType *variant_type + = TypeCheckType::Resolve (variant.get_field_type ().get ()); + TyTy::StructFieldType *ty_variant + = new TyTy::StructFieldType (variant.get_mappings ().get_hirid (), + variant.get_field_name (), variant_type, + variant.get_locus ()); + fields.push_back (ty_variant); + context->insert_type (variant.get_mappings (), + ty_variant->get_field_type ()); + } + + // get the path + const CanonicalPath *canonical_path = nullptr; + bool ok + = mappings->lookup_canonical_path (union_decl.get_mappings ().get_nodeid (), + &canonical_path); + rust_assert (ok); + RustIdent ident{*canonical_path, union_decl.get_locus ()}; + + // there is only a single variant + std::vector variants; + variants.push_back (new TyTy::VariantDef ( + union_decl.get_mappings ().get_hirid (), union_decl.get_identifier (), + ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields))); + + TyTy::BaseType *type + = new TyTy::ADTType (union_decl.get_mappings ().get_hirid (), + mappings->get_next_hir_id (), + union_decl.get_identifier (), ident, + TyTy::ADTType::ADTKind::UNION, std::move (variants), + std::move (substitutions)); + + context->insert_type (union_decl.get_mappings (), type); + infered = type; +} + +void +TypeCheckItem::visit (HIR::StaticItem &var) +{ + TyTy::BaseType *type = TypeCheckType::Resolve (var.get_type ()); + TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (var.get_expr ()); + + TyTy::BaseType *unified + = coercion_site (var.get_mappings ().get_hirid (), + TyTy::TyWithLocation (type, var.get_type ()->get_locus ()), + TyTy::TyWithLocation (expr_type, + var.get_expr ()->get_locus ()), + var.get_locus ()); + context->insert_type (var.get_mappings (), unified); + infered = unified; +} + +void +TypeCheckItem::visit (HIR::ConstantItem &constant) +{ + TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ()); + TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); + + TyTy::BaseType *unified = unify_site ( + constant.get_mappings ().get_hirid (), + TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()), + TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()), + constant.get_locus ()); + context->insert_type (constant.get_mappings (), unified); + infered = unified; } void TypeCheckItem::visit (HIR::ImplBlock &impl_block) +{ + bool failed_flag = false; + std::vector substitutions + = resolve_impl_block_substitutions (impl_block, failed_flag); + if (failed_flag) + { + infered = new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ()); + return; + } + + TyTy::BaseType *self = resolve_impl_block_self (impl_block); + + // resolve each impl_item + for (auto &impl_item : impl_block.get_impl_items ()) + { + TypeCheckImplItem::Resolve (&impl_block, impl_item.get (), self, + substitutions); + } + + // validate the impl items + validate_trait_impl_block (impl_block, self, substitutions); +} + +TyTy::BaseType * +TypeCheckItem::resolve_impl_item (HIR::ImplBlock &impl_block, + HIR::ImplItem &item) +{ + bool failed_flag = false; + std::vector substitutions + = resolve_impl_block_substitutions (impl_block, failed_flag); + if (failed_flag) + { + return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ()); + } + + TyTy::BaseType *self = resolve_impl_block_self (impl_block); + + return TypeCheckImplItem::Resolve (&impl_block, &item, self, substitutions); +} + +void +TypeCheckItem::visit (HIR::Function &function) { std::vector substitutions; - if (impl_block.has_generics ()) + if (function.has_generics ()) + resolve_generic_params (function.get_generic_params (), substitutions); + + for (auto &where_clause_item : function.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); + } + + TyTy::BaseType *ret_type = nullptr; + if (!function.has_function_return_type ()) + ret_type + = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid ()); + else { - for (auto &generic_param : impl_block.get_generic_params ()) + auto resolved + = TypeCheckType::Resolve (function.get_return_type ().get ()); + if (resolved->get_kind () == TyTy::TypeKind::ERROR) { - switch (generic_param.get ()->get_kind ()) - { - case HIR::GenericParam::GenericKind::LIFETIME: - case HIR::GenericParam::GenericKind::CONST: - // FIXME: Skipping Lifetime and Const completely until better - // handling. - break; - - case HIR::GenericParam::GenericKind::TYPE: { - TyTy::BaseType *l = nullptr; - bool ok = context->lookup_type ( - generic_param->get_mappings ().get_hirid (), &l); - if (ok && l->get_kind () == TyTy::TypeKind::PARAM) - { - substitutions.push_back (TyTy::SubstitutionParamMapping ( - static_cast (*generic_param), - static_cast (l))); - } - } - break; - } + rust_error_at (function.get_locus (), + "failed to resolve return type"); + return; } + + ret_type = resolved->clone (); + ret_type->set_ref ( + function.get_return_type ()->get_mappings ().get_hirid ()); + } + + std::vector> params; + for (auto ¶m : function.get_function_params ()) + { + // get the name as well required for later on + auto param_tyty = TypeCheckType::Resolve (param.get_type ()); + params.push_back ( + std::pair (param.get_param_name (), + param_tyty)); + + context->insert_type (param.get_mappings (), param_tyty); + TypeCheckPattern::Resolve (param.get_param_name (), param_tyty); + } + + const CanonicalPath *canonical_path = nullptr; + bool ok + = mappings->lookup_canonical_path (function.get_mappings ().get_nodeid (), + &canonical_path); + rust_assert (ok); + + RustIdent ident{*canonical_path, function.get_locus ()}; + auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (), + function.get_mappings ().get_defid (), + function.get_function_name (), ident, + TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST, + std::move (params), ret_type, + std::move (substitutions)); + + context->insert_type (function.get_mappings (), fnType); + + // need to get the return type from this + TyTy::FnType *resolved_fn_type = fnType; + auto expected_ret_tyty = resolved_fn_type->get_return_type (); + context->push_return_type (TypeCheckContextItem (&function), + expected_ret_tyty); + + auto block_expr_ty + = TypeCheckExpr::Resolve (function.get_definition ().get ()); + + Location fn_return_locus = function.has_function_return_type () + ? function.get_return_type ()->get_locus () + : function.get_locus (); + coercion_site (function.get_definition ()->get_mappings ().get_hirid (), + TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus), + TyTy::TyWithLocation (block_expr_ty), + function.get_definition ()->get_locus ()); + + context->pop_return_type (); + + infered = fnType; +} + +void +TypeCheckItem::visit (HIR::Module &module) +{ + for (auto &item : module.get_items ()) + TypeCheckItem::Resolve (*item.get ()); +} + +void +TypeCheckItem::visit (HIR::Trait &trait) +{ + TraitResolver::Resolve (trait); +} + +void +TypeCheckItem::visit (HIR::ExternBlock &extern_block) +{ + for (auto &item : extern_block.get_extern_items ()) + { + TypeCheckTopLevelExternItem::Resolve (item.get (), extern_block); + } +} + +std::vector +TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block, + bool &failure_flag) +{ + std::vector substitutions; + if (impl_block.has_generics ()) + resolve_generic_params (impl_block.get_generic_params (), substitutions); + + for (auto &where_clause_item : impl_block.get_where_clause ().get_items ()) + { + ResolveWhereClauseItem::Resolve (*where_clause_item.get ()); } auto specified_bound = TyTy::TypeBoundPredicate::error (); @@ -84,14 +491,7 @@ TypeCheckItem::visit (HIR::ImplBlock &impl_block) specified_bound = get_predicate_from_bound (*ref.get ()); } - TyTy::BaseType *self = nullptr; - if (!context->lookup_type ( - impl_block.get_type ()->get_mappings ().get_hirid (), &self)) - { - rust_error_at (impl_block.get_locus (), - "failed to resolve Self for ImplBlock"); - return; - } + TyTy::BaseType *self = TypeCheckType::Resolve (impl_block.get_type ().get ()); // inherit the bounds if (!specified_bound.is_error ()) @@ -103,20 +503,35 @@ TypeCheckItem::visit (HIR::ImplBlock &impl_block) const TyTy::SubstitutionArgumentMappings impl_constraints = GetUsedSubstArgs::From (self); - bool impl_block_has_unconstrained_typarams - = check_for_unconstrained (substitutions, trait_constraints, - impl_constraints, self); - if (impl_block_has_unconstrained_typarams) - return; + failure_flag = check_for_unconstrained (substitutions, trait_constraints, + impl_constraints, self); + + return substitutions; +} + +void +TypeCheckItem::validate_trait_impl_block ( + HIR::ImplBlock &impl_block, TyTy::BaseType *self, + std::vector &substitutions) +{ + auto specified_bound = TyTy::TypeBoundPredicate::error (); + TraitReference *trait_reference = &TraitReference::error_node (); + if (impl_block.has_trait_ref ()) + { + std::unique_ptr &ref = impl_block.get_trait_ref (); + trait_reference = TraitResolver::Resolve (*ref.get ()); + rust_assert (!trait_reference->is_error ()); + + // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs + // for example + specified_bound = get_predicate_from_bound (*ref.get ()); + } - // validate the impl items bool is_trait_impl_block = !trait_reference->is_error (); std::vector trait_item_refs; for (auto &impl_item : impl_block.get_impl_items ()) { - if (!is_trait_impl_block) - TypeCheckImplItem::Resolve (&impl_block, impl_item.get (), self); - else + if (!specified_bound.is_error ()) { auto trait_item_ref = TypeCheckImplItemWithTrait::Resolve (&impl_block, @@ -128,7 +543,7 @@ TypeCheckItem::visit (HIR::ImplBlock &impl_block) } bool impl_block_missing_trait_items - = is_trait_impl_block + = !specified_bound.is_error () && trait_reference->size () != trait_item_refs.size (); if (impl_block_missing_trait_items) { @@ -187,55 +602,10 @@ TypeCheckItem::visit (HIR::ImplBlock &impl_block) } } -void -TypeCheckItem::visit (HIR::Function &function) +TyTy::BaseType * +TypeCheckItem::resolve_impl_block_self (HIR::ImplBlock &impl_block) { - TyTy::BaseType *lookup; - if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup)) - { - rust_error_at (function.get_locus (), "failed to lookup function type"); - return; - } - - if (lookup->get_kind () != TyTy::TypeKind::FNDEF) - { - rust_error_at (function.get_locus (), - "found invalid type for function [%s]", - lookup->as_string ().c_str ()); - return; - } - - // need to get the return type from this - TyTy::FnType *resolved_fn_type = static_cast (lookup); - auto expected_ret_tyty = resolved_fn_type->get_return_type (); - context->push_return_type (TypeCheckContextItem (&function), - expected_ret_tyty); - - auto block_expr_ty - = TypeCheckExpr::Resolve (function.get_definition ().get ()); - - Location fn_return_locus = function.has_function_return_type () - ? function.get_return_type ()->get_locus () - : function.get_locus (); - coercion_site (function.get_definition ()->get_mappings ().get_hirid (), - TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus), - TyTy::TyWithLocation (block_expr_ty), - function.get_definition ()->get_locus ()); - - context->pop_return_type (); -} - -void -TypeCheckItem::visit (HIR::Module &module) -{ - for (auto &item : module.get_items ()) - TypeCheckItem::Resolve (*item.get ()); -} - -void -TypeCheckItem::visit (HIR::Trait &trait) -{ - TraitResolver::Resolve (trait); + return TypeCheckType::Resolve (impl_block.get_type ().get ()); } } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 18fffa18459..10085c90629 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -27,29 +27,48 @@ namespace Resolver { class TypeCheckItem : private TypeCheckBase, private HIR::HIRVisItemVisitor { public: - static void Resolve (HIR::Item &item); + static TyTy::BaseType *Resolve (HIR::Item &item); + + static TyTy::BaseType *ResolveImplItem (HIR::ImplBlock &impl_block, + HIR::ImplItem &item); + + static TyTy::BaseType *ResolveImplBlockSelf (HIR::ImplBlock &impl_block); - void visit (HIR::ImplBlock &impl_block) override; - void visit (HIR::Function &function) override; void visit (HIR::Module &module) override; - void visit (HIR::Trait &trait) override; - - // FIXME - get rid of toplevel pass - void visit (HIR::TypeAlias &alias) override{}; - void visit (HIR::TupleStruct &struct_decl) override{}; - void visit (HIR::StructStruct &struct_decl) override{}; - void visit (HIR::Enum &enum_decl) override{}; - void visit (HIR::Union &union_decl) override{}; - void visit (HIR::StaticItem &var) override{}; - void visit (HIR::ConstantItem &constant) override{}; - void visit (HIR::ExternBlock &extern_block) override{}; + void visit (HIR::Function &function) override; + void visit (HIR::TypeAlias &alias) override; + void visit (HIR::TupleStruct &struct_decl) override; + void visit (HIR::StructStruct &struct_decl) override; + void visit (HIR::Enum &enum_decl) override; + void visit (HIR::Union &union_decl) override; + void visit (HIR::StaticItem &var) override; + void visit (HIR::ConstantItem &constant) override; + void visit (HIR::ImplBlock &impl_block) override; + void visit (HIR::ExternBlock &extern_block) override; + void visit (HIR::Trait &trait_block) override; // nothing to do void visit (HIR::ExternCrate &crate) override {} void visit (HIR::UseDeclaration &use_decl) override {} +protected: + std::vector + resolve_impl_block_substitutions (HIR::ImplBlock &impl_block, + bool &failure_flag); + + void validate_trait_impl_block ( + HIR::ImplBlock &impl_block, TyTy::BaseType *self, + std::vector &substitutions); + + TyTy::BaseType *resolve_impl_item (HIR::ImplBlock &impl_block, + HIR::ImplItem &item); + + TyTy::BaseType *resolve_impl_block_self (HIR::ImplBlock &impl_block); + private: TypeCheckItem (); + + TyTy::BaseType *infered; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index bf1de21ee4f..f404ea64bcc 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -235,7 +235,7 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset, } TyTy::BaseType *lookup = nullptr; - if (!context->lookup_type (ref, &lookup)) + if (!query_type (ref, &lookup)) { if (is_root) { @@ -383,7 +383,7 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id, HirId impl_ty_id = associated_impl_block->get_type ()->get_mappings ().get_hirid (); TyTy::BaseType *impl_block_ty = nullptr; - bool ok = context->lookup_type (impl_ty_id, &impl_block_ty); + bool ok = query_type (impl_ty_id, &impl_block_ty); rust_assert (ok); if (impl_block_ty->needs_generic_substitutions ()) diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc index a55cf22ba23..437782e8102 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc @@ -22,6 +22,7 @@ #include "rust-hir-type-check-expr.h" #include "rust-hir-type-check-enumitem.h" #include "rust-hir-type-check-implitem.h" +#include "rust-hir-type-check-item.h" #include "rust-hir-type-check-pattern.h" namespace Rust { @@ -139,378 +140,74 @@ TypeCheckStmt::visit (HIR::LetStmt &stmt) } void -TypeCheckStmt::visit (HIR::TupleStruct &struct_decl) +TypeCheckStmt::visit (HIR::TypePath &path) { - std::vector substitutions; - if (struct_decl.has_generics ()) - { - for (auto &generic_param : struct_decl.get_generic_params ()) - { - switch (generic_param.get ()->get_kind ()) - { - case HIR::GenericParam::GenericKind::LIFETIME: - case HIR::GenericParam::GenericKind::CONST: - // FIXME: Skipping Lifetime and Const completely until better - // handling. - break; - - case HIR::GenericParam::GenericKind::TYPE: { - auto param_type - = TypeResolveGenericParam::Resolve (generic_param.get ()); - context->insert_type (generic_param->get_mappings (), - param_type); - - substitutions.push_back (TyTy::SubstitutionParamMapping ( - static_cast (*generic_param), param_type)); - } - break; - } - } - } - - std::vector fields; - size_t idx = 0; - for (auto &field : struct_decl.get_fields ()) - { - TyTy::BaseType *field_type - = TypeCheckType::Resolve (field.get_field_type ().get ()); - TyTy::StructFieldType *ty_field - = new TyTy::StructFieldType (field.get_mappings ().get_hirid (), - std::to_string (idx), field_type, - field.get_locus ()); - fields.push_back (ty_field); - context->insert_type (field.get_mappings (), ty_field->get_field_type ()); - idx++; - } - - // get the path - const CanonicalPath *canonical_path = nullptr; - bool ok = mappings->lookup_canonical_path ( - struct_decl.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); - RustIdent ident{*canonical_path, struct_decl.get_locus ()}; - - // there is only a single variant - std::vector variants; - variants.push_back (new TyTy::VariantDef ( - struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (), - ident, TyTy::VariantDef::VariantType::TUPLE, nullptr, std::move (fields))); - - // Process #[repr(...)] attribute, if any - const AST::AttrVec &attrs = struct_decl.get_outer_attrs (); - TyTy::ADTType::ReprOptions repr - = parse_repr_options (attrs, struct_decl.get_locus ()); - - TyTy::BaseType *type - = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), - mappings->get_next_hir_id (), - struct_decl.get_identifier (), ident, - TyTy::ADTType::ADTKind::TUPLE_STRUCT, - std::move (variants), std::move (substitutions), repr); + infered = TypeCheckType::Resolve (&path); +} +void +TypeCheckStmt::visit (HIR::QualifiedPathInType &path) +{ + infered = TypeCheckType::Resolve (&path); +} - context->insert_type (struct_decl.get_mappings (), type); - infered = type; +void +TypeCheckStmt::visit (HIR::TupleStruct &struct_decl) +{ + infered = TypeCheckItem::Resolve (struct_decl); } void TypeCheckStmt::visit (HIR::Enum &enum_decl) { - std::vector substitutions; - if (enum_decl.has_generics ()) - { - for (auto &generic_param : enum_decl.get_generic_params ()) - { - switch (generic_param.get ()->get_kind ()) - { - case HIR::GenericParam::GenericKind::LIFETIME: - case HIR::GenericParam::GenericKind::CONST: - // FIXME: Skipping Lifetime and Const completely until better - // handling. - break; - - case HIR::GenericParam::GenericKind::TYPE: { - auto param_type - = TypeResolveGenericParam::Resolve (generic_param.get ()); - context->insert_type (generic_param->get_mappings (), - param_type); - - substitutions.push_back (TyTy::SubstitutionParamMapping ( - static_cast (*generic_param), param_type)); - } - break; - } - } - } - - std::vector variants; - int64_t discriminant_value = 0; - for (auto &variant : enum_decl.get_variants ()) - { - TyTy::VariantDef *field_type - = TypeCheckEnumItem::Resolve (variant.get (), discriminant_value); - - discriminant_value++; - variants.push_back (field_type); - } - - // get the path - const CanonicalPath *canonical_path = nullptr; - bool ok - = mappings->lookup_canonical_path (enum_decl.get_mappings ().get_nodeid (), - &canonical_path); - rust_assert (ok); - RustIdent ident{*canonical_path, enum_decl.get_locus ()}; - - TyTy::BaseType *type - = new TyTy::ADTType (enum_decl.get_mappings ().get_hirid (), - mappings->get_next_hir_id (), - enum_decl.get_identifier (), ident, - TyTy::ADTType::ADTKind::ENUM, std::move (variants), - std::move (substitutions)); - - context->insert_type (enum_decl.get_mappings (), type); - infered = type; + infered = TypeCheckItem::Resolve (enum_decl); } void TypeCheckStmt::visit (HIR::StructStruct &struct_decl) { - std::vector substitutions; - if (struct_decl.has_generics ()) - { - for (auto &generic_param : struct_decl.get_generic_params ()) - { - switch (generic_param.get ()->get_kind ()) - { - case HIR::GenericParam::GenericKind::LIFETIME: - case HIR::GenericParam::GenericKind::CONST: - // FIXME: Skipping Lifetime and Const completely until better - // handling. - break; - - case HIR::GenericParam::GenericKind::TYPE: { - auto param_type - = TypeResolveGenericParam::Resolve (generic_param.get ()); - context->insert_type (generic_param->get_mappings (), - param_type); - - substitutions.push_back (TyTy::SubstitutionParamMapping ( - static_cast (*generic_param), param_type)); - } - break; - } - } - } - - std::vector fields; - for (auto &field : struct_decl.get_fields ()) - { - TyTy::BaseType *field_type - = TypeCheckType::Resolve (field.get_field_type ().get ()); - TyTy::StructFieldType *ty_field - = new TyTy::StructFieldType (field.get_mappings ().get_hirid (), - field.get_field_name (), field_type, - field.get_locus ()); - fields.push_back (ty_field); - context->insert_type (field.get_mappings (), ty_field->get_field_type ()); - } - - // get the path - const CanonicalPath *canonical_path = nullptr; - bool ok = mappings->lookup_canonical_path ( - struct_decl.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); - RustIdent ident{*canonical_path, struct_decl.get_locus ()}; - - // there is only a single variant - std::vector variants; - variants.push_back (new TyTy::VariantDef ( - struct_decl.get_mappings ().get_hirid (), struct_decl.get_identifier (), - ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields))); - - // Process #[repr(...)] attribute, if any - const AST::AttrVec &attrs = struct_decl.get_outer_attrs (); - TyTy::ADTType::ReprOptions repr - = parse_repr_options (attrs, struct_decl.get_locus ()); - - TyTy::BaseType *type - = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (), - mappings->get_next_hir_id (), - struct_decl.get_identifier (), ident, - TyTy::ADTType::ADTKind::STRUCT_STRUCT, - std::move (variants), std::move (substitutions), repr); - - context->insert_type (struct_decl.get_mappings (), type); - infered = type; + infered = TypeCheckItem::Resolve (struct_decl); } void TypeCheckStmt::visit (HIR::Union &union_decl) { - std::vector substitutions; - if (union_decl.has_generics ()) - { - for (auto &generic_param : union_decl.get_generic_params ()) - { - switch (generic_param.get ()->get_kind ()) - { - case HIR::GenericParam::GenericKind::LIFETIME: - case HIR::GenericParam::GenericKind::CONST: - // FIXME: Skipping Lifetime and Const completely until better - // handling. - break; - - case HIR::GenericParam::GenericKind::TYPE: { - auto param_type - = TypeResolveGenericParam::Resolve (generic_param.get ()); - context->insert_type (generic_param->get_mappings (), - param_type); - - substitutions.push_back (TyTy::SubstitutionParamMapping ( - static_cast (*generic_param), param_type)); - } - break; - } - } - } - - std::vector fields; - for (auto &variant : union_decl.get_variants ()) - { - TyTy::BaseType *variant_type - = TypeCheckType::Resolve (variant.get_field_type ().get ()); - TyTy::StructFieldType *ty_variant - = new TyTy::StructFieldType (variant.get_mappings ().get_hirid (), - variant.get_field_name (), variant_type, - variant.get_locus ()); - fields.push_back (ty_variant); - context->insert_type (variant.get_mappings (), - ty_variant->get_field_type ()); - } - - // get the path - const CanonicalPath *canonical_path = nullptr; - bool ok - = mappings->lookup_canonical_path (union_decl.get_mappings ().get_nodeid (), - &canonical_path); - rust_assert (ok); - RustIdent ident{*canonical_path, union_decl.get_locus ()}; - - // there is only a single variant - std::vector variants; - variants.push_back (new TyTy::VariantDef ( - union_decl.get_mappings ().get_hirid (), union_decl.get_identifier (), - ident, TyTy::VariantDef::VariantType::STRUCT, nullptr, std::move (fields))); - - TyTy::BaseType *type - = new TyTy::ADTType (union_decl.get_mappings ().get_hirid (), - mappings->get_next_hir_id (), - union_decl.get_identifier (), ident, - TyTy::ADTType::ADTKind::UNION, std::move (variants), - std::move (substitutions)); - - context->insert_type (union_decl.get_mappings (), type); - infered = type; + infered = TypeCheckItem::Resolve (union_decl); } void TypeCheckStmt::visit (HIR::Function &function) { - std::vector substitutions; - if (function.has_generics ()) - { - for (auto &generic_param : function.get_generic_params ()) - { - switch (generic_param.get ()->get_kind ()) - { - case HIR::GenericParam::GenericKind::LIFETIME: - case HIR::GenericParam::GenericKind::CONST: - // FIXME: Skipping Lifetime and Const completely until better - // handling. - break; - - case HIR::GenericParam::GenericKind::TYPE: { - auto param_type - = TypeResolveGenericParam::Resolve (generic_param.get ()); - context->insert_type (generic_param->get_mappings (), - param_type); - - substitutions.push_back (TyTy::SubstitutionParamMapping ( - static_cast (*generic_param), param_type)); - } - break; - } - } - } - - TyTy::BaseType *ret_type = nullptr; - if (!function.has_function_return_type ()) - ret_type - = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid ()); - else - { - auto resolved - = TypeCheckType::Resolve (function.get_return_type ().get ()); - if (resolved == nullptr) - { - rust_error_at (function.get_locus (), - "failed to resolve return type"); - return; - } - - ret_type = resolved->clone (); - ret_type->set_ref ( - function.get_return_type ()->get_mappings ().get_hirid ()); - } - - std::vector > params; - for (auto ¶m : function.get_function_params ()) - { - // get the name as well required for later on - auto param_tyty = TypeCheckType::Resolve (param.get_type ()); - params.push_back ( - std::pair (param.get_param_name (), - param_tyty)); - - context->insert_type (param.get_mappings (), param_tyty); - TypeCheckPattern::Resolve (param.get_param_name (), param_tyty); - } - - // get the path - const CanonicalPath *canonical_path = nullptr; - bool ok - = mappings->lookup_canonical_path (function.get_mappings ().get_nodeid (), - &canonical_path); - rust_assert (ok); - - RustIdent ident{*canonical_path, function.get_locus ()}; - auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (), - function.get_mappings ().get_defid (), - function.get_function_name (), ident, - TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST, - std::move (params), ret_type, - std::move (substitutions)); - context->insert_type (function.get_mappings (), fnType); + infered = TypeCheckItem::Resolve (function); +} - TyTy::FnType *resolved_fn_type = fnType; - auto expected_ret_tyty = resolved_fn_type->get_return_type (); - context->push_return_type (TypeCheckContextItem (&function), - expected_ret_tyty); +void +TypeCheckStmt::visit (HIR::Module &module) +{ + infered = TypeCheckItem::Resolve (module); +} - auto block_expr_ty - = TypeCheckExpr::Resolve (function.get_definition ().get ()); +void +TypeCheckStmt::visit (HIR::TypeAlias &type_alias) +{ + infered = TypeCheckItem::Resolve (type_alias); +} - context->pop_return_type (); +void +TypeCheckStmt::visit (HIR::StaticItem &static_item) +{ + infered = TypeCheckItem::Resolve (static_item); +} - Location fn_return_locus = function.has_function_return_type () - ? function.get_return_type ()->get_locus () - : function.get_locus (); - coercion_site (function.get_definition ()->get_mappings ().get_hirid (), - TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus), - TyTy::TyWithLocation (block_expr_ty), - function.get_definition ()->get_locus ()); +void +TypeCheckStmt::visit (HIR::Trait &trait) +{ + infered = TypeCheckItem::Resolve (trait); +} - infered = fnType; +void +TypeCheckStmt::visit (HIR::ImplBlock &impl) +{ + infered = TypeCheckItem::Resolve (impl); } } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index d7edfad7302..04878b8c531 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -40,50 +40,32 @@ public: void visit (HIR::StructStruct &struct_decl) override; void visit (HIR::Union &union_decl) override; void visit (HIR::Function &function) override; + void visit (HIR::Module &module) override; + void visit (HIR::TypeAlias &type_alias) override; + void visit (HIR::StaticItem &static_item) override; + void visit (HIR::Trait &trait) override; + void visit (HIR::ImplBlock &impl) override; + void visit (HIR::TypePath &path) override; + void visit (HIR::QualifiedPathInType &path) override; - void visit (HIR::EnumItemTuple &) override - { /* TODO? */ - } - void visit (HIR::EnumItemStruct &) override - { /* TODO? */ - } - void visit (HIR::EnumItem &item) override - { /* TODO? */ - } - void visit (HIR::EnumItemDiscriminant &) override - { /* TODO? */ - } + // FIXME + // this seems like it should not be part of this visitor void visit (HIR::TypePathSegmentFunction &segment) override - { /* TODO? */ - } - void visit (HIR::TypePath &path) override - { /* TODO? */ - } - void visit (HIR::QualifiedPathInType &path) override - { /* TODO? */ - } - void visit (HIR::Module &module) override - { /* TODO? */ - } - void visit (HIR::ExternCrate &crate) override - { /* TODO? */ - } - void visit (HIR::UseDeclaration &use_decl) override - { /* TODO? */ - } - void visit (HIR::TypeAlias &type_alias) override - { /* TODO? */ - } - void visit (HIR::StaticItem &static_item) override - { /* TODO? */ - } - void visit (HIR::Trait &trait) override - { /* TODO? */ - } - void visit (HIR::ImplBlock &impl) override - { /* TODO? */ + { + gcc_unreachable (); } + // nothing to do for these + void visit (HIR::ExternCrate &crate) override {} + void visit (HIR::UseDeclaration &use_decl) override {} + + // nothing to do for these as they are taken care of by the + // hir-type-check-enumitem.h + void visit (HIR::EnumItemTuple &) override {} + void visit (HIR::EnumItemStruct &) override {} + void visit (HIR::EnumItem &) override {} + void visit (HIR::EnumItemDiscriminant &) override {} + private: TypeCheckStmt () : TypeCheckBase (), infered (nullptr) {} diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 06dc8e042d9..5a6d00a0e9d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -48,6 +48,14 @@ TypeCheckResolveGenericArguments::visit (HIR::TypePathSegmentGeneric &generic) TyTy::BaseType * TypeCheckType::Resolve (HIR::Type *type) { + // is it already resolved? + auto context = TypeCheckContext::get (); + TyTy::BaseType *resolved = nullptr; + bool already_resolved + = context->lookup_type (type->get_mappings ().get_hirid (), &resolved); + if (already_resolved) + return resolved; + TypeCheckType resolver (type->get_mappings ().get_hirid ()); type->accept_vis (resolver); rust_assert (resolver.translated != nullptr); @@ -103,77 +111,29 @@ TypeCheckType::visit (HIR::TupleType &tuple) void TypeCheckType::visit (HIR::TypePath &path) { - // lookup the Node this resolves to - NodeId ref; - auto nid = path.get_mappings ().get_nodeid (); - bool is_fully_resolved = resolver->lookup_resolved_type (nid, &ref); - - TyTy::BaseType *lookup = nullptr; - if (!is_fully_resolved) - { - // this can happen so we need to look up the root then resolve the - // remaining segments if possible - size_t offset = 0; - NodeId resolved_node_id = UNKNOWN_NODEID; - TyTy::BaseType *root - = resolve_root_path (path, &offset, &resolved_node_id); - - rust_assert (root != nullptr); - if (root->get_kind () == TyTy::TypeKind::ERROR) - return; - - translated - = resolve_segments (resolved_node_id, path.get_mappings ().get_hirid (), - path.get_segments (), offset, root, - path.get_mappings (), path.get_locus ()); - return; - } - - HirId hir_lookup; - if (!context->lookup_type_by_node_id (ref, &hir_lookup)) - { - rust_error_at (path.get_locus (), "failed to lookup HIR %d for node '%s'", - ref, path.as_string ().c_str ()); - return; - } - - if (!context->lookup_type (hir_lookup, &lookup)) - { - rust_error_at (path.get_locus (), "failed to lookup HIR TyTy"); - return; - } + // this can happen so we need to look up the root then resolve the + // remaining segments if possible + size_t offset = 0; + NodeId resolved_node_id = UNKNOWN_NODEID; + TyTy::BaseType *root = resolve_root_path (path, &offset, &resolved_node_id); + if (root->get_kind () == TyTy::TypeKind::ERROR) + return; - TyTy::BaseType *path_type = lookup->clone (); + TyTy::BaseType *path_type = root->clone (); path_type->set_ref (path.get_mappings ().get_hirid ()); + context->insert_implicit_type (path.get_mappings ().get_hirid (), path_type); - HIR::TypePathSegment *final_seg = path.get_final_segment ().get (); - HIR::GenericArgs args = TypeCheckResolveGenericArguments::resolve (final_seg); - - bool is_big_self = final_seg->is_ident_only () - && (final_seg->as_string ().compare ("Self") == 0); - - if (path_type->needs_generic_substitutions ()) - { - if (is_big_self) - { - translated = path_type; - return; - } - - translated = SubstMapper::Resolve (path_type, path.get_locus (), &args); - } - else if (!args.is_empty ()) - { - rust_error_at (path.get_locus (), - "TypePath %s declares generic arguments but " - "the type %s does not have any", - path.as_string ().c_str (), - path_type->as_string ().c_str ()); - } - else + bool fully_resolved = offset >= path.get_segments ().size (); + if (fully_resolved) { translated = path_type; + return; } + + translated + = resolve_segments (resolved_node_id, path.get_mappings ().get_hirid (), + path.get_segments (), offset, path_type, + path.get_mappings (), path.get_locus ()); } void @@ -389,7 +349,7 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, } TyTy::BaseType *lookup = nullptr; - if (!context->lookup_type (ref, &lookup)) + if (!query_type (ref, &lookup)) { if (is_root) { @@ -428,14 +388,22 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, if (!lookup->can_substitute ()) { - rust_error_at (seg->get_locus (), - "substitutions not supported for %s", + rust_error_at (path.get_locus (), + "TypePath %s declares generic arguments but the " + "type %s does not have any", + path.as_string ().c_str (), lookup->as_string ().c_str ()); return new TyTy::ErrorType (lookup->get_ref ()); } lookup = SubstMapper::Resolve (lookup, path.get_locus (), &generic_segment->get_generic_args ()); } + else if (lookup->needs_generic_substitutions ()) + { + HIR::GenericArgs empty + = HIR::GenericArgs::create_empty (path.get_locus ()); + lookup = SubstMapper::Resolve (lookup, path.get_locus (), &empty); + } *root_resolved_node_id = ref_node_id; *offset = *offset + 1; @@ -531,7 +499,7 @@ TypeCheckType::resolve_segments ( context->insert_receiver (expr_mappings.get_hirid (), prev_segment); if (tyseg->needs_generic_substitutions ()) { - Location locus = segments.back ()->get_locus (); + // Location locus = segments.back ()->get_locus (); if (!prev_segment->needs_generic_substitutions ()) { auto used_args_in_prev_segment @@ -540,10 +508,6 @@ TypeCheckType::resolve_segments ( tyseg = SubstMapperInternal::Resolve (tyseg, used_args_in_prev_segment); } - else - { - tyseg = SubstMapper::InferSubst (tyseg, locus); - } if (tyseg->get_kind () == TyTy::TypeKind::ERROR) return new TyTy::ErrorType (expr_id); diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index f2445cd3ba2..d73e31efab8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -18,7 +18,6 @@ #include "rust-hir-type-check.h" #include "rust-hir-full.h" -#include "rust-hir-type-check-toplevel.h" #include "rust-hir-type-check-item.h" #include "rust-hir-type-check-expr.h" #include "rust-hir-type-check-pattern.h" @@ -35,7 +34,7 @@ void TypeResolution::Resolve (HIR::Crate &crate) { for (auto it = crate.items.begin (); it != crate.items.end (); it++) - TypeCheckTopLevel::Resolve (*it->get ()); + TypeCheckItem::Resolve (*it->get ()); if (saw_errors ()) return; @@ -44,12 +43,6 @@ TypeResolution::Resolve (HIR::Crate &crate) if (saw_errors ()) return; - for (auto it = crate.items.begin (); it != crate.items.end (); it++) - TypeCheckItem::Resolve (*it->get ()); - - if (saw_errors ()) - return; - auto mappings = Analysis::Mappings::get (); auto context = TypeCheckContext::get (); diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 5a6c0426fd6..3e9c9c4d21a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -337,6 +337,41 @@ public: return true; } + void insert_unconstrained_check_marker (HirId id, bool status) + { + unconstrained[id] = status; + } + + bool have_checked_for_unconstrained (HirId id, bool *result) + { + auto it = unconstrained.find (id); + bool found = it != unconstrained.end (); + if (!found) + return false; + + *result = it->second; + return true; + } + + void insert_resolved_predicate (HirId id, TyTy::TypeBoundPredicate predicate) + { + auto it = predicates.find (id); + rust_assert (it == predicates.end ()); + + predicates.insert ({id, predicate}); + } + + bool lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result) + { + auto it = predicates.find (id); + bool found = it != predicates.end (); + if (!found) + return false; + + *result = it->second; + return true; + } + private: TypeCheckContext (); @@ -365,6 +400,12 @@ private: // variants std::map variants; + + // unconstrained type-params check + std::map unconstrained; + + // predicates + std::map predicates; }; class TypeResolution diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index 14b4e060d21..995d9c88ec4 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -102,7 +102,7 @@ public: if (!have_generic_args ()) { TyTy::BaseType *substs = type.infer_substitions (locus); - rust_assert (substs->get_kind () == TyTy::TypeKind::ADT); + rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION); concrete = static_cast (substs); } else diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index 69376aaa373..5b5ff751e2b 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -18,6 +18,7 @@ #include "rust-hir-type-bounds.h" #include "rust-hir-trait-resolve.h" +#include "rust-hir-type-check-item.h" namespace Rust { namespace Resolver { @@ -33,11 +34,8 @@ TypeBoundsProbe::scan () if (!impl->has_trait_ref ()) return true; - TyTy::BaseType *impl_type = nullptr; - bool ok - = context->lookup_type (impl->get_type ()->get_mappings ().get_hirid (), - &impl_type); - if (!ok) + TyTy::BaseType *impl_type = TypeCheckItem::ResolveImplBlockSelf (*impl); + if (impl_type->get_kind () == TyTy::TypeKind::ERROR) return true; if (!receiver->can_eq (impl_type, false)) @@ -69,6 +67,13 @@ TypeCheckBase::resolve_trait_path (HIR::TypePath &path) TyTy::TypeBoundPredicate TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path) { + TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error (); + bool already_resolved + = context->lookup_predicate (type_path.get_mappings ().get_hirid (), + &lookup); + if (already_resolved) + return lookup; + TraitReference *trait = resolve_trait_path (type_path); if (trait->is_error ()) return TyTy::TypeBoundPredicate::error (); @@ -94,6 +99,8 @@ TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path) predicate.apply_generic_arguments (&args); } + context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (), + predicate); return predicate; } @@ -470,6 +477,13 @@ TypeBoundsMappings::raw_bounds_as_name () const void TypeBoundsMappings::add_bound (TypeBoundPredicate predicate) { + for (auto &bound : specified_bounds) + { + bool same_trait_ref_p = bound.get_id () == predicate.get_id (); + if (same_trait_ref_p) + return; + } + specified_bounds.push_back (predicate); } diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h index 2813bf42c1c..d47cbb4369a 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -1358,6 +1358,8 @@ public: // generic arguments void visit (const ParamType &) override { ok = true; } + void visit (const TupleType &) override { ok = true; } + void visit (const InferType &) override { ok = true; } void visit (const FnType &) override { ok = true; } diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 3e29bd2a92c..64fe0f6cfb0 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -208,9 +208,6 @@ void BaseType::inherit_bounds ( const std::vector &specified_bounds) { - // FIXME - // 1. This needs to union the bounds - // 2. Do some checking for trait polarity to ensure compatibility for (auto &bound : specified_bounds) { add_bound (bound); @@ -754,6 +751,40 @@ SubstitutionRef::get_mappings_from_generic_args (HIR::GenericArgs &args) return SubstitutionArgumentMappings (mappings, args.get_locus ()); } +BaseType * +SubstitutionRef::infer_substitions (Location locus) +{ + std::vector args; + std::map argument_mappings; + for (auto &p : get_substs ()) + { + if (p.needs_substitution ()) + { + const std::string &symbol = p.get_param_ty ()->get_symbol (); + auto it = argument_mappings.find (symbol); + bool have_mapping = it != argument_mappings.end (); + + if (have_mapping) + { + args.push_back (SubstitutionArg (&p, it->second)); + } + else + { + TyVar infer_var = TyVar::get_implicit_infer_var (locus); + args.push_back (SubstitutionArg (&p, infer_var.get_tyty ())); + argument_mappings[symbol] = infer_var.get_tyty (); + } + } + else + { + args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ())); + } + } + + SubstitutionArgumentMappings infer_arguments (std::move (args), locus); + return handle_substitions (std::move (infer_arguments)); +} + SubstitutionArgumentMappings SubstitutionRef::adjust_mappings_for_this ( SubstitutionArgumentMappings &mappings) @@ -2479,7 +2510,13 @@ ParamType::resolve () const break; TyVar v (rr->get_ty_ref ()); - r = v.get_tyty (); + BaseType *n = v.get_tyty (); + + // fix infinite loop + if (r == n) + break; + + r = n; } if (r->get_kind () == TypeKind::PARAM && (r->get_ref () == r->get_ty_ref ())) diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 43460d2dd2f..e3cf4d667c7 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -960,37 +960,7 @@ public: solve_missing_mappings_from_this (SubstitutionRef &ref, SubstitutionRef &to); // TODO comment - BaseType *infer_substitions (Location locus) - { - std::vector args; - std::map argument_mappings; - for (auto &p : get_substs ()) - { - if (p.needs_substitution ()) - { - const std::string &symbol = p.get_param_ty ()->get_symbol (); - auto it = argument_mappings.find (symbol); - if (it == argument_mappings.end ()) - { - TyVar infer_var = TyVar::get_implicit_infer_var (locus); - args.push_back (SubstitutionArg (&p, infer_var.get_tyty ())); - argument_mappings[symbol] = infer_var.get_tyty (); - } - else - { - args.push_back (SubstitutionArg (&p, it->second)); - } - } - else - { - args.push_back ( - SubstitutionArg (&p, p.get_param_ty ()->resolve ())); - } - } - - SubstitutionArgumentMappings infer_arguments (std::move (args), locus); - return handle_substitions (std::move (infer_arguments)); - } + BaseType *infer_substitions (Location locus); // TODO comment bool monomorphize (); @@ -1059,6 +1029,8 @@ public: bool contains_associated_types () const; + DefId get_id () const { return reference; } + private: DefId reference; Location locus; diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 103d6869b81..80434489fcd 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -419,7 +419,9 @@ Mappings::insert_hir_impl_block (HIR::ImplBlock *item) auto id = item->get_mappings ().get_hirid (); rust_assert (lookup_hir_impl_block (id) == nullptr); + HirId impl_type_id = item->get_type ()->get_mappings ().get_hirid (); hirImplBlockMappings[id] = item; + hirImplBlockTypeMappings[impl_type_id] = item; insert_node_to_hir (item->get_mappings ().get_nodeid (), id); } @@ -433,6 +435,17 @@ Mappings::lookup_hir_impl_block (HirId id) return it->second; } +bool +Mappings::lookup_impl_block_type (HirId id, HIR::ImplBlock **impl_block) +{ + auto it = hirImplBlockTypeMappings.find (id); + if (it == hirImplBlockTypeMappings.end ()) + return false; + + *impl_block = it->second; + return true; +} + void Mappings::insert_module (HIR::Module *module) { diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index fadbdde21b5..474bd5fa229 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -123,6 +123,7 @@ public: void insert_hir_impl_block (HIR::ImplBlock *item); HIR::ImplBlock *lookup_hir_impl_block (HirId id); + bool lookup_impl_block_type (HirId id, HIR::ImplBlock **impl_block); void insert_module (HIR::Module *module); HIR::Module *lookup_module (HirId id); @@ -314,6 +315,7 @@ private: std::map hirSelfParamMappings; std::map hirImplItemsToImplMappings; std::map hirImplBlockMappings; + std::map hirImplBlockTypeMappings; std::map hirTraitItemMappings; std::map hirExternBlockMappings; std::map> hirExternItemMappings; diff --git a/gcc/testsuite/rust/compile/const_generics_5.rs b/gcc/testsuite/rust/compile/const_generics_5.rs index 5344e31a140..46cf6c93968 100644 --- a/gcc/testsuite/rust/compile/const_generics_5.rs +++ b/gcc/testsuite/rust/compile/const_generics_5.rs @@ -1,12 +1,15 @@ +// bogus errors but shows the type checking system needs to support const +// generics with defaults + struct Foo; const M: usize = 15; -type N = Foo<3>; +type N = Foo<3>; // { dg-error "TypePath Foo<> declares generic arguments but the type Foo{Foo {}} does not have any" } fn main() { - let _: Foo<15> = Foo; - let _: Foo<{ M }> = Foo; - let _: Foo = Foo; - // bogus error, but it means the above const generic gets disambiguated properly + let _: Foo<15> = Foo; // { dg-error "TypePath Foo<> declares generic arguments but the type Foo{Foo {}} does not have any" } + let _: Foo<{ M }> = Foo; // { dg-error "TypePath Foo<> declares generic arguments but the type Foo{Foo {}} does not have any" } + let _: Foo = Foo; // { dg-error "TypePath Foo<> declares generic arguments but the type Foo{Foo {}} does not have any" } + let _: Foo = Foo; // { dg-error "TypePath Foo declares generic arguments but the type Foo{Foo {}} does not have any" } } diff --git a/gcc/testsuite/rust/compile/unconstrained_type_param.rs b/gcc/testsuite/rust/compile/unconstrained_type_param.rs index c4aaa10146f..7fe74c2c798 100644 --- a/gcc/testsuite/rust/compile/unconstrained_type_param.rs +++ b/gcc/testsuite/rust/compile/unconstrained_type_param.rs @@ -9,4 +9,6 @@ impl Foo { fn main() { let a = Foo::test(); + // { dg-error "Failed to resolve expression of function call" "" { target *-*-* } .-1 } + // { dg-error "failed to type resolve expression" "" { target *-*-* } .-2 } } -- 2.39.1