aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/rust/Make-lang.in3
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h28
-rw-r--r--gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h6
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.h10
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.h12
-rw-r--r--gcc/rust/typecheck/rust-hir-type-bounds.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.h6
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-enumitem.cc213
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-enumitem.h177
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc966
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h977
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.cc583
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.h540
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.cc19
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h28
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-path.cc2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-pattern.cc46
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-pattern.h34
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.cc498
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.h511
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct-field.h27
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct.cc37
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.cc16
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h23
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.cc53
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h41
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc46
-rw-r--r--gcc/rust/typecheck/rust-tycheck-dump.h4
28 files changed, 2666 insertions, 2242 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 886bafb..23dad26 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 7cb86a6..8327852 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 9abf872..2890b54 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 348b9f7..bd4f91e 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<PathProbeCandidate>
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<PathProbeCandidate> &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 a73b67f..c4aaf42 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<TyTy::SubstitutionParamMapping> 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 a0016ee..44400ef 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<std::pair<TraitReference *, HIR::ImplBlock *>>
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 b6f4b63..449ff6a 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 0000000..e65b201
--- /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
+// <http://www.gnu.org/licenses/>.
+
+#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<HIR::EnumItem &> (*item));
+ break;
+
+ case HIR::EnumItem::EnumItemKind::Tuple:
+ resolver.visit (static_cast<HIR::EnumItemTuple &> (*item));
+ break;
+
+ case HIR::EnumItem::EnumItemKind::Struct:
+ resolver.visit (static_cast<HIR::EnumItemStruct &> (*item));
+ break;
+
+ case HIR::EnumItem::EnumItemKind::Discriminant:
+ resolver.visit (static_cast<HIR::EnumItemDiscriminant &> (*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<TyTy::StructFieldType *> 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<TyTy::StructFieldType *> 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 bc91f45..c771ea3 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;
- }
-
- 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<TyTy::StructFieldType *> 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<TyTy::StructFieldType *> 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);
+ int64_t last_discriminant);
- 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 ff1165d..03999ba 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
// <http://www.gnu.org/licenses/>.
+#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<TyTy::ReferenceType *> (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<TyTy::TupleType *> (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<TyTy::ADTType *> (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<TyTy::TyVar> 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<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);
+}
+
+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)
{
@@ -305,6 +849,146 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
}
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<HIR::ArrayElemsCopied &> (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<HIR::ArrayElemsValues &> (elements);
+
+ std::vector<TyTy::BaseType *> 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<TyTy::ReferenceType *> (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<TyTy::ADTType *> (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)
{
auto receiver_tyty = TypeCheckExpr::Resolve (expr.get_receiver ().get ());
@@ -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 %<break%> 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 %<loop%>");
+ 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 %<continue%> 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<const TyTy::ReferenceType *> (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<TyTy::ReferenceType *> (resolved_base);
+ infered = ref_base->get_base ()->clone ();
+ }
+ else
+ {
+ TyTy::PointerType *ref_base
+ = static_cast<TyTy::PointerType *> (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<TyTy::BaseType *> 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 0c44f28..01cb213 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -20,888 +20,85 @@
#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<TyTy::ReferenceType *> (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<TyTy::TupleType *> (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<TyTy::ADTType *> (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<TyTy::TyVar> 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<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);
- }
+ 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<HIR::ArrayElemsCopied &> (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<HIR::ArrayElemsValues &> (elements);
-
- std::vector<TyTy::BaseType *> 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<TyTy::ReferenceType *> (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<TyTy::ADTType *> (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 %<break%> 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 %<loop%>");
- 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 %<continue%> 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<const TyTy::ReferenceType *> (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
+ 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
{
- 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<TyTy::ReferenceType *> (resolved_base);
- infered = ref_base->get_base ()->clone ();
- }
- else
- {
- TyTy::PointerType *ref_base
- = static_cast<TyTy::PointerType *> (resolved_base);
- infered = ref_base->get_base ()->clone ();
- }
+ gcc_unreachable ();
}
-
- void visit (HIR::TypeCastExpr &expr) override
+ void visit (HIR::StructExprFieldIdentifierValue &field) 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);
+ gcc_unreachable ();
}
-
- void visit (HIR::MatchExpr &expr) override
+ void visit (HIR::StructExprFieldIndexValue &field) 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<TyTy::BaseType *> 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;
- }
+ gcc_unreachable ();
}
- 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;
-
protected:
bool
resolve_operator_overload (Analysis::RustLangItem::ItemType lang_item_type,
@@ -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 0000000..784e499
--- /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
+// <http://www.gnu.org/licenses/>.
+
+#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<TyTy::SubstitutionParamMapping> 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<HIR::TypeParam &> (*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<std::pair<HIR::Pattern *, TyTy::BaseType *> > params;
+ for (auto &param : 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<HIR::Pattern> (nullptr));
+
+ params.push_back (
+ std::pair<HIR::Pattern *, TyTy::BaseType *> (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<TyTy::SubstitutionParamMapping> substitutions)
+ : TypeCheckBase (), self (self), substitutions (substitutions)
+{}
+
+void
+TypeCheckTopLevelImplItem::Resolve (
+ HIR::ImplItem *item, TyTy::BaseType *self,
+ std::vector<TyTy::SubstitutionParamMapping> 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<HIR::TypeParam &> (*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<std::pair<HIR::Pattern *, TyTy::BaseType *> > 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<HIR::Pattern> (nullptr));
+
+ // might have a specified type
+ TyTy::BaseType *self_type = nullptr;
+ if (self_param.has_type ())
+ {
+ std::unique_ptr<HIR::Type> &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<HIR::Pattern *, TyTy::BaseType *> (self_pattern, self_type));
+ }
+
+ for (auto &param : 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<HIR::Pattern *, TyTy::BaseType *> (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<TyTy::FnType *> (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<TyTy::SubstitutionParamMapping> 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<TyTy::SubstitutionParamMapping> 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 294dffd..f2f3faa 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);
- }
-
- 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<TyTy::SubstitutionParamMapping> 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<HIR::TypeParam &> (*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<std::pair<HIR::Pattern *, TyTy::BaseType *> > params;
- for (auto &param : 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<HIR::Pattern> (nullptr));
-
- params.push_back (
- std::pair<HIR::Pattern *, TyTy::BaseType *> (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));
+ static void Resolve (HIR::ExternalItem *item, const HIR::ExternBlock &parent);
- 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<TyTy::SubstitutionParamMapping> substitutions)
- {
- TypeCheckTopLevelImplItem resolver (self, substitutions);
- item->accept_vis (resolver);
- }
-
- 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<HIR::TypeParam &> (*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<std::pair<HIR::Pattern *, TyTy::BaseType *> > 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<HIR::Pattern> (nullptr));
-
- // might have a specified type
- TyTy::BaseType *self_type = nullptr;
- if (self_param.has_type ())
- {
- std::unique_ptr<HIR::Type> &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;
+ std::vector<TyTy::SubstitutionParamMapping> substitutions);
- default:
- gcc_unreachable ();
- return;
- }
- }
-
- context->insert_type (self_param.get_mappings (), self_type);
- params.push_back (
- std::pair<HIR::Pattern *, TyTy::BaseType *> (self_pattern,
- self_type));
- }
-
- for (auto &param : 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<HIR::Pattern *, TyTy::BaseType *> (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<TyTy::SubstitutionParamMapping> substitutions)
- : TypeCheckBase (), self (self), substitutions (substitutions)
- {}
+ std::vector<TyTy::SubstitutionParamMapping> substitutions);
TyTy::BaseType *self;
std::vector<TyTy::SubstitutionParamMapping> 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);
- }
-
- 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;
- }
+ TyTy::BaseType *self);
- // need to get the return type from this
- TyTy::FnType *resolve_fn_type = static_cast<TyTy::FnType *> (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<TyTy::SubstitutionParamMapping> substitutions)
- {
- TypeCheckImplItemWithTrait resolver (parent, self, trait_reference,
- substitutions);
- item->accept_vis (resolver);
- return resolver.resolved_trait_item;
- }
-
- 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 ());
+ std::vector<TyTy::SubstitutionParamMapping> substitutions);
- 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<TyTy::SubstitutionParamMapping> substitutions)
- : TypeCheckImplItem (parent, self), trait_reference (trait_reference),
- resolved_trait_item (TyTy::TypeBoundPredicateItem::error ()),
- substitutions (substitutions)
- {
- rust_assert (is_trait_impl_block ());
- }
+ std::vector<TyTy::SubstitutionParamMapping> 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 28cac51..d31a6df 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 @@
// <http://www.gnu.org/licenses/>.
#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<HIR::VisItem &> (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 b9a0d9b..ba4de19 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 ac1ebfd..fd0ca3e 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 @@
// <http://www.gnu.org/licenses/>.
#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 df312af..a62fbc9 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 860aca9..8af1060 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 0000000..9f34ed4
--- /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
+// <http://www.gnu.org/licenses/>.
+
+#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<TyTy::SubstitutionParamMapping> 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<HIR::TypeParam &> (*generic_param), param_type));
+ }
+ break;
+ }
+ }
+ }
+
+ std::vector<TyTy::StructFieldType *> 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<TyTy::VariantDef *> 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<TyTy::SubstitutionParamMapping> 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<HIR::TypeParam &> (*generic_param), param_type));
+ }
+ break;
+ }
+ }
+ }
+
+ std::vector<TyTy::VariantDef *> 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<TyTy::SubstitutionParamMapping> 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<HIR::TypeParam &> (*generic_param), param_type));
+ }
+ break;
+ }
+ }
+ }
+
+ std::vector<TyTy::StructFieldType *> 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<TyTy::VariantDef *> 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<TyTy::SubstitutionParamMapping> 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<HIR::TypeParam &> (*generic_param), param_type));
+ }
+ break;
+ }
+ }
+ }
+
+ std::vector<TyTy::StructFieldType *> 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<TyTy::VariantDef *> 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<TyTy::SubstitutionParamMapping> 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<HIR::TypeParam &> (*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<std::pair<HIR::Pattern *, TyTy::BaseType *> > params;
+ for (auto &param : 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<HIR::Pattern *, TyTy::BaseType *> (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 f8bf6e0..a79f17a 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<TyTy::SubstitutionParamMapping> 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<HIR::TypeParam &> (*generic_param),
- param_type));
- }
- break;
- }
- }
- }
-
- std::vector<TyTy::StructFieldType *> 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<TyTy::VariantDef *> 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<TyTy::SubstitutionParamMapping> 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<HIR::TypeParam &> (*generic_param),
- param_type));
- }
- break;
- }
- }
- }
-
- std::vector<TyTy::VariantDef *> 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<TyTy::SubstitutionParamMapping> 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<HIR::TypeParam &> (*generic_param),
- param_type));
- }
- break;
- }
- }
- }
-
- std::vector<TyTy::StructFieldType *> 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<TyTy::VariantDef *> 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<TyTy::SubstitutionParamMapping> 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<HIR::TypeParam &> (*generic_param),
- param_type));
- }
- break;
- }
- }
- }
-
- std::vector<TyTy::StructFieldType *> 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<TyTy::VariantDef *> 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<TyTy::SubstitutionParamMapping> 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<HIR::TypeParam &> (*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<std::pair<HIR::Pattern *, TyTy::BaseType *> > params;
- for (auto &param : 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<HIR::Pattern *, TyTy::BaseType *> (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 014489d..22af1aa 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;
- }
-
- void visit (HIR::StructExprStructFields &struct_expr) override;
-
- void visit (HIR::StructExprFieldIdentifierValue &field) override;
+ static TyTy::BaseType *Resolve (HIR::StructExprStructFields *expr);
- void visit (HIR::StructExprFieldIndexValue &field) override;
+protected:
+ void resolve (HIR::StructExprStructFields &struct_expr);
- 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 5b52277..ec82442 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<HIR::StructExprFieldIdentifier &> (*field.get ()));
+ break;
+
+ case HIR::StructExprField::StructExprFieldKind::IDENTIFIER_VALUE:
+ visit (
+ static_cast<HIR::StructExprFieldIdentifierValue &> (*field.get ()));
+ break;
+
+ case HIR::StructExprField::StructExprFieldKind::INDEX_VALUE:
+ visit (static_cast<HIR::StructExprFieldIndexValue &> (*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 d5270c9..27f36b6 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 @@
// <http://www.gnu.org/licenses/>.
#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<HIR::VisItem &> (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 d2785b1..d0db07d 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 3c2a7c5..3538d77 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<HIR::TypePathSegmentGeneric &> (*segment));
+ break;
+
+ default:
+ break;
+ }
return resolver.args;
}
@@ -674,18 +682,36 @@ 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<HIR::TypeParam &> (*param));
+ break;
+ case HIR::GenericParam::GenericKind::CONST:
+ resolver.visit (static_cast<HIR::ConstGenericParam &> (*param));
+ break;
+
+ case HIR::GenericParam::GenericKind::LIFETIME:
+ resolver.visit (static_cast<HIR::LifetimeParam &> (*param));
+ break;
+ }
return resolver.resolved;
}
void
+TypeResolveGenericParam::visit (HIR::LifetimeParam &param)
+{
+ // nothing to do
+}
+
+void
+TypeResolveGenericParam::visit (HIR::ConstGenericParam &param)
+{
+ // TODO
+}
+
+void
TypeResolveGenericParam::visit (HIR::TypeParam &param)
{
if (param.has_type ())
@@ -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<HIR::LifetimeWhereClauseItem &> (item));
+ break;
+
+ case HIR::WhereClauseItem::TYPE_BOUND:
+ resolver.visit (static_cast<HIR::TypeBoundWhereClauseItem &> (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 151e87d..90d5ddb 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 &param) override;
+protected:
+ void visit (HIR::TypeParam &param);
+ void visit (HIR::LifetimeParam &param);
+ void visit (HIR::ConstGenericParam &param);
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 37a085f..c314585 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 36963e5..f66d7eb 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)