public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Thomas Schwinge <tschwinge@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] typecheck: Move TypeCheckItem into source and header file Date: Wed, 6 Jul 2022 20:27:37 +0000 (GMT) [thread overview] Message-ID: <20220706202737.9A9A53858D28@sourceware.org> (raw) https://gcc.gnu.org/g:9cc83569d196ef1fd2e19abda06231b42dce4f51 commit 9cc83569d196ef1fd2e19abda06231b42dce4f51 Author: Arthur Cohen <arthur.cohen@embecosm.com> Date: Wed Jul 6 11:26:13 2022 +0200 typecheck: Move TypeCheckItem into source and header file Diff: --- gcc/rust/Make-lang.in | 1 + gcc/rust/typecheck/rust-hir-type-check-item.cc | 226 +++++++++++++++++++++++++ gcc/rust/typecheck/rust-hir-type-check-item.h | 196 +-------------------- 3 files changed, 232 insertions(+), 191 deletions(-) diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index cfe23728b8d..b448da95aea 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -110,6 +110,7 @@ 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-item.o \ rust/rust-hir-type-check-type.o \ rust/rust-hir-type-check-struct.o \ rust/rust-hir-type-check-pattern.o \ diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc new file mode 100644 index 00000000000..28cac51f793 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -0,0 +1,226 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-hir-type-check-item.h" + +namespace Rust { + +namespace Resolver { +void +TypeCheckItem::Resolve (HIR::Item *item) +{ + TypeCheckItem resolver; + item->accept_vis (resolver); +} + +void +TypeCheckItem::visit (HIR::ImplBlock &impl_block) +{ + std::vector<TyTy::SubstitutionParamMapping> substitutions; + if (impl_block.has_generics ()) + { + for (auto &generic_param : impl_block.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: { + 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<HIR::TypeParam &> (*generic_param), + static_cast<TyTy::ParamType *> (l))); + } + } + break; + } + } + } + + auto specified_bound = TyTy::TypeBoundPredicate::error (); + TraitReference *trait_reference = &TraitReference::error_node (); + if (impl_block.has_trait_ref ()) + { + std::unique_ptr<HIR::TypePath> &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 ()); + } + + 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; + } + + // inherit the bounds + if (!specified_bound.is_error ()) + self->inherit_bounds ({specified_bound}); + + // check for any unconstrained type-params + const TyTy::SubstitutionArgumentMappings trait_constraints + = specified_bound.get_substitution_arguments (); + 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; + + // validate the impl items + bool is_trait_impl_block = !trait_reference->is_error (); + std::vector<const TraitItemReference *> 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 + { + auto trait_item_ref + = TypeCheckImplItemWithTrait::Resolve (&impl_block, + impl_item.get (), self, + specified_bound, + substitutions); + trait_item_refs.push_back (trait_item_ref.get_raw_item ()); + } + } + + bool impl_block_missing_trait_items + = is_trait_impl_block + && trait_reference->size () != trait_item_refs.size (); + if (impl_block_missing_trait_items) + { + // filter the missing impl_items + std::vector<std::reference_wrapper<const TraitItemReference>> + missing_trait_items; + for (const auto &trait_item_ref : trait_reference->get_trait_items ()) + { + bool found = false; + for (auto implemented_trait_item : trait_item_refs) + { + std::string trait_item_name = trait_item_ref.get_identifier (); + std::string impl_item_name + = implemented_trait_item->get_identifier (); + found = trait_item_name.compare (impl_item_name) == 0; + if (found) + break; + } + + bool is_required_trait_item = !trait_item_ref.is_optional (); + if (!found && is_required_trait_item) + missing_trait_items.push_back (trait_item_ref); + } + + if (missing_trait_items.size () > 0) + { + std::string missing_items_buf; + RichLocation r (impl_block.get_locus ()); + for (size_t i = 0; i < missing_trait_items.size (); i++) + { + bool has_more = (i + 1) < missing_trait_items.size (); + const TraitItemReference &missing_trait_item + = missing_trait_items.at (i); + missing_items_buf += missing_trait_item.get_identifier () + + (has_more ? ", " : ""); + r.add_range (missing_trait_item.get_locus ()); + } + + rust_error_at (r, "missing %s in implementation of trait %<%s%>", + missing_items_buf.c_str (), + trait_reference->get_name ().c_str ()); + } + } + + if (is_trait_impl_block) + { + trait_reference->clear_associated_types (); + + AssociatedImplTrait associated (trait_reference, &impl_block, self, + context); + context->insert_associated_trait_impl ( + impl_block.get_mappings ().get_hirid (), std::move (associated)); + context->insert_associated_impl_mapping ( + trait_reference->get_mappings ().get_hirid (), self, + impl_block.get_mappings ().get_hirid ()); + } +} + +void +TypeCheckItem::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; + } + + // need to get the return type from this + TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (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 ()); + + context->pop_return_type (); + + if (block_expr_ty->get_kind () != TyTy::NEVER) + expected_ret_tyty->unify (block_expr_ty); +} + +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); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 84a33f85c62..b9a0d9b2e90 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -35,198 +35,12 @@ class TypeCheckItem : public TypeCheckBase using Rust::Resolver::TypeCheckBase::visit; public: - static void Resolve (HIR::Item *item) - { - TypeCheckItem resolver; - item->accept_vis (resolver); - } + static void Resolve (HIR::Item *item); - void visit (HIR::ImplBlock &impl_block) override - { - std::vector<TyTy::SubstitutionParamMapping> substitutions; - if (impl_block.has_generics ()) - { - for (auto &generic_param : impl_block.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: { - 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<HIR::TypeParam &> (*generic_param), - static_cast<TyTy::ParamType *> (l))); - } - } - break; - } - } - } - - auto specified_bound = TyTy::TypeBoundPredicate::error (); - TraitReference *trait_reference = &TraitReference::error_node (); - if (impl_block.has_trait_ref ()) - { - std::unique_ptr<HIR::TypePath> &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 ()); - } - - 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; - } - - // inherit the bounds - if (!specified_bound.is_error ()) - self->inherit_bounds ({specified_bound}); - - // check for any unconstrained type-params - const TyTy::SubstitutionArgumentMappings trait_constraints - = specified_bound.get_substitution_arguments (); - 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; - - // validate the impl items - bool is_trait_impl_block = !trait_reference->is_error (); - std::vector<const TraitItemReference *> 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 - { - auto trait_item_ref - = TypeCheckImplItemWithTrait::Resolve (&impl_block, - impl_item.get (), self, - specified_bound, - substitutions); - trait_item_refs.push_back (trait_item_ref.get_raw_item ()); - } - } - - bool impl_block_missing_trait_items - = is_trait_impl_block - && trait_reference->size () != trait_item_refs.size (); - if (impl_block_missing_trait_items) - { - // filter the missing impl_items - std::vector<std::reference_wrapper<const TraitItemReference>> - missing_trait_items; - for (const auto &trait_item_ref : trait_reference->get_trait_items ()) - { - bool found = false; - for (auto implemented_trait_item : trait_item_refs) - { - std::string trait_item_name = trait_item_ref.get_identifier (); - std::string impl_item_name - = implemented_trait_item->get_identifier (); - found = trait_item_name.compare (impl_item_name) == 0; - if (found) - break; - } - - bool is_required_trait_item = !trait_item_ref.is_optional (); - if (!found && is_required_trait_item) - missing_trait_items.push_back (trait_item_ref); - } - - if (missing_trait_items.size () > 0) - { - std::string missing_items_buf; - RichLocation r (impl_block.get_locus ()); - for (size_t i = 0; i < missing_trait_items.size (); i++) - { - bool has_more = (i + 1) < missing_trait_items.size (); - const TraitItemReference &missing_trait_item - = missing_trait_items.at (i); - missing_items_buf += missing_trait_item.get_identifier () - + (has_more ? ", " : ""); - r.add_range (missing_trait_item.get_locus ()); - } - - rust_error_at (r, "missing %s in implementation of trait %<%s%>", - missing_items_buf.c_str (), - trait_reference->get_name ().c_str ()); - } - } - - if (is_trait_impl_block) - { - trait_reference->clear_associated_types (); - - AssociatedImplTrait associated (trait_reference, &impl_block, self, - context); - context->insert_associated_trait_impl ( - impl_block.get_mappings ().get_hirid (), std::move (associated)); - context->insert_associated_impl_mapping ( - trait_reference->get_mappings ().get_hirid (), self, - impl_block.get_mappings ().get_hirid ()); - } - } - - void visit (HIR::Function &function) override - { - 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<TyTy::FnType *> (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 ()); - - context->pop_return_type (); - - if (block_expr_ty->get_kind () != TyTy::NEVER) - expected_ret_tyty->unify (block_expr_ty); - } - - void visit (HIR::Module &module) override - { - for (auto &item : module.get_items ()) - TypeCheckItem::Resolve (item.get ()); - } - - void visit (HIR::Trait &trait) override { TraitResolver::Resolve (trait); } + 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; private: TypeCheckItem () : TypeCheckBase () {}
reply other threads:[~2022-07-06 20:27 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220706202737.9A9A53858D28@sourceware.org \ --to=tschwinge@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).