From 630ef83dfc9a62ef0b0b822b34bfd7e3389b909d Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 10 Aug 2022 14:47:44 +0100 Subject: [PATCH 1/4] Refactor helper from TypeCheckResolveToplevel The reason we cannot type-resolve forward declared items is due to the fact our type-resolver runs in a toplevel pass trying to type resolve as best it can but when we hit structs for example which contain types that are forward declared they need to be resolved in a query based manar. We have all the missing pieces to do this now and this means we need to get rid of this toplevel pass as the starting point. Addresses #1455 --- .../typecheck/rust-hir-type-check-base.cc | 46 +++++++++++++++++++ gcc/rust/typecheck/rust-hir-type-check-base.h | 4 ++ .../typecheck/rust-hir-type-check-toplevel.cc | 44 ------------------ .../typecheck/rust-hir-type-check-toplevel.h | 4 -- 4 files changed, 50 insertions(+), 48 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index c50199847b7..e263056a82c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -17,6 +17,8 @@ // . #include "rust-hir-type-check-base.h" +#include "rust-hir-type-check-type.h" +#include "rust-hir-type-check-expr.h" #include "rust-coercion.h" namespace Rust { @@ -349,5 +351,49 @@ TypeCheckBase::coercion_site (HirId id, TyTy::BaseType *expected, return expected->coerce (expr); } +void +TypeCheckBase::resolve_generic_params ( + const std::vector> &generic_params, + std::vector &substitutions) +{ + for (auto &generic_param : generic_params) + { + switch (generic_param.get ()->get_kind ()) + { + case HIR::GenericParam::GenericKind::LIFETIME: + // FIXME: Skipping Lifetime completely until better + // handling. + break; + case HIR::GenericParam::GenericKind::CONST: { + auto param + = static_cast (generic_param.get ()); + auto specified_type + = TypeCheckType::Resolve (param->get_type ().get ()); + + if (param->has_default_expression ()) + { + auto expr_type = TypeCheckExpr::Resolve ( + param->get_default_expression ().get ()); + specified_type->coerce (expr_type); + } + + context->insert_type (generic_param->get_mappings (), + specified_type); + } + 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; + } + } +} + } // 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 4078697c927..b6f4b636789 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.h +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -64,6 +64,10 @@ protected: TyTy::ADTType::ReprOptions parse_repr_options (const AST::AttrVec &attrs, Location locus); + void resolve_generic_params ( + const std::vector> &generic_params, + std::vector &substitutions); + Analysis::Mappings *mappings; Resolver *resolver; TypeCheckContext *context; diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc b/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc index 69377e28d22..d5270c9acbb 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc @@ -28,50 +28,6 @@ TypeCheckTopLevel::Resolve (HIR::Item *item) item->accept_vis (resolver); } -void -TypeCheckTopLevel::resolve_generic_params ( - const std::vector> &generic_params, - std::vector &substitutions) -{ - for (auto &generic_param : generic_params) - { - switch (generic_param.get ()->get_kind ()) - { - case HIR::GenericParam::GenericKind::LIFETIME: - // FIXME: Skipping Lifetime completely until better - // handling. - break; - case HIR::GenericParam::GenericKind::CONST: { - auto param - = static_cast (generic_param.get ()); - auto specified_type - = TypeCheckType::Resolve (param->get_type ().get ()); - - if (param->has_default_expression ()) - { - auto expr_type = TypeCheckExpr::Resolve ( - param->get_default_expression ().get ()); - specified_type->coerce (expr_type); - } - - context->insert_type (generic_param->get_mappings (), - specified_type); - } - 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; - } - } -} - void TypeCheckTopLevel::visit (HIR::TypeAlias &alias) { diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index fdc13f7684d..d2785b15e54 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -51,10 +51,6 @@ public: private: TypeCheckTopLevel () : TypeCheckBase () {} - - void resolve_generic_params ( - const std::vector> &generic_params, - std::vector &substitutions); }; } // namespace Resolver From 2ad0cde0a506d3a8a284a7e1178830f53648f9c3 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 10 Aug 2022 16:54:16 +0100 Subject: [PATCH 2/4] Refactor the TypeResolution pass to use fine grained visitors This is a huge refactor but no logic has been changed. Most implementation has now been moved from the headers and into cc files now. This should help alot with compilation times when working within the type system. This is another incremental step to improve our coercion site logic as also support forward declared items. Addresses #1455 --- gcc/rust/Make-lang.in | 3 + gcc/rust/hir/tree/rust-hir-expr.h | 28 +- .../rust-hir-inherent-impl-overlap.h | 6 +- gcc/rust/typecheck/rust-hir-path-probe.h | 10 +- gcc/rust/typecheck/rust-hir-trait-resolve.h | 12 +- gcc/rust/typecheck/rust-hir-type-bounds.h | 2 - gcc/rust/typecheck/rust-hir-type-check-base.h | 6 +- .../typecheck/rust-hir-type-check-enumitem.cc | 213 ++++ .../typecheck/rust-hir-type-check-enumitem.h | 177 +--- .../typecheck/rust-hir-type-check-expr.cc | 966 +++++++++++++++++ gcc/rust/typecheck/rust-hir-type-check-expr.h | 979 ++---------------- .../typecheck/rust-hir-type-check-implitem.cc | 583 +++++++++++ .../typecheck/rust-hir-type-check-implitem.h | 540 +--------- .../typecheck/rust-hir-type-check-item.cc | 19 +- gcc/rust/typecheck/rust-hir-type-check-item.h | 28 +- .../typecheck/rust-hir-type-check-path.cc | 2 + .../typecheck/rust-hir-type-check-pattern.cc | 46 + .../typecheck/rust-hir-type-check-pattern.h | 34 +- .../typecheck/rust-hir-type-check-stmt.cc | 498 +++++++++ gcc/rust/typecheck/rust-hir-type-check-stmt.h | 511 +-------- .../rust-hir-type-check-struct-field.h | 27 +- .../typecheck/rust-hir-type-check-struct.cc | 37 +- .../typecheck/rust-hir-type-check-toplevel.cc | 16 +- .../typecheck/rust-hir-type-check-toplevel.h | 23 +- .../typecheck/rust-hir-type-check-type.cc | 53 +- gcc/rust/typecheck/rust-hir-type-check-type.h | 41 +- gcc/rust/typecheck/rust-hir-type-check.cc | 46 +- gcc/rust/typecheck/rust-tycheck-dump.h | 4 +- 28 files changed, 2667 insertions(+), 2243 deletions(-) create mode 100644 gcc/rust/typecheck/rust-hir-type-check-enumitem.cc create mode 100644 gcc/rust/typecheck/rust-hir-type-check-implitem.cc create mode 100644 gcc/rust/typecheck/rust-hir-type-check-stmt.cc diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 886bafbe1e0..23dad26e8c4 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -117,6 +117,9 @@ GRS_OBJS = \ rust/rust-hir-type-check-struct.o \ rust/rust-hir-type-check-pattern.o \ rust/rust-hir-type-check-expr.o \ + rust/rust-hir-type-check-stmt.o \ + rust/rust-hir-type-check-enumitem.o \ + rust/rust-hir-type-check-implitem.o \ rust/rust-hir-dot-operator.o \ rust/rust-coercion.o \ rust/rust-hir-type-check-base.o \ diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 7cb86a69b2c..83278529646 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -1409,6 +1409,13 @@ public: class StructExprField { public: + enum StructExprFieldKind + { + IDENTIFIER_VALUE, + IDENTIFIER, + INDEX_VALUE, + }; + virtual ~StructExprField () {} // Unique pointer custom clone function @@ -1426,6 +1433,8 @@ public: Location get_locus () { return locus; } + virtual StructExprFieldKind get_kind () const = 0; + protected: // pure virtual clone implementation virtual StructExprField *clone_struct_expr_field_impl () const = 0; @@ -1441,11 +1450,11 @@ protected: // Identifier-only variant of StructExprField HIR node class StructExprFieldIdentifier : public StructExprField { -public: +private: Identifier field_name; // TODO: should this store location data? - +public: StructExprFieldIdentifier (Analysis::NodeMapping mapping, Identifier field_identifier, Location locus) : StructExprField (mapping, locus), @@ -1459,6 +1468,11 @@ public: Identifier get_field_name () const { return field_name; } + StructExprFieldKind get_kind () const override + { + return StructExprFieldKind::IDENTIFIER; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1527,6 +1541,11 @@ public: void accept_vis (HIRFullVisitor &vis) override; void accept_vis (HIRExpressionVisitor &vis) override; + StructExprFieldKind get_kind () const override + { + return StructExprFieldKind::IDENTIFIER_VALUE; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1558,6 +1577,11 @@ public: void accept_vis (HIRFullVisitor &vis) override; void accept_vis (HIRExpressionVisitor &vis) override; + StructExprFieldKind get_kind () const override + { + return StructExprFieldKind::INDEX_VALUE; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h index 9abf87280ad..2890b54a00d 100644 --- a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h +++ b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h @@ -25,10 +25,8 @@ namespace Rust { namespace Resolver { -class ImplItemToName : public TypeCheckBase +class ImplItemToName : private TypeCheckBase, private HIR::HIRImplVisitor { - using Rust::Resolver::TypeCheckBase::visit; - public: static bool resolve (HIR::ImplItem *item, std::string &name_result) { @@ -66,8 +64,6 @@ private: class OverlappingImplItemPass : public TypeCheckBase { - using Rust::Resolver::TypeCheckBase::visit; - public: static void go () { diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h index 348b9f775e8..bd4f91e49bf 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -125,11 +125,8 @@ struct PathProbeCandidate bool is_error () const { return type == ERROR; } }; -class PathProbeType : public TypeCheckBase +class PathProbeType : public TypeCheckBase, public HIR::HIRImplVisitor { -protected: - using Rust::Resolver::TypeCheckBase::visit; - public: static std::vector Probe (const TyTy::BaseType *receiver, @@ -452,10 +449,9 @@ protected: DefId specific_trait_id; }; -class ReportMultipleCandidateError : private TypeCheckBase +class ReportMultipleCandidateError : private TypeCheckBase, + private HIR::HIRImplVisitor { - using Rust::Resolver::TypeCheckBase::visit; - public: static void Report (std::vector &candidates, const HIR::PathIdentSegment &query, Location query_locus) diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h index a73b67fc142..c4aaf42b141 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.h +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h @@ -20,19 +20,15 @@ #define RUST_HIR_TRAIT_RESOLVE_H #include "rust-hir-type-check-base.h" -#include "rust-hir-full.h" -#include "rust-tyty-visitor.h" #include "rust-hir-type-check-type.h" #include "rust-hir-trait-ref.h" -#include "rust-expr.h" namespace Rust { namespace Resolver { -class ResolveTraitItemToRef : public TypeCheckBase +class ResolveTraitItemToRef : public TypeCheckBase, + private HIR::HIRTraitItemVisitor { - using Rust::Resolver::TypeCheckBase::visit; - public: static TraitItemReference Resolve (HIR::TraitItem &item, TyTy::BaseType *self, @@ -59,9 +55,9 @@ private: std::vector substitutions; }; -class TraitResolver : public TypeCheckBase +class TraitResolver : public TypeCheckBase, private HIR::HIRFullVisitorBase { - using Rust::Resolver::TypeCheckBase::visit; + using HIR::HIRFullVisitorBase::visit; public: static TraitReference *Resolve (HIR::TypePath &path); diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h index a0016ee7f1f..44400efbbf7 100644 --- a/gcc/rust/typecheck/rust-hir-type-bounds.h +++ b/gcc/rust/typecheck/rust-hir-type-bounds.h @@ -28,8 +28,6 @@ namespace Resolver { class TypeBoundsProbe : public TypeCheckBase { - using Rust::Resolver::TypeCheckBase::visit; - public: static std::vector> Probe (const TyTy::BaseType *receiver) diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h index b6f4b636789..449ff6ab92a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.h +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -30,13 +30,9 @@ namespace Rust { namespace Resolver { class TraitReference; - -// base class to allow derivatives to overload as needed -class TypeCheckBase : public HIR::HIRFullVisitorBase +class TypeCheckBase { public: - using Rust::HIR::HIRFullVisitorBase::visit; - virtual ~TypeCheckBase () {} static TyTy::BaseType *coercion_site (HirId id, TyTy::BaseType *lhs, diff --git a/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc new file mode 100644 index 00000000000..e65b2011d36 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc @@ -0,0 +1,213 @@ +// 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-full.h" +#include "rust-hir-type-check-type.h" +#include "rust-hir-type-check-expr.h" +#include "rust-hir-type-check-enumitem.h" + +namespace Rust { +namespace Resolver { + +TyTy::VariantDef * +TypeCheckEnumItem::Resolve (HIR::EnumItem *item, int64_t last_discriminant) +{ + TypeCheckEnumItem resolver (last_discriminant); + switch (item->get_enum_item_kind ()) + { + case HIR::EnumItem::EnumItemKind::Named: + resolver.visit (static_cast (*item)); + break; + + case HIR::EnumItem::EnumItemKind::Tuple: + resolver.visit (static_cast (*item)); + break; + + case HIR::EnumItem::EnumItemKind::Struct: + resolver.visit (static_cast (*item)); + break; + + case HIR::EnumItem::EnumItemKind::Discriminant: + resolver.visit (static_cast (*item)); + break; + } + return resolver.variant; +} + +TypeCheckEnumItem::TypeCheckEnumItem (int64_t last_discriminant) + : TypeCheckBase (), variant (nullptr), last_discriminant (last_discriminant) +{} + +void +TypeCheckEnumItem::visit (HIR::EnumItem &item) +{ + if (last_discriminant == INT64_MAX) + rust_error_at (item.get_locus (), "discriminant too big"); + + Analysis::NodeMapping mapping (item.get_mappings ().get_crate_num (), + item.get_mappings ().get_nodeid (), + mappings->get_next_hir_id ( + item.get_mappings ().get_crate_num ()), + item.get_mappings ().get_local_defid ()); + HIR::LiteralExpr *discim_expr + = new HIR::LiteralExpr (mapping, std::to_string (last_discriminant), + HIR::Literal::LitType::INT, + PrimitiveCoreType::CORETYPE_I64, item.get_locus (), + {}); + + TyTy::BaseType *isize = nullptr; + bool ok = context->lookup_builtin ("isize", &isize); + rust_assert (ok); + context->insert_type (mapping, isize); + + const CanonicalPath *canonical_path = nullptr; + ok = mappings->lookup_canonical_path (item.get_mappings ().get_nodeid (), + &canonical_path); + rust_assert (ok); + + RustIdent ident{*canonical_path, item.get_locus ()}; + variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (), + item.get_identifier (), ident, discim_expr); +} + +void +TypeCheckEnumItem::visit (HIR::EnumItemDiscriminant &item) +{ + if (last_discriminant == INT64_MAX) + rust_error_at (item.get_locus (), "discriminant too big"); + + auto &discriminant = item.get_discriminant_expression (); + auto capacity_type = TypeCheckExpr::Resolve (discriminant.get ()); + if (capacity_type->get_kind () == TyTy::TypeKind::ERROR) + return; + + TyTy::ISizeType *expected_ty + = new TyTy::ISizeType (discriminant->get_mappings ().get_hirid ()); + context->insert_type (discriminant->get_mappings (), expected_ty); + + auto unified = expected_ty->unify (capacity_type); + if (unified->get_kind () == TyTy::TypeKind::ERROR) + return; + + const CanonicalPath *canonical_path = nullptr; + bool ok = mappings->lookup_canonical_path (item.get_mappings ().get_nodeid (), + &canonical_path); + rust_assert (ok); + + RustIdent ident{*canonical_path, item.get_locus ()}; + variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (), + item.get_identifier (), ident, + item.get_discriminant_expression ().get ()); +} + +void +TypeCheckEnumItem::visit (HIR::EnumItemTuple &item) +{ + if (last_discriminant == INT64_MAX) + rust_error_at (item.get_locus (), "discriminant too big"); + + std::vector fields; + size_t idx = 0; + for (auto &field : item.get_tuple_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); + fields.push_back (ty_field); + context->insert_type (field.get_mappings (), ty_field->get_field_type ()); + idx++; + } + + Analysis::NodeMapping mapping (item.get_mappings ().get_crate_num (), + item.get_mappings ().get_nodeid (), + mappings->get_next_hir_id ( + item.get_mappings ().get_crate_num ()), + item.get_mappings ().get_local_defid ()); + HIR::LiteralExpr *discim_expr + = new HIR::LiteralExpr (mapping, std::to_string (last_discriminant), + HIR::Literal::LitType::INT, + PrimitiveCoreType::CORETYPE_I64, item.get_locus (), + {}); + + TyTy::BaseType *isize = nullptr; + bool ok = context->lookup_builtin ("isize", &isize); + rust_assert (ok); + context->insert_type (mapping, isize); + + const CanonicalPath *canonical_path = nullptr; + ok = mappings->lookup_canonical_path (item.get_mappings ().get_nodeid (), + &canonical_path); + rust_assert (ok); + + RustIdent ident{*canonical_path, item.get_locus ()}; + variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (), + item.get_identifier (), ident, + TyTy::VariantDef::VariantType::TUPLE, + discim_expr, fields); +} + +void +TypeCheckEnumItem::visit (HIR::EnumItemStruct &item) +{ + if (last_discriminant == INT64_MAX) + rust_error_at (item.get_locus (), "discriminant too big"); + + std::vector fields; + for (auto &field : item.get_struct_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); + fields.push_back (ty_field); + context->insert_type (field.get_mappings (), ty_field->get_field_type ()); + } + + Analysis::NodeMapping mapping (item.get_mappings ().get_crate_num (), + item.get_mappings ().get_nodeid (), + mappings->get_next_hir_id ( + item.get_mappings ().get_crate_num ()), + item.get_mappings ().get_local_defid ()); + HIR::LiteralExpr *discrim_expr + = new HIR::LiteralExpr (mapping, std::to_string (last_discriminant), + HIR::Literal::LitType::INT, + PrimitiveCoreType::CORETYPE_I64, item.get_locus (), + {}); + + TyTy::BaseType *isize = nullptr; + bool ok = context->lookup_builtin ("isize", &isize); + rust_assert (ok); + context->insert_type (mapping, isize); + + const CanonicalPath *canonical_path = nullptr; + ok = mappings->lookup_canonical_path (item.get_mappings ().get_nodeid (), + &canonical_path); + rust_assert (ok); + + RustIdent ident{*canonical_path, item.get_locus ()}; + variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (), + item.get_identifier (), ident, + TyTy::VariantDef::VariantType::STRUCT, + discrim_expr, fields); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-enumitem.h b/gcc/rust/typecheck/rust-hir-type-check-enumitem.h index bc91f458b72..c771ea3782d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-enumitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-enumitem.h @@ -21,187 +21,24 @@ #include "rust-hir-type-check-base.h" #include "rust-hir-full.h" -#include "rust-hir-type-check-type.h" -#include "rust-hir-type-check-expr.h" - -extern ::Backend * -rust_get_backend (); namespace Rust { namespace Resolver { class TypeCheckEnumItem : public TypeCheckBase { - using Rust::Resolver::TypeCheckBase::visit; - public: static TyTy::VariantDef *Resolve (HIR::EnumItem *item, - int64_t last_discriminant) - { - TypeCheckEnumItem resolver (last_discriminant); - item->accept_vis (resolver); - return resolver.variant; - } + int64_t last_discriminant); - void visit (HIR::EnumItem &item) override - { - if (last_discriminant == INT64_MAX) - rust_error_at (item.get_locus (), "discriminant too big"); - - Analysis::NodeMapping mapping (item.get_mappings ().get_crate_num (), - item.get_mappings ().get_nodeid (), - mappings->get_next_hir_id ( - item.get_mappings ().get_crate_num ()), - item.get_mappings ().get_local_defid ()); - HIR::LiteralExpr *discim_expr - = new HIR::LiteralExpr (mapping, std::to_string (last_discriminant), - HIR::Literal::LitType::INT, - PrimitiveCoreType::CORETYPE_I64, - item.get_locus (), {}); - - TyTy::BaseType *isize = nullptr; - bool ok = context->lookup_builtin ("isize", &isize); - rust_assert (ok); - context->insert_type (mapping, isize); - - const CanonicalPath *canonical_path = nullptr; - ok = mappings->lookup_canonical_path (item.get_mappings ().get_nodeid (), - &canonical_path); - rust_assert (ok); - - RustIdent ident{*canonical_path, item.get_locus ()}; - variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (), - item.get_identifier (), ident, discim_expr); - } - - void visit (HIR::EnumItemDiscriminant &item) override - { - if (last_discriminant == INT64_MAX) - rust_error_at (item.get_locus (), "discriminant too big"); - - auto &discriminant = item.get_discriminant_expression (); - auto capacity_type = TypeCheckExpr::Resolve (discriminant.get ()); - if (capacity_type->get_kind () == TyTy::TypeKind::ERROR) - return; - - TyTy::ISizeType *expected_ty - = new TyTy::ISizeType (discriminant->get_mappings ().get_hirid ()); - context->insert_type (discriminant->get_mappings (), expected_ty); - - auto unified = expected_ty->unify (capacity_type); - if (unified->get_kind () == TyTy::TypeKind::ERROR) - return; - - const CanonicalPath *canonical_path = nullptr; - bool ok - = mappings->lookup_canonical_path (item.get_mappings ().get_nodeid (), - &canonical_path); - rust_assert (ok); - - RustIdent ident{*canonical_path, item.get_locus ()}; - variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (), - item.get_identifier (), ident, - item.get_discriminant_expression ().get ()); - } - - void visit (HIR::EnumItemTuple &item) override - { - if (last_discriminant == INT64_MAX) - rust_error_at (item.get_locus (), "discriminant too big"); - - std::vector fields; - size_t idx = 0; - for (auto &field : item.get_tuple_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); - fields.push_back (ty_field); - context->insert_type (field.get_mappings (), - ty_field->get_field_type ()); - idx++; - } - - Analysis::NodeMapping mapping (item.get_mappings ().get_crate_num (), - item.get_mappings ().get_nodeid (), - mappings->get_next_hir_id ( - item.get_mappings ().get_crate_num ()), - item.get_mappings ().get_local_defid ()); - HIR::LiteralExpr *discim_expr - = new HIR::LiteralExpr (mapping, std::to_string (last_discriminant), - HIR::Literal::LitType::INT, - PrimitiveCoreType::CORETYPE_I64, - item.get_locus (), {}); - - TyTy::BaseType *isize = nullptr; - bool ok = context->lookup_builtin ("isize", &isize); - rust_assert (ok); - context->insert_type (mapping, isize); - - const CanonicalPath *canonical_path = nullptr; - ok = mappings->lookup_canonical_path (item.get_mappings ().get_nodeid (), - &canonical_path); - rust_assert (ok); - - RustIdent ident{*canonical_path, item.get_locus ()}; - variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (), - item.get_identifier (), ident, - TyTy::VariantDef::VariantType::TUPLE, - discim_expr, fields); - } - - void visit (HIR::EnumItemStruct &item) override - { - if (last_discriminant == INT64_MAX) - rust_error_at (item.get_locus (), "discriminant too big"); - - std::vector fields; - for (auto &field : item.get_struct_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); - fields.push_back (ty_field); - context->insert_type (field.get_mappings (), - ty_field->get_field_type ()); - } - - Analysis::NodeMapping mapping (item.get_mappings ().get_crate_num (), - item.get_mappings ().get_nodeid (), - mappings->get_next_hir_id ( - item.get_mappings ().get_crate_num ()), - item.get_mappings ().get_local_defid ()); - HIR::LiteralExpr *discrim_expr - = new HIR::LiteralExpr (mapping, std::to_string (last_discriminant), - HIR::Literal::LitType::INT, - PrimitiveCoreType::CORETYPE_I64, - item.get_locus (), {}); - - TyTy::BaseType *isize = nullptr; - bool ok = context->lookup_builtin ("isize", &isize); - rust_assert (ok); - context->insert_type (mapping, isize); - - const CanonicalPath *canonical_path = nullptr; - ok = mappings->lookup_canonical_path (item.get_mappings ().get_nodeid (), - &canonical_path); - rust_assert (ok); - - RustIdent ident{*canonical_path, item.get_locus ()}; - variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (), - item.get_identifier (), ident, - TyTy::VariantDef::VariantType::STRUCT, - discrim_expr, fields); - } +protected: + void visit (HIR::EnumItem &item); + void visit (HIR::EnumItemDiscriminant &item); + void visit (HIR::EnumItemTuple &item); + void visit (HIR::EnumItemStruct &item); private: - TypeCheckEnumItem (int64_t last_discriminant) - : TypeCheckBase (), variant (nullptr), last_discriminant (last_discriminant) - {} + TypeCheckEnumItem (int64_t last_discriminant); TyTy::VariantDef *variant; int64_t last_discriminant; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index ff1165d093f..03999baffa4 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -16,11 +16,555 @@ // along with GCC; see the file COPYING3. If not see // . +#include "rust-hir-full.h" +#include "rust-tyty-call.h" +#include "rust-hir-type-check-struct-field.h" +#include "rust-hir-path-probe.h" +#include "rust-substitution-mapper.h" +#include "rust-hir-trait-resolve.h" +#include "rust-hir-type-bounds.h" +#include "rust-hir-dot-operator.h" +#include "rust-hir-type-check-pattern.h" #include "rust-hir-type-check-expr.h" +#include "rust-hir-type-check-stmt.h" namespace Rust { namespace Resolver { +TypeCheckExpr::TypeCheckExpr () : TypeCheckBase (), infered (nullptr) {} + +// Perform type checking on expr. Also runs type unification algorithm. +// Returns the unified type of expr +TyTy::BaseType * +TypeCheckExpr::Resolve (HIR::Expr *expr) +{ + TypeCheckExpr resolver; + expr->accept_vis (resolver); + + if (resolver.infered == nullptr) + { + // FIXME + // this is an internal error message for debugging and should be removed + // at some point + rust_error_at (expr->get_locus (), "failed to type resolve expression"); + return new TyTy::ErrorType (expr->get_mappings ().get_hirid ()); + } + + auto ref = expr->get_mappings ().get_hirid (); + resolver.infered->set_ref (ref); + resolver.context->insert_type (expr->get_mappings (), resolver.infered); + + return resolver.infered; +} + +void +TypeCheckExpr::visit (HIR::TupleIndexExpr &expr) +{ + auto resolved = TypeCheckExpr::Resolve (expr.get_tuple_expr ().get ()); + if (resolved->get_kind () == TyTy::TypeKind::ERROR) + { + rust_error_at (expr.get_tuple_expr ()->get_locus (), + "failed to resolve TupleIndexExpr receiver"); + return; + } + + // FIXME does this require autoderef here? + if (resolved->get_kind () == TyTy::TypeKind::REF) + { + TyTy::ReferenceType *r = static_cast (resolved); + resolved = r->get_base (); + } + + bool is_valid_type = resolved->get_kind () == TyTy::TypeKind::ADT + || resolved->get_kind () == TyTy::TypeKind::TUPLE; + if (!is_valid_type) + { + rust_error_at (expr.get_tuple_expr ()->get_locus (), + "Expected Tuple or ADT got: %s", + resolved->as_string ().c_str ()); + return; + } + + if (resolved->get_kind () == TyTy::TypeKind::TUPLE) + { + TyTy::TupleType *tuple = static_cast (resolved); + TupleIndex index = expr.get_tuple_index (); + if ((size_t) index >= tuple->num_fields ()) + { + rust_error_at (expr.get_locus (), "unknown field at index %i", index); + return; + } + + auto field_tyty = tuple->get_field ((size_t) index); + if (field_tyty == nullptr) + { + rust_error_at (expr.get_locus (), + "failed to lookup field type at index %i", index); + return; + } + + infered = field_tyty; + return; + } + + TyTy::ADTType *adt = static_cast (resolved); + rust_assert (!adt->is_enum ()); + rust_assert (adt->number_of_variants () == 1); + + TyTy::VariantDef *variant = adt->get_variants ().at (0); + TupleIndex index = expr.get_tuple_index (); + if ((size_t) index >= variant->num_fields ()) + { + rust_error_at (expr.get_locus (), "unknown field at index %i", index); + return; + } + + auto field_tyty = variant->get_field_at_index ((size_t) index); + if (field_tyty == nullptr) + { + rust_error_at (expr.get_locus (), + "failed to lookup field type at index %i", index); + return; + } + + infered = field_tyty->get_field_type (); +} + +void +TypeCheckExpr::visit (HIR::TupleExpr &expr) +{ + if (expr.is_unit ()) + { + auto unit_node_id = resolver->get_unit_type_node_id (); + if (!context->lookup_builtin (unit_node_id, &infered)) + { + rust_error_at (expr.get_locus (), + "failed to lookup builtin unit type"); + } + return; + } + + std::vector fields; + for (auto &elem : expr.get_tuple_elems ()) + { + auto field_ty = TypeCheckExpr::Resolve (elem.get ()); + fields.push_back (TyTy::TyVar (field_ty->get_ref ())); + } + infered = new TyTy::TupleType (expr.get_mappings ().get_hirid (), + expr.get_locus (), fields); +} + +void +TypeCheckExpr::visit (HIR::ReturnExpr &expr) +{ + auto fn_return_tyty = context->peek_return_type (); + rust_assert (fn_return_tyty != nullptr); + + TyTy::BaseType *expr_ty + = expr.has_return_expr () + ? TypeCheckExpr::Resolve (expr.get_expr ()) + : TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); + + infered = fn_return_tyty->unify (expr_ty); + fn_return_tyty->append_reference (expr_ty->get_ref ()); + for (auto &ref : infered->get_combined_refs ()) + fn_return_tyty->append_reference (ref); + + infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ()); +} + +void +TypeCheckExpr::visit (HIR::CallExpr &expr) +{ + TyTy::BaseType *function_tyty = TypeCheckExpr::Resolve (expr.get_fnexpr ()); + + bool valid_tyty = function_tyty->get_kind () == TyTy::TypeKind::ADT + || function_tyty->get_kind () == TyTy::TypeKind::FNDEF + || function_tyty->get_kind () == TyTy::TypeKind::FNPTR; + if (!valid_tyty) + { + rust_error_at (expr.get_locus (), + "Failed to resolve expression of function call"); + return; + } + + TyTy::VariantDef &variant = TyTy::VariantDef::get_error_node (); + if (function_tyty->get_kind () == TyTy::TypeKind::ADT) + { + TyTy::ADTType *adt = static_cast (function_tyty); + if (adt->is_enum ()) + { + // lookup variant id + HirId variant_id; + bool ok = context->lookup_variant_definition ( + expr.get_fnexpr ()->get_mappings ().get_hirid (), &variant_id); + rust_assert (ok); + + TyTy::VariantDef *lookup_variant = nullptr; + ok = adt->lookup_variant_by_id (variant_id, &lookup_variant); + rust_assert (ok); + + variant = *lookup_variant; + } + else + { + rust_assert (adt->number_of_variants () == 1); + variant = *adt->get_variants ().at (0); + } + } + + infered = TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, context); +} + +void +TypeCheckExpr::visit (HIR::AssignmentExpr &expr) +{ + infered = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); + + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + + coercion_site (expr.get_mappings ().get_hirid (), lhs, rhs, + expr.get_locus ()); +} + +void +TypeCheckExpr::visit (HIR::CompoundAssignmentExpr &expr) +{ + infered = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); + + auto lhs = TypeCheckExpr::Resolve (expr.get_left_expr ().get ()); + auto rhs = TypeCheckExpr::Resolve (expr.get_right_expr ().get ()); + + // we dont care about the result of the unify from a compound assignment + // since this is a unit-type expr + auto result = lhs->unify (rhs); + if (result->get_kind () == TyTy::TypeKind::ERROR) + return; + + auto lang_item_type + = Analysis::RustLangItem::CompoundAssignmentOperatorToLangItem ( + expr.get_expr_type ()); + bool operator_overloaded + = resolve_operator_overload (lang_item_type, expr, lhs, rhs); + if (operator_overloaded) + return; + + bool valid_lhs = validate_arithmetic_type (lhs, expr.get_expr_type ()); + bool valid_rhs = validate_arithmetic_type (rhs, expr.get_expr_type ()); + bool valid = valid_lhs && valid_rhs; + if (!valid) + { + rust_error_at (expr.get_locus (), + "cannot apply this operator to types %s and %s", + lhs->as_string ().c_str (), rhs->as_string ().c_str ()); + return; + } +} + +void +TypeCheckExpr::visit (HIR::IdentifierExpr &expr) +{ + NodeId ast_node_id = expr.get_mappings ().get_nodeid (); + + // then lookup the reference_node_id + NodeId ref_node_id = UNKNOWN_NODEID; + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + { + resolver->lookup_resolved_type (ast_node_id, &ref_node_id); + } + + if (ref_node_id == UNKNOWN_NODEID) + { + // FIXME this needs to go away and just return error node + rust_error_at (expr.get_locus (), "unresolved node: %s", + expr.as_string ().c_str ()); + return; + } + + // node back to HIR + HirId ref; + if (!mappings->lookup_node_to_hir (ref_node_id, &ref)) + { + // FIXME + // this is an internal error + rust_error_at (expr.get_locus (), "123 reverse lookup failure"); + return; + } + + // the base reference for this name _must_ have a type set + TyTy::BaseType *lookup; + if (!context->lookup_type (ref, &lookup)) + { + // FIXME + // this is an internal error + rust_error_at (mappings->lookup_location (ref), + "Failed to resolve IdentifierExpr type: %s", + expr.as_string ().c_str ()); + return; + } + + infered = lookup->clone (); + + // Generic unit structs look like an identifier but they actually need be + // handled as a path-in-expression so this gives us a chance to infer the + // generic parameters. + // see https://github.com/Rust-GCC/gccrs/issues/1447 + bool is_unit_struct + = infered->get_kind () == TyTy::TypeKind::ADT && infered->is_unit (); + if (is_unit_struct && infered->needs_generic_substitutions ()) + { + infered = SubstMapper::InferSubst (infered, expr.get_locus ()); + } +} + +void +TypeCheckExpr::visit (HIR::LiteralExpr &expr) +{ + infered = resolve_literal (expr.get_mappings (), expr.get_literal (), + expr.get_locus ()); +} + +void +TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) +{ + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + + auto lang_item_type + = Analysis::RustLangItem::OperatorToLangItem (expr.get_expr_type ()); + bool operator_overloaded + = resolve_operator_overload (lang_item_type, expr, lhs, rhs); + if (operator_overloaded) + return; + + bool valid_lhs = validate_arithmetic_type (lhs, expr.get_expr_type ()); + bool valid_rhs = validate_arithmetic_type (rhs, expr.get_expr_type ()); + bool valid = valid_lhs && valid_rhs; + if (!valid) + { + rust_error_at (expr.get_locus (), + "cannot apply this operator to types %s and %s", + lhs->as_string ().c_str (), rhs->as_string ().c_str ()); + return; + } + + switch (expr.get_expr_type ()) + { + case ArithmeticOrLogicalOperator::LEFT_SHIFT: + case ArithmeticOrLogicalOperator::RIGHT_SHIFT: + infered = rhs->cast (lhs); + break; + + default: + infered = lhs->unify (rhs); + break; + } +} + +void +TypeCheckExpr::visit (HIR::ComparisonExpr &expr) +{ + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + + auto result = lhs->unify (rhs); + if (result == nullptr || result->get_kind () == TyTy::TypeKind::ERROR) + return; + + bool ok = context->lookup_builtin ("bool", &infered); + rust_assert (ok); +} + +void +TypeCheckExpr::visit (HIR::LazyBooleanExpr &expr) +{ + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + + // we expect the lhs and rhs must be bools at this point + TyTy::BoolType elhs (expr.get_mappings ().get_hirid ()); + lhs = elhs.unify (lhs); + if (lhs->get_kind () == TyTy::TypeKind::ERROR) + return; + + TyTy::BoolType rlhs (expr.get_mappings ().get_hirid ()); + rhs = elhs.unify (rhs); + if (lhs->get_kind () == TyTy::TypeKind::ERROR) + return; + + infered = lhs->unify (rhs); +} + +void +TypeCheckExpr::visit (HIR::NegationExpr &expr) +{ + auto negated_expr_ty = TypeCheckExpr::Resolve (expr.get_expr ().get ()); + + // check for operator overload + auto lang_item_type = Analysis::RustLangItem::NegationOperatorToLangItem ( + expr.get_expr_type ()); + bool operator_overloaded + = resolve_operator_overload (lang_item_type, expr, negated_expr_ty, + nullptr); + if (operator_overloaded) + return; + + // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators + switch (expr.get_expr_type ()) + { + case NegationOperator::NEGATE: { + bool valid + = (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::FLOAT) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::ISIZE) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::USIZE) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind () + == TyTy::InferType::INTEGRAL)) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind () + == TyTy::InferType::FLOAT)); + if (!valid) + { + rust_error_at (expr.get_locus (), "cannot apply unary - to %s", + negated_expr_ty->as_string ().c_str ()); + return; + } + } + break; + + case NegationOperator::NOT: { + bool valid + = (negated_expr_ty->get_kind () == TyTy::TypeKind::BOOL) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT) + || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind () + == TyTy::InferType::INTEGRAL)); + if (!valid) + { + rust_error_at (expr.get_locus (), "cannot apply unary % to %s", + negated_expr_ty->as_string ().c_str ()); + return; + } + } + break; + } + + infered = negated_expr_ty->clone (); + infered->append_reference (negated_expr_ty->get_ref ()); +} + +void +TypeCheckExpr::visit (HIR::IfExpr &expr) +{ + TypeCheckExpr::Resolve (expr.get_if_condition ()); + TypeCheckExpr::Resolve (expr.get_if_block ()); + + infered = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); +} + +void +TypeCheckExpr::visit (HIR::IfExprConseqElse &expr) +{ + TypeCheckExpr::Resolve (expr.get_if_condition ()); + auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ()); + auto else_blk_resolved = TypeCheckExpr::Resolve (expr.get_else_block ()); + + if (if_blk_resolved->get_kind () == TyTy::NEVER) + infered = else_blk_resolved; + else if (else_blk_resolved->get_kind () == TyTy::NEVER) + infered = if_blk_resolved; + else + infered = if_blk_resolved->unify (else_blk_resolved); +} + +void +TypeCheckExpr::visit (HIR::IfExprConseqIf &expr) +{ + TypeCheckExpr::Resolve (expr.get_if_condition ()); + auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ()); + auto else_blk_resolved = TypeCheckExpr::Resolve (expr.get_conseq_if_expr ()); + + if (if_blk_resolved->get_kind () == TyTy::NEVER) + infered = else_blk_resolved; + else if (else_blk_resolved->get_kind () == TyTy::NEVER) + infered = if_blk_resolved; + else + infered = if_blk_resolved->unify (else_blk_resolved); +} + +void +TypeCheckExpr::visit (HIR::IfLetExpr &expr) +{ + // this needs to perform a least upper bound coercion on the blocks and then + // unify the scruintee and arms + TyTy::BaseType *scrutinee_tyty + = TypeCheckExpr::Resolve (expr.get_scrutinee_expr ().get ()); + + for (auto &pattern : expr.get_patterns ()) + { + TyTy::BaseType *kase_arm_ty + = TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty); + + TyTy::BaseType *checked_kase = scrutinee_tyty->unify (kase_arm_ty); + if (checked_kase->get_kind () == TyTy::TypeKind::ERROR) + return; + } + + TypeCheckExpr::Resolve (expr.get_if_block ()); + + infered = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); +} + +void +TypeCheckExpr::visit (HIR::UnsafeBlockExpr &expr) +{ + infered = TypeCheckExpr::Resolve (expr.get_block_expr ().get ()); +} + +void +TypeCheckExpr::visit (HIR::BlockExpr &expr) +{ + for (auto &s : expr.get_statements ()) + { + if (!s->is_item ()) + continue; + + TypeCheckStmt::Resolve (s.get ()); + } + + for (auto &s : expr.get_statements ()) + { + if (s->is_item ()) + continue; + + auto resolved = TypeCheckStmt::Resolve (s.get ()); + if (resolved == nullptr) + { + rust_error_at (s->get_locus (), "failure to resolve type"); + return; + } + + if (s->is_unit_check_needed () && !resolved->is_unit ()) + { + auto unit + = TyTy::TupleType::get_unit_type (s->get_mappings ().get_hirid ()); + resolved = unit->unify (resolved); + } + } + + if (expr.has_expr ()) + infered = TypeCheckExpr::Resolve (expr.get_final_expr ().get ())->clone (); + else if (expr.is_tail_reachable ()) + infered + = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); + else + infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ()); +} + void TypeCheckExpr::visit (HIR::RangeFromToExpr &expr) { @@ -304,6 +848,146 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr) index_expr_ty->get_name ().c_str ()); } +void +TypeCheckExpr::visit (HIR::ArrayExpr &expr) +{ + HIR::ArrayElems &elements = *expr.get_internal_elements (); + + HIR::Expr *capacity_expr = nullptr; + TyTy::BaseType *element_type = nullptr; + switch (elements.get_array_expr_type ()) + { + case HIR::ArrayElems::ArrayExprType::COPIED: { + HIR::ArrayElemsCopied &elems + = static_cast (elements); + element_type = TypeCheckExpr::Resolve (elems.get_elem_to_copy ()); + + auto capacity_type + = TypeCheckExpr::Resolve (elems.get_num_copies_expr ()); + + TyTy::BaseType *expected_ty = nullptr; + bool ok = context->lookup_builtin ("usize", &expected_ty); + rust_assert (ok); + context->insert_type (elems.get_num_copies_expr ()->get_mappings (), + expected_ty); + + auto unified = expected_ty->unify (capacity_type); + if (unified->get_kind () == TyTy::TypeKind::ERROR) + return; + + capacity_expr = elems.get_num_copies_expr (); + } + break; + + case HIR::ArrayElems::ArrayExprType::VALUES: { + HIR::ArrayElemsValues &elems + = static_cast (elements); + + std::vector types; + for (auto &elem : elems.get_values ()) + { + types.push_back (TypeCheckExpr::Resolve (elem.get ())); + } + + element_type + = TyTy::TyVar::get_implicit_infer_var (expr.get_locus ()).get_tyty (); + for (auto &type : types) + { + element_type = element_type->unify (type); + } + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, UNKNOWN_NODEID, + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + std::string capacity_str = std::to_string (elems.get_num_elements ()); + capacity_expr = new HIR::LiteralExpr (mapping, capacity_str, + HIR::Literal::LitType::INT, + PrimitiveCoreType::CORETYPE_USIZE, + Location (), {}); + + // mark the type for this implicit node + TyTy::BaseType *expected_ty = nullptr; + bool ok = context->lookup_builtin ("usize", &expected_ty); + rust_assert (ok); + context->insert_type (mapping, expected_ty); + } + break; + } + + infered = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), + expr.get_locus (), *capacity_expr, + TyTy::TyVar (element_type->get_ref ())); +} + +// empty struct +void +TypeCheckExpr::visit (HIR::StructExprStruct &struct_expr) +{ + TyTy::BaseType *struct_path_ty + = TypeCheckExpr::Resolve (&struct_expr.get_struct_name ()); + if (struct_path_ty->get_kind () != TyTy::TypeKind::ADT) + { + rust_error_at (struct_expr.get_struct_name ().get_locus (), + "expected an ADT type for constructor"); + return; + } + + infered = struct_path_ty; +} + +void +TypeCheckExpr::visit (HIR::StructExprStructFields &struct_expr) +{ + infered = TypeCheckStructExpr::Resolve (&struct_expr); +} + +void +TypeCheckExpr::visit (HIR::GroupedExpr &expr) +{ + infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get ()); +} + +void +TypeCheckExpr::visit (HIR::FieldAccessExpr &expr) +{ + auto struct_base = TypeCheckExpr::Resolve (expr.get_receiver_expr ().get ()); + + // FIXME does this require autoderef here? + if (struct_base->get_kind () == TyTy::TypeKind::REF) + { + TyTy::ReferenceType *r = static_cast (struct_base); + struct_base = r->get_base (); + } + + bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT; + if (!is_valid_type) + { + rust_error_at (expr.get_locus (), + "expected algebraic data type got: [%s]", + struct_base->as_string ().c_str ()); + return; + } + + TyTy::ADTType *adt = static_cast (struct_base); + rust_assert (!adt->is_enum ()); + rust_assert (adt->number_of_variants () == 1); + + TyTy::VariantDef *vaiant = adt->get_variants ().at (0); + + TyTy::StructFieldType *lookup = nullptr; + bool found = vaiant->lookup_field (expr.get_field_name (), &lookup, nullptr); + if (!found) + { + rust_error_at (expr.get_locus (), "unknown field [%s] for type [%s]", + expr.get_field_name ().c_str (), + adt->as_string ().c_str ()); + return; + } + + infered = lookup->get_field_type (); +} + void TypeCheckExpr::visit (HIR::MethodCallExpr &expr) { @@ -459,6 +1143,232 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr) infered = function_ret_tyty; } +void +TypeCheckExpr::visit (HIR::LoopExpr &expr) +{ + context->push_new_loop_context (expr.get_mappings ().get_hirid (), + expr.get_locus ()); + TyTy::BaseType *block_expr + = TypeCheckExpr::Resolve (expr.get_loop_block ().get ()); + if (!block_expr->is_unit ()) + { + rust_error_at (expr.get_loop_block ()->get_locus (), + "expected %<()%> got %s", + block_expr->as_string ().c_str ()); + return; + } + + TyTy::BaseType *loop_context_type = context->pop_loop_context (); + + bool loop_context_type_infered + = (loop_context_type->get_kind () != TyTy::TypeKind::INFER) + || ((loop_context_type->get_kind () == TyTy::TypeKind::INFER) + && (((TyTy::InferType *) loop_context_type)->get_infer_kind () + != TyTy::InferType::GENERAL)); + + infered + = loop_context_type_infered + ? loop_context_type + : TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); +} + +void +TypeCheckExpr::visit (HIR::WhileLoopExpr &expr) +{ + context->push_new_while_loop_context (expr.get_mappings ().get_hirid ()); + + TypeCheckExpr::Resolve (expr.get_predicate_expr ().get ()); + TyTy::BaseType *block_expr + = TypeCheckExpr::Resolve (expr.get_loop_block ().get ()); + + if (!block_expr->is_unit ()) + { + rust_error_at (expr.get_loop_block ()->get_locus (), + "expected %<()%> got %s", + block_expr->as_string ().c_str ()); + return; + } + + context->pop_loop_context (); + infered = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); +} + +void +TypeCheckExpr::visit (HIR::BreakExpr &expr) +{ + if (!context->have_loop_context ()) + { + rust_error_at (expr.get_locus (), "cannot % outside of a loop"); + return; + } + + if (expr.has_break_expr ()) + { + TyTy::BaseType *break_expr_tyty + = TypeCheckExpr::Resolve (expr.get_expr ().get ()); + + TyTy::BaseType *loop_context = context->peek_loop_context (); + if (loop_context->get_kind () == TyTy::TypeKind::ERROR) + { + rust_error_at (expr.get_locus (), + "can only break with a value inside %"); + return; + } + + TyTy::BaseType *unified_ty = loop_context->unify (break_expr_tyty); + context->swap_head_loop_context (unified_ty); + } + + infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ()); +} + +void +TypeCheckExpr::visit (HIR::ContinueExpr &expr) +{ + if (!context->have_loop_context ()) + { + rust_error_at (expr.get_locus (), + "cannot % outside of a loop"); + return; + } + + infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ()); +} + +void +TypeCheckExpr::visit (HIR::BorrowExpr &expr) +{ + TyTy::BaseType *resolved_base + = TypeCheckExpr::Resolve (expr.get_expr ().get ()); + + // In Rust this is valid because of DST's + // + // fn test() { + // let a:&str = "TEST 1"; + // let b:&str = &"TEST 2"; + // } + if (resolved_base->get_kind () == TyTy::TypeKind::REF) + { + const TyTy::ReferenceType *ref + = static_cast (resolved_base); + + // this might end up being a more generic is_dyn object check but lets + // double check dyn traits type-layout first + if (ref->is_dyn_str_type ()) + { + infered = resolved_base; + return; + } + } + + if (expr.get_is_double_borrow ()) + { + // FIXME double_reference + gcc_unreachable (); + } + + infered = new TyTy::ReferenceType (expr.get_mappings ().get_hirid (), + TyTy::TyVar (resolved_base->get_ref ()), + expr.get_mut ()); +} + +void +TypeCheckExpr::visit (HIR::DereferenceExpr &expr) +{ + TyTy::BaseType *resolved_base + = TypeCheckExpr::Resolve (expr.get_expr ().get ()); + + auto lang_item_type = Analysis::RustLangItem::ItemType::DEREF; + bool operator_overloaded + = resolve_operator_overload (lang_item_type, expr, resolved_base, nullptr); + if (operator_overloaded) + { + // operator overloaded deref always refurns a reference type lets assert + // this + rust_assert (infered->get_kind () == TyTy::TypeKind::REF); + resolved_base = infered; + } + + bool is_valid_type = resolved_base->get_kind () == TyTy::TypeKind::REF + || resolved_base->get_kind () == TyTy::TypeKind::POINTER; + if (!is_valid_type) + { + rust_error_at (expr.get_locus (), "expected reference type got %s", + resolved_base->as_string ().c_str ()); + return; + } + + if (resolved_base->get_kind () == TyTy::TypeKind::REF) + { + TyTy::ReferenceType *ref_base + = static_cast (resolved_base); + infered = ref_base->get_base ()->clone (); + } + else + { + TyTy::PointerType *ref_base + = static_cast (resolved_base); + infered = ref_base->get_base ()->clone (); + } +} + +void +TypeCheckExpr::visit (HIR::TypeCastExpr &expr) +{ + TyTy::BaseType *expr_to_convert + = TypeCheckExpr::Resolve (expr.get_casted_expr ().get ()); + TyTy::BaseType *tyty_to_convert_to + = TypeCheckType::Resolve (expr.get_type_to_convert_to ().get ()); + + infered = expr_to_convert->cast (tyty_to_convert_to); +} + +void +TypeCheckExpr::visit (HIR::MatchExpr &expr) +{ + // this needs to perform a least upper bound coercion on the blocks and then + // unify the scruintee and arms + TyTy::BaseType *scrutinee_tyty + = TypeCheckExpr::Resolve (expr.get_scrutinee_expr ().get ()); + + std::vector kase_block_tys; + for (auto &kase : expr.get_match_cases ()) + { + // lets check the arms + HIR::MatchArm &kase_arm = kase.get_arm (); + for (auto &pattern : kase_arm.get_patterns ()) + { + TyTy::BaseType *kase_arm_ty + = TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty); + + TyTy::BaseType *checked_kase = scrutinee_tyty->unify (kase_arm_ty); + if (checked_kase->get_kind () == TyTy::TypeKind::ERROR) + return; + } + + // check the kase type + TyTy::BaseType *kase_block_ty + = TypeCheckExpr::Resolve (kase.get_expr ().get ()); + kase_block_tys.push_back (kase_block_ty); + } + + if (kase_block_tys.size () == 0) + { + infered + = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); + return; + } + + infered = kase_block_tys.at (0); + for (size_t i = 1; i < kase_block_tys.size (); i++) + { + TyTy::BaseType *kase_ty = kase_block_tys.at (i); + infered = infered->unify (kase_ty); + if (infered->get_kind () == TyTy::TypeKind::ERROR) + return; + } +} + bool TypeCheckExpr::resolve_operator_overload ( Analysis::RustLangItem::ItemType lang_item_type, HIR::OperatorExprMeta expr, @@ -644,5 +1554,61 @@ TypeCheckExpr::resolve_operator_overload ( return true; } +bool +TypeCheckExpr::validate_arithmetic_type ( + const TyTy::BaseType *tyty, HIR::ArithmeticOrLogicalExpr::ExprType expr_type) +{ + const TyTy::BaseType *type = tyty->destructure (); + + // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators + // this will change later when traits are added + switch (expr_type) + { + case ArithmeticOrLogicalOperator::ADD: + case ArithmeticOrLogicalOperator::SUBTRACT: + case ArithmeticOrLogicalOperator::MULTIPLY: + case ArithmeticOrLogicalOperator::DIVIDE: + case ArithmeticOrLogicalOperator::MODULUS: + return (type->get_kind () == TyTy::TypeKind::INT) + || (type->get_kind () == TyTy::TypeKind::UINT) + || (type->get_kind () == TyTy::TypeKind::FLOAT) + || (type->get_kind () == TyTy::TypeKind::USIZE) + || (type->get_kind () == TyTy::TypeKind::ISIZE) + || (type->get_kind () == TyTy::TypeKind::INFER + && (((const TyTy::InferType *) type)->get_infer_kind () + == TyTy::InferType::INTEGRAL)) + || (type->get_kind () == TyTy::TypeKind::INFER + && (((const TyTy::InferType *) type)->get_infer_kind () + == TyTy::InferType::FLOAT)); + + // integers or bools + case ArithmeticOrLogicalOperator::BITWISE_AND: + case ArithmeticOrLogicalOperator::BITWISE_OR: + case ArithmeticOrLogicalOperator::BITWISE_XOR: + return (type->get_kind () == TyTy::TypeKind::INT) + || (type->get_kind () == TyTy::TypeKind::UINT) + || (type->get_kind () == TyTy::TypeKind::USIZE) + || (type->get_kind () == TyTy::TypeKind::ISIZE) + || (type->get_kind () == TyTy::TypeKind::BOOL) + || (type->get_kind () == TyTy::TypeKind::INFER + && (((const TyTy::InferType *) type)->get_infer_kind () + == TyTy::InferType::INTEGRAL)); + + // integers only + case ArithmeticOrLogicalOperator::LEFT_SHIFT: + case ArithmeticOrLogicalOperator::RIGHT_SHIFT: + return (type->get_kind () == TyTy::TypeKind::INT) + || (type->get_kind () == TyTy::TypeKind::UINT) + || (type->get_kind () == TyTy::TypeKind::USIZE) + || (type->get_kind () == TyTy::TypeKind::ISIZE) + || (type->get_kind () == TyTy::TypeKind::INFER + && (((const TyTy::InferType *) type)->get_infer_kind () + == TyTy::InferType::INTEGRAL)); + } + + gcc_unreachable (); + return false; +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 0c44f28e4ac..01cb213f002 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -20,887 +20,84 @@ #define RUST_HIR_TYPE_CHECK_EXPR #include "rust-hir-type-check-base.h" -#include "rust-hir-full.h" -#include "rust-system.h" #include "rust-tyty.h" -#include "rust-tyty-call.h" -#include "rust-hir-type-check-struct-field.h" -#include "rust-hir-path-probe.h" -#include "rust-substitution-mapper.h" -#include "rust-hir-trait-resolve.h" -#include "rust-hir-type-bounds.h" -#include "rust-hir-dot-operator.h" -#include "rust-hir-type-check-pattern.h" namespace Rust { namespace Resolver { -class TypeCheckExpr : public TypeCheckBase +class TypeCheckExpr : public TypeCheckBase, private HIR::HIRExpressionVisitor { - using Rust::Resolver::TypeCheckBase::visit; - public: - // Perform type checking on expr. Also runs type unification algorithm. - // Returns the unified type of expr - static TyTy::BaseType *Resolve (HIR::Expr *expr) - { - TypeCheckExpr resolver; - expr->accept_vis (resolver); - - if (resolver.infered == nullptr) - { - // FIXME - // this is an internal error message for debugging and should be removed - // at some point - rust_error_at (expr->get_locus (), "failed to type resolve expression"); - return new TyTy::ErrorType (expr->get_mappings ().get_hirid ()); - } - - auto ref = expr->get_mappings ().get_hirid (); - resolver.infered->set_ref (ref); - resolver.context->insert_type (expr->get_mappings (), resolver.infered); - - return resolver.infered; - } - - void visit (HIR::TupleIndexExpr &expr) override - { - auto resolved = TypeCheckExpr::Resolve (expr.get_tuple_expr ().get ()); - if (resolved->get_kind () == TyTy::TypeKind::ERROR) - { - rust_error_at (expr.get_tuple_expr ()->get_locus (), - "failed to resolve TupleIndexExpr receiver"); - return; - } - - // FIXME does this require autoderef here? - if (resolved->get_kind () == TyTy::TypeKind::REF) - { - TyTy::ReferenceType *r = static_cast (resolved); - resolved = r->get_base (); - } - - bool is_valid_type = resolved->get_kind () == TyTy::TypeKind::ADT - || resolved->get_kind () == TyTy::TypeKind::TUPLE; - if (!is_valid_type) - { - rust_error_at (expr.get_tuple_expr ()->get_locus (), - "Expected Tuple or ADT got: %s", - resolved->as_string ().c_str ()); - return; - } - - if (resolved->get_kind () == TyTy::TypeKind::TUPLE) - { - TyTy::TupleType *tuple = static_cast (resolved); - TupleIndex index = expr.get_tuple_index (); - if ((size_t) index >= tuple->num_fields ()) - { - rust_error_at (expr.get_locus (), "unknown field at index %i", - index); - return; - } - - auto field_tyty = tuple->get_field ((size_t) index); - if (field_tyty == nullptr) - { - rust_error_at (expr.get_locus (), - "failed to lookup field type at index %i", index); - return; - } - - infered = field_tyty; - return; - } - - TyTy::ADTType *adt = static_cast (resolved); - rust_assert (!adt->is_enum ()); - rust_assert (adt->number_of_variants () == 1); - - TyTy::VariantDef *variant = adt->get_variants ().at (0); - TupleIndex index = expr.get_tuple_index (); - if ((size_t) index >= variant->num_fields ()) - { - rust_error_at (expr.get_locus (), "unknown field at index %i", index); - return; - } - - auto field_tyty = variant->get_field_at_index ((size_t) index); - if (field_tyty == nullptr) - { - rust_error_at (expr.get_locus (), - "failed to lookup field type at index %i", index); - return; - } - - infered = field_tyty->get_field_type (); - } - - void visit (HIR::TupleExpr &expr) override - { - if (expr.is_unit ()) - { - auto unit_node_id = resolver->get_unit_type_node_id (); - if (!context->lookup_builtin (unit_node_id, &infered)) - { - rust_error_at (expr.get_locus (), - "failed to lookup builtin unit type"); - } - return; - } - - std::vector fields; - for (auto &elem : expr.get_tuple_elems ()) - { - auto field_ty = TypeCheckExpr::Resolve (elem.get ()); - fields.push_back (TyTy::TyVar (field_ty->get_ref ())); - } - infered = new TyTy::TupleType (expr.get_mappings ().get_hirid (), - expr.get_locus (), fields); - } - - void visit (HIR::ReturnExpr &expr) override - { - auto fn_return_tyty = context->peek_return_type (); - rust_assert (fn_return_tyty != nullptr); - - TyTy::BaseType *expr_ty - = expr.has_return_expr () - ? TypeCheckExpr::Resolve (expr.get_expr ()) - : TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); - - infered = fn_return_tyty->unify (expr_ty); - fn_return_tyty->append_reference (expr_ty->get_ref ()); - for (auto &ref : infered->get_combined_refs ()) - fn_return_tyty->append_reference (ref); - - infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ()); - } - - void visit (HIR::CallExpr &expr) override - { - TyTy::BaseType *function_tyty = TypeCheckExpr::Resolve (expr.get_fnexpr ()); - - bool valid_tyty = function_tyty->get_kind () == TyTy::TypeKind::ADT - || function_tyty->get_kind () == TyTy::TypeKind::FNDEF - || function_tyty->get_kind () == TyTy::TypeKind::FNPTR; - if (!valid_tyty) - { - rust_error_at (expr.get_locus (), - "Failed to resolve expression of function call"); - return; - } - - TyTy::VariantDef &variant = TyTy::VariantDef::get_error_node (); - if (function_tyty->get_kind () == TyTy::TypeKind::ADT) - { - TyTy::ADTType *adt = static_cast (function_tyty); - if (adt->is_enum ()) - { - // lookup variant id - HirId variant_id; - bool ok = context->lookup_variant_definition ( - expr.get_fnexpr ()->get_mappings ().get_hirid (), &variant_id); - rust_assert (ok); - - TyTy::VariantDef *lookup_variant = nullptr; - ok = adt->lookup_variant_by_id (variant_id, &lookup_variant); - rust_assert (ok); - - variant = *lookup_variant; - } - else - { - rust_assert (adt->number_of_variants () == 1); - variant = *adt->get_variants ().at (0); - } - } - - infered - = TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, context); - } + static TyTy::BaseType *Resolve (HIR::Expr *expr); + void visit (HIR::TupleIndexExpr &expr) override; + void visit (HIR::TupleExpr &expr) override; + void visit (HIR::ReturnExpr &expr) override; + void visit (HIR::CallExpr &expr) override; void visit (HIR::MethodCallExpr &expr) override; - - void visit (HIR::AssignmentExpr &expr) override - { - infered - = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); - - auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); - auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); - - coercion_site (expr.get_mappings ().get_hirid (), lhs, rhs, - expr.get_locus ()); - } - - void visit (HIR::CompoundAssignmentExpr &expr) override - { - infered - = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); - - auto lhs = TypeCheckExpr::Resolve (expr.get_left_expr ().get ()); - auto rhs = TypeCheckExpr::Resolve (expr.get_right_expr ().get ()); - - // we dont care about the result of the unify from a compound assignment - // since this is a unit-type expr - auto result = lhs->unify (rhs); - if (result->get_kind () == TyTy::TypeKind::ERROR) - return; - - auto lang_item_type - = Analysis::RustLangItem::CompoundAssignmentOperatorToLangItem ( - expr.get_expr_type ()); - bool operator_overloaded - = resolve_operator_overload (lang_item_type, expr, lhs, rhs); - if (operator_overloaded) - return; - - bool valid_lhs = validate_arithmetic_type (lhs, expr.get_expr_type ()); - bool valid_rhs = validate_arithmetic_type (rhs, expr.get_expr_type ()); - bool valid = valid_lhs && valid_rhs; - if (!valid) - { - rust_error_at (expr.get_locus (), - "cannot apply this operator to types %s and %s", - lhs->as_string ().c_str (), rhs->as_string ().c_str ()); - return; - } - } - - void visit (HIR::IdentifierExpr &expr) override - { - NodeId ast_node_id = expr.get_mappings ().get_nodeid (); - - // then lookup the reference_node_id - NodeId ref_node_id = UNKNOWN_NODEID; - if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - { - resolver->lookup_resolved_type (ast_node_id, &ref_node_id); - } - - if (ref_node_id == UNKNOWN_NODEID) - { - // FIXME this needs to go away and just return error node - rust_error_at (expr.get_locus (), "unresolved node: %s", - expr.as_string ().c_str ()); - return; - } - - // node back to HIR - HirId ref; - if (!mappings->lookup_node_to_hir (ref_node_id, &ref)) - { - // FIXME - // this is an internal error - rust_error_at (expr.get_locus (), "123 reverse lookup failure"); - return; - } - - // the base reference for this name _must_ have a type set - TyTy::BaseType *lookup; - if (!context->lookup_type (ref, &lookup)) - { - // FIXME - // this is an internal error - rust_error_at (mappings->lookup_location (ref), - "Failed to resolve IdentifierExpr type: %s", - expr.as_string ().c_str ()); - return; - } - - infered = lookup->clone (); - - // Generic unit structs look like an identifier but they actually need be - // handled as a path-in-expression so this gives us a chance to infer the - // generic parameters. - // see https://github.com/Rust-GCC/gccrs/issues/1447 - bool is_unit_struct - = infered->get_kind () == TyTy::TypeKind::ADT && infered->is_unit (); - if (is_unit_struct && infered->needs_generic_substitutions ()) - { - infered = SubstMapper::InferSubst (infered, expr.get_locus ()); - } - } - - void visit (HIR::LiteralExpr &expr) override - { - infered = resolve_literal (expr.get_mappings (), expr.get_literal (), - expr.get_locus ()); - } - - void visit (HIR::ArithmeticOrLogicalExpr &expr) override - { - auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); - auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); - - auto lang_item_type - = Analysis::RustLangItem::OperatorToLangItem (expr.get_expr_type ()); - bool operator_overloaded - = resolve_operator_overload (lang_item_type, expr, lhs, rhs); - if (operator_overloaded) - return; - - bool valid_lhs = validate_arithmetic_type (lhs, expr.get_expr_type ()); - bool valid_rhs = validate_arithmetic_type (rhs, expr.get_expr_type ()); - bool valid = valid_lhs && valid_rhs; - if (!valid) - { - rust_error_at (expr.get_locus (), - "cannot apply this operator to types %s and %s", - lhs->as_string ().c_str (), rhs->as_string ().c_str ()); - return; - } - - switch (expr.get_expr_type ()) - { - case ArithmeticOrLogicalOperator::LEFT_SHIFT: - case ArithmeticOrLogicalOperator::RIGHT_SHIFT: - infered = rhs->cast (lhs); - break; - - default: - infered = lhs->unify (rhs); - break; - } - } - - void visit (HIR::ComparisonExpr &expr) override - { - auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); - auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); - - auto result = lhs->unify (rhs); - if (result == nullptr || result->get_kind () == TyTy::TypeKind::ERROR) - return; - - bool ok = context->lookup_builtin ("bool", &infered); - rust_assert (ok); - } - - void visit (HIR::LazyBooleanExpr &expr) override - { - auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); - auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); - - // we expect the lhs and rhs must be bools at this point - TyTy::BoolType elhs (expr.get_mappings ().get_hirid ()); - lhs = elhs.unify (lhs); - if (lhs->get_kind () == TyTy::TypeKind::ERROR) - return; - - TyTy::BoolType rlhs (expr.get_mappings ().get_hirid ()); - rhs = elhs.unify (rhs); - if (lhs->get_kind () == TyTy::TypeKind::ERROR) - return; - - infered = lhs->unify (rhs); - } - - void visit (HIR::NegationExpr &expr) override - { - auto negated_expr_ty = TypeCheckExpr::Resolve (expr.get_expr ().get ()); - - // check for operator overload - auto lang_item_type = Analysis::RustLangItem::NegationOperatorToLangItem ( - expr.get_expr_type ()); - bool operator_overloaded - = resolve_operator_overload (lang_item_type, expr, negated_expr_ty, - nullptr); - if (operator_overloaded) - return; - - // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators - switch (expr.get_expr_type ()) - { - case NegationOperator::NEGATE: { - bool valid - = (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) - || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT) - || (negated_expr_ty->get_kind () == TyTy::TypeKind::FLOAT) - || (negated_expr_ty->get_kind () == TyTy::TypeKind::ISIZE) - || (negated_expr_ty->get_kind () == TyTy::TypeKind::USIZE) - || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER - && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind () - == TyTy::InferType::INTEGRAL)) - || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER - && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind () - == TyTy::InferType::FLOAT)); - if (!valid) - { - rust_error_at (expr.get_locus (), "cannot apply unary - to %s", - negated_expr_ty->as_string ().c_str ()); - return; - } - } - break; - - case NegationOperator::NOT: { - bool valid - = (negated_expr_ty->get_kind () == TyTy::TypeKind::BOOL) - || (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) - || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT) - || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER - && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind () - == TyTy::InferType::INTEGRAL)); - if (!valid) - { - rust_error_at (expr.get_locus (), - "cannot apply unary % to %s", - negated_expr_ty->as_string ().c_str ()); - return; - } - } - break; - } - - infered = negated_expr_ty->clone (); - infered->append_reference (negated_expr_ty->get_ref ()); - } - - void visit (HIR::IfExpr &expr) override - { - TypeCheckExpr::Resolve (expr.get_if_condition ()); - TypeCheckExpr::Resolve (expr.get_if_block ()); - - infered - = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); - } - - void visit (HIR::IfExprConseqElse &expr) override - { - TypeCheckExpr::Resolve (expr.get_if_condition ()); - auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ()); - auto else_blk_resolved = TypeCheckExpr::Resolve (expr.get_else_block ()); - - if (if_blk_resolved->get_kind () == TyTy::NEVER) - infered = else_blk_resolved; - else if (else_blk_resolved->get_kind () == TyTy::NEVER) - infered = if_blk_resolved; - else - infered = if_blk_resolved->unify (else_blk_resolved); - } - - void visit (HIR::IfExprConseqIf &expr) override - { - TypeCheckExpr::Resolve (expr.get_if_condition ()); - auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ()); - auto else_blk_resolved - = TypeCheckExpr::Resolve (expr.get_conseq_if_expr ()); - - if (if_blk_resolved->get_kind () == TyTy::NEVER) - infered = else_blk_resolved; - else if (else_blk_resolved->get_kind () == TyTy::NEVER) - infered = if_blk_resolved; - else - infered = if_blk_resolved->unify (else_blk_resolved); - } - - void visit (HIR::IfLetExpr &expr) override - { - // this needs to perform a least upper bound coercion on the blocks and then - // unify the scruintee and arms - TyTy::BaseType *scrutinee_tyty - = TypeCheckExpr::Resolve (expr.get_scrutinee_expr ().get ()); - - for (auto &pattern : expr.get_patterns ()) - { - TyTy::BaseType *kase_arm_ty - = TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty); - - TyTy::BaseType *checked_kase = scrutinee_tyty->unify (kase_arm_ty); - if (checked_kase->get_kind () == TyTy::TypeKind::ERROR) - return; - } - - TypeCheckExpr::Resolve (expr.get_if_block ()); - - infered - = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); - } - + void visit (HIR::AssignmentExpr &expr) override; + void visit (HIR::CompoundAssignmentExpr &expr) override; + void visit (HIR::IdentifierExpr &expr) override; + void visit (HIR::LiteralExpr &expr) override; + void visit (HIR::ArithmeticOrLogicalExpr &expr) override; + void visit (HIR::ComparisonExpr &expr) override; + void visit (HIR::LazyBooleanExpr &expr) override; + void visit (HIR::NegationExpr &expr) override; + void visit (HIR::IfExpr &expr) override; + void visit (HIR::IfExprConseqElse &expr) override; + void visit (HIR::IfExprConseqIf &expr) override; + void visit (HIR::IfLetExpr &expr) override; void visit (HIR::BlockExpr &expr) override; - - void visit (HIR::UnsafeBlockExpr &expr) override - { - infered = TypeCheckExpr::Resolve (expr.get_block_expr ().get ()); - } - + void visit (HIR::UnsafeBlockExpr &expr) override; void visit (HIR::ArrayIndexExpr &expr) override; - - void visit (HIR::ArrayExpr &expr) override - { - HIR::ArrayElems &elements = *expr.get_internal_elements (); - - HIR::Expr *capacity_expr = nullptr; - TyTy::BaseType *element_type = nullptr; - switch (elements.get_array_expr_type ()) - { - case HIR::ArrayElems::ArrayExprType::COPIED: { - HIR::ArrayElemsCopied &elems - = static_cast (elements); - element_type = TypeCheckExpr::Resolve (elems.get_elem_to_copy ()); - - auto capacity_type - = TypeCheckExpr::Resolve (elems.get_num_copies_expr ()); - - TyTy::BaseType *expected_ty = nullptr; - bool ok = context->lookup_builtin ("usize", &expected_ty); - rust_assert (ok); - context->insert_type (elems.get_num_copies_expr ()->get_mappings (), - expected_ty); - - auto unified = expected_ty->unify (capacity_type); - if (unified->get_kind () == TyTy::TypeKind::ERROR) - return; - - capacity_expr = elems.get_num_copies_expr (); - } - break; - - case HIR::ArrayElems::ArrayExprType::VALUES: { - HIR::ArrayElemsValues &elems - = static_cast (elements); - - std::vector types; - for (auto &elem : elems.get_values ()) - { - types.push_back (TypeCheckExpr::Resolve (elem.get ())); - } - - element_type = TyTy::TyVar::get_implicit_infer_var (expr.get_locus ()) - .get_tyty (); - for (auto &type : types) - { - element_type = element_type->unify (type); - } - - auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, UNKNOWN_NODEID, - mappings->get_next_hir_id (crate_num), - UNKNOWN_LOCAL_DEFID); - std::string capacity_str = std::to_string (elems.get_num_elements ()); - capacity_expr - = new HIR::LiteralExpr (mapping, capacity_str, - HIR::Literal::LitType::INT, - PrimitiveCoreType::CORETYPE_USIZE, - Location (), {}); - - // mark the type for this implicit node - TyTy::BaseType *expected_ty = nullptr; - bool ok = context->lookup_builtin ("usize", &expected_ty); - rust_assert (ok); - context->insert_type (mapping, expected_ty); - } - break; - } - - infered = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), - expr.get_locus (), *capacity_expr, - TyTy::TyVar (element_type->get_ref ())); - } - - // empty struct - void visit (HIR::StructExprStruct &struct_expr) override - { - TyTy::BaseType *struct_path_ty - = TypeCheckExpr::Resolve (&struct_expr.get_struct_name ()); - if (struct_path_ty->get_kind () != TyTy::TypeKind::ADT) - { - rust_error_at (struct_expr.get_struct_name ().get_locus (), - "expected an ADT type for constructor"); - return; - } - - infered = struct_path_ty; - } - - void visit (HIR::StructExprStructFields &struct_expr) override - { - infered = TypeCheckStructExpr::Resolve (&struct_expr); - } - - void visit (HIR::GroupedExpr &expr) override - { - infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get ()); - } - - void visit (HIR::FieldAccessExpr &expr) override - { - auto struct_base - = TypeCheckExpr::Resolve (expr.get_receiver_expr ().get ()); - - // FIXME does this require autoderef here? - if (struct_base->get_kind () == TyTy::TypeKind::REF) - { - TyTy::ReferenceType *r - = static_cast (struct_base); - struct_base = r->get_base (); - } - - bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT; - if (!is_valid_type) - { - rust_error_at (expr.get_locus (), - "expected algebraic data type got: [%s]", - struct_base->as_string ().c_str ()); - return; - } - - TyTy::ADTType *adt = static_cast (struct_base); - rust_assert (!adt->is_enum ()); - rust_assert (adt->number_of_variants () == 1); - - TyTy::VariantDef *vaiant = adt->get_variants ().at (0); - - TyTy::StructFieldType *lookup = nullptr; - bool found - = vaiant->lookup_field (expr.get_field_name (), &lookup, nullptr); - if (!found) - { - rust_error_at (expr.get_locus (), "unknown field [%s] for type [%s]", - expr.get_field_name ().c_str (), - adt->as_string ().c_str ()); - return; - } - - infered = lookup->get_field_type (); - } - + void visit (HIR::ArrayExpr &expr) override; + void visit (HIR::StructExprStruct &struct_expr) override; + void visit (HIR::StructExprStructFields &struct_expr) override; + void visit (HIR::GroupedExpr &expr) override; + void visit (HIR::FieldAccessExpr &expr) override; void visit (HIR::QualifiedPathInExpression &expr) override; - void visit (HIR::PathInExpression &expr) override; - - void visit (HIR::LoopExpr &expr) override - { - context->push_new_loop_context (expr.get_mappings ().get_hirid (), - expr.get_locus ()); - TyTy::BaseType *block_expr - = TypeCheckExpr::Resolve (expr.get_loop_block ().get ()); - if (!block_expr->is_unit ()) - { - rust_error_at (expr.get_loop_block ()->get_locus (), - "expected %<()%> got %s", - block_expr->as_string ().c_str ()); - return; - } - - TyTy::BaseType *loop_context_type = context->pop_loop_context (); - - bool loop_context_type_infered - = (loop_context_type->get_kind () != TyTy::TypeKind::INFER) - || ((loop_context_type->get_kind () == TyTy::TypeKind::INFER) - && (((TyTy::InferType *) loop_context_type)->get_infer_kind () - != TyTy::InferType::GENERAL)); - - infered - = loop_context_type_infered - ? loop_context_type - : TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); - } - - void visit (HIR::WhileLoopExpr &expr) override - { - context->push_new_while_loop_context (expr.get_mappings ().get_hirid ()); - - TypeCheckExpr::Resolve (expr.get_predicate_expr ().get ()); - TyTy::BaseType *block_expr - = TypeCheckExpr::Resolve (expr.get_loop_block ().get ()); - - if (!block_expr->is_unit ()) - { - rust_error_at (expr.get_loop_block ()->get_locus (), - "expected %<()%> got %s", - block_expr->as_string ().c_str ()); - return; - } - - context->pop_loop_context (); - infered - = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); - } - - void visit (HIR::BreakExpr &expr) override - { - if (!context->have_loop_context ()) - { - rust_error_at (expr.get_locus (), "cannot % outside of a loop"); - return; - } - - if (expr.has_break_expr ()) - { - TyTy::BaseType *break_expr_tyty - = TypeCheckExpr::Resolve (expr.get_expr ().get ()); - - TyTy::BaseType *loop_context = context->peek_loop_context (); - if (loop_context->get_kind () == TyTy::TypeKind::ERROR) - { - rust_error_at (expr.get_locus (), - "can only break with a value inside %"); - return; - } - - TyTy::BaseType *unified_ty = loop_context->unify (break_expr_tyty); - context->swap_head_loop_context (unified_ty); - } - - infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ()); - } - - void visit (HIR::ContinueExpr &expr) override - { - if (!context->have_loop_context ()) - { - rust_error_at (expr.get_locus (), - "cannot % outside of a loop"); - return; - } - - infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ()); - } - - void visit (HIR::BorrowExpr &expr) override - { - TyTy::BaseType *resolved_base - = TypeCheckExpr::Resolve (expr.get_expr ().get ()); - - // In Rust this is valid because of DST's - // - // fn test() { - // let a:&str = "TEST 1"; - // let b:&str = &"TEST 2"; - // } - if (resolved_base->get_kind () == TyTy::TypeKind::REF) - { - const TyTy::ReferenceType *ref - = static_cast (resolved_base); - - // this might end up being a more generic is_dyn object check but lets - // double check dyn traits type-layout first - if (ref->is_dyn_str_type ()) - { - infered = resolved_base; - return; - } - } - - if (expr.get_is_double_borrow ()) - { - // FIXME double_reference - gcc_unreachable (); - } - - infered = new TyTy::ReferenceType (expr.get_mappings ().get_hirid (), - TyTy::TyVar (resolved_base->get_ref ()), - expr.get_mut ()); - } - - void visit (HIR::DereferenceExpr &expr) override - { - TyTy::BaseType *resolved_base - = TypeCheckExpr::Resolve (expr.get_expr ().get ()); - - auto lang_item_type = Analysis::RustLangItem::ItemType::DEREF; - bool operator_overloaded - = resolve_operator_overload (lang_item_type, expr, resolved_base, - nullptr); - if (operator_overloaded) - { - // operator overloaded deref always refurns a reference type lets assert - // this - rust_assert (infered->get_kind () == TyTy::TypeKind::REF); - resolved_base = infered; - } - - bool is_valid_type - = resolved_base->get_kind () == TyTy::TypeKind::REF - || resolved_base->get_kind () == TyTy::TypeKind::POINTER; - if (!is_valid_type) - { - rust_error_at (expr.get_locus (), "expected reference type got %s", - resolved_base->as_string ().c_str ()); - return; - } - - if (resolved_base->get_kind () == TyTy::TypeKind::REF) - { - TyTy::ReferenceType *ref_base - = static_cast (resolved_base); - infered = ref_base->get_base ()->clone (); - } - else - { - TyTy::PointerType *ref_base - = static_cast (resolved_base); - infered = ref_base->get_base ()->clone (); - } - } - - void visit (HIR::TypeCastExpr &expr) override - { - TyTy::BaseType *expr_to_convert - = TypeCheckExpr::Resolve (expr.get_casted_expr ().get ()); - TyTy::BaseType *tyty_to_convert_to - = TypeCheckType::Resolve (expr.get_type_to_convert_to ().get ()); - - infered = expr_to_convert->cast (tyty_to_convert_to); - } - - void visit (HIR::MatchExpr &expr) override - { - // this needs to perform a least upper bound coercion on the blocks and then - // unify the scruintee and arms - TyTy::BaseType *scrutinee_tyty - = TypeCheckExpr::Resolve (expr.get_scrutinee_expr ().get ()); - - std::vector kase_block_tys; - for (auto &kase : expr.get_match_cases ()) - { - // lets check the arms - HIR::MatchArm &kase_arm = kase.get_arm (); - for (auto &pattern : kase_arm.get_patterns ()) - { - TyTy::BaseType *kase_arm_ty - = TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty); - - TyTy::BaseType *checked_kase = scrutinee_tyty->unify (kase_arm_ty); - if (checked_kase->get_kind () == TyTy::TypeKind::ERROR) - return; - } - - // check the kase type - TyTy::BaseType *kase_block_ty - = TypeCheckExpr::Resolve (kase.get_expr ().get ()); - kase_block_tys.push_back (kase_block_ty); - } - - if (kase_block_tys.size () == 0) - { - infered - = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); - return; - } - - infered = kase_block_tys.at (0); - for (size_t i = 1; i < kase_block_tys.size (); i++) - { - TyTy::BaseType *kase_ty = kase_block_tys.at (i); - infered = infered->unify (kase_ty); - if (infered->get_kind () == TyTy::TypeKind::ERROR) - return; - } - } - + void visit (HIR::LoopExpr &expr) override; + void visit (HIR::BreakExpr &expr) override; + void visit (HIR::ContinueExpr &expr) override; + void visit (HIR::BorrowExpr &expr) override; + void visit (HIR::DereferenceExpr &expr) override; + void visit (HIR::TypeCastExpr &expr) override; + void visit (HIR::MatchExpr &expr) override; void visit (HIR::RangeFromToExpr &expr) override; - void visit (HIR::RangeFromExpr &expr) override; - void visit (HIR::RangeToExpr &expr) override; - void visit (HIR::RangeFullExpr &expr) override; - void visit (HIR::RangeFromToInclExpr &expr) override; + void visit (HIR::WhileLoopExpr &expr) override; + + // TODO + void visit (HIR::ClosureExprInnerTyped &) override {} + void visit (HIR::ClosureExprInner &expr) override {} + void visit (HIR::ErrorPropagationExpr &expr) override {} + void visit (HIR::RangeToInclExpr &expr) override {} + void visit (HIR::WhileLetLoopExpr &expr) override {} + void visit (HIR::ForLoopExpr &expr) override {} + void visit (HIR::IfExprConseqIfLet &expr) override {} + void visit (HIR::IfLetExprConseqElse &expr) override {} + void visit (HIR::IfLetExprConseqIf &expr) override {} + void visit (HIR::IfLetExprConseqIfLet &expr) override {} + void visit (HIR::AwaitExpr &expr) override {} + void visit (HIR::AsyncBlockExpr &expr) override {} + + // don't need to implement these see rust-hir-type-check-struct-field.h + void visit (HIR::StructExprFieldIdentifier &field) override + { + gcc_unreachable (); + } + void visit (HIR::StructExprFieldIdentifierValue &field) override + { + gcc_unreachable (); + } + void visit (HIR::StructExprFieldIndexValue &field) override + { + gcc_unreachable (); + } protected: bool @@ -909,7 +106,7 @@ protected: TyTy::BaseType *rhs); private: - TypeCheckExpr () : TypeCheckBase (), infered (nullptr) {} + TypeCheckExpr (); TyTy::BaseType *resolve_root_path (HIR::PathInExpression &expr, size_t *offset, @@ -923,59 +120,7 @@ private: bool validate_arithmetic_type (const TyTy::BaseType *tyty, - HIR::ArithmeticOrLogicalExpr::ExprType expr_type) - { - const TyTy::BaseType *type = tyty->destructure (); - - // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators - // this will change later when traits are added - switch (expr_type) - { - case ArithmeticOrLogicalOperator::ADD: - case ArithmeticOrLogicalOperator::SUBTRACT: - case ArithmeticOrLogicalOperator::MULTIPLY: - case ArithmeticOrLogicalOperator::DIVIDE: - case ArithmeticOrLogicalOperator::MODULUS: - return (type->get_kind () == TyTy::TypeKind::INT) - || (type->get_kind () == TyTy::TypeKind::UINT) - || (type->get_kind () == TyTy::TypeKind::FLOAT) - || (type->get_kind () == TyTy::TypeKind::USIZE) - || (type->get_kind () == TyTy::TypeKind::ISIZE) - || (type->get_kind () == TyTy::TypeKind::INFER - && (((const TyTy::InferType *) type)->get_infer_kind () - == TyTy::InferType::INTEGRAL)) - || (type->get_kind () == TyTy::TypeKind::INFER - && (((const TyTy::InferType *) type)->get_infer_kind () - == TyTy::InferType::FLOAT)); - - // integers or bools - case ArithmeticOrLogicalOperator::BITWISE_AND: - case ArithmeticOrLogicalOperator::BITWISE_OR: - case ArithmeticOrLogicalOperator::BITWISE_XOR: - return (type->get_kind () == TyTy::TypeKind::INT) - || (type->get_kind () == TyTy::TypeKind::UINT) - || (type->get_kind () == TyTy::TypeKind::USIZE) - || (type->get_kind () == TyTy::TypeKind::ISIZE) - || (type->get_kind () == TyTy::TypeKind::BOOL) - || (type->get_kind () == TyTy::TypeKind::INFER - && (((const TyTy::InferType *) type)->get_infer_kind () - == TyTy::InferType::INTEGRAL)); - - // integers only - case ArithmeticOrLogicalOperator::LEFT_SHIFT: - case ArithmeticOrLogicalOperator::RIGHT_SHIFT: - return (type->get_kind () == TyTy::TypeKind::INT) - || (type->get_kind () == TyTy::TypeKind::UINT) - || (type->get_kind () == TyTy::TypeKind::USIZE) - || (type->get_kind () == TyTy::TypeKind::ISIZE) - || (type->get_kind () == TyTy::TypeKind::INFER - && (((const TyTy::InferType *) type)->get_infer_kind () - == TyTy::InferType::INTEGRAL)); - } - - gcc_unreachable (); - return false; - } + HIR::ArithmeticOrLogicalExpr::ExprType expr_type); /* The return value of TypeCheckExpr::Resolve */ TyTy::BaseType *infered; diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc new file mode 100644 index 00000000000..784e4990409 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc @@ -0,0 +1,583 @@ +// 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-type-check-implitem.h" +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-type.h" +#include "rust-hir-type-check-expr.h" +#include "rust-hir-type-check-pattern.h" +#include "rust-tyty.h" + +namespace Rust { +namespace Resolver { + +TypeCheckTopLevelExternItem::TypeCheckTopLevelExternItem ( + const HIR::ExternBlock &parent) + : TypeCheckBase (), parent (parent) +{} + +void +TypeCheckTopLevelExternItem::Resolve (HIR::ExternalItem *item, + const HIR::ExternBlock &parent) +{ + TypeCheckTopLevelExternItem resolver (parent); + item->accept_vis (resolver); +} + +void +TypeCheckTopLevelExternItem::visit (HIR::ExternalStaticItem &item) +{ + TyTy::BaseType *actual_type + = TypeCheckType::Resolve (item.get_item_type ().get ()); + + context->insert_type (item.get_mappings (), actual_type); +} + +void +TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &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_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 ().get ()); + + // these are implicit mappings and not used + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, mappings->get_next_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + HIR::IdentifierPattern *param_pattern + = new HIR::IdentifierPattern (mapping, param.get_param_name (), + Location (), false, Mutability::Imm, + std::unique_ptr (nullptr)); + + params.push_back ( + std::pair (param_pattern, + param_tyty)); + + context->insert_type (param.get_mappings (), param_tyty); + + // FIXME do we need error checking for patterns here? + // see https://github.com/Rust-GCC/gccrs/issues/995 + } + + uint8_t flags = TyTy::FnType::FNTYPE_IS_EXTERN_FLAG; + if (function.is_variadic ()) + flags |= TyTy::FnType::FNTYPE_IS_VARADIC_FLAG; + + RustIdent ident{ + CanonicalPath::new_seg (function.get_mappings ().get_nodeid (), + function.get_item_name ()), + function.get_locus ()}; + + auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (), + function.get_mappings ().get_defid (), + function.get_item_name (), ident, flags, + parent.get_abi (), std::move (params), + ret_type, std::move (substitutions)); + + context->insert_type (function.get_mappings (), fnType); +} + +TypeCheckTopLevelImplItem::TypeCheckTopLevelImplItem ( + TyTy::BaseType *self, + std::vector substitutions) + : TypeCheckBase (), self (self), substitutions (substitutions) +{} + +void +TypeCheckTopLevelImplItem::Resolve ( + HIR::ImplItem *item, TyTy::BaseType *self, + std::vector substitutions) +{ + TypeCheckTopLevelImplItem resolver (self, substitutions); + item->accept_vis (resolver); +} + +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 ()); + + context->insert_type (constant.get_mappings (), type->unify (expr_type)); +} + +void +TypeCheckTopLevelImplItem::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; + } + } + } + + 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 + { + 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; + if (function.is_method ()) + { + // these are implicit mappings and not used + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, mappings->get_next_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + // add the synthetic self param at the front, this is a placeholder for + // compilation to know parameter names. The types are ignored but we + // reuse the HIR identifier pattern which requires it + HIR::SelfParam &self_param = function.get_self_param (); + HIR::IdentifierPattern *self_pattern + = new HIR::IdentifierPattern (mapping, "self", self_param.get_locus (), + self_param.is_ref (), + self_param.get_mut (), + std::unique_ptr (nullptr)); + + // might have a specified type + TyTy::BaseType *self_type = nullptr; + if (self_param.has_type ()) + { + std::unique_ptr &specified_type = self_param.get_type (); + self_type = TypeCheckType::Resolve (specified_type.get ()); + } + else + { + switch (self_param.get_self_kind ()) + { + case HIR::SelfParam::IMM: + case HIR::SelfParam::MUT: + self_type = self->clone (); + break; + + case HIR::SelfParam::IMM_REF: + self_type = new TyTy::ReferenceType ( + self_param.get_mappings ().get_hirid (), + TyTy::TyVar (self->get_ref ()), Mutability::Imm); + break; + + case HIR::SelfParam::MUT_REF: + self_type = new TyTy::ReferenceType ( + self_param.get_mappings ().get_hirid (), + TyTy::TyVar (self->get_ref ()), Mutability::Mut); + break; + + default: + gcc_unreachable (); + return; + } + } + + context->insert_type (self_param.get_mappings (), self_type); + params.push_back ( + std::pair (self_pattern, self_type)); + } + + 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, + function.is_method () + ? TyTy::FnType::FNTYPE_IS_METHOD_FLAG + : TyTy::FnType::FNTYPE_DEFAULT_FLAGS, + ABI::RUST, std::move (params), ret_type, + 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; + } + + // need to get the return type from this + TyTy::FnType *resolve_fn_type = static_cast (lookup); + auto expected_ret_tyty = resolve_fn_type->get_return_type (); + context->push_return_type (TypeCheckContextItem (parent, &function), + expected_ret_tyty); + + auto block_expr_ty + = TypeCheckExpr::Resolve (function.get_definition ().get ()); + + context->pop_return_type (); + expected_ret_tyty->unify (block_expr_ty); +} + +void +TypeCheckImplItem::visit (HIR::ConstantItem &const_item) +{} + +void +TypeCheckImplItem::visit (HIR::TypeAlias &type_alias) +{} + +TypeCheckImplItemWithTrait::TypeCheckImplItemWithTrait ( + HIR::ImplBlock *parent, TyTy::BaseType *self, + TyTy::TypeBoundPredicate &trait_reference, + std::vector substitutions) + : TypeCheckImplItem (parent, self), trait_reference (trait_reference), + resolved_trait_item (TyTy::TypeBoundPredicateItem::error ()), + substitutions (substitutions) +{ + rust_assert (is_trait_impl_block ()); +} + +TyTy::TypeBoundPredicateItem +TypeCheckImplItemWithTrait::Resolve ( + HIR::ImplBlock *parent, HIR::ImplItem *item, TyTy::BaseType *self, + TyTy::TypeBoundPredicate &trait_reference, + std::vector substitutions) +{ + TypeCheckImplItemWithTrait resolver (parent, self, trait_reference, + substitutions); + item->accept_vis (resolver); + return resolver.resolved_trait_item; +} + +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; + + // map the impl item to the associated trait item + const auto tref = trait_reference.get (); + const TraitItemReference *raw_trait_item = nullptr; + bool found + = tref->lookup_trait_item_by_type (constant.get_identifier (), + TraitItemReference::TraitItemType::CONST, + &raw_trait_item); + + // unknown trait item + if (!found || raw_trait_item->is_error ()) + { + RichLocation r (constant.get_locus ()); + r.add_range (trait_reference.get_locus ()); + rust_error_at (r, "constant %<%s%> is not a member of trait %<%s%>", + constant.get_identifier ().c_str (), + trait_reference.get_name ().c_str ()); + return; + } + + // get the item from the predicate + resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item); + rust_assert (!resolved_trait_item.is_error ()); + + // merge the attributes + const HIR::TraitItem *hir_trait_item + = resolved_trait_item.get_raw_item ()->get_hir_trait_item (); + merge_attributes (constant.get_outer_attrs (), *hir_trait_item); + + // check the types are compatible + auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self); + if (!trait_item_type->can_eq (lookup, true)) + { + RichLocation r (constant.get_locus ()); + r.add_range (resolved_trait_item.get_locus ()); + + rust_error_at ( + r, "constant %<%s%> has an incompatible type for trait %<%s%>", + constant.get_identifier ().c_str (), + trait_reference.get_name ().c_str ()); + } +} + +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; + + // map the impl item to the associated trait item + const auto tref = trait_reference.get (); + const TraitItemReference *raw_trait_item = nullptr; + bool found + = tref->lookup_trait_item_by_type (type.get_new_type_name (), + TraitItemReference::TraitItemType::TYPE, + &raw_trait_item); + + // unknown trait item + if (!found || raw_trait_item->is_error ()) + { + RichLocation r (type.get_locus ()); + r.add_range (trait_reference.get_locus ()); + rust_error_at (r, "type alias %<%s%> is not a member of trait %<%s%>", + type.get_new_type_name ().c_str (), + trait_reference.get_name ().c_str ()); + return; + } + + // get the item from the predicate + resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item); + rust_assert (!resolved_trait_item.is_error ()); + + // merge the attributes + const HIR::TraitItem *hir_trait_item + = resolved_trait_item.get_raw_item ()->get_hir_trait_item (); + merge_attributes (type.get_outer_attrs (), *hir_trait_item); + + // check the types are compatible + auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self); + if (!trait_item_type->can_eq (lookup, true)) + { + RichLocation r (type.get_locus ()); + r.add_range (resolved_trait_item.get_locus ()); + + rust_error_at ( + r, "type alias %<%s%> has an incompatible type for trait %<%s%>", + type.get_new_type_name ().c_str (), + trait_reference.get_name ().c_str ()); + } + + // its actually a projection, since we need a way to actually bind the + // generic substitutions to the type itself + TyTy::ProjectionType *projection + = new TyTy::ProjectionType (type.get_mappings ().get_hirid (), lookup, tref, + raw_trait_item->get_mappings ().get_defid (), + substitutions); + + context->insert_type (type.get_mappings (), projection); + raw_trait_item->associated_type_set (projection); +} + +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; + + // map the impl item to the associated trait item + const auto tref = trait_reference.get (); + const TraitItemReference *raw_trait_item = nullptr; + bool found + = tref->lookup_trait_item_by_type (function.get_function_name (), + TraitItemReference::TraitItemType::FN, + &raw_trait_item); + + // unknown trait item + if (!found || raw_trait_item->is_error ()) + { + RichLocation r (function.get_locus ()); + r.add_range (trait_reference.get_locus ()); + rust_error_at (r, "method %<%s%> is not a member of trait %<%s%>", + function.get_function_name ().c_str (), + trait_reference.get_name ().c_str ()); + return; + } + + // get the item from the predicate + resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item); + rust_assert (!resolved_trait_item.is_error ()); + + // merge the attributes + const HIR::TraitItem *hir_trait_item + = resolved_trait_item.get_raw_item ()->get_hir_trait_item (); + merge_attributes (function.get_outer_attrs (), *hir_trait_item); + + // check the types are compatible + auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self); + if (!trait_item_type->can_eq (lookup, true)) + { + RichLocation r (function.get_locus ()); + r.add_range (resolved_trait_item.get_locus ()); + + rust_error_at (r, + "method %<%s%> has an incompatible type for trait %<%s%>", + function.get_function_name ().c_str (), + trait_reference.get_name ().c_str ()); + } +} + +void +TypeCheckImplItemWithTrait::merge_attributes (AST::AttrVec &impl_item_attrs, + const HIR::TraitItem &trait_item) +{ + for (const auto &attr : trait_item.get_outer_attrs ()) + { + impl_item_attrs.push_back (attr); + } +} + +bool +TypeCheckImplItemWithTrait::is_trait_impl_block () const +{ + return !trait_reference.is_error (); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index 294dffdead2..f2f3faab9e0 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -20,368 +20,58 @@ #define RUST_HIR_TYPE_CHECK_IMPLITEM_H #include "rust-hir-type-check-base.h" -#include "rust-hir-full.h" -#include "rust-hir-type-check-type.h" -#include "rust-hir-type-check-expr.h" -#include "rust-tyty.h" namespace Rust { namespace Resolver { -class TypeCheckTopLevelExternItem : public TypeCheckBase +class TypeCheckTopLevelExternItem : public TypeCheckBase, + public HIR::HIRExternalItemVisitor { - using Rust::Resolver::TypeCheckBase::visit; - public: - static void Resolve (HIR::ExternalItem *item, const HIR::ExternBlock &parent) - { - TypeCheckTopLevelExternItem resolver (parent); - item->accept_vis (resolver); - } + static void Resolve (HIR::ExternalItem *item, const HIR::ExternBlock &parent); - void visit (HIR::ExternalStaticItem &item) override - { - TyTy::BaseType *actual_type - = TypeCheckType::Resolve (item.get_item_type ().get ()); - - context->insert_type (item.get_mappings (), actual_type); - } - - void visit (HIR::ExternalFunctionItem &function) override - { - 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_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 ().get ()); - - // these are implicit mappings and not used - auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, mappings->get_next_node_id (), - mappings->get_next_hir_id (crate_num), - UNKNOWN_LOCAL_DEFID); - - HIR::IdentifierPattern *param_pattern = new HIR::IdentifierPattern ( - mapping, param.get_param_name (), Location (), false, Mutability::Imm, - std::unique_ptr (nullptr)); - - params.push_back ( - std::pair (param_pattern, - param_tyty)); - - context->insert_type (param.get_mappings (), param_tyty); - - // FIXME do we need error checking for patterns here? - // see https://github.com/Rust-GCC/gccrs/issues/995 - } - - uint8_t flags = TyTy::FnType::FNTYPE_IS_EXTERN_FLAG; - if (function.is_variadic ()) - flags |= TyTy::FnType::FNTYPE_IS_VARADIC_FLAG; - - RustIdent ident{ - CanonicalPath::new_seg (function.get_mappings ().get_nodeid (), - function.get_item_name ()), - function.get_locus ()}; - - auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (), - function.get_mappings ().get_defid (), - function.get_item_name (), ident, flags, - parent.get_abi (), std::move (params), - ret_type, std::move (substitutions)); - - context->insert_type (function.get_mappings (), fnType); - } + void visit (HIR::ExternalStaticItem &item) override; + void visit (HIR::ExternalFunctionItem &function) override; private: - TypeCheckTopLevelExternItem (const HIR::ExternBlock &parent) - : TypeCheckBase (), parent (parent) - {} + TypeCheckTopLevelExternItem (const HIR::ExternBlock &parent); const HIR::ExternBlock &parent; }; -class TypeCheckTopLevelImplItem : public TypeCheckBase +class TypeCheckTopLevelImplItem : public TypeCheckBase, + public HIR::HIRImplVisitor { - using Rust::Resolver::TypeCheckBase::visit; - public: static void Resolve (HIR::ImplItem *item, TyTy::BaseType *self, - std::vector substitutions) - { - TypeCheckTopLevelImplItem resolver (self, substitutions); - item->accept_vis (resolver); - } + std::vector substitutions); - void visit (HIR::TypeAlias &alias) override - { - 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 visit (HIR::ConstantItem &constant) override - { - TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ()); - TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); - - context->insert_type (constant.get_mappings (), type->unify (expr_type)); - } - - void visit (HIR::Function &function) override - { - 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; - } - } - } - - 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 - { - 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; - if (function.is_method ()) - { - // these are implicit mappings and not used - auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, mappings->get_next_node_id (), - mappings->get_next_hir_id (crate_num), - UNKNOWN_LOCAL_DEFID); - - // add the synthetic self param at the front, this is a placeholder for - // compilation to know parameter names. The types are ignored but we - // reuse the HIR identifier pattern which requires it - HIR::SelfParam &self_param = function.get_self_param (); - HIR::IdentifierPattern *self_pattern = new HIR::IdentifierPattern ( - mapping, "self", self_param.get_locus (), self_param.is_ref (), - self_param.get_mut (), std::unique_ptr (nullptr)); - - // might have a specified type - TyTy::BaseType *self_type = nullptr; - if (self_param.has_type ()) - { - std::unique_ptr &specified_type = self_param.get_type (); - self_type = TypeCheckType::Resolve (specified_type.get ()); - } - else - { - switch (self_param.get_self_kind ()) - { - case HIR::SelfParam::IMM: - case HIR::SelfParam::MUT: - self_type = self->clone (); - break; - - case HIR::SelfParam::IMM_REF: - self_type = new TyTy::ReferenceType ( - self_param.get_mappings ().get_hirid (), - TyTy::TyVar (self->get_ref ()), Mutability::Imm); - break; - - case HIR::SelfParam::MUT_REF: - self_type = new TyTy::ReferenceType ( - self_param.get_mappings ().get_hirid (), - TyTy::TyVar (self->get_ref ()), Mutability::Mut); - break; - - default: - gcc_unreachable (); - return; - } - } - - context->insert_type (self_param.get_mappings (), self_type); - params.push_back ( - std::pair (self_pattern, - self_type)); - } - - 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, - function.is_method () - ? TyTy::FnType::FNTYPE_IS_METHOD_FLAG - : TyTy::FnType::FNTYPE_DEFAULT_FLAGS, - ABI::RUST, std::move (params), ret_type, - std::move (substitutions)); - - context->insert_type (function.get_mappings (), fnType); - } + 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) - : TypeCheckBase (), self (self), substitutions (substitutions) - {} + std::vector substitutions); TyTy::BaseType *self; std::vector substitutions; }; -class TypeCheckImplItem : public TypeCheckBase +class TypeCheckImplItem : public TypeCheckBase, public HIR::HIRImplVisitor { public: - using Rust::Resolver::TypeCheckBase::visit; - static void Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item, - TyTy::BaseType *self) - { - TypeCheckImplItem resolver (parent, self); - item->accept_vis (resolver); - } + TyTy::BaseType *self); - 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 *resolve_fn_type = static_cast (lookup); - auto expected_ret_tyty = resolve_fn_type->get_return_type (); - context->push_return_type (TypeCheckContextItem (parent, &function), - expected_ret_tyty); - - auto block_expr_ty - = TypeCheckExpr::Resolve (function.get_definition ().get ()); - - context->pop_return_type (); - expected_ret_tyty->unify (block_expr_ty); - } + 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) - : TypeCheckBase (), parent (parent), self (self) - {} + TypeCheckImplItem (HIR::ImplBlock *parent, TyTy::BaseType *self); HIR::ImplBlock *parent; TyTy::BaseType *self; @@ -389,207 +79,29 @@ protected: class TypeCheckImplItemWithTrait : public TypeCheckImplItem { - using Rust::Resolver::TypeCheckBase::visit; - public: static TyTy::TypeBoundPredicateItem Resolve (HIR::ImplBlock *parent, HIR::ImplItem *item, TyTy::BaseType *self, TyTy::TypeBoundPredicate &trait_reference, - std::vector substitutions) - { - TypeCheckImplItemWithTrait resolver (parent, self, trait_reference, - substitutions); - item->accept_vis (resolver); - return resolver.resolved_trait_item; - } + std::vector substitutions); - void visit (HIR::ConstantItem &constant) override - { - // normal resolution of the item - TypeCheckImplItem::visit (constant); - TyTy::BaseType *lookup; - if (!context->lookup_type (constant.get_mappings ().get_hirid (), &lookup)) - return; - - // map the impl item to the associated trait item - const auto tref = trait_reference.get (); - const TraitItemReference *raw_trait_item = nullptr; - bool found = tref->lookup_trait_item_by_type ( - constant.get_identifier (), TraitItemReference::TraitItemType::CONST, - &raw_trait_item); - - // unknown trait item - if (!found || raw_trait_item->is_error ()) - { - RichLocation r (constant.get_locus ()); - r.add_range (trait_reference.get_locus ()); - rust_error_at (r, "constant %<%s%> is not a member of trait %<%s%>", - constant.get_identifier ().c_str (), - trait_reference.get_name ().c_str ()); - return; - } - - // get the item from the predicate - resolved_trait_item - = trait_reference.lookup_associated_item (raw_trait_item); - rust_assert (!resolved_trait_item.is_error ()); - - // merge the attributes - const HIR::TraitItem *hir_trait_item - = resolved_trait_item.get_raw_item ()->get_hir_trait_item (); - merge_attributes (constant.get_outer_attrs (), *hir_trait_item); - - // check the types are compatible - auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self); - if (!trait_item_type->can_eq (lookup, true)) - { - RichLocation r (constant.get_locus ()); - r.add_range (resolved_trait_item.get_locus ()); - - rust_error_at ( - r, "constant %<%s%> has an incompatible type for trait %<%s%>", - constant.get_identifier ().c_str (), - trait_reference.get_name ().c_str ()); - } - } - - void visit (HIR::TypeAlias &type) override - { - // normal resolution of the item - TypeCheckImplItem::visit (type); - TyTy::BaseType *lookup; - if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup)) - return; - - // map the impl item to the associated trait item - const auto tref = trait_reference.get (); - const TraitItemReference *raw_trait_item = nullptr; - bool found = tref->lookup_trait_item_by_type ( - type.get_new_type_name (), TraitItemReference::TraitItemType::TYPE, - &raw_trait_item); - - // unknown trait item - if (!found || raw_trait_item->is_error ()) - { - RichLocation r (type.get_locus ()); - r.add_range (trait_reference.get_locus ()); - rust_error_at (r, "type alias %<%s%> is not a member of trait %<%s%>", - type.get_new_type_name ().c_str (), - trait_reference.get_name ().c_str ()); - return; - } - - // get the item from the predicate - resolved_trait_item - = trait_reference.lookup_associated_item (raw_trait_item); - rust_assert (!resolved_trait_item.is_error ()); - - // merge the attributes - const HIR::TraitItem *hir_trait_item - = resolved_trait_item.get_raw_item ()->get_hir_trait_item (); - merge_attributes (type.get_outer_attrs (), *hir_trait_item); - - // check the types are compatible - auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self); - if (!trait_item_type->can_eq (lookup, true)) - { - RichLocation r (type.get_locus ()); - r.add_range (resolved_trait_item.get_locus ()); - - rust_error_at ( - r, "type alias %<%s%> has an incompatible type for trait %<%s%>", - type.get_new_type_name ().c_str (), - trait_reference.get_name ().c_str ()); - } - - // its actually a projection, since we need a way to actually bind the - // generic substitutions to the type itself - TyTy::ProjectionType *projection - = new TyTy::ProjectionType (type.get_mappings ().get_hirid (), lookup, - tref, - raw_trait_item->get_mappings ().get_defid (), - substitutions); - - context->insert_type (type.get_mappings (), projection); - raw_trait_item->associated_type_set (projection); - } - - void visit (HIR::Function &function) override - { - // 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; - - // map the impl item to the associated trait item - const auto tref = trait_reference.get (); - const TraitItemReference *raw_trait_item = nullptr; - bool found - = tref->lookup_trait_item_by_type (function.get_function_name (), - TraitItemReference::TraitItemType::FN, - &raw_trait_item); - - // unknown trait item - if (!found || raw_trait_item->is_error ()) - { - RichLocation r (function.get_locus ()); - r.add_range (trait_reference.get_locus ()); - rust_error_at (r, "method %<%s%> is not a member of trait %<%s%>", - function.get_function_name ().c_str (), - trait_reference.get_name ().c_str ()); - return; - } - - // get the item from the predicate - resolved_trait_item - = trait_reference.lookup_associated_item (raw_trait_item); - rust_assert (!resolved_trait_item.is_error ()); - - // merge the attributes - const HIR::TraitItem *hir_trait_item - = resolved_trait_item.get_raw_item ()->get_hir_trait_item (); - merge_attributes (function.get_outer_attrs (), *hir_trait_item); - - // check the types are compatible - auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self); - if (!trait_item_type->can_eq (lookup, true)) - { - RichLocation r (function.get_locus ()); - r.add_range (resolved_trait_item.get_locus ()); - - rust_error_at ( - r, "method %<%s%> has an incompatible type for trait %<%s%>", - function.get_function_name ().c_str (), - trait_reference.get_name ().c_str ()); - } - } + void visit (HIR::ConstantItem &constant) override; + void visit (HIR::TypeAlias &type) override; + void visit (HIR::Function &function) override; protected: // this allows us to inherit the must_use specified on a trait definition onto // its implementation void merge_attributes (AST::AttrVec &impl_item_attrs, - const HIR::TraitItem &trait_item) - { - for (const auto &attr : trait_item.get_outer_attrs ()) - { - impl_item_attrs.push_back (attr); - } - } + const HIR::TraitItem &trait_item); private: TypeCheckImplItemWithTrait ( HIR::ImplBlock *parent, TyTy::BaseType *self, TyTy::TypeBoundPredicate &trait_reference, - std::vector substitutions) - : TypeCheckImplItem (parent, self), trait_reference (trait_reference), - resolved_trait_item (TyTy::TypeBoundPredicateItem::error ()), - substitutions (substitutions) - { - rust_assert (is_trait_impl_block ()); - } + std::vector substitutions); - bool is_trait_impl_block () const { return !trait_reference.is_error (); } + bool is_trait_impl_block () const; TyTy::TypeBoundPredicate &trait_reference; TyTy::TypeBoundPredicateItem resolved_trait_item; diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 28cac51f793..d31a6df4777 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -17,15 +17,26 @@ // . #include "rust-hir-type-check-item.h" +#include "rust-hir-full.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-trait-resolve.h" namespace Rust { - namespace Resolver { + +TypeCheckItem::TypeCheckItem () : TypeCheckBase () {} + void -TypeCheckItem::Resolve (HIR::Item *item) +TypeCheckItem::Resolve (HIR::Item &item) { + rust_assert (item.get_hir_kind () == HIR::Node::BaseKind::VIS_ITEM); + HIR::VisItem &vis_item = static_cast (item); + TypeCheckItem resolver; - item->accept_vis (resolver); + vis_item.accept_vis (resolver); } void @@ -213,7 +224,7 @@ void TypeCheckItem::visit (HIR::Module &module) { for (auto &item : module.get_items ()) - TypeCheckItem::Resolve (item.get ()); + TypeCheckItem::Resolve (*item.get ()); } void diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index b9a0d9b2e90..ba4de19c9c7 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -20,30 +20,36 @@ #define RUST_HIR_TYPE_CHECK_ITEM #include "rust-hir-type-check-base.h" -#include "rust-hir-full.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-trait-resolve.h" -#include "rust-tyty-visitor.h" namespace Rust { namespace Resolver { -class TypeCheckItem : public TypeCheckBase +class TypeCheckItem : private TypeCheckBase, private HIR::HIRVisItemVisitor { - using Rust::Resolver::TypeCheckBase::visit; - public: - static void Resolve (HIR::Item *item); + static void Resolve (HIR::Item &item); 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{}; + + // nothing to do + void visit (HIR::ExternCrate &crate) override {} + void visit (HIR::UseDeclaration &use_decl) override {} + private: - TypeCheckItem () : TypeCheckBase () {} + TypeCheckItem (); }; } // 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 ac1ebfd6c95..fd0ca3ea16b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -17,6 +17,8 @@ // . #include "rust-hir-type-check-expr.h" +#include "rust-hir-type-check-type.h" +#include "rust-hir-trait-resolve.h" namespace Rust { namespace Resolver { diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index df312af6dab..a62fbc96a08 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -22,6 +22,24 @@ namespace Rust { namespace Resolver { +TypeCheckPattern::TypeCheckPattern (TyTy::BaseType *parent) + : TypeCheckBase (), parent (parent), infered (nullptr) +{} + +TyTy::BaseType * +TypeCheckPattern::Resolve (HIR::Pattern *pattern, TyTy::BaseType *parent) +{ + TypeCheckPattern resolver (parent); + pattern->accept_vis (resolver); + + if (resolver.infered == nullptr) + return new TyTy::ErrorType (pattern->get_pattern_mappings ().get_hirid ()); + + resolver.context->insert_type (pattern->get_pattern_mappings (), + resolver.infered); + return resolver.infered; +} + void TypeCheckPattern::visit (HIR::PathInExpression &pattern) { @@ -357,5 +375,33 @@ TypeCheckPattern::visit (HIR::IdentifierPattern &pattern) infered = parent; } +void +TypeCheckPattern::visit (HIR::GroupedPattern &pattern) +{ + // TODO + gcc_unreachable (); +} + +void +TypeCheckPattern::visit (HIR::QualifiedPathInExpression &pattern) +{ + // TODO + gcc_unreachable (); +} + +void +TypeCheckPattern::visit (HIR::ReferencePattern &pattern) +{ + // TODO + gcc_unreachable (); +} + +void +TypeCheckPattern::visit (HIR::SlicePattern &pattern) +{ + // TODO + gcc_unreachable (); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.h b/gcc/rust/typecheck/rust-hir-type-check-pattern.h index 860aca9207f..8af106033b7 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.h +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.h @@ -25,45 +25,27 @@ namespace Rust { namespace Resolver { -class TypeCheckPattern : public TypeCheckBase +class TypeCheckPattern : public TypeCheckBase, public HIR::HIRPatternVisitor { - using Rust::Resolver::TypeCheckBase::visit; - public: - static TyTy::BaseType *Resolve (HIR::Pattern *pattern, TyTy::BaseType *parent) - { - TypeCheckPattern resolver (parent); - pattern->accept_vis (resolver); - - if (resolver.infered == nullptr) - return new TyTy::ErrorType ( - pattern->get_pattern_mappings ().get_hirid ()); - - resolver.context->insert_type (pattern->get_pattern_mappings (), - resolver.infered); - return resolver.infered; - } + static TyTy::BaseType *Resolve (HIR::Pattern *pattern, + TyTy::BaseType *parent); void visit (HIR::PathInExpression &pattern) override; - void visit (HIR::StructPattern &pattern) override; - void visit (HIR::TupleStructPattern &pattern) override; - void visit (HIR::WildcardPattern &pattern) override; - void visit (HIR::TuplePattern &pattern) override; - void visit (HIR::LiteralPattern &pattern) override; - void visit (HIR::RangePattern &pattern) override; - void visit (HIR::IdentifierPattern &pattern) override; + void visit (HIR::GroupedPattern &pattern) override; + void visit (HIR::QualifiedPathInExpression &pattern) override; + void visit (HIR::ReferencePattern &pattern) override; + void visit (HIR::SlicePattern &pattern) override; private: - TypeCheckPattern (TyTy::BaseType *parent) - : TypeCheckBase (), parent (parent), infered (nullptr) - {} + TypeCheckPattern (TyTy::BaseType *parent); static TyTy::BaseType * typecheck_range_pattern_bound (HIR::RangePatternBound *bound, diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc new file mode 100644 index 00000000000..9f34ed49165 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc @@ -0,0 +1,498 @@ +// 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-type-check-stmt.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-type.h" +#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-pattern.h" + +namespace Rust { +namespace Resolver { + +TyTy::BaseType * +TypeCheckStmt::Resolve (HIR::Stmt *stmt) +{ + TypeCheckStmt resolver; + stmt->accept_vis (resolver); + return resolver.infered; +} + +void +TypeCheckStmt::visit (HIR::ExprStmtWithBlock &stmt) +{ + infered = TypeCheckExpr::Resolve (stmt.get_expr ()); +} + +void +TypeCheckStmt::visit (HIR::ExprStmtWithoutBlock &stmt) +{ + infered = TypeCheckExpr::Resolve (stmt.get_expr ()); +} + +void +TypeCheckStmt::visit (HIR::EmptyStmt &stmt) +{ + infered = TyTy::TupleType::get_unit_type (stmt.get_mappings ().get_hirid ()); +} + +void +TypeCheckStmt::visit (HIR::ExternBlock &extern_block) +{ + for (auto &item : extern_block.get_extern_items ()) + { + TypeCheckTopLevelExternItem::Resolve (item.get (), extern_block); + } +} + +void +TypeCheckStmt::visit (HIR::ConstantItem &constant) +{ + TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ()); + TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); + + infered = type->unify (expr_type); + context->insert_type (constant.get_mappings (), infered); +} + +void +TypeCheckStmt::visit (HIR::LetStmt &stmt) +{ + infered = TyTy::TupleType::get_unit_type (stmt.get_mappings ().get_hirid ()); + + const HIR::Pattern &stmt_pattern = *stmt.get_pattern (); + TyTy::BaseType *init_expr_ty = nullptr; + if (stmt.has_init_expr ()) + { + init_expr_ty = TypeCheckExpr::Resolve (stmt.get_init_expr ()); + if (init_expr_ty->get_kind () == TyTy::TypeKind::ERROR) + return; + + init_expr_ty->append_reference ( + stmt_pattern.get_pattern_mappings ().get_hirid ()); + } + + TyTy::BaseType *specified_ty = nullptr; + if (stmt.has_type ()) + specified_ty = TypeCheckType::Resolve (stmt.get_type ()); + + // let x:i32 = 123; + if (specified_ty != nullptr && init_expr_ty != nullptr) + { + // FIXME use this result and look at the regressions + coercion_site (stmt.get_mappings ().get_hirid (), specified_ty, + init_expr_ty, stmt.get_locus ()); + context->insert_type (stmt_pattern.get_pattern_mappings (), specified_ty); + } + else + { + // let x:i32; + if (specified_ty != nullptr) + { + context->insert_type (stmt_pattern.get_pattern_mappings (), + specified_ty); + } + // let x = 123; + else if (init_expr_ty != nullptr) + { + context->insert_type (stmt_pattern.get_pattern_mappings (), + init_expr_ty); + } + // let x; + else + { + context->insert_type ( + stmt_pattern.get_pattern_mappings (), + new TyTy::InferType ( + stmt_pattern.get_pattern_mappings ().get_hirid (), + TyTy::InferType::InferTypeKind::GENERAL, stmt.get_locus ())); + } + } +} + +void +TypeCheckStmt::visit (HIR::TupleStruct &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; + 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); + 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); + + context->insert_type (struct_decl.get_mappings (), type); + infered = type; +} + +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; +} + +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); + 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; +} + +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); + 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 +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); + + 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 ()); + + context->pop_return_type (); + + if (block_expr_ty->get_kind () != TyTy::NEVER) + expected_ret_tyty->unify (block_expr_ty); + + infered = fnType; +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index f8bf6e083dd..a79f17a59ce 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -20,489 +20,68 @@ #define RUST_HIR_TYPE_CHECK_STMT #include "rust-hir-type-check-base.h" -#include "rust-hir-full.h" -#include "rust-hir-type-check-type.h" -#include "rust-hir-type-check-expr.h" -#include "rust-hir-type-check-enumitem.h" -#include "rust-hir-type-check-implitem.h" namespace Rust { namespace Resolver { -class TypeCheckStmt : public TypeCheckBase +class TypeCheckStmt : private TypeCheckBase, private HIR::HIRStmtVisitor { - using Rust::Resolver::TypeCheckBase::visit; - public: - static TyTy::BaseType *Resolve (HIR::Stmt *stmt) - { - TypeCheckStmt resolver; - stmt->accept_vis (resolver); - return resolver.infered; + static TyTy::BaseType *Resolve (HIR::Stmt *stmt); + + void visit (HIR::ExprStmtWithBlock &stmt) override; + void visit (HIR::ExprStmtWithoutBlock &stmt) override; + void visit (HIR::EmptyStmt &stmt) override; + void visit (HIR::ExternBlock &extern_block) override; + void visit (HIR::ConstantItem &constant) override; + void visit (HIR::LetStmt &stmt) override; + void visit (HIR::TupleStruct &struct_decl) override; + void visit (HIR::Enum &enum_decl) override; + void visit (HIR::StructStruct &struct_decl) override; + void visit (HIR::Union &union_decl) override; + void visit (HIR::Function &function) override; + + void visit (HIR::EnumItemTuple &) override + { /* TODO? */ } - - void visit (HIR::ExprStmtWithBlock &stmt) override - { - infered = TypeCheckExpr::Resolve (stmt.get_expr ()); + void visit (HIR::EnumItemStruct &) override + { /* TODO? */ } - - void visit (HIR::ExprStmtWithoutBlock &stmt) override - { - infered = TypeCheckExpr::Resolve (stmt.get_expr ()); + void visit (HIR::EnumItem &item) override + { /* TODO? */ } - - void visit (HIR::EmptyStmt &stmt) override - { - infered - = TyTy::TupleType::get_unit_type (stmt.get_mappings ().get_hirid ()); + void visit (HIR::EnumItemDiscriminant &) override + { /* TODO? */ } - - void visit (HIR::ExternBlock &extern_block) override - { - for (auto &item : extern_block.get_extern_items ()) - { - TypeCheckTopLevelExternItem::Resolve (item.get (), extern_block); - } + void visit (HIR::TypePathSegmentFunction &segment) override + { /* TODO? */ } - - void visit (HIR::ConstantItem &constant) override - { - TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ()); - TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); - - infered = type->unify (expr_type); - context->insert_type (constant.get_mappings (), infered); + void visit (HIR::TypePath &path) override + { /* TODO? */ } - - void visit (HIR::LetStmt &stmt) override - { - infered - = TyTy::TupleType::get_unit_type (stmt.get_mappings ().get_hirid ()); - - const HIR::Pattern &stmt_pattern = *stmt.get_pattern (); - TyTy::BaseType *init_expr_ty = nullptr; - if (stmt.has_init_expr ()) - { - init_expr_ty = TypeCheckExpr::Resolve (stmt.get_init_expr ()); - if (init_expr_ty->get_kind () == TyTy::TypeKind::ERROR) - return; - - init_expr_ty->append_reference ( - stmt_pattern.get_pattern_mappings ().get_hirid ()); - } - - TyTy::BaseType *specified_ty = nullptr; - if (stmt.has_type ()) - specified_ty = TypeCheckType::Resolve (stmt.get_type ()); - - // let x:i32 = 123; - if (specified_ty != nullptr && init_expr_ty != nullptr) - { - // FIXME use this result and look at the regressions - coercion_site (stmt.get_mappings ().get_hirid (), specified_ty, - init_expr_ty, stmt.get_locus ()); - context->insert_type (stmt_pattern.get_pattern_mappings (), - specified_ty); - } - else - { - // let x:i32; - if (specified_ty != nullptr) - { - context->insert_type (stmt_pattern.get_pattern_mappings (), - specified_ty); - } - // let x = 123; - else if (init_expr_ty != nullptr) - { - context->insert_type (stmt_pattern.get_pattern_mappings (), - init_expr_ty); - } - // let x; - else - { - context->insert_type ( - stmt_pattern.get_pattern_mappings (), - new TyTy::InferType ( - stmt_pattern.get_pattern_mappings ().get_hirid (), - TyTy::InferType::InferTypeKind::GENERAL, stmt.get_locus ())); - } - } + void visit (HIR::QualifiedPathInType &path) override + { /* TODO? */ } - - void visit (HIR::TupleStruct &struct_decl) override - { - 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); - 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); - - context->insert_type (struct_decl.get_mappings (), type); - infered = type; + void visit (HIR::Module &module) override + { /* TODO? */ } - - void visit (HIR::Enum &enum_decl) override - { - 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; + void visit (HIR::ExternCrate &crate) override + { /* TODO? */ } - - void visit (HIR::StructStruct &struct_decl) override - { - 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); - 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; + void visit (HIR::UseDeclaration &use_decl) override + { /* TODO? */ } - - void visit (HIR::Union &union_decl) override - { - 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); - 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 visit (HIR::TypeAlias &type_alias) override + { /* TODO? */ } - - void visit (HIR::Function &function) override - { - 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); - - 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 ()); - - context->pop_return_type (); - - if (block_expr_ty->get_kind () != TyTy::NEVER) - expected_ret_tyty->unify (block_expr_ty); - - infered = fnType; + void visit (HIR::StaticItem &static_item) override + { /* TODO? */ + } + void visit (HIR::Trait &trait) override + { /* TODO? */ + } + void visit (HIR::ImplBlock &impl) override + { /* TODO? */ } private: diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h index 014489d90ce..22af1aad4c3 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -29,31 +29,18 @@ namespace Resolver { class TypeCheckStructExpr : public TypeCheckBase { - using Rust::Resolver::TypeCheckBase::visit; - public: - static TyTy::BaseType *Resolve (HIR::StructExprStructFields *expr) - { - TypeCheckStructExpr resolver (expr); - expr->accept_vis (resolver); - return resolver.resolved; - } + static TyTy::BaseType *Resolve (HIR::StructExprStructFields *expr); - void visit (HIR::StructExprStructFields &struct_expr) override; +protected: + void resolve (HIR::StructExprStructFields &struct_expr); - void visit (HIR::StructExprFieldIdentifierValue &field) override; - - void visit (HIR::StructExprFieldIndexValue &field) override; - - void visit (HIR::StructExprFieldIdentifier &field) override; + void visit (HIR::StructExprFieldIdentifierValue &field); + void visit (HIR::StructExprFieldIndexValue &field); + void visit (HIR::StructExprFieldIdentifier &field); private: - TypeCheckStructExpr (HIR::Expr *e) - : TypeCheckBase (), - resolved (new TyTy::ErrorType (e->get_mappings ().get_hirid ())), - struct_path_resolved (nullptr), - variant (&TyTy::VariantDef::get_error_node ()) - {} + TypeCheckStructExpr (HIR::Expr *e); // result TyTy::BaseType *resolved; diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index 5b522772a3e..ec82442beb2 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -24,8 +24,23 @@ namespace Rust { namespace Resolver { +TypeCheckStructExpr::TypeCheckStructExpr (HIR::Expr *e) + : TypeCheckBase (), + resolved (new TyTy::ErrorType (e->get_mappings ().get_hirid ())), + struct_path_resolved (nullptr), + variant (&TyTy::VariantDef::get_error_node ()) +{} + +TyTy::BaseType * +TypeCheckStructExpr::Resolve (HIR::StructExprStructFields *expr) +{ + TypeCheckStructExpr resolver (expr); + resolver.resolve (*expr); + return resolver.resolved; +} + void -TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) +TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) { TyTy::BaseType *struct_path_ty = TypeCheckExpr::Resolve (&struct_expr.get_struct_name ()); @@ -77,7 +92,23 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) for (auto &field : struct_expr.get_fields ()) { resolved_field_value_expr = nullptr; - field->accept_vis (*this); + + switch (field->get_kind ()) + { + case HIR::StructExprField::StructExprFieldKind::IDENTIFIER: + visit (static_cast (*field.get ())); + break; + + case HIR::StructExprField::StructExprFieldKind::IDENTIFIER_VALUE: + visit ( + static_cast (*field.get ())); + break; + + case HIR::StructExprField::StructExprFieldKind::INDEX_VALUE: + visit (static_cast (*field.get ())); + break; + } + if (resolved_field_value_expr == nullptr) { rust_fatal_error (field->get_locus (), @@ -294,7 +325,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) if (resolved_field_value_expr != nullptr) { - fields_assigned.insert (field.field_name); + fields_assigned.insert (field.get_field_name ()); adtFieldIndexToField[field_index] = &field; } } diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc b/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc index d5270c9acbb..27f36b642fc 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc @@ -17,15 +17,25 @@ // . #include "rust-hir-type-check-toplevel.h" +#include "rust-hir-type-check-enumitem.h" +#include "rust-hir-type-check-type.h" +#include "rust-hir-type-check-expr.h" +#include "rust-hir-type-check-pattern.h" +#include "rust-hir-type-check-implitem.h" namespace Rust { namespace Resolver { +TypeCheckTopLevel::TypeCheckTopLevel () : TypeCheckBase () {} + void -TypeCheckTopLevel::Resolve (HIR::Item *item) +TypeCheckTopLevel::Resolve (HIR::Item &item) { + rust_assert (item.get_hir_kind () == HIR::Node::BaseKind::VIS_ITEM); + HIR::VisItem &vis_item = static_cast (item); + TypeCheckTopLevel resolver; - item->accept_vis (resolver); + vis_item.accept_vis (resolver); } void @@ -100,7 +110,7 @@ void TypeCheckTopLevel::visit (HIR::Module &module) { for (auto &item : module.get_items ()) - TypeCheckTopLevel::Resolve (item.get ()); + TypeCheckTopLevel::Resolve (*item.get ()); } void diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index d2785b15e54..d0db07d7281 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -20,37 +20,34 @@ #define RUST_HIR_TYPE_CHECK_TOPLEVEL #include "rust-hir-type-check-base.h" -#include "rust-hir-full.h" -#include "rust-hir-type-check-implitem.h" -#include "rust-hir-type-check-type.h" -#include "rust-hir-type-check-expr.h" -#include "rust-hir-type-check-enumitem.h" -#include "rust-tyty.h" namespace Rust { namespace Resolver { -class TypeCheckTopLevel : public TypeCheckBase +class TypeCheckTopLevel : private TypeCheckBase, public HIR::HIRVisItemVisitor { - using Rust::Resolver::TypeCheckBase::visit; - public: - static void Resolve (HIR::Item *item); + static void Resolve (HIR::Item &item); + void visit (HIR::Module &module) override; + void visit (HIR::Function &function) override; void visit (HIR::TypeAlias &alias) override; void visit (HIR::TupleStruct &struct_decl) override; - void visit (HIR::Module &module) 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::Function &function) override; void visit (HIR::ImplBlock &impl_block) override; void visit (HIR::ExternBlock &extern_block) override; + // nothing to do + void visit (HIR::Trait &trait_block) override {} + void visit (HIR::ExternCrate &crate) override {} + void visit (HIR::UseDeclaration &use_decl) override {} + private: - TypeCheckTopLevel () : TypeCheckBase () {} + TypeCheckTopLevel (); }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 3c2a7c5c75b..3538d77b220 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -27,7 +27,15 @@ HIR::GenericArgs TypeCheckResolveGenericArguments::resolve (HIR::TypePathSegment *segment) { TypeCheckResolveGenericArguments resolver (segment->get_locus ()); - segment->accept_vis (resolver); + switch (segment->get_type ()) + { + case HIR::TypePathSegment::SegmentType::GENERIC: + resolver.visit (static_cast (*segment)); + break; + + default: + break; + } return resolver.args; } @@ -674,17 +682,35 @@ TyTy::ParamType * TypeResolveGenericParam::Resolve (HIR::GenericParam *param) { TypeResolveGenericParam resolver; - param->accept_vis (resolver); - - if (resolver.resolved == nullptr) + switch (param->get_kind ()) { - rust_error_at (param->get_locus (), "failed to setup generic parameter"); - return nullptr; - } + case HIR::GenericParam::GenericKind::TYPE: + resolver.visit (static_cast (*param)); + break; + case HIR::GenericParam::GenericKind::CONST: + resolver.visit (static_cast (*param)); + break; + + case HIR::GenericParam::GenericKind::LIFETIME: + resolver.visit (static_cast (*param)); + break; + } return resolver.resolved; } +void +TypeResolveGenericParam::visit (HIR::LifetimeParam ¶m) +{ + // nothing to do +} + +void +TypeResolveGenericParam::visit (HIR::ConstGenericParam ¶m) +{ + // TODO +} + void TypeResolveGenericParam::visit (HIR::TypeParam ¶m) { @@ -725,11 +751,20 @@ void ResolveWhereClauseItem::Resolve (HIR::WhereClauseItem &item) { ResolveWhereClauseItem resolver; - item.accept_vis (resolver); + switch (item.get_item_type ()) + { + case HIR::WhereClauseItem::LIFETIME: + resolver.visit (static_cast (item)); + break; + + case HIR::WhereClauseItem::TYPE_BOUND: + resolver.visit (static_cast (item)); + break; + } } void -ResolveWhereClauseItem::visit (HIR::LifetimeWhereClauseItem &) +ResolveWhereClauseItem::visit (HIR::LifetimeWhereClauseItem &item) {} void diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 151e87de601..90d5ddbb411 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -27,14 +27,15 @@ namespace Rust { namespace Resolver { +// FIXME +// This simply fetches the HIR:::GenericArgs from the base class. Check to see +// if we can get rid of this class class TypeCheckResolveGenericArguments : public TypeCheckBase { - using Rust::Resolver::TypeCheckBase::visit; - public: static HIR::GenericArgs resolve (HIR::TypePathSegment *segment); - void visit (HIR::TypePathSegmentGeneric &generic) override; + void visit (HIR::TypePathSegmentGeneric &generic); private: TypeCheckResolveGenericArguments (Location locus) @@ -44,10 +45,8 @@ private: HIR::GenericArgs args; }; -class TypeCheckType : public TypeCheckBase +class TypeCheckType : public TypeCheckBase, public HIR::HIRTypeVisitor { - using Rust::Resolver::TypeCheckBase::visit; - public: static TyTy::BaseType *Resolve (HIR::Type *type); @@ -63,6 +62,22 @@ public: void visit (HIR::NeverType &type) override; void visit (HIR::TraitObjectType &type) override; + void visit (HIR::TypePathSegmentFunction &segment) override + { /* TODO */ + } + void visit (HIR::TraitBound &bound) override + { /* TODO */ + } + void visit (HIR::ImplTraitType &type) override + { /* TODO */ + } + void visit (HIR::ParenthesisedType &type) override + { /* TODO */ + } + void visit (HIR::ImplTraitTypeOneBound &type) override + { /* TODO */ + } + private: TypeCheckType (HirId id) : TypeCheckBase (), translated (new TyTy::ErrorType (id)) @@ -82,12 +97,13 @@ private: class TypeResolveGenericParam : public TypeCheckBase { - using Rust::Resolver::TypeCheckBase::visit; - public: static TyTy::ParamType *Resolve (HIR::GenericParam *param); - void visit (HIR::TypeParam ¶m) override; +protected: + void visit (HIR::TypeParam ¶m); + void visit (HIR::LifetimeParam ¶m); + void visit (HIR::ConstGenericParam ¶m); private: TypeResolveGenericParam () : TypeCheckBase (), resolved (nullptr) {} @@ -97,13 +113,12 @@ private: class ResolveWhereClauseItem : public TypeCheckBase { - using Rust::Resolver::TypeCheckBase::visit; - public: static void Resolve (HIR::WhereClauseItem &item); - void visit (HIR::LifetimeWhereClauseItem &) override; - void visit (HIR::TypeBoundWhereClauseItem &item) override; +protected: + void visit (HIR::LifetimeWhereClauseItem &item); + void visit (HIR::TypeBoundWhereClauseItem &item); private: ResolveWhereClauseItem () : TypeCheckBase () {} diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 37a085f521b..c314585cd3d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -21,6 +21,7 @@ #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" #include "rust-hir-type-check-struct-field.h" #include "rust-hir-inherent-impl-overlap.h" @@ -34,7 +35,7 @@ void TypeResolution::Resolve (HIR::Crate &crate) { for (auto it = crate.items.begin (); it != crate.items.end (); it++) - TypeCheckTopLevel::Resolve (it->get ()); + TypeCheckTopLevel::Resolve (*it->get ()); if (saw_errors ()) return; @@ -44,7 +45,7 @@ TypeResolution::Resolve (HIR::Crate &crate) return; for (auto it = crate.items.begin (); it != crate.items.end (); it++) - TypeCheckItem::Resolve (it->get ()); + TypeCheckItem::Resolve (*it->get ()); if (saw_errors ()) return; @@ -81,47 +82,6 @@ TypeResolution::Resolve (HIR::Crate &crate) }); } -// RUST_HIR_TYPE_CHECK_EXPR -void -TypeCheckExpr::visit (HIR::BlockExpr &expr) -{ - for (auto &s : expr.get_statements ()) - { - if (!s->is_item ()) - continue; - - TypeCheckStmt::Resolve (s.get ()); - } - - for (auto &s : expr.get_statements ()) - { - if (s->is_item ()) - continue; - - auto resolved = TypeCheckStmt::Resolve (s.get ()); - if (resolved == nullptr) - { - rust_error_at (s->get_locus (), "failure to resolve type"); - return; - } - - if (s->is_unit_check_needed () && !resolved->is_unit ()) - { - auto unit - = TyTy::TupleType::get_unit_type (s->get_mappings ().get_hirid ()); - resolved = unit->unify (resolved); - } - } - - if (expr.has_expr ()) - infered = TypeCheckExpr::Resolve (expr.get_final_expr ().get ())->clone (); - else if (expr.is_tail_reachable ()) - infered - = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ()); - else - infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ()); -} - // rust-hir-trait-ref.h TraitItemReference::TraitItemReference ( diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h index 36963e5efa3..f66d7eb4b8c 100644 --- a/gcc/rust/typecheck/rust-tycheck-dump.h +++ b/gcc/rust/typecheck/rust-tycheck-dump.h @@ -25,9 +25,9 @@ namespace Rust { namespace Resolver { -class TypeResolverDump : public TypeCheckBase +class TypeResolverDump : private TypeCheckBase, private HIR::HIRFullVisitorBase { - using Rust::HIR::HIRFullVisitorBase::visit; + using HIR::HIRFullVisitorBase::visit; public: static void go (HIR::Crate &crate, std::ofstream &out) From 113b830ca0f80cf02d2db993fb3850b1f8c3293e Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 11 Aug 2022 12:54:42 +0100 Subject: [PATCH 3/4] Remove unused switch statement wrapper --- gcc/rust/rust-backend.h | 12 -------- gcc/rust/rust-gcc.cc | 65 ----------------------------------------- 2 files changed, 77 deletions(-) diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index f7c0b083370..126283c1a54 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -306,18 +306,6 @@ public: // exit expressions virtual tree exit_expression (tree condition, Location) = 0; - // Create a switch statement where the case values are constants. - // CASES and STATEMENTS must have the same number of entries. If - // VALUE matches any of the list in CASES[i], which will all be - // integers, then STATEMENTS[i] is executed. STATEMENTS[i] will - // either end with a goto statement or will fall through into - // STATEMENTS[i + 1]. CASES[i] is empty for the default clause, - // which need not be last. FUNCTION is the current function. - virtual tree switch_statement (tree function, tree value, - const std::vector > &cases, - const std::vector &statements, Location) - = 0; - // Create a single statement from two statements. virtual tree compound_statement (tree, tree) = 0; diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 27196e88593..f6c053465fb 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -264,10 +264,6 @@ public: tree if_statement (tree, tree condition, tree then_block, tree else_block, Location); - tree switch_statement (tree function, tree value, - const std::vector> &cases, - const std::vector &statements, Location); - tree compound_statement (tree, tree); tree statement_list (const std::vector &); @@ -2054,67 +2050,6 @@ Gcc_backend::exit_expression (tree cond_tree, Location locus) cond_tree); } -// Switch. - -tree -Gcc_backend::switch_statement (tree decl, tree value, - const std::vector> &cases, - const std::vector &statements, - Location switch_location) -{ - gcc_assert (cases.size () == statements.size ()); - - if (DECL_STRUCT_FUNCTION (decl) == NULL) - push_struct_function (decl); - else - push_cfun (DECL_STRUCT_FUNCTION (decl)); - - tree stmt_list = NULL_TREE; - std::vector>::const_iterator pc = cases.begin (); - for (std::vector::const_iterator ps = statements.begin (); - ps != statements.end (); ++ps, ++pc) - { - if (pc->empty ()) - { - location_t loc - = (*ps != NULL ? EXPR_LOCATION (*ps) : UNKNOWN_LOCATION); - tree label = create_artificial_label (loc); - tree c = build_case_label (NULL_TREE, NULL_TREE, label); - append_to_statement_list (c, &stmt_list); - } - else - { - for (std::vector::const_iterator pcv = pc->begin (); - pcv != pc->end (); ++pcv) - { - tree t = (*pcv); - if (t == error_mark_node) - return error_mark_node; - location_t loc = EXPR_LOCATION (t); - tree label = create_artificial_label (loc); - tree c = build_case_label ((*pcv), NULL_TREE, label); - append_to_statement_list (c, &stmt_list); - } - } - - if (*ps != NULL) - { - tree t = (*ps); - if (t == error_mark_node) - return error_mark_node; - append_to_statement_list (t, &stmt_list); - } - } - pop_cfun (); - - tree tv = value; - if (tv == error_mark_node) - return error_mark_node; - tree t = build2_loc (switch_location.gcc_location (), SWITCH_EXPR, NULL_TREE, - tv, stmt_list); - return t; -} - // Pair of statements. tree From d91796f90d437ed003cae88a7d9f8eb7a573f21b Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 11 Aug 2022 12:55:44 +0100 Subject: [PATCH 4/4] Remove unused prototypes --- gcc/rust/rust-gcc.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index f6c053465fb..66fd8bce84e 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -323,10 +323,6 @@ public: bool function_set_parameters (tree function, const std::vector &); - tree lookup_gcc_builtin (const std::string &); - - tree lookup_builtin_by_rust_name (const std::string &); - void write_global_definitions (const std::vector &, const std::vector &, const std::vector &,