aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2020-12-30 22:13:41 +0000
committerPhilip Herron <herron.philip@googlemail.com>2021-01-06 10:01:17 +0000
commit36ebe9a0380694c8517536eb37c7134f1323a30b (patch)
tree06901ff25aa5ea093184e0713bd0363735408959 /gcc
parent467141184aa274126ff7e2a41d08bb621b7a3fdf (diff)
downloadgcc-36ebe9a0380694c8517536eb37c7134f1323a30b.zip
gcc-36ebe9a0380694c8517536eb37c7134f1323a30b.tar.gz
gcc-36ebe9a0380694c8517536eb37c7134f1323a30b.tar.bz2
This brings structs back in post HIR changes. It supports structs
where no base struct is referenced and the constructor is in order.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-expr.h21
-rw-r--r--gcc/rust/ast/rust-item.h15
-rw-r--r--gcc/rust/backend/rust-compile-context.h8
-rw-r--r--gcc/rust/backend/rust-compile-expr.h22
-rw-r--r--gcc/rust/backend/rust-compile-item.h29
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc30
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.h27
-rw-r--r--gcc/rust/backend/rust-compile-struct-field-expr.h52
-rw-r--r--gcc/rust/backend/rust-compile.cc9
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h101
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.h51
-rw-r--r--gcc/rust/hir/rust-ast-lower-struct-field-expr.h58
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc17
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h84
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-test.cc4
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h47
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h35
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h8
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h53
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-toplevel.h6
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc8
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h11
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct-field.h61
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h22
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc119
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h18
-rw-r--r--gcc/rust/typecheck/rust-tyty-visitor.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc41
-rw-r--r--gcc/rust/typecheck/rust-tyty.h62
29 files changed, 933 insertions, 88 deletions
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index cc87498..584e210 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -1571,9 +1571,16 @@ public:
virtual Location get_locus_slow () const = 0;
+ NodeId get_node_id () const { return node_id; }
+
protected:
// pure virtual clone implementation
virtual StructExprField *clone_struct_expr_field_impl () const = 0;
+
+ StructExprField () : node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ {}
+
+ NodeId node_id;
};
// Identifier-only variant of StructExprField AST node
@@ -1584,7 +1591,8 @@ class StructExprFieldIdentifier : public StructExprField
public:
StructExprFieldIdentifier (Identifier field_identifier, Location locus)
- : field_name (std::move (field_identifier)), locus (locus)
+ : StructExprField (), field_name (std::move (field_identifier)),
+ locus (locus)
{}
std::string as_string () const override { return field_name; }
@@ -1611,7 +1619,7 @@ class StructExprFieldWithVal : public StructExprField
protected:
StructExprFieldWithVal (std::unique_ptr<Expr> field_value)
- : value (std::move (field_value))
+ : StructExprField (), value (std::move (field_value))
{}
// Copy constructor requires clone
@@ -1769,6 +1777,15 @@ public:
return fields;
}
+ void iterate (std::function<bool (StructExprField *)> cb)
+ {
+ for (auto &field : fields)
+ {
+ if (!cb (field.get ()))
+ return;
+ }
+ }
+
StructBase &get_struct_base () { return struct_base; }
const StructBase &get_struct_base () const { return struct_base; }
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 1088842..9bd8de4 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -1746,6 +1746,8 @@ public:
return where_clause;
}
+ Identifier get_identifier () const { return struct_name; }
+
protected:
Struct (Identifier struct_name,
std::vector<std::unique_ptr<GenericParam> > generic_params,
@@ -1802,6 +1804,8 @@ private:
// should this store location info?
+ NodeId node_id;
+
public:
// Returns whether struct field has any outer attributes.
bool has_outer_attributes () const { return !outer_attrs.empty (); }
@@ -1877,6 +1881,8 @@ public:
}
Visibility get_visibility () const { return visibility; }
+
+ NodeId get_node_id () const { return node_id; }
};
// Rust struct declaration with true struct type AST node
@@ -1922,6 +1928,15 @@ public:
std::vector<StructField> &get_fields () { return fields; }
const std::vector<StructField> &get_fields () const { return fields; }
+ void iterate (std::function<bool (StructField &)> cb)
+ {
+ for (auto &field : fields)
+ {
+ if (!cb (field))
+ return;
+ }
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index 288dbda..9f1475a 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -227,6 +227,14 @@ public:
void visit (TyTy::FnType &type) override { gcc_unreachable (); }
+ void visit (TyTy::ADTType &type) override
+ {
+ ::Btype *compiled_type = nullptr;
+ bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type);
+ rust_assert (ok);
+ translated = compiled_type;
+ }
+
void visit (TyTy::ArrayType &type) override
{
mpz_t ival;
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 871b4ba..7b01e0e 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -23,6 +23,7 @@
#include "rust-compile-tyty.h"
#include "rust-compile-resolve-path.h"
#include "rust-compile-block.h"
+#include "rust-compile-struct-field-expr.h"
namespace Rust {
namespace Compile {
@@ -56,7 +57,7 @@ public:
void visit (HIR::CallExpr &expr)
{
- Bexpression *fn = ResolvePath::Compile (expr.get_fnexpr (), ctx);
+ Bexpression *fn = ResolvePathRef::Compile (expr.get_fnexpr (), ctx);
rust_assert (fn != nullptr);
std::vector<Bexpression *> args;
@@ -355,6 +356,25 @@ public:
ctx->add_statement (block_stmt);
}
+ void visit (HIR::StructExprStructFields &struct_expr)
+ {
+ Btype *type
+ = ResolvePathType::Compile (&struct_expr.get_struct_name (), ctx);
+
+ // this assumes all fields are in order from type resolution and if a base
+ // struct was specified those fields are filed via accesors
+ std::vector<Bexpression *> vals;
+ struct_expr.iterate ([&] (HIR::StructExprField *field) mutable -> bool {
+ Bexpression *expr = CompileStructExprField::Compile (field, ctx);
+ vals.push_back (expr);
+ return true;
+ });
+
+ translated
+ = ctx->get_backend ()->constructor_expression (type, vals,
+ struct_expr.get_locus ());
+ }
+
private:
CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {}
diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h
index 10bdce0..aa65962 100644
--- a/gcc/rust/backend/rust-compile-item.h
+++ b/gcc/rust/backend/rust-compile-item.h
@@ -39,6 +39,35 @@ public:
virtual ~CompileItem () {}
+ void visit (HIR::StructStruct &struct_decl)
+ {
+ std::vector<Backend::Btyped_identifier> fields;
+ struct_decl.iterate ([&] (HIR::StructField &field) mutable -> bool {
+ TyTy::TyBase *resolved_type = nullptr;
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (field.get_mappings ().get_hirid (),
+ &resolved_type);
+ rust_assert (ok);
+
+ Btype *compiled_field_ty
+ = TyTyCompile::compile (ctx->get_backend (), resolved_type);
+
+ Backend::Btyped_identifier f (field.field_name, compiled_field_ty,
+ field.get_locus ());
+ fields.push_back (std::move (f));
+ return true;
+ });
+
+ Btype *struct_type_record = ctx->get_backend ()->struct_type (fields);
+ Btype *named_struct
+ = ctx->get_backend ()->named_type (struct_decl.get_identifier (),
+ struct_type_record,
+ struct_decl.get_locus ());
+ ctx->push_type (named_struct);
+ ctx->insert_compiled_type (struct_decl.get_mappings ().get_hirid (),
+ named_struct);
+ }
+
void visit (HIR::ConstantItem &constant)
{
TyTy::TyBase *resolved_type = nullptr;
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index c5c646d..c24005e 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -25,7 +25,7 @@ namespace Rust {
namespace Compile {
void
-ResolvePath::visit (HIR::PathInExpression &expr)
+ResolvePathRef::visit (HIR::PathInExpression &expr)
{
// need to look up the reference for this identifier
NodeId ref_node_id;
@@ -70,5 +70,33 @@ ResolvePath::visit (HIR::PathInExpression &expr)
= ctx->get_backend ()->function_code_expression (fn, expr.get_locus ());
}
+void
+ResolvePathType::visit (HIR::PathInExpression &expr)
+{
+ // need to look up the reference for this identifier
+ NodeId ref_node_id;
+ if (!ctx->get_resolver ()->lookup_resolved_name (
+ expr.get_mappings ().get_nodeid (), &ref_node_id))
+ {
+ rust_fatal_error (expr.get_locus (), "failed to look up resolved name");
+ return;
+ }
+
+ HirId ref;
+ if (!ctx->get_mappings ()->lookup_node_to_hir (
+ expr.get_mappings ().get_crate_num (), ref_node_id, &ref))
+ {
+ rust_fatal_error (expr.get_locus (), "reverse lookup failure");
+ return;
+ }
+
+ // assumes paths are functions for now
+ if (!ctx->lookup_compiled_types (ref, &resolved))
+ {
+ rust_fatal_error (expr.get_locus (), "forward decl was not compiled");
+ return;
+ }
+}
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h
index d8f393d..a5543d2 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.h
+++ b/gcc/rust/backend/rust-compile-resolve-path.h
@@ -25,27 +25,44 @@
namespace Rust {
namespace Compile {
-class ResolvePath : public HIRCompileBase
+class ResolvePathRef : public HIRCompileBase
{
public:
static Bexpression *Compile (HIR::Expr *expr, Context *ctx)
{
- ResolvePath resolver (ctx);
+ ResolvePathRef resolver (ctx);
expr->accept_vis (resolver);
rust_assert (resolver.resolved != nullptr);
return resolver.resolved;
}
- virtual ~ResolvePath () {}
-
void visit (HIR::PathInExpression &expr);
private:
- ResolvePath (Context *ctx) : HIRCompileBase (ctx), resolved (nullptr) {}
+ ResolvePathRef (Context *ctx) : HIRCompileBase (ctx), resolved (nullptr) {}
Bexpression *resolved;
};
+class ResolvePathType : public HIRCompileBase
+{
+public:
+ static Btype *Compile (HIR::Expr *expr, Context *ctx)
+ {
+ ResolvePathType resolver (ctx);
+ expr->accept_vis (resolver);
+ rust_assert (resolver.resolved != nullptr);
+ return resolver.resolved;
+ }
+
+ void visit (HIR::PathInExpression &expr);
+
+private:
+ ResolvePathType (Context *ctx) : HIRCompileBase (ctx), resolved (nullptr) {}
+
+ Btype *resolved;
+};
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.h b/gcc/rust/backend/rust-compile-struct-field-expr.h
new file mode 100644
index 0000000..a394f7a
--- /dev/null
+++ b/gcc/rust/backend/rust-compile-struct-field-expr.h
@@ -0,0 +1,52 @@
+// Copyright (C) 2020 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/>.
+
+#ifndef RUST_COMPILE_STRUCT_FIELD_EXPR
+#define RUST_COMPILE_STRUCT_FIELD_EXPR
+
+#include "rust-compile-base.h"
+#include "rust-compile-tyty.h"
+
+namespace Rust {
+namespace Compile {
+
+class CompileStructExprField : public HIRCompileBase
+{
+public:
+ static Bexpression *Compile (HIR::StructExprField *field, Context *ctx)
+ {
+ CompileStructExprField compiler (ctx);
+ field->accept_vis (compiler);
+ rust_assert (compiler.translated != nullptr);
+ return compiler.translated;
+ }
+
+ void visit (HIR::StructExprFieldIdentifierValue &field);
+
+private:
+ CompileStructExprField (Context *ctx)
+ : HIRCompileBase (ctx), translated (nullptr)
+ {}
+
+ Bexpression *translated;
+};
+
+} // namespace Compile
+} // namespace Rust
+
+#endif // RUST_COMPILE_STRUCT_FIELD_EXPR
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 02fa3a0..24b45ee 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -19,6 +19,7 @@
#include "rust-compile.h"
#include "rust-compile-item.h"
#include "rust-compile-expr.h"
+#include "rust-compile-struct-field-expr.h"
namespace Rust {
namespace Compile {
@@ -152,5 +153,13 @@ CompileConditionalBlocks::visit (HIR::IfExprConseqIf &expr)
else_block, expr.get_locus ());
}
+// rust-compile-struct-field-expr.h
+
+void
+CompileStructExprField::visit (HIR::StructExprFieldIdentifierValue &field)
+{
+ translated = CompileExpr::Compile (field.get_value (), ctx);
+}
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h
index a165eaf..6fdb32c 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -22,6 +22,7 @@
#include "rust-diagnostics.h"
#include "rust-ast-lower-base.h"
#include "rust-ast-lower-block.h"
+#include "rust-ast-lower-struct-field-expr.h"
namespace Rust {
namespace HIR {
@@ -62,6 +63,47 @@ private:
size_t result;
}; // namespace Resolver
+class ASTLowerPathInExpression : public ASTLoweringBase
+{
+public:
+ static HIR::PathInExpression *translate (AST::PathInExpression *expr)
+ {
+ ASTLowerPathInExpression compiler;
+ expr->accept_vis (compiler);
+ rust_assert (compiler.translated);
+ return compiler.translated;
+ }
+
+ ~ASTLowerPathInExpression () {}
+
+ void visit (AST::PathInExpression &expr)
+ {
+ std::vector<HIR::PathExprSegment> path_segments;
+ expr.iterate_path_segments ([&] (AST::PathExprSegment &s) mutable -> bool {
+ rust_assert (s.has_generic_args () == false); // TODO
+
+ HIR::PathIdentSegment is (s.get_ident_segment ().as_string ());
+ HIR::PathExprSegment seg (is, s.get_locus ());
+ path_segments.push_back (seg);
+ return true;
+ });
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated = new HIR::PathInExpression (mapping, std::move (path_segments),
+ expr.get_locus (),
+ expr.opening_scope_resolution ());
+ }
+
+private:
+ ASTLowerPathInExpression () : translated (nullptr) {}
+
+ HIR::PathInExpression *translated;
+};
+
class ASTLoweringExpr : public ASTLoweringBase
{
public:
@@ -107,24 +149,7 @@ public:
void visit (AST::PathInExpression &expr)
{
- std::vector<HIR::PathExprSegment> path_segments;
- expr.iterate_path_segments ([&] (AST::PathExprSegment &s) mutable -> bool {
- rust_assert (s.has_generic_args () == false); // TODO
-
- HIR::PathIdentSegment is (s.get_ident_segment ().as_string ());
- HIR::PathExprSegment seg (is, s.get_locus ());
- path_segments.push_back (seg);
- return true;
- });
-
- auto crate_num = mappings->get_current_crate ();
- Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
- mappings->get_next_hir_id (crate_num),
- UNKNOWN_LOCAL_DEFID);
-
- translated = new HIR::PathInExpression (mapping, std::move (path_segments),
- expr.get_locus (),
- expr.opening_scope_resolution ());
+ translated = ASTLowerPathInExpression::translate (&expr);
}
void visit (AST::ReturnExpr &expr)
@@ -431,6 +456,46 @@ public:
expr.get_locus ());
}
+ void visit (AST::StructExprStructFields &struct_expr)
+ {
+ std::vector<HIR::Attribute> inner_attribs;
+ std::vector<HIR::Attribute> outer_attribs;
+
+ // bit of a hack for now
+ HIR::PathInExpression *path
+ = ASTLowerPathInExpression::translate (&struct_expr.get_struct_name ());
+ HIR::PathInExpression copied_path (*path);
+ delete path;
+
+ HIR::StructBase *base = nullptr;
+ if (struct_expr.has_struct_base ())
+ {
+ HIR::Expr *translated_base = ASTLoweringExpr::translate (
+ struct_expr.get_struct_base ().get_base_struct ().get ());
+ base
+ = new HIR::StructBase (std::unique_ptr<HIR::Expr> (translated_base));
+ }
+
+ std::vector<std::unique_ptr<HIR::StructExprField> > fields;
+ struct_expr.iterate ([&] (AST::StructExprField *field) mutable -> bool {
+ HIR::StructExprField *translated
+ = ASTLowerStructExprField::translate (field);
+ fields.push_back (std::unique_ptr<HIR::StructExprField> (translated));
+ return true;
+ });
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::StructExprStructFields (mapping, copied_path,
+ std::move (fields),
+ struct_expr.get_locus (), base,
+ inner_attribs, outer_attribs);
+ }
+
private:
ASTLoweringExpr () : translated (nullptr), translated_array_elems (nullptr) {}
diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h
index 9722390..3ac85aa 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -43,6 +43,57 @@ public:
virtual ~ASTLoweringItem () {}
+ void visit (AST::StructStruct &struct_decl)
+ {
+ std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
+ std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items;
+ HIR::WhereClause where_clause (std::move (where_clause_items));
+ HIR::Visibility vis = HIR::Visibility::create_public ();
+ std::vector<HIR::Attribute> outer_attrs;
+
+ bool is_unit = false;
+ std::vector<HIR::StructField> fields;
+ struct_decl.iterate ([&] (AST::StructField &field) mutable -> bool {
+ std::vector<HIR::Attribute> outer_attrs;
+ HIR::Visibility vis = HIR::Visibility::create_public ();
+ HIR::Type *type
+ = ASTLoweringType::translate (field.get_field_type ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, field.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ mappings->get_next_localdef_id (
+ crate_num));
+
+ // FIXME
+ // AST::StructField is missing Location info
+ Location field_locus;
+ HIR::StructField translated_field (mapping, field.get_field_name (),
+ std::unique_ptr<HIR::Type> (type), vis,
+ field_locus, outer_attrs);
+ fields.push_back (std::move (translated_field));
+ return true;
+ });
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, struct_decl.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ mappings->get_next_localdef_id (crate_num));
+
+ translated = new HIR::StructStruct (mapping, std::move (fields),
+ struct_decl.get_identifier (),
+ std::move (generic_params),
+ std::move (where_clause), is_unit, vis,
+ std::move (outer_attrs),
+ struct_decl.get_locus ());
+
+ mappings->insert_defid_mapping (mapping.get_defid (), translated);
+ mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (),
+ translated);
+ mappings->insert_location (crate_num, mapping.get_hirid (),
+ struct_decl.get_locus ());
+ }
+
void visit (AST::ConstantItem &constant)
{
std::vector<HIR::Attribute> outer_attrs;
diff --git a/gcc/rust/hir/rust-ast-lower-struct-field-expr.h b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h
new file mode 100644
index 0000000..1b444a5
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h
@@ -0,0 +1,58 @@
+// Copyright (C) 2020 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/>.
+
+#ifndef RUST_AST_LOWER_STRUCT_FIELD_EXPR
+#define RUST_AST_LOWER_STRUCT_FIELD_EXPR
+
+#include "rust-diagnostics.h"
+#include "rust-ast-lower-base.h"
+
+namespace Rust {
+namespace HIR {
+
+class ASTLowerStructExprField : public ASTLoweringBase
+{
+public:
+ static HIR::StructExprField *translate (AST::StructExprField *field)
+ {
+ ASTLowerStructExprField compiler;
+ field->accept_vis (compiler);
+ rust_assert (compiler.translated != nullptr);
+
+ // compiler.mappings->insert_hir_expr (
+ // compiler.translated->get_mappings ().get_crate_num (),
+ // compiler.translated->get_mappings ().get_hirid (),
+ // compiler.translated);
+
+ return compiler.translated;
+ }
+
+ ~ASTLowerStructExprField () {}
+
+ void visit (AST::StructExprFieldIdentifierValue &field);
+
+private:
+ ASTLowerStructExprField () : translated (nullptr) {}
+
+ HIR::StructExprField *translated;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_AST_LOWER_STRUCT_FIELD_EXPR
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index 93288c3..8dd8800 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -149,5 +149,22 @@ ASTLoweringIfBlock::visit (AST::IfExprConseqIf &expr)
expr.get_locus ());
}
+// rust-ast-lower-struct-field-expr.h
+
+void
+ASTLowerStructExprField::visit (AST::StructExprFieldIdentifierValue &field)
+{
+ HIR::Expr *value = ASTLoweringExpr::translate (field.get_value ().get ());
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, field.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated = new HIR::StructExprFieldIdentifierValue (
+ mapping, field.get_field_name (), std::unique_ptr<HIR::Expr> (value),
+ field.get_locus ());
+}
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index 1110f98..bf564cd 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -1315,9 +1315,9 @@ protected:
// Base struct/tuple/union value creator HIR node (abstract)
class StructExpr : public ExprWithoutBlock
{
+protected:
PathInExpression struct_name;
-protected:
// Protected constructor to allow initialising struct_name
StructExpr (Analysis::NodeMapping mappings, PathInExpression struct_path,
std::vector<Attribute> outer_attribs)
@@ -1326,7 +1326,7 @@ protected:
{}
public:
- const PathInExpression &get_struct_name () const { return struct_name; }
+ PathInExpression &get_struct_name () { return struct_name; }
std::string as_string () const override;
};
@@ -1417,6 +1417,8 @@ public:
bool is_invalid () const { return base_struct == nullptr; }
std::string as_string () const;
+
+ Expr *get_base () { return base_struct.get (); }
};
/* Base HIR node for a single struct expression field (in struct instance
@@ -1436,9 +1438,20 @@ public:
virtual void accept_vis (HIRVisitor &vis) = 0;
+ Analysis::NodeMapping &get_mappings () { return mappings; }
+
+ Location get_locus () { return locus; }
+
protected:
// pure virtual clone implementation
virtual StructExprField *clone_struct_expr_field_impl () const = 0;
+
+ StructExprField (Analysis::NodeMapping mapping, Location locus)
+ : mappings (mapping), locus (locus)
+ {}
+
+ Analysis::NodeMapping mappings;
+ Location locus;
};
// Identifier-only variant of StructExprField HIR node
@@ -1449,8 +1462,10 @@ public:
// TODO: should this store location data?
- StructExprFieldIdentifier (Identifier field_identifier)
- : field_name (std::move (field_identifier))
+ StructExprFieldIdentifier (Analysis::NodeMapping mapping,
+ Identifier field_identifier, Location locus)
+ : StructExprField (mapping, locus),
+ field_name (std::move (field_identifier))
{}
std::string as_string () const override { return field_name; }
@@ -1470,23 +1485,26 @@ protected:
* abstract */
class StructExprFieldWithVal : public StructExprField
{
-public:
std::unique_ptr<Expr> value;
protected:
- StructExprFieldWithVal (std::unique_ptr<Expr> field_value)
- : value (std::move (field_value))
+ StructExprFieldWithVal (Analysis::NodeMapping mapping,
+ std::unique_ptr<Expr> field_value, Location locus)
+ : StructExprField (mapping, locus), value (std::move (field_value))
{}
// Copy constructor requires clone
StructExprFieldWithVal (StructExprFieldWithVal const &other)
- : value (other.value->clone_expr ())
+ : StructExprField (other.mappings, other.locus),
+ value (other.value->clone_expr ())
{}
// Overload assignment operator to clone unique_ptr
StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other)
{
value = other.value->clone_expr ();
+ mappings = other.mappings;
+ locus = other.locus;
return *this;
}
@@ -1497,6 +1515,8 @@ protected:
public:
std::string as_string () const override;
+
+ Expr *get_value () { return value.get (); }
};
// Identifier and value variant of StructExprField HIR node
@@ -1507,9 +1527,11 @@ public:
// TODO: should this store location data?
- StructExprFieldIdentifierValue (Identifier field_identifier,
- std::unique_ptr<Expr> field_value)
- : StructExprFieldWithVal (std::move (field_value)),
+ StructExprFieldIdentifierValue (Analysis::NodeMapping mapping,
+ Identifier field_identifier,
+ std::unique_ptr<Expr> field_value,
+ Location locus)
+ : StructExprFieldWithVal (mapping, std::move (field_value), locus),
field_name (std::move (field_identifier))
{}
@@ -1534,9 +1556,11 @@ public:
// TODO: should this store location data?
- StructExprFieldIndexValue (TupleIndex tuple_index,
- std::unique_ptr<Expr> field_value)
- : StructExprFieldWithVal (std::move (field_value)), index (tuple_index)
+ StructExprFieldIndexValue (Analysis::NodeMapping mapping,
+ TupleIndex tuple_index,
+ std::unique_ptr<Expr> field_value, Location locus)
+ : StructExprFieldWithVal (mapping, std::move (field_value), locus),
+ index (tuple_index)
{}
std::string as_string () const override;
@@ -1560,31 +1584,24 @@ public:
std::vector<std::unique_ptr<StructExprField> > fields;
// bool has_struct_base;
- StructBase struct_base;
+ // FIXME make unique_ptr
+ StructBase *struct_base;
std::string as_string () const override;
- bool has_struct_base () const { return !struct_base.is_invalid (); }
-
- /*inline std::vector<std::unique_ptr<StructExprField>> get_fields()
- const { return fields;
- }*/
-
- /*inline StructBase get_struct_base() const {
- return has_struct_base ? struct_base : StructBase::error();
- }*/
+ bool has_struct_base () const { return struct_base != nullptr; }
// Constructor for StructExprStructFields when no struct base is used
StructExprStructFields (
Analysis::NodeMapping mappings, PathInExpression struct_path,
std::vector<std::unique_ptr<StructExprField> > expr_fields, Location locus,
- StructBase base_struct = StructBase::error (),
+ StructBase *base_struct,
std::vector<Attribute> inner_attribs = std::vector<Attribute> (),
std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
: StructExprStruct (std::move (mappings), std::move (struct_path),
std::move (inner_attribs), std::move (outer_attribs),
locus),
- fields (std::move (expr_fields)), struct_base (std::move (base_struct))
+ fields (std::move (expr_fields)), struct_base (base_struct)
{}
// copy constructor with vector clone
@@ -1615,6 +1632,15 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ void iterate (std::function<bool (StructExprField *)> cb)
+ {
+ for (auto &field : fields)
+ {
+ if (!cb (field.get ()))
+ return;
+ }
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1752,11 +1778,7 @@ class StructExprUnit : public StructExpr
Location locus;
public:
- std::string as_string () const override
- {
- return get_struct_name ().as_string ();
- // return struct_name.as_string();
- }
+ std::string as_string () const override { return struct_name.as_string (); }
StructExprUnit (Analysis::NodeMapping mappings, PathInExpression struct_path,
std::vector<Attribute> outer_attribs, Location locus)
diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc
index 2e30b59..c72ca65 100644
--- a/gcc/rust/hir/tree/rust-hir-full-test.cc
+++ b/gcc/rust/hir/tree/rust-hir-full-test.cc
@@ -3683,7 +3683,7 @@ StructExprStruct::as_string () const
{
std::string str ("StructExprStruct (or subclass): ");
- str += "\n Path: " + get_struct_name ().as_string ();
+ str += "\n Path: " + struct_name.as_string ();
// inner attributes
str += "\n inner attributes: ";
@@ -3761,7 +3761,7 @@ StructExprStructFields::as_string () const
}
else
{
- str += struct_base.as_string ();
+ str += struct_base->as_string ();
}
return str;
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index b961a6c..1046186 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -1390,7 +1390,7 @@ protected:
// Rust base struct declaration HIR node - abstract base class
class Struct : public VisItem
{
-public:
+protected:
// protected to enable access by derived classes - allows better as_string
Identifier struct_name;
@@ -1403,6 +1403,9 @@ public:
Location locus;
+public:
+ Identifier get_identifier () const { return struct_name; }
+
// Returns whether struct has generic parameters.
bool has_generics () const { return !generic_params.empty (); }
@@ -1465,6 +1468,10 @@ public:
Identifier field_name;
std::unique_ptr<Type> field_type;
+ Analysis::NodeMapping mappings;
+
+ Location locus;
+
// should this store location info?
// Returns whether struct field has any outer attributes.
@@ -1473,18 +1480,19 @@ public:
// Returns whether struct field has a non-private (non-default) visibility.
bool has_visibility () const { return !visibility.is_error (); }
- StructField (Identifier field_name, std::unique_ptr<Type> field_type,
- Visibility vis,
+ StructField (Analysis::NodeMapping mappings, Identifier field_name,
+ std::unique_ptr<Type> field_type, Visibility vis, Location locus,
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
: outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
- field_name (std::move (field_name)), field_type (std::move (field_type))
+ field_name (std::move (field_name)), field_type (std::move (field_type)),
+ mappings (mappings), locus (locus)
{}
// Copy constructor
StructField (StructField const &other)
: outer_attrs (other.outer_attrs), visibility (other.visibility),
field_name (other.field_name),
- field_type (other.field_type->clone_type ())
+ field_type (other.field_type->clone_type ()), mappings (other.mappings)
{}
~StructField () = default;
@@ -1496,6 +1504,7 @@ public:
field_type = other.field_type->clone_type ();
visibility = other.visibility;
outer_attrs = other.outer_attrs;
+ mappings = other.mappings;
return *this;
}
@@ -1504,20 +1513,19 @@ public:
StructField (StructField &&other) = default;
StructField &operator= (StructField &&other) = default;
- // Returns whether struct field is in an error state.
- bool is_error () const
- {
- return field_name.empty () && field_type == nullptr;
- // this should really be an or since neither are allowed
- }
+ std::string as_string () const;
- // Creates an error state struct field.
- static StructField create_error ()
+ Identifier get_field_name () const { return field_name; }
+
+ std::unique_ptr<Type> &get_field_type ()
{
- return StructField (std::string (""), nullptr, Visibility::create_error ());
+ rust_assert (field_type != nullptr);
+ return field_type;
}
- std::string as_string () const;
+ Analysis::NodeMapping get_mappings () const { return mappings; }
+
+ Location get_locus () { return locus; }
};
// Rust struct declaration with true struct type HIR node
@@ -1560,6 +1568,15 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ void iterate (std::function<bool (StructField &)> cb)
+ {
+ for (auto &field : fields)
+ {
+ if (!cb (field))
+ return;
+ }
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index d86866c..2292d16 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -21,6 +21,7 @@
#include "rust-ast-resolve-base.h"
#include "rust-ast-full.h"
+#include "rust-ast-resolve-struct-expr-field.h"
namespace Rust {
namespace Resolver {
@@ -38,19 +39,22 @@ public:
void visit (AST::PathInExpression &expr)
{
+ // name scope first
if (!resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node))
{
- rust_error_at (expr.get_locus (), "unknown path %s",
- expr.as_string ().c_str ());
- return;
- }
- else
- {
- resolver->insert_resolved_name (expr.get_node_id (), resolved_node);
- resolver->insert_new_definition (expr.get_node_id (),
- Definition{expr.get_node_id (),
- parent});
+ // check the type scope
+ if (!resolver->get_type_scope ().lookup (expr.as_string (),
+ &resolved_node))
+ {
+ rust_error_at (expr.get_locus (), "unknown path %s",
+ expr.as_string ().c_str ());
+ return;
+ }
}
+
+ resolver->insert_resolved_name (expr.get_node_id (), resolved_node);
+ resolver->insert_new_definition (expr.get_node_id (),
+ Definition{expr.get_node_id (), parent});
}
void visit (AST::ReturnExpr &expr)
@@ -154,6 +158,17 @@ public:
ResolveExpr::go (elems.get_elem_to_copy ().get (), elems.get_node_id ());
}
+ void visit (AST::StructExprStructFields &struct_expr)
+ {
+ ResolveExpr::go (&struct_expr.get_struct_name (),
+ struct_expr.get_node_id ());
+ struct_expr.iterate (
+ [&] (AST::StructExprField *struct_field) mutable -> bool {
+ ResolveStructExprField::go (struct_field, struct_expr.get_node_id ());
+ return true;
+ });
+ }
+
private:
ResolveExpr (NodeId parent) : ResolverBase (parent) {}
};
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h
index eca52dc..523f985 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ b/gcc/rust/resolve/rust-ast-resolve-item.h
@@ -39,6 +39,14 @@ public:
~ResolveItem () {}
+ void visit (AST::StructStruct &struct_decl)
+ {
+ struct_decl.iterate ([&] (AST::StructField &field) mutable -> bool {
+ ResolveType::go (field.get_field_type ().get (), field.get_node_id ());
+ return true;
+ });
+ }
+
void visit (AST::ConstantItem &constant)
{
ResolveType::go (constant.get_type ().get (), constant.get_node_id ());
diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h
new file mode 100644
index 0000000..c705a03
--- /dev/null
+++ b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h
@@ -0,0 +1,53 @@
+// Copyright (C) 2020 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/>.
+
+#ifndef RUST_AST_RESOLVE_STRUCT_EXPR_FIELD
+#define RUST_AST_RESOLVE_STRUCT_EXPR_FIELD
+
+#include "rust-ast-resolve-base.h"
+#include "rust-ast-full.h"
+
+namespace Rust {
+namespace Resolver {
+
+// this resolves values being assigned not that the field actually exists yet.
+// We cant resolve the field to struct until type resolution since the HIR
+// Mappings don't exist yet.
+class ResolveStructExprField : public ResolverBase
+{
+public:
+ static void go (AST::StructExprField *field, NodeId parent)
+ {
+ ResolveStructExprField resolver (parent);
+ field->accept_vis (resolver);
+ }
+
+ virtual ~ResolveStructExprField () {}
+
+ void visit (AST::StructExprFieldIdentifierValue &field);
+
+ // TODO
+
+private:
+ ResolveStructExprField (NodeId parent) : ResolverBase (parent) {}
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_AST_RESOLVE_STRUCT_EXPR_FIELD
diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
index 0b6256e..f770ed7 100644
--- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h
+++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
@@ -36,6 +36,12 @@ public:
~ResolveTopLevel () {}
+ void visit (AST::StructStruct &struct_decl)
+ {
+ resolver->get_type_scope ().insert (struct_decl.get_identifier (),
+ struct_decl.get_node_id ());
+ }
+
void visit (AST::ConstantItem &constant)
{
resolver->get_name_scope ().insert (constant.get_identifier (),
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
index 8370a5b..dc368aa 100644
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ b/gcc/rust/resolve/rust-ast-resolve.cc
@@ -271,5 +271,13 @@ ResolveExpr::visit (AST::BlockExpr &expr)
resolver->get_type_scope ().pop ();
}
+// rust-ast-resolve-struct-expr-field.h
+
+void
+ResolveStructExprField::visit (AST::StructExprFieldIdentifierValue &field)
+{
+ ResolveExpr::go (field.get_value ().get (), field.get_node_id ());
+}
+
} // 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 116fab7..fd5a617 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -24,6 +24,7 @@
#include "rust-tyty.h"
#include "rust-tyty-call.h"
#include "rust-tyty-resolver.h"
+#include "rust-hir-type-check-struct-field.h"
namespace Rust {
namespace Resolver {
@@ -136,9 +137,8 @@ public:
TyTy::TyBase *lookup;
if (!context->lookup_type (ref, &lookup))
{
- // FIXME we need to be able to lookup the location info for the
- // reference here
- rust_error_at (expr.get_locus (), "consider giving this a type: %s",
+ rust_error_at (mappings->lookup_location (ref),
+ "consider giving this a type: %s",
expr.as_string ().c_str ());
return;
}
@@ -269,6 +269,11 @@ public:
infered_array_elems = TypeCheckExpr::Resolve (elems.get_elem_to_copy ());
}
+ void visit (HIR::StructExprStructFields &struct_expr)
+ {
+ infered = TypeCheckStructExpr::Resolve (&struct_expr);
+ }
+
private:
TypeCheckExpr ()
: TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr)
diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
new file mode 100644
index 0000000..727569d
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2020 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/>.
+
+#ifndef RUST_HIR_TYPE_CHECK_STRUCT_FIELD
+#define RUST_HIR_TYPE_CHECK_STRUCT_FIELD
+
+#include "rust-hir-type-check-base.h"
+#include "rust-hir-full.h"
+#include "rust-hir-type-check-type.h"
+#include "rust-tyty.h"
+
+namespace Rust {
+namespace Resolver {
+
+class TypeCheckStructExpr : public TypeCheckBase
+{
+public:
+ static TyTy::TyBase *Resolve (HIR::StructExprStructFields *expr)
+ {
+ TypeCheckStructExpr resolver;
+ expr->accept_vis (resolver);
+ rust_assert (resolver.resolved != nullptr);
+ return resolver.resolved;
+ }
+
+ void visit (HIR::StructExprStructFields &struct_expr);
+
+ void visit (HIR::PathInExpression &path);
+
+ void visit (HIR::StructExprFieldIdentifierValue &field);
+
+private:
+ TypeCheckStructExpr ()
+ : TypeCheckBase (), resolved (nullptr), struct_path_resolved (nullptr)
+ {}
+
+ TyTy::TyBase *resolved;
+ TyTy::ADTType *struct_path_resolved;
+ TyTy::TyBase *resolved_field;
+ std::set<std::string> fields_assigned;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_HIR_TYPE_CHECK_STRUCT_FIELD
diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
index 85cfe92..bcffe24 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
@@ -37,6 +37,28 @@ public:
item->accept_vis (resolver);
}
+ void visit (HIR::StructStruct &struct_decl)
+ {
+ std::vector<TyTy::StructFieldType *> fields;
+ struct_decl.iterate ([&] (HIR::StructField &field) mutable -> bool {
+ TyTy::TyBase *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 ().get_hirid (),
+ ty_field->get_field_type ());
+ return true;
+ });
+
+ TyTy::TyBase *type
+ = new TyTy::ADTType (struct_decl.get_mappings ().get_hirid (),
+ struct_decl.get_identifier (), std::move (fields));
+
+ context->insert_type (struct_decl.get_mappings ().get_hirid (), type);
+ }
+
void visit (HIR::ConstantItem &constant)
{
TyTy::TyBase *type = TypeCheckType::Resolve (constant.get_type ());
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index 79e0190..e7d3366 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-struct-field.h"
namespace Rust {
namespace Resolver {
@@ -45,5 +46,123 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
});
}
+// RUST_HIR_TYPE_CHECK_STRUCT_FIELD
+
+void
+TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr)
+{
+ struct_expr.get_struct_name ().accept_vis (*this);
+ if (struct_path_resolved == nullptr)
+ {
+ rust_fatal_error (struct_expr.get_struct_name ().get_locus (),
+ "Failed to resolve type");
+ return;
+ }
+
+ struct_expr.iterate ([&] (HIR::StructExprField *field) mutable -> bool {
+ resolved_field = nullptr;
+ field->accept_vis (*this);
+ if (resolved_field == nullptr)
+ {
+ rust_fatal_error (field->get_locus (),
+ "failed to resolve type for field");
+ return false;
+ }
+
+ context->insert_type (field->get_mappings ().get_hirid (), resolved_field);
+ return true;
+ });
+
+ TyTy::TyBase *expr_type = struct_path_resolved;
+ if (struct_expr.has_struct_base ())
+ {
+ TyTy::TyBase *base_resolved
+ = TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get ());
+ expr_type = expr_type->combine (base_resolved);
+ if (resolved == nullptr)
+ {
+ rust_fatal_error (
+ struct_expr.struct_base->base_struct->get_locus_slow (),
+ "incompatible types for base struct reference");
+ return;
+ }
+ }
+ else if (fields_assigned.size () != struct_path_resolved->num_fields ())
+ {
+ rust_fatal_error (struct_expr.get_locus (),
+ "some fields are not fully assigned");
+ return;
+ }
+
+ resolved = expr_type;
+}
+
+void
+TypeCheckStructExpr::visit (HIR::PathInExpression &expr)
+{
+ NodeId ast_node_id = expr.get_mappings ().get_nodeid ();
+
+ // then lookup the reference_node_id
+ NodeId ref_node_id;
+ if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
+ {
+ rust_error_at (expr.get_locus (),
+ "Failed to lookup reference for node: %s",
+ expr.as_string ().c_str ());
+ return;
+ }
+
+ // node back to HIR
+ HirId ref;
+ if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
+ ref_node_id, &ref))
+ {
+ rust_error_at (expr.get_locus (), "reverse lookup failure");
+ return;
+ }
+
+ // the base reference for this name _must_ have a type set
+ TyTy::TyBase *lookup;
+ if (!context->lookup_type (ref, &lookup))
+ {
+ rust_error_at (mappings->lookup_location (ref),
+ "consider giving this a type: %s",
+ expr.as_string ().c_str ());
+ return;
+ }
+
+ if (lookup->get_kind () != TyTy::TypeKind::ADT)
+ {
+ rust_fatal_error (mappings->lookup_location (ref),
+ "expected an ADT type");
+ return;
+ }
+ struct_path_resolved = (TyTy::ADTType *) lookup;
+}
+
+void
+TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
+{
+ auto it = fields_assigned.find (field.field_name);
+ if (it != fields_assigned.end ())
+ {
+ rust_fatal_error (field.get_locus (), "used more than once");
+ return;
+ }
+
+ TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ());
+ TyTy::StructFieldType *field_type
+ = struct_path_resolved->get_field (field.field_name);
+ if (field_type == nullptr)
+ {
+ rust_error_at (field.get_locus (), "unknown field");
+ return;
+ }
+
+ resolved_field = field_type->get_field_type ()->combine (value);
+ if (resolved_field != nullptr)
+ fields_assigned.insert (field.field_name);
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index 97ee895..e5d3398 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -134,6 +134,24 @@ private:
TyBase *resolved;
};
+class StructFieldTypeRules : protected BaseRules
+{
+public:
+ StructFieldTypeRules (StructFieldType *base)
+ : BaseRules (base), base (base), resolved (nullptr)
+ {}
+
+ TyBase *combine (TyBase *other)
+ {
+ other->accept_vis (*this);
+ return resolved;
+ }
+
+private:
+ StructFieldType *base;
+ TyBase *resolved;
+};
+
class UnitRules : protected BaseRules
{
public:
diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h
index 427190f..7658fed 100644
--- a/gcc/rust/typecheck/rust-tyty-visitor.h
+++ b/gcc/rust/typecheck/rust-tyty-visitor.h
@@ -29,6 +29,8 @@ class TyVisitor
public:
virtual void visit (UnitType &type) {}
virtual void visit (InferType &type) {}
+ virtual void visit (StructFieldType &type) {}
+ virtual void visit (ADTType &type) {}
virtual void visit (FnType &type) {}
virtual void visit (ParamType &type) {}
virtual void visit (ArrayType &type) {}
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 2023523..756301b 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -64,6 +64,47 @@ InferType::combine (TyBase *other)
}
void
+StructFieldType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+std::string
+StructFieldType::as_string () const
+{
+ return name + ":" + ty->as_string ();
+}
+
+TyBase *
+StructFieldType::combine (TyBase *other)
+{
+ StructFieldTypeRules r (this);
+ return r.combine (other);
+}
+
+void
+ADTType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+std::string
+ADTType::as_string () const
+{
+ std::string fields_buffer;
+ for (auto &field : fields)
+ fields_buffer += field->as_string () + "\n";
+
+ return identifier + "{\n" + fields_buffer + "\n}";
+}
+
+TyBase *
+ADTType::combine (TyBase *other)
+{
+ return nullptr;
+}
+
+void
FnType::accept_vis (TyVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index b9dc268..4ff78ff 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -41,6 +41,7 @@ enum TypeKind
UINT,
FLOAT,
UNIT,
+ FIELD,
// there are more to add...
};
@@ -60,6 +61,8 @@ public:
virtual bool is_unit () const { return kind == TypeKind::UNIT; }
+ TypeKind get_kind () const { return kind; }
+
protected:
TyBase (HirId ref, TypeKind kind) : kind (kind), ref (ref) {}
@@ -95,6 +98,65 @@ public:
TyBase *combine (TyBase *other) override;
};
+class StructFieldType : public TyBase
+{
+public:
+ StructFieldType (HirId ref, std::string name, TyBase *ty)
+ : TyBase (ref, TypeKind::FIELD), name (name), ty (ty)
+ {}
+
+ void accept_vis (TyVisitor &vis) override;
+
+ bool is_unit () const override { return ty->is_unit (); }
+
+ std::string as_string () const override;
+
+ TyBase *combine (TyBase *other) override;
+
+ std::string get_name () const { return name; }
+
+ TyBase *get_field_type () { return ty; }
+
+private:
+ std::string name;
+ TyBase *ty;
+};
+
+class ADTType : public TyBase
+{
+public:
+ ADTType (HirId ref, std::string identifier,
+ std::vector<StructFieldType *> fields)
+ : TyBase (ref, TypeKind::ADT), identifier (identifier), fields (fields)
+ {}
+
+ void accept_vis (TyVisitor &vis) override;
+
+ bool is_unit () const override { return false; }
+
+ std::string as_string () const override;
+
+ TyBase *combine (TyBase *other) override;
+
+ size_t num_fields () const { return fields.size (); }
+
+ StructFieldType *get_field (size_t index) { return fields.at (index); }
+
+ StructFieldType *get_field (const std::string &lookup)
+ {
+ for (auto &field : fields)
+ {
+ if (field->get_name ().compare (lookup) == 0)
+ return field;
+ }
+ return nullptr;
+ }
+
+private:
+ std::string identifier;
+ std::vector<StructFieldType *> fields;
+};
+
class ParamType : public TyBase
{
public: