public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] Support Typechecking of ADT's of enums
@ 2022-06-08 11:46 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-06-08 11:46 UTC (permalink / raw)
  To: gcc-cvs

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;


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-06-08 11:46 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-08 11:46 [gcc/devel/rust/master] Support Typechecking of ADT's of enums Thomas Schwinge

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).