public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Thomas Schwinge <tschwinge@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] Support Typechecking of ADT's of enums Date: Wed, 8 Jun 2022 11:46:55 +0000 (GMT) [thread overview] Message-ID: <20220608114655.0245F382B273@sourceware.org> (raw) https://gcc.gnu.org/g:e3defa10bc63ba3f81da00fc322b5b1e0d1717ed commit e3defa10bc63ba3f81da00fc322b5b1e0d1717ed Author: Philip Herron <philip.herron@embecosm.com> Date: Sun Oct 31 00:02:58 2021 +0100 Support Typechecking of ADT's of enums Enums are ADT's with multiple variants where as structs are ADT's with a single variant, this changes the typechecking on construction of these to support enums. Addresses #79 Diff: --- gcc/rust/typecheck/rust-hir-type-check-expr.h | 28 ++++++++++++++++- gcc/rust/typecheck/rust-hir-type-check-path.cc | 19 +++++++++++- .../typecheck/rust-hir-type-check-struct-field.h | 4 ++- gcc/rust/typecheck/rust-hir-type-check-struct.cc | 35 ++++++++++++---------- gcc/rust/typecheck/rust-hir-type-check.h | 21 +++++++++++++ gcc/rust/typecheck/rust-tyty-call.h | 11 ++++--- gcc/rust/typecheck/rust-tyty.cc | 13 ++++---- gcc/rust/typecheck/rust-tyty.h | 21 +++++++++++++ 8 files changed, 121 insertions(+), 31 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 851407e04b3..2a6bae9ca7d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -198,7 +198,33 @@ public: return; } - infered = TyTy::TypeCheckCallExpr::go (function_tyty, expr, context); + TyTy::VariantDef &variant = TyTy::VariantDef::get_error_node (); + if (function_tyty->get_kind () == TyTy::TypeKind::ADT) + { + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (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); if (infered == nullptr) { rust_error_at (expr.get_locus (), "failed to lookup type to CallExpr"); diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index 20f71563dca..8aa4484f628 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -359,7 +359,24 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id, prev_segment = tyseg; tyseg = candidate.ty; - if (candidate.is_impl_candidate ()) + if (candidate.is_enum_candidate ()) + { + const TyTy::VariantDef *variant = candidate.item.enum_field.variant; + + CrateNum crate_num = mappings->get_current_crate (); + HirId variant_id = variant->get_id (); + + HIR::Item *enum_item + = mappings->lookup_hir_item (crate_num, variant_id); + rust_assert (enum_item != nullptr); + + resolved_node_id = enum_item->get_mappings ().get_nodeid (); + + // insert the id of the variant we are resolved to + context->insert_variant_definition (expr_mappings.get_hirid (), + variant_id); + } + else if (candidate.is_impl_candidate ()) { resolved_node_id = candidate.item.impl.impl_item->get_impl_mappings ().get_nodeid (); 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 6aa3134c553..4c4b128fc98 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -51,7 +51,8 @@ private: TypeCheckStructExpr (HIR::Expr *e) : TypeCheckBase (), resolved (new TyTy::ErrorType (e->get_mappings ().get_hirid ())), - struct_path_resolved (nullptr) + struct_path_resolved (nullptr), + variant (&TyTy::VariantDef::get_error_node ()) {} // result @@ -59,6 +60,7 @@ private: // internal state: TyTy::ADTType *struct_path_resolved; + TyTy::VariantDef *variant; TyTy::BaseType *resolved_field_value_expr; std::set<std::string> fields_assigned; std::map<size_t, HIR::StructExprField *> adtFieldIndexToField; diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index eedd5817ac9..78340c3f182 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -53,6 +53,25 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) } } + // figure out the variant + if (struct_path_resolved->is_enum ()) + { + // lookup variant id + HirId variant_id; + bool ok = context->lookup_variant_definition ( + struct_expr.get_struct_name ().get_mappings ().get_hirid (), + &variant_id); + rust_assert (ok); + + ok = struct_path_resolved->lookup_variant_by_id (variant_id, &variant); + rust_assert (ok); + } + else + { + rust_assert (struct_path_resolved->number_of_variants () == 1); + variant = struct_path_resolved->get_variants ().at (0); + } + std::vector<TyTy::StructFieldType *> infered_fields; bool ok = true; @@ -80,10 +99,6 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) } // check the arguments are all assigned and fix up the ordering - rust_assert (!struct_path_resolved->is_enum ()); - rust_assert (struct_path_resolved->number_of_variants () == 1); - TyTy::VariantDef *variant = struct_path_resolved->get_variants ().at (0); - if (fields_assigned.size () != variant->num_fields ()) { if (struct_def->is_union ()) @@ -197,10 +212,6 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) return; } - rust_assert (!struct_path_resolved->is_enum ()); - rust_assert (struct_path_resolved->number_of_variants () == 1); - TyTy::VariantDef *variant = struct_path_resolved->get_variants ().at (0); - size_t field_index; TyTy::StructFieldType *field_type; bool ok = variant->lookup_field (field.field_name, &field_type, &field_index); @@ -230,10 +241,6 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) return; } - rust_assert (!struct_path_resolved->is_enum ()); - rust_assert (struct_path_resolved->number_of_variants () == 1); - TyTy::VariantDef *variant = struct_path_resolved->get_variants ().at (0); - size_t field_index; TyTy::StructFieldType *field_type; bool ok = variant->lookup_field (field_name, &field_type, &field_index); @@ -262,10 +269,6 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) return; } - rust_assert (!struct_path_resolved->is_enum ()); - rust_assert (struct_path_resolved->number_of_variants () == 1); - TyTy::VariantDef *variant = struct_path_resolved->get_variants ().at (0); - size_t field_index; TyTy::StructFieldType *field_type; bool ok = variant->lookup_field (field.get_field_name (), &field_type, diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 76eac3feae9..aa10f411d01 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -214,6 +214,24 @@ public: return true; } + void insert_variant_definition (HirId id, HirId variant) + { + auto it = variants.find (id); + rust_assert (it == variants.end ()); + + variants[id] = variant; + } + + bool lookup_variant_definition (HirId id, HirId *variant) + { + auto it = variants.find (id); + if (it == variants.end ()) + return false; + + *variant = it->second; + return true; + } + private: TypeCheckContext (); @@ -234,6 +252,9 @@ private: // adjustment mappings std::map<HirId, std::vector<Adjustment>> autoderef_mappings; + + // variants + std::map<HirId, HirId> variants; }; class TypeResolution diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index c7001dd37d8..9ff5f6f3934 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -32,9 +32,10 @@ class TypeCheckCallExpr : private TyVisitor { public: static BaseType *go (BaseType *ref, HIR::CallExpr &call, + TyTy::VariantDef &variant, Resolver::TypeCheckContext *context) { - TypeCheckCallExpr checker (call, context); + TypeCheckCallExpr checker (call, variant, context); ref->accept_vis (checker); return checker.resolved; } @@ -58,6 +59,7 @@ public: void visit (PlaceholderType &) override { gcc_unreachable (); } void visit (ProjectionType &) override { gcc_unreachable (); } void visit (DynamicObjectType &) override { gcc_unreachable (); } + void visit (ClosureType &type) override { gcc_unreachable (); } // tuple-structs void visit (ADTType &type) override; @@ -65,16 +67,17 @@ public: // call fns void visit (FnType &type) override; void visit (FnPtr &type) override; - void visit (ClosureType &type) override { gcc_unreachable (); } private: - TypeCheckCallExpr (HIR::CallExpr &c, Resolver::TypeCheckContext *context) - : resolved (nullptr), call (c), context (context), + TypeCheckCallExpr (HIR::CallExpr &c, TyTy::VariantDef &variant, + Resolver::TypeCheckContext *context) + : resolved (nullptr), call (c), variant (variant), context (context), mappings (Analysis::Mappings::get ()) {} BaseType *resolved; HIR::CallExpr &call; + TyTy::VariantDef &variant; Resolver::TypeCheckContext *context; Analysis::Mappings *mappings; }; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 9f345c3c259..16cabc8bb1b 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -2537,7 +2537,8 @@ DynamicObjectType::get_object_items () const void TypeCheckCallExpr::visit (ADTType &type) { - if (!type.is_tuple_struct ()) + rust_assert (!variant.is_error ()); + if (variant.get_variant_type () != TyTy::VariantDef::VariantType::TUPLE) { rust_error_at ( call.get_locus (), @@ -2546,22 +2547,18 @@ TypeCheckCallExpr::visit (ADTType &type) return; } - rust_assert (!type.is_enum ()); - rust_assert (type.number_of_variants () == 1); - TyTy::VariantDef *variant = type.get_variants ().at (0); - - if (call.num_params () != variant->num_fields ()) + if (call.num_params () != variant.num_fields ()) { rust_error_at (call.get_locus (), "unexpected number of arguments %lu expected %lu", - call.num_params (), variant->num_fields ()); + call.num_params (), variant.num_fields ()); return; } size_t i = 0; for (auto &argument : call.get_arguments ()) { - StructFieldType *field = variant->get_field_at_index (i); + StructFieldType *field = variant.get_field_at_index (i); BaseType *field_tyty = field->get_field_type (); BaseType *arg = Resolver::TypeCheckExpr::Resolve (argument.get (), false); diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 473572f39e9..5ffd95c29da 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -1045,6 +1045,14 @@ public: || (type == VariantType::STRUCT && discriminant == 0)); } + static VariantDef &get_error_node () + { + static VariantDef node = VariantDef (UNKNOWN_HIRID, "", -1); + return node; + } + + bool is_error () const { return get_id () == UNKNOWN_HIRID; } + HirId get_id () const { return id; } VariantType get_variant_type () const { return type; } @@ -1249,6 +1257,19 @@ public: return false; } + bool lookup_variant_by_id (HirId id, VariantDef **found_variant) const + { + for (auto &variant : variants) + { + if (variant->get_id () == id) + { + *found_variant = variant; + return true; + } + } + return false; + } + ADTType * handle_substitions (SubstitutionArgumentMappings mappings) override final;
reply other threads:[~2022-06-08 11:46 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220608114655.0245F382B273@sourceware.org \ --to=tschwinge@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).