aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimplyTheOther <simplytheother@gmail.com>2021-02-02 17:13:10 +0800
committerSimplyTheOther <simplytheother@gmail.com>2021-02-02 17:13:10 +0800
commit61b498895bcc0d99f00f0a89707d068d08e14246 (patch)
tree86a866a4467c6612ad1b8b68e6395f20aeb2daf6
parent3a0c8ca2156038b726e2689e9b46be4d8c40c55f (diff)
parente0e49f434423def63312084b04ea0e60e7787e27 (diff)
downloadgcc-61b498895bcc0d99f00f0a89707d068d08e14246.zip
gcc-61b498895bcc0d99f00f0a89707d068d08e14246.tar.gz
gcc-61b498895bcc0d99f00f0a89707d068d08e14246.tar.bz2
Merge with upstream
-rw-r--r--README.md6
-rw-r--r--gcc/rust/ast/rust-ast.h2
-rw-r--r--gcc/rust/ast/rust-expr.h4
-rw-r--r--gcc/rust/ast/rust-item.h25
-rw-r--r--gcc/rust/ast/rust-type.h4
-rw-r--r--gcc/rust/backend/rust-compile-context.h130
-rw-r--r--gcc/rust/backend/rust-compile-expr.h152
-rw-r--r--gcc/rust/backend/rust-compile-fnparam.h67
-rw-r--r--gcc/rust/backend/rust-compile-item.h112
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc42
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.h2
-rw-r--r--gcc/rust/backend/rust-compile-stmt.h15
-rw-r--r--gcc/rust/backend/rust-compile-struct-field-expr.h4
-rw-r--r--gcc/rust/backend/rust-compile-tyty.h158
-rw-r--r--gcc/rust/backend/rust-compile-var-decl.h22
-rw-r--r--gcc/rust/backend/rust-compile.cc72
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h165
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.h71
-rw-r--r--gcc/rust/hir/rust-ast-lower-struct-field-expr.h15
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.h82
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc50
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h151
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-test.cc85
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h42
-rw-r--r--gcc/rust/hir/tree/rust-hir-type.h40
-rw-r--r--gcc/rust/hir/tree/rust-hir-visitor.h1
-rw-r--r--gcc/rust/hir/tree/rust-hir.h13
-rw-r--r--gcc/rust/lex/rust-lex.cc4
-rw-r--r--gcc/rust/parse/rust-parse-impl.h9
-rw-r--r--gcc/rust/parse/rust-parse.cc2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h73
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h27
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-pattern.h2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-stmt.h8
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h7
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-toplevel.h11
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.h37
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc31
-rw-r--r--gcc/rust/resolve/rust-ast-verify-assignee.h83
-rw-r--r--gcc/rust/resolve/rust-name-resolver.h44
-rw-r--r--gcc/rust/rust-backend.h8
-rw-r--r--gcc/rust/rust-gcc.cc24
-rw-r--r--gcc/rust/rust-session-manager.cc5
-rw-r--r--gcc/rust/rust-system.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h532
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h67
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.h30
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct-field.h5
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h63
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h76
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc263
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h12
-rw-r--r--gcc/rust/typecheck/rust-tycheck-dump.h178
-rw-r--r--gcc/rust/typecheck/rust-tyctx.cc21
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.h22
-rw-r--r--gcc/rust/typecheck/rust-tyty-resolver.h177
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h571
-rw-r--r--gcc/rust/typecheck/rust-tyty-visitor.h4
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc303
-rw-r--r--gcc/rust/typecheck/rust-tyty.h295
-rw-r--r--gcc/rust/util/rust-hir-map.cc27
-rw-r--r--gcc/rust/util/rust-hir-map.h14
-rw-r--r--gcc/testsuite/rust.test/compilable/arithmetic_expressions1.rs28
-rw-r--r--gcc/testsuite/rust.test/compilable/arrays_index2.rs4
-rw-r--r--gcc/testsuite/rust.test/compilable/comparison_expr1.rs34
-rw-r--r--gcc/testsuite/rust.test/compilable/compound_assignment_expr1.rs24
-rw-r--r--gcc/testsuite/rust.test/compilable/forward_decl_2.rs5
-rw-r--r--gcc/testsuite/rust.test/compilable/forward_decl_3.rs8
-rw-r--r--gcc/testsuite/rust.test/compilable/forward_decl_4.rs8
-rw-r--r--gcc/testsuite/rust.test/compilable/function_reference1.rs8
-rw-r--r--gcc/testsuite/rust.test/compilable/function_reference2.rs8
-rw-r--r--gcc/testsuite/rust.test/compilable/ints_infer1.rs18
-rw-r--r--gcc/testsuite/rust.test/compilable/parameter_usage1.rs7
-rw-r--r--gcc/testsuite/rust.test/compilable/parens1.rs4
-rw-r--r--gcc/testsuite/rust.test/compilable/recursive_fn1.rs11
-rw-r--r--gcc/testsuite/rust.test/compilable/scoping1.rs2
-rw-r--r--gcc/testsuite/rust.test/compilable/struct_access1.rs10
-rw-r--r--gcc/testsuite/rust.test/compilable/struct_base_init_1.rs12
-rw-r--r--gcc/testsuite/rust.test/compilable/struct_init_2.rs5
-rw-r--r--gcc/testsuite/rust.test/compilable/struct_init_3.rs10
-rw-r--r--gcc/testsuite/rust.test/compilable/struct_init_4.rs9
-rw-r--r--gcc/testsuite/rust.test/compilable/struct_init_5.rs9
-rw-r--r--gcc/testsuite/rust.test/compilable/struct_init_6.rs9
-rw-r--r--gcc/testsuite/rust.test/compilable/struct_init_7.rs9
-rw-r--r--gcc/testsuite/rust.test/compilable/struct_init_8.rs6
-rw-r--r--gcc/testsuite/rust.test/compilable/tuple1.rs5
-rw-r--r--gcc/testsuite/rust.test/compilable/tuple2.rs4
-rw-r--r--gcc/testsuite/rust.test/compilable/tuple3.rs9
-rw-r--r--gcc/testsuite/rust.test/compilable/tuple_field_access.rs6
-rw-r--r--gcc/testsuite/rust.test/compilable/tuple_struct1.rs5
-rw-r--r--gcc/testsuite/rust.test/compilable/tuple_struct2.rs11
-rw-r--r--gcc/testsuite/rust.test/compilable/type_infer5.rs11
-rw-r--r--gcc/testsuite/rust.test/compilable/type_infer6.rs12
-rw-r--r--gcc/testsuite/rust.test/compilable/unary_operators.rs6
-rw-r--r--gcc/testsuite/rust.test/compilable/unit_type1.rs6
-rw-r--r--gcc/testsuite/rust.test/compilable/usize1.rs5
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/func2.rs7
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/func3.rs7
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/immutable1.rs5
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/immutable2.rs5
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/immutable3.rs4
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/immutable4.rs4
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/immutable5.rs6
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/implicit_returns_err1.rs12
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/implicit_returns_err2.rs8
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/implicit_returns_err3.rs9
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/struct_init1.rs8
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/tuple1.rs5
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/tuple_struct1.rs8
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/tuple_struct2.rs5
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/tuple_struct3.rs5
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/unary_negation.rs8
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/unary_not.rs8
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/usize1.rs5
114 files changed, 3975 insertions, 1041 deletions
diff --git a/README.md b/README.md
index 0c7670d..e0c8fe7 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,8 @@
# GCC Rust
![GCC Rust](logo.png?raw=true "GCC rust Logo")
+Please note, the compiler is in a very early stage and not usable yet for compiling real rust programs.
+
gccrs is a full alternative implementation of the Rust language ontop of GCC with the goal
to become fully upstream with the GNU toolchain.
@@ -14,6 +16,10 @@ Now that the language is stable, it is an excellent time to create alternative c
the project are keen “Rustaceans” with a desire to give back to the Rust community and to learn what GCC is capable
of when it comes to a modern language.
+## FAQ
+
+Please find the answers to frequently asked questions over on: https://github.com/Rust-GCC/gccrs/wiki/Frequently-Asked-Questions
+
## Development Environment
Fetch dependencies for Ubuntu:
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 9c7c567..ddeb176 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -880,6 +880,8 @@ public:
virtual NodeId get_node_id () const { return node_id; }
+ virtual void set_node_id (NodeId id) { node_id = id; }
+
protected:
// Constructor
Expr () : node_id (Analysis::Mappings::get ()->get_next_node_id ())
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index 5177785..b9a6c88 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -1373,6 +1373,8 @@ public:
return tuple_elems;
}
+ bool is_unit () const { return tuple_elems.size () == 0; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1642,6 +1644,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ Identifier get_field_name () const { return field_name; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index f558195..6de37f6 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -1819,13 +1819,14 @@ public:
Visibility vis,
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)),
+ node_id (Analysis::Mappings::get ()->get_next_node_id ())
{}
// Copy constructor
StructField (StructField const &other)
: outer_attrs (other.outer_attrs), visibility (other.visibility),
- field_name (other.field_name)
+ field_name (other.field_name), node_id (other.node_id)
{
// guard to prevent null dereference
if (other.field_type != nullptr)
@@ -1840,6 +1841,7 @@ public:
field_name = other.field_name;
visibility = other.visibility;
outer_attrs = other.outer_attrs;
+ node_id = other.node_id;
// guard to prevent null dereference
if (other.field_type != nullptr)
@@ -1961,6 +1963,7 @@ private:
std::unique_ptr<Type> field_type;
// should this store location info?
+ NodeId node_id;
public:
// Returns whether tuple field has outer attributes.
@@ -1974,12 +1977,14 @@ public:
TupleField (std::unique_ptr<Type> field_type, Visibility vis,
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
: outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
- field_type (std::move (field_type))
+ field_type (std::move (field_type)),
+ node_id (Analysis::Mappings::get ()->get_next_node_id ())
{}
// Copy constructor with clone
TupleField (TupleField const &other)
- : outer_attrs (other.outer_attrs), visibility (other.visibility)
+ : outer_attrs (other.outer_attrs), visibility (other.visibility),
+ node_id (other.node_id)
{
// guard to prevent null dereference (only required if error)
if (other.field_type != nullptr)
@@ -1993,6 +1998,7 @@ public:
{
visibility = other.visibility;
outer_attrs = other.outer_attrs;
+ node_id = other.node_id;
// guard to prevent null dereference (only required if error)
if (other.field_type != nullptr)
@@ -2018,6 +2024,8 @@ public:
std::string as_string () const;
+ NodeId get_node_id () const { return node_id; };
+
// TODO: this mutable getter seems really dodgy. Think up better way.
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
@@ -2055,6 +2063,15 @@ public:
std::vector<TupleField> &get_fields () { return fields; }
const std::vector<TupleField> &get_fields () const { return fields; }
+ void iterate (std::function<bool (TupleField &)> 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/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 0dfeb07..a9e0f0f 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -816,6 +816,10 @@ public:
rust_assert (param_type != nullptr);
return param_type;
}
+
+ ParamKind get_param_kind () const { return param_kind; }
+
+ Identifier get_name () const { return name; }
};
/* A function pointer type - can be created via coercion from function items and
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index 298ff50..034568f 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -26,6 +26,7 @@
#include "rust-backend.h"
#include "rust-compile-tyty.h"
#include "rust-ast-full.h"
+#include "rust-hir-full.h"
namespace Rust {
namespace Compile {
@@ -223,22 +224,109 @@ public:
void visit (TyTy::ErrorType &type) override { gcc_unreachable (); }
- void visit (TyTy::UnitType &type) override { gcc_unreachable (); }
-
void visit (TyTy::InferType &type) override { gcc_unreachable (); }
- void visit (TyTy::FnType &type) override { gcc_unreachable (); }
-
void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); }
- void visit (TyTy::ParamType &type) override { gcc_unreachable (); }
+ void visit (TyTy::FnType &type) override
+ {
+ Backend::Btyped_identifier receiver;
+ std::vector<Backend::Btyped_identifier> parameters;
+ std::vector<Backend::Btyped_identifier> results;
+
+ if (!type.get_return_type ()->is_unit ())
+ {
+ auto hir_type = type.get_return_type ();
+ auto ret = TyTyResolveCompile::compile (ctx, hir_type);
+ results.push_back (Backend::Btyped_identifier (
+ "_", ret,
+ ctx->get_mappings ()->lookup_location (hir_type->get_ref ())));
+ }
+
+ for (auto &param_pair : type.get_params ())
+ {
+ auto param_tyty = param_pair.second;
+ auto compiled_param_type
+ = TyTyResolveCompile::compile (ctx, param_tyty);
+
+ auto compiled_param = Backend::Btyped_identifier (
+ param_pair.first->as_string (), compiled_param_type,
+ ctx->get_mappings ()->lookup_location (param_tyty->get_ref ()));
+
+ parameters.push_back (compiled_param);
+ }
+
+ translated = ctx->get_backend ()->function_type (
+ receiver, parameters, results, NULL,
+ ctx->get_mappings ()->lookup_location (type.get_ref ()));
+ }
+
+ void visit (TyTy::UnitType &type) override
+ {
+ translated = ctx->get_backend ()->void_type ();
+ }
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;
+ bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &translated);
+ if (ok)
+ return;
+
+ // create implicit struct
+ std::vector<Backend::Btyped_identifier> fields;
+ for (size_t i = 0; i < type.num_fields (); i++)
+ {
+ TyTy::StructFieldType *field = type.get_field (i);
+ Btype *compiled_field_ty
+ = TyTyCompile::compile (ctx->get_backend (),
+ field->get_field_type ());
+
+ Backend::Btyped_identifier f (field->get_name (), compiled_field_ty,
+ ctx->get_mappings ()->lookup_location (
+ type.get_ty_ref ()));
+ fields.push_back (std::move (f));
+ }
+
+ Btype *struct_type_record = ctx->get_backend ()->struct_type (fields);
+ Btype *named_struct
+ = ctx->get_backend ()->named_type (type.get_name (), struct_type_record,
+ ctx->get_mappings ()->lookup_location (
+ type.get_ty_ref ()));
+
+ ctx->push_type (named_struct);
+ ctx->insert_compiled_type (type.get_ty_ref (), named_struct);
+ translated = named_struct;
+ }
+
+ void visit (TyTy::TupleType &type) override
+ {
+ bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &translated);
+ if (ok)
+ return;
+
+ // create implicit struct
+ std::vector<Backend::Btyped_identifier> fields;
+ for (size_t i = 0; i < type.num_fields (); i++)
+ {
+ TyTy::TyBase *field = type.get_field (i);
+ Btype *compiled_field_ty
+ = TyTyCompile::compile (ctx->get_backend (), field);
+
+ Backend::Btyped_identifier f (std::to_string (i), compiled_field_ty,
+ ctx->get_mappings ()->lookup_location (
+ type.get_ty_ref ()));
+ fields.push_back (std::move (f));
+ }
+
+ Btype *struct_type_record = ctx->get_backend ()->struct_type (fields);
+ Btype *named_struct
+ = ctx->get_backend ()->named_type (type.as_string (), struct_type_record,
+ ctx->get_mappings ()->lookup_location (
+ type.get_ty_ref ()));
+
+ ctx->push_type (named_struct);
+ ctx->insert_compiled_type (type.get_ty_ref (), named_struct);
+ translated = named_struct;
}
void visit (TyTy::ArrayType &type) override
@@ -257,7 +345,7 @@ public:
void visit (TyTy::BoolType &type) override
{
::Btype *compiled_type = nullptr;
- bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type);
+ bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type);
rust_assert (ok);
translated = compiled_type;
}
@@ -265,7 +353,7 @@ public:
void visit (TyTy::IntType &type) override
{
::Btype *compiled_type = nullptr;
- bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type);
+ bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type);
rust_assert (ok);
translated = compiled_type;
}
@@ -273,7 +361,7 @@ public:
void visit (TyTy::UintType &type) override
{
::Btype *compiled_type = nullptr;
- bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type);
+ bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type);
rust_assert (ok);
translated = compiled_type;
}
@@ -281,7 +369,23 @@ public:
void visit (TyTy::FloatType &type) override
{
::Btype *compiled_type = nullptr;
- bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type);
+ bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type);
+ rust_assert (ok);
+ translated = compiled_type;
+ }
+
+ void visit (TyTy::USizeType &type) override
+ {
+ ::Btype *compiled_type = nullptr;
+ bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type);
+ rust_assert (ok);
+ translated = compiled_type;
+ }
+
+ void visit (TyTy::ISizeType &type) override
+ {
+ ::Btype *compiled_type = nullptr;
+ bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type);
rust_assert (ok);
translated = compiled_type;
}
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 0370129..81d7786 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -38,7 +38,49 @@ public:
return compiler.translated;
}
- virtual ~CompileExpr () {}
+ void visit (HIR::TupleIndexExpr &expr)
+ {
+ HIR::Expr *tuple_expr = expr.get_tuple_expr ().get ();
+ TupleIndex index = expr.get_tuple_index ();
+
+ Bexpression *receiver_ref = CompileExpr::Compile (tuple_expr, ctx);
+ translated
+ = ctx->get_backend ()->struct_field_expression (receiver_ref, index,
+ expr.get_locus ());
+ }
+
+ void visit (HIR::TupleExpr &expr)
+ {
+ if (expr.is_unit ())
+ {
+ translated = ctx->get_backend ()->unit_expression ();
+ return;
+ }
+
+ TyTy::TyBase *tyty = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
+ &tyty))
+ {
+ rust_fatal_error (expr.get_locus (),
+ "did not resolve type for this TupleExpr");
+ return;
+ }
+
+ Btype *tuple_type = TyTyResolveCompile::compile (ctx, tyty);
+ rust_assert (tuple_type != nullptr);
+
+ // this assumes all fields are in order from type resolution
+ std::vector<Bexpression *> vals;
+ for (auto &elem : expr.get_tuple_elems ())
+ {
+ auto e = CompileExpr::Compile (elem.get (), ctx);
+ vals.push_back (e);
+ }
+
+ translated
+ = ctx->get_backend ()->constructor_expression (tuple_type, vals,
+ expr.get_locus ());
+ }
void visit (HIR::ReturnExpr &expr)
{
@@ -55,24 +97,7 @@ public:
ctx->add_statement (s);
}
- void visit (HIR::CallExpr &expr)
- {
- Bexpression *fn = ResolvePathRef::Compile (expr.get_fnexpr (), ctx);
- rust_assert (fn != nullptr);
-
- std::vector<Bexpression *> args;
- expr.iterate_params ([&] (HIR::Expr *p) mutable -> bool {
- Bexpression *compiled_expr = CompileExpr::Compile (p, ctx);
- rust_assert (compiled_expr != nullptr);
- args.push_back (compiled_expr);
- return true;
- });
-
- auto fncontext = ctx->peek_fn ();
- translated
- = ctx->get_backend ()->call_expression (fncontext.fndecl, fn, args,
- nullptr, expr.get_locus ());
- }
+ void visit (HIR::CallExpr &expr);
void visit (HIR::IdentifierExpr &expr)
{
@@ -85,10 +110,6 @@ public:
return;
}
- printf ("have ast node id %u ref %u for expr [%s]\n",
- expr.get_mappings ().get_nodeid (), ref_node_id,
- expr.as_string ().c_str ());
-
// these ref_node_ids will resolve to a pattern declaration but we are
// interested in the definition that this refers to get the parent id
Resolver::Definition def;
@@ -106,35 +127,45 @@ public:
return;
}
- // this could be a constant reference
- if (ctx->lookup_const_decl (ref, &translated))
- return;
-
- // must be an identifier
+ Bfunction *fn = nullptr;
Bvariable *var = nullptr;
- if (!ctx->lookup_var_decl (ref, &var))
+ if (ctx->lookup_const_decl (ref, &translated))
{
- rust_fatal_error (expr.get_locus (),
- "failed to lookup compiled variable");
return;
}
-
- translated = ctx->get_backend ()->var_expression (var, expr.get_locus ());
+ else if (ctx->lookup_function_decl (ref, &fn))
+ {
+ translated
+ = ctx->get_backend ()->function_code_expression (fn,
+ expr.get_locus ());
+ }
+ else if (ctx->lookup_var_decl (ref, &var))
+ {
+ translated
+ = ctx->get_backend ()->var_expression (var, expr.get_locus ());
+ }
+ else
+ {
+ rust_fatal_error (expr.get_locus (),
+ "failed to lookup compiled reference");
+ }
}
void visit (HIR::LiteralExpr &expr)
{
+ auto literal_value = expr.get_literal ();
switch (expr.get_lit_type ())
{
case HIR::Literal::BOOL: {
- bool bval = expr.as_string ().compare ("true") == 0;
+ bool bval = literal_value->as_string ().compare ("true") == 0;
translated = ctx->get_backend ()->boolean_constant_expression (bval);
}
return;
case HIR::Literal::INT: {
mpz_t ival;
- if (mpz_init_set_str (ival, expr.as_string ().c_str (), 10) != 0)
+ if (mpz_init_set_str (ival, literal_value->as_string ().c_str (), 10)
+ != 0)
{
rust_fatal_error (expr.get_locus (), "bad number in literal");
return;
@@ -157,7 +188,7 @@ public:
case HIR::Literal::FLOAT: {
mpfr_t fval;
- if (mpfr_init_set_str (fval, expr.as_string ().c_str (), 10,
+ if (mpfr_init_set_str (fval, literal_value->as_string ().c_str (), 10,
MPFR_RNDN)
!= 0)
{
@@ -357,6 +388,25 @@ public:
expr.get_locus ());
}
+ void visit (HIR::NegationExpr &expr)
+ {
+ Operator op (OPERATOR_INVALID);
+ switch (expr.get_negation_type ())
+ {
+ case HIR::NegationExpr::NegationType::NEGATE:
+ op = OPERATOR_MINUS;
+ break;
+
+ case HIR::NegationExpr::NegationType::NOT:
+ op = OPERATOR_NOT;
+ break;
+ }
+
+ Bexpression *negated_expr = CompileExpr::Compile (expr.get_expr (), ctx);
+ translated = ctx->get_backend ()->unary_expression (op, negated_expr,
+ expr.get_locus ());
+ }
+
void visit (HIR::IfExpr &expr)
{
auto stmt = CompileConditionalBlocks::compile (&expr, ctx);
@@ -401,6 +451,36 @@ public:
struct_expr.get_locus ());
}
+ void visit (HIR::GroupedExpr &expr)
+ {
+ translated = CompileExpr::Compile (expr.get_expr_in_parens ().get (), ctx);
+ }
+
+ void visit (HIR::FieldAccessExpr &expr)
+ {
+ // resolve the receiver back to ADT type
+ TyTy::TyBase *receiver = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ expr.get_receiver_expr ()->get_mappings ().get_hirid (), &receiver))
+ {
+ rust_error_at (expr.get_receiver_expr ()->get_locus_slow (),
+ "unresolved type for receiver");
+ return;
+ }
+ rust_assert (receiver->get_kind () == TyTy::TypeKind::ADT);
+
+ TyTy::ADTType *adt = (TyTy::ADTType *) receiver;
+ size_t index = 0;
+ adt->get_field (expr.get_field_name (), &index);
+
+ Bexpression *struct_ref
+ = CompileExpr::Compile (expr.get_receiver_expr ().get (), ctx);
+
+ translated
+ = ctx->get_backend ()->struct_field_expression (struct_ref, index,
+ expr.get_locus ());
+ }
+
private:
CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {}
diff --git a/gcc/rust/backend/rust-compile-fnparam.h b/gcc/rust/backend/rust-compile-fnparam.h
new file mode 100644
index 0000000..cf6e6f7
--- /dev/null
+++ b/gcc/rust/backend/rust-compile-fnparam.h
@@ -0,0 +1,67 @@
+// 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_FNPARAM
+#define RUST_COMPILE_FNPARAM
+
+#include "rust-compile-base.h"
+
+namespace Rust {
+namespace Compile {
+
+class CompileFnParam : public HIRCompileBase
+{
+public:
+ static Bvariable *compile (Context *ctx, Bfunction *fndecl,
+ HIR::FunctionParam *param, Btype *decl_type,
+ Location locus)
+ {
+ CompileFnParam compiler (ctx, fndecl, decl_type, locus);
+ param->get_param_name ()->accept_vis (compiler);
+ return compiler.translated;
+ }
+
+ void visit (HIR::IdentifierPattern &pattern)
+ {
+ if (!pattern.is_mut)
+ decl_type = ctx->get_backend ()->immutable_type (decl_type);
+
+ translated
+ = ctx->get_backend ()->parameter_variable (fndecl, pattern.variable_ident,
+ decl_type,
+ false /* address_taken */,
+ locus);
+ }
+
+private:
+ CompileFnParam (Context *ctx, ::Bfunction *fndecl, ::Btype *decl_type,
+ Location locus)
+ : HIRCompileBase (ctx), fndecl (fndecl), decl_type (decl_type),
+ locus (locus), translated (nullptr)
+ {}
+
+ ::Bfunction *fndecl;
+ ::Btype *decl_type;
+ Location locus;
+ ::Bvariable *translated;
+};
+
+} // namespace Compile
+} // namespace Rust
+
+#endif // RUST_COMPILE_FNPARAM
diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h
index c5fe9a2..1bb7c91 100644
--- a/gcc/rust/backend/rust-compile-item.h
+++ b/gcc/rust/backend/rust-compile-item.h
@@ -24,6 +24,7 @@
#include "rust-compile-var-decl.h"
#include "rust-compile-stmt.h"
#include "rust-compile-expr.h"
+#include "rust-compile-fnparam.h"
namespace Rust {
namespace Compile {
@@ -31,41 +32,38 @@ namespace Compile {
class CompileItem : public HIRCompileBase
{
public:
- static void compile (HIR::Item *item, Context *ctx)
+ static void compile (HIR::Item *item, Context *ctx, bool compile_fns = true)
{
- CompileItem compiler (ctx);
+ CompileItem compiler (ctx, compile_fns);
item->accept_vis (compiler);
}
- virtual ~CompileItem () {}
-
- void visit (HIR::StructStruct &struct_decl)
+ void visit (HIR::TupleStruct &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);
+ TyTy::TyBase *resolved = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ struct_decl.get_mappings ().get_hirid (), &resolved))
+ {
+ rust_fatal_error (struct_decl.get_locus (),
+ "Failed to lookup type for struct decl");
+ return;
+ }
- Btype *compiled_field_ty
- = TyTyCompile::compile (ctx->get_backend (), resolved_type);
+ TyTyResolveCompile::compile (ctx, resolved);
+ }
- Backend::Btyped_identifier f (field.field_name, compiled_field_ty,
- field.get_locus ());
- fields.push_back (std::move (f));
- return true;
- });
+ void visit (HIR::StructStruct &struct_decl)
+ {
+ TyTy::TyBase *resolved = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ struct_decl.get_mappings ().get_hirid (), &resolved))
+ {
+ rust_fatal_error (struct_decl.get_locus (),
+ "Failed to lookup type for struct decl");
+ return;
+ }
- 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);
+ TyTyResolveCompile::compile (ctx, resolved);
}
void visit (HIR::StaticItem &var)
@@ -116,6 +114,9 @@ public:
void visit (HIR::Function &function)
{
+ if (!compile_fns)
+ return;
+
// items can be forward compiled which means we may not need to invoke this
// code
Bfunction *lookup = nullptr;
@@ -127,16 +128,23 @@ public:
return;
}
- TyTy::TyBase *fnType;
+ TyTy::TyBase *fntype_tyty;
if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (),
- &fnType))
+ &fntype_tyty))
{
rust_fatal_error (function.locus, "failed to lookup function type");
return;
}
+ if (fntype_tyty->get_kind () != TyTy::TypeKind::FNDEF)
+ {
+ rust_error_at (function.get_locus (), "invalid TyTy for function item");
+ return;
+ }
+
+ TyTy::FnType *fntype = (TyTy::FnType *) fntype_tyty;
// convert to the actual function type
- auto compiled_fn_type = TyTyCompile::compile (ctx->get_backend (), fnType);
+ ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
unsigned int flags = 0;
bool is_main_fn = function.function_name.compare ("main") == 0;
@@ -159,18 +167,34 @@ public:
ctx->insert_function_decl (function.get_mappings ().get_hirid (), fndecl);
// setup the params
- TyTy::TyBase *tyret = TyTyExtractRetFromFnType::compile (fnType);
- std::vector<TyTy::ParamType *> typarams
- = TyTyExtractParamsFromFnType::compile (fnType);
+
+ TyTy::TyBase *tyret = fntype->return_type ();
std::vector<Bvariable *> param_vars;
- for (auto &it : typarams)
+ size_t i = 0;
+ for (auto &it : fntype->get_params ())
{
- auto compiled_param
- = TyTyCompileParam::compile (ctx->get_backend (), fndecl, it);
- param_vars.push_back (compiled_param);
-
- ctx->insert_var_decl (it->get_ref (), compiled_param);
+ HIR::FunctionParam &referenced_param = function.function_params.at (i);
+ auto param_tyty = it.second;
+ auto compiled_param_type
+ = TyTyResolveCompile::compile (ctx, param_tyty);
+
+ Location param_locus
+ = ctx->get_mappings ()->lookup_location (param_tyty->get_ref ());
+ Bvariable *compiled_param_var
+ = CompileFnParam::compile (ctx, fndecl, &referenced_param,
+ compiled_param_type, param_locus);
+ if (compiled_param_var == nullptr)
+ {
+ rust_error_at (param_locus, "failed to compile parameter variable");
+ return;
+ }
+
+ param_vars.push_back (compiled_param_var);
+
+ ctx->insert_var_decl (referenced_param.get_mappings ().get_hirid (),
+ compiled_param_var);
+ i++;
}
if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars))
@@ -226,7 +250,7 @@ public:
Bvariable *return_address = nullptr;
if (function.has_function_return_type ())
{
- Btype *return_type = TyTyCompile::compile (ctx->get_backend (), tyret);
+ Btype *return_type = TyTyResolveCompile::compile (ctx, tyret);
bool address_is_taken = false;
Bstatement *ret_var_stmt = nullptr;
@@ -246,7 +270,7 @@ public:
return true;
});
- if (function_body->has_expr ())
+ if (function_body->has_expr () && function_body->tail_expr_reachable ())
{
// the previous passes will ensure this is a valid return
// dead code elimination should remove any bad trailing expressions
@@ -277,7 +301,11 @@ public:
}
private:
- CompileItem (Context *ctx) : HIRCompileBase (ctx) {}
+ CompileItem (Context *ctx, bool compile_fns)
+ : HIRCompileBase (ctx), compile_fns (compile_fns)
+ {}
+
+ bool compile_fns;
};
} // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index 374f8a0..818d5cb 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -28,24 +28,43 @@ void
ResolvePathRef::visit (HIR::PathInExpression &expr)
{
// need to look up the reference for this identifier
- NodeId ref_node_id;
- if (!ctx->get_resolver ()->lookup_resolved_name (
+ NodeId ref_node_id = UNKNOWN_NODEID;
+ 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;
+ Resolver::Definition def;
+ if (!ctx->get_resolver ()->lookup_definition (ref_node_id, &def))
+ {
+ rust_error_at (expr.get_locus (),
+ "unknown reference for resolved name");
+ return;
+ }
+ ref_node_id = def.parent;
}
+ // this can fail because it might be a Constructor for something
+ // in that case the caller should attempt ResolvePathType::Compile
+ if (ref_node_id == UNKNOWN_NODEID)
+ 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");
+ rust_error_at (expr.get_locus (), "reverse call path lookup failure");
return;
}
- // assumes paths are functions for now
- Bfunction *fn;
+ // this might be a variable reference or a function reference
+ Bvariable *var = nullptr;
+ if (ctx->lookup_var_decl (ref, &var))
+ {
+ resolved = ctx->get_backend ()->var_expression (var, expr.get_locus ());
+ return;
+ }
+
+ // must be a function call
+ Bfunction *fn = nullptr;
if (!ctx->lookup_function_decl (ref, &fn))
{
// this might fail because its a forward decl so we can attempt to
@@ -54,14 +73,14 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
expr.get_mappings ().get_crate_num (), ref);
if (resolved_item == nullptr)
{
- rust_fatal_error (expr.get_locus (), "failed to lookup forward decl");
+ rust_error_at (expr.get_locus (), "failed to lookup forward decl");
return;
}
CompileItem::compile (resolved_item, ctx);
if (!ctx->lookup_function_decl (ref, &fn))
{
- rust_fatal_error (expr.get_locus (), "forward decl was not compiled");
+ rust_error_at (expr.get_locus (), "forward decl was not compiled");
return;
}
}
@@ -78,7 +97,6 @@ ResolvePathType::visit (HIR::PathInExpression &expr)
if (!ctx->get_resolver ()->lookup_resolved_type (
expr.get_mappings ().get_nodeid (), &ref_node_id))
{
- rust_fatal_error (expr.get_locus (), "failed to look up resolved name");
return;
}
@@ -86,14 +104,14 @@ ResolvePathType::visit (HIR::PathInExpression &expr)
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");
+ rust_error_at (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");
+ rust_error_at (expr.get_locus (), "forward decl was not compiled");
return;
}
}
diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h
index a5543d2..2f3cb68 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.h
+++ b/gcc/rust/backend/rust-compile-resolve-path.h
@@ -32,7 +32,6 @@ public:
{
ResolvePathRef resolver (ctx);
expr->accept_vis (resolver);
- rust_assert (resolver.resolved != nullptr);
return resolver.resolved;
}
@@ -51,7 +50,6 @@ public:
{
ResolvePathType resolver (ctx);
expr->accept_vis (resolver);
- rust_assert (resolver.resolved != nullptr);
return resolver.resolved;
}
diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h
index 5f7decb..c52f605 100644
--- a/gcc/rust/backend/rust-compile-stmt.h
+++ b/gcc/rust/backend/rust-compile-stmt.h
@@ -71,6 +71,18 @@ public:
if (!stmt.has_init_expr ())
return;
+ TyTy::TyBase *ty = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (stmt.get_mappings ().get_hirid (),
+ &ty))
+ {
+ rust_fatal_error (stmt.get_locus (), "failed to lookup var decl type");
+ return;
+ }
+
+ // there is an ICE in GCC for void_node
+ if (ty->get_kind () == TyTy::TypeKind::UNIT)
+ return;
+
Bvariable *var = nullptr;
if (!ctx->lookup_var_decl (stmt.get_mappings ().get_hirid (), &var))
{
@@ -79,7 +91,8 @@ public:
return;
}
- auto *init = CompileExpr::Compile (stmt.get_init_expr (), ctx);
+ Bexpression *init = CompileExpr::Compile (stmt.get_init_expr (), ctx);
+
auto fnctx = ctx->peek_fn ();
auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var, init);
ctx->add_statement (s);
diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.h b/gcc/rust/backend/rust-compile-struct-field-expr.h
index a394f7a..0a16f6a 100644
--- a/gcc/rust/backend/rust-compile-struct-field-expr.h
+++ b/gcc/rust/backend/rust-compile-struct-field-expr.h
@@ -38,6 +38,10 @@ public:
void visit (HIR::StructExprFieldIdentifierValue &field);
+ void visit (HIR::StructExprFieldIndexValue &field);
+
+ void visit (HIR::StructExprFieldIdentifier &field);
+
private:
CompileStructExprField (Context *ctx)
: HIRCompileBase (ctx), translated (nullptr)
diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h
index 137b74b..2c54b17 100644
--- a/gcc/rust/backend/rust-compile-tyty.h
+++ b/gcc/rust/backend/rust-compile-tyty.h
@@ -26,6 +26,7 @@
#include "rust-tyty.h"
#include "rust-tyty-visitor.h"
#include "rust-hir-map.h"
+#include "rust-hir-full.h"
namespace Rust {
namespace Compile {
@@ -45,18 +46,21 @@ public:
void visit (TyTy::ErrorType &type) override { gcc_unreachable (); }
- void visit (TyTy::UnitType &type) override { gcc_unreachable (); }
-
void visit (TyTy::InferType &type) override { gcc_unreachable (); }
void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); }
- void visit (TyTy::ParamType &type) override { gcc_unreachable (); }
-
void visit (TyTy::ADTType &type) override { gcc_unreachable (); }
+ void visit (TyTy::TupleType &type) override { gcc_unreachable (); }
+
void visit (TyTy::ArrayType &type) override { gcc_unreachable (); }
+ void visit (TyTy::UnitType &type) override
+ {
+ translated = backend->void_type ();
+ }
+
void visit (TyTy::FnType &type) override
{
Backend::Btyped_identifier receiver;
@@ -71,13 +75,14 @@ public:
"_", ret, mappings->lookup_location (hir_type->get_ref ())));
}
- for (size_t i = 0; i < type.num_params (); i++)
+ for (auto &params : type.get_params ())
{
- auto param_tyty = type.param_at (i);
- auto compiled_param_type
- = TyTyCompile::compile (backend, param_tyty->get_base_type ());
+ auto param_pattern = params.first;
+ auto param_tyty = params.second;
+ auto compiled_param_type = TyTyCompile::compile (backend, param_tyty);
+
auto compiled_param = Backend::Btyped_identifier (
- param_tyty->get_identifier (), compiled_param_type,
+ param_pattern->as_string (), compiled_param_type,
mappings->lookup_location (param_tyty->get_ref ()));
parameters.push_back (compiled_param);
@@ -185,141 +190,28 @@ public:
gcc_unreachable ();
}
-private:
- TyTyCompile (::Backend *backend)
- : backend (backend), translated (nullptr),
- mappings (Analysis::Mappings::get ())
- {}
-
- ::Backend *backend;
- ::Btype *translated;
- Analysis::Mappings *mappings;
-};
-
-class TyTyExtractParamsFromFnType : public TyTy::TyVisitor
-{
-public:
- static std::vector<TyTy::ParamType *> compile (TyTy::TyBase *ty)
+ void visit (TyTy::USizeType &type) override
{
- TyTyExtractParamsFromFnType compiler;
- ty->accept_vis (compiler);
- rust_assert (compiler.ok);
- return compiler.translated;
+ translated = backend->named_type (
+ "usize", backend->integer_type (true, backend->get_pointer_size ()),
+ Linemap::predeclared_location ());
}
- ~TyTyExtractParamsFromFnType () {}
-
- void visit (TyTy::UnitType &type) override { gcc_unreachable (); }
- void visit (TyTy::InferType &type) override { gcc_unreachable (); }
- void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); }
- void visit (TyTy::ADTType &type) override { gcc_unreachable (); }
- void visit (TyTy::ParamType &type) override { gcc_unreachable (); }
- void visit (TyTy::ArrayType &type) override { gcc_unreachable (); }
- void visit (TyTy::BoolType &type) override { gcc_unreachable (); }
- void visit (TyTy::IntType &type) override { gcc_unreachable (); }
- void visit (TyTy::UintType &type) override { gcc_unreachable (); }
- void visit (TyTy::FloatType &type) override { gcc_unreachable (); }
- void visit (TyTy::ErrorType &type) override { gcc_unreachable (); }
-
- void visit (TyTy::FnType &type) override
+ void visit (TyTy::ISizeType &type) override
{
- ok = true;
- for (size_t i = 0; i < type.num_params (); i++)
- {
- translated.push_back (type.param_at (i));
- }
+ translated = backend->named_type (
+ "isize", backend->integer_type (false, backend->get_pointer_size ()),
+ Linemap::predeclared_location ());
}
private:
- TyTyExtractParamsFromFnType () : ok (false) {}
-
- bool ok;
- std::vector<TyTy::ParamType *> translated;
-};
-
-class TyTyExtractRetFromFnType : public TyTy::TyVisitor
-{
-public:
- static TyTy::TyBase *compile (TyTy::TyBase *ty)
- {
- TyTyExtractRetFromFnType compiler;
- ty->accept_vis (compiler);
- rust_assert (compiler.ok);
- return compiler.translated;
- }
-
- ~TyTyExtractRetFromFnType () {}
-
- void visit (TyTy::UnitType &type) override { gcc_unreachable (); }
- void visit (TyTy::InferType &type) override { gcc_unreachable (); }
- void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); }
- void visit (TyTy::ADTType &type) override { gcc_unreachable (); }
- void visit (TyTy::ParamType &type) override { gcc_unreachable (); }
- void visit (TyTy::ArrayType &type) override { gcc_unreachable (); }
- void visit (TyTy::BoolType &type) override { gcc_unreachable (); }
- void visit (TyTy::IntType &type) override { gcc_unreachable (); }
- void visit (TyTy::UintType &type) override { gcc_unreachable (); }
- void visit (TyTy::FloatType &type) override { gcc_unreachable (); }
- void visit (TyTy::ErrorType &type) override { gcc_unreachable (); }
-
- void visit (TyTy::FnType &type) override
- {
- ok = true;
- translated = type.get_return_type ();
- }
-
-private:
- TyTyExtractRetFromFnType () : ok (false), translated (nullptr) {}
-
- bool ok;
- TyTy::TyBase *translated;
-};
-
-class TyTyCompileParam : public TyTy::TyVisitor
-{
-public:
- static ::Bvariable *compile (::Backend *backend, Bfunction *fndecl,
- TyTy::TyBase *ty)
- {
- TyTyCompileParam compiler (backend, fndecl);
- ty->accept_vis (compiler);
- rust_assert (compiler.translated != nullptr);
- return compiler.translated;
- }
-
- ~TyTyCompileParam () {}
-
- void visit (TyTy::UnitType &type) override { gcc_unreachable (); }
- void visit (TyTy::InferType &type) override { gcc_unreachable (); }
- void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); }
- void visit (TyTy::ADTType &type) override { gcc_unreachable (); }
- void visit (TyTy::FnType &type) override { gcc_unreachable (); }
- void visit (TyTy::ArrayType &type) override { gcc_unreachable (); }
- void visit (TyTy::BoolType &type) override { gcc_unreachable (); }
- void visit (TyTy::IntType &type) override { gcc_unreachable (); }
- void visit (TyTy::UintType &type) override { gcc_unreachable (); }
- void visit (TyTy::FloatType &type) override { gcc_unreachable (); }
- void visit (TyTy::ErrorType &type) override { gcc_unreachable (); }
-
- void visit (TyTy::ParamType &type) override
- {
- auto btype = TyTyCompile::compile (backend, type.get_base_type ());
- bool tree_addressable = false;
- translated = backend->parameter_variable (fndecl, type.get_identifier (),
- btype, tree_addressable,
- mappings->lookup_location (
- type.get_ref ()));
- }
-
-private:
- TyTyCompileParam (::Backend *backend, ::Bfunction *fndecl)
- : backend (backend), translated (nullptr), fndecl (fndecl),
+ TyTyCompile (::Backend *backend)
+ : backend (backend), translated (nullptr),
mappings (Analysis::Mappings::get ())
{}
::Backend *backend;
- ::Bvariable *translated;
- ::Bfunction *fndecl;
+ ::Btype *translated;
Analysis::Mappings *mappings;
};
diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h
index be3141a..06ea5a9 100644
--- a/gcc/rust/backend/rust-compile-var-decl.h
+++ b/gcc/rust/backend/rust-compile-var-decl.h
@@ -42,24 +42,36 @@ public:
void visit (HIR::LetStmt &stmt)
{
+ locus = stmt.get_locus ();
TyTy::TyBase *resolved_type = nullptr;
bool ok = ctx->get_tyctx ()->lookup_type (stmt.get_mappings ().get_hirid (),
&resolved_type);
rust_assert (ok);
- ::Btype *translated_type = TyTyResolveCompile::compile (ctx, resolved_type);
+ translated_type = TyTyResolveCompile::compile (ctx, resolved_type);
+ stmt.get_pattern ()->accept_vis (*this);
+ }
+
+ void visit (HIR::IdentifierPattern &pattern)
+ {
+ if (!pattern.is_mut)
+ translated_type = ctx->get_backend ()->immutable_type (translated_type);
- translated = ctx->get_backend ()->local_variable (
- fndecl, stmt.get_pattern ()->as_string (), translated_type,
- NULL /*decl_var*/, false /*address_taken*/, stmt.get_locus ());
+ translated
+ = ctx->get_backend ()->local_variable (fndecl, pattern.variable_ident,
+ translated_type, NULL /*decl_var*/,
+ false /*address_taken*/, locus);
}
private:
CompileVarDecl (Context *ctx, ::Bfunction *fndecl)
- : HIRCompileBase (ctx), fndecl (fndecl), translated (nullptr)
+ : HIRCompileBase (ctx), fndecl (fndecl), translated_type (nullptr),
+ translated (nullptr)
{}
::Bfunction *fndecl;
+ ::Btype *translated_type;
+ Location locus;
::Bvariable *translated;
};
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 3f8a962..ce6d827 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -41,8 +41,58 @@ CompileCrate::Compile (HIR::Crate &crate, Context *ctx)
void
CompileCrate::go ()
{
- for (auto it = crate.items.begin (); it != crate.items.end (); it++)
- CompileItem::compile (it->get (), ctx);
+ for (auto &item : crate.items)
+ CompileItem::compile (item.get (), ctx, false);
+
+ for (auto &item : crate.items)
+ CompileItem::compile (item.get (), ctx, true);
+}
+
+// rust-compile-expr.h
+
+void
+CompileExpr::visit (HIR::CallExpr &expr)
+{
+ // this can be a function call or it can be a constructor for a tuple struct
+ Bexpression *fn = ResolvePathRef::Compile (expr.get_fnexpr (), ctx);
+ if (fn != nullptr)
+ {
+ std::vector<Bexpression *> args;
+ expr.iterate_params ([&] (HIR::Expr *p) mutable -> bool {
+ Bexpression *compiled_expr = CompileExpr::Compile (p, ctx);
+ rust_assert (compiled_expr != nullptr);
+ args.push_back (compiled_expr);
+ return true;
+ });
+
+ auto fncontext = ctx->peek_fn ();
+ translated
+ = ctx->get_backend ()->call_expression (fncontext.fndecl, fn, args,
+ nullptr, expr.get_locus ());
+ }
+ else
+ {
+ Btype *type = ResolvePathType::Compile (expr.get_fnexpr (), ctx);
+ if (type == nullptr)
+ {
+ rust_fatal_error (expr.get_locus (),
+ "failed to lookup type associated with call");
+ return;
+ }
+
+ // 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;
+ expr.iterate_params ([&] (HIR::Expr *argument) mutable -> bool {
+ Bexpression *e = CompileExpr::Compile (argument, ctx);
+ vals.push_back (e);
+ return true;
+ });
+
+ translated
+ = ctx->get_backend ()->constructor_expression (type, vals,
+ expr.get_locus ());
+ }
}
// rust-compile-block.h
@@ -90,7 +140,7 @@ CompileBlock::visit (HIR::BlockExpr &expr)
return true;
});
- if (expr.has_expr ())
+ if (expr.has_expr () && expr.tail_expr_reachable ())
{
// the previous passes will ensure this is a valid return
// dead code elimination should remove any bad trailing expressions
@@ -178,5 +228,21 @@ CompileStructExprField::visit (HIR::StructExprFieldIdentifierValue &field)
translated = CompileExpr::Compile (field.get_value (), ctx);
}
+void
+CompileStructExprField::visit (HIR::StructExprFieldIndexValue &field)
+{
+ translated = CompileExpr::Compile (field.get_value (), ctx);
+}
+
+void
+CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field)
+{
+ // we can make the field look like an identifier expr to take advantage of
+ // existing code
+ HIR::IdentifierExpr expr (field.get_mappings (), field.get_field_name (),
+ field.get_locus ());
+ translated = CompileExpr::Compile (&expr, 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 51bf108..fc18e27 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -132,7 +132,46 @@ public:
return resolver.translated;
}
- virtual ~ASTLoweringExpr () {}
+ void visit (AST::TupleIndexExpr &expr)
+ {
+ std::vector<HIR::Attribute> outer_attribs;
+
+ HIR::Expr *tuple_expr
+ = ASTLoweringExpr::translate (expr.get_tuple_expr ().get (), &terminated);
+
+ 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::TupleIndexExpr (mapping,
+ std::unique_ptr<HIR::Expr> (tuple_expr),
+ expr.get_tuple_index (),
+ std::move (outer_attribs), expr.get_locus ());
+ }
+
+ void visit (AST::TupleExpr &expr)
+ {
+ std::vector<HIR::Attribute> inner_attribs;
+ std::vector<HIR::Attribute> outer_attribs;
+ std::vector<std::unique_ptr<HIR::Expr> > tuple_elements;
+ for (auto &e : expr.get_tuple_elems ())
+ {
+ HIR::Expr *t = ASTLoweringExpr::translate (e.get ());
+ tuple_elements.push_back (std::unique_ptr<HIR::Expr> (t));
+ }
+
+ 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::TupleExpr (std::move (mapping), std::move (tuple_elements),
+ std::move (inner_attribs),
+ std::move (outer_attribs), expr.get_locus ());
+ }
void visit (AST::IfExpr &expr)
{
@@ -465,6 +504,92 @@ public:
expr.get_locus ());
}
+ void visit (AST::NegationExpr &expr)
+ {
+ std::vector<HIR::Attribute> outer_attribs;
+
+ HIR::NegationExpr::NegationType type;
+ switch (expr.get_negation_type ())
+ {
+ case AST::NegationExpr::NegationType::NEGATE:
+ type = HIR::NegationExpr::NegationType::NEGATE;
+ break;
+ case AST::NegationExpr::NegationType::NOT:
+ type = HIR::NegationExpr::NegationType::NOT;
+ break;
+ }
+
+ HIR::Expr *negated_value
+ = ASTLoweringExpr::translate (expr.get_negated_expr ().get ());
+
+ 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::NegationExpr (mapping,
+ std::unique_ptr<HIR::Expr> (negated_value), type,
+ std::move (outer_attribs), expr.get_locus ());
+ }
+
+ void visit (AST::CompoundAssignmentExpr &expr)
+ {
+ HIR::ArithmeticOrLogicalExpr::ExprType kind
+ = HIR::ArithmeticOrLogicalExpr::ExprType::ADD;
+ switch (expr.get_expr_type ())
+ {
+ case AST::CompoundAssignmentExpr::ExprType::ADD:
+ kind = HIR::ArithmeticOrLogicalExpr::ExprType::ADD;
+ break;
+ case AST::CompoundAssignmentExpr::ExprType::SUBTRACT:
+ kind = HIR::ArithmeticOrLogicalExpr::ExprType::SUBTRACT;
+ break;
+ case AST::CompoundAssignmentExpr::ExprType::MULTIPLY:
+ kind = HIR::ArithmeticOrLogicalExpr::ExprType::MULTIPLY;
+ break;
+ case AST::CompoundAssignmentExpr::ExprType::DIVIDE:
+ kind = HIR::ArithmeticOrLogicalExpr::ExprType::DIVIDE;
+ break;
+ case AST::CompoundAssignmentExpr::ExprType::MODULUS:
+ kind = HIR::ArithmeticOrLogicalExpr::ExprType::MODULUS;
+ break;
+ case AST::CompoundAssignmentExpr::ExprType::BITWISE_AND:
+ kind = HIR::ArithmeticOrLogicalExpr::ExprType::BITWISE_AND;
+ break;
+ case AST::CompoundAssignmentExpr::ExprType::BITWISE_OR:
+ kind = HIR::ArithmeticOrLogicalExpr::ExprType::BITWISE_OR;
+ break;
+ case AST::CompoundAssignmentExpr::ExprType::BITWISE_XOR:
+ kind = HIR::ArithmeticOrLogicalExpr::ExprType::BITWISE_XOR;
+ break;
+ case AST::CompoundAssignmentExpr::ExprType::LEFT_SHIFT:
+ kind = HIR::ArithmeticOrLogicalExpr::ExprType::LEFT_SHIFT;
+ break;
+ case AST::CompoundAssignmentExpr::ExprType::RIGHT_SHIFT:
+ kind = HIR::ArithmeticOrLogicalExpr::ExprType::RIGHT_SHIFT;
+ break;
+ }
+
+ HIR::Expr *asignee_expr
+ = ASTLoweringExpr::translate (expr.get_left_expr ().get ());
+ HIR::Expr *value
+ = ASTLoweringExpr::translate (expr.get_right_expr ().get ());
+
+ 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);
+ HIR::Expr *operator_expr
+ = new HIR::ArithmeticOrLogicalExpr (mapping, asignee_expr->clone_expr (),
+ std::unique_ptr<HIR::Expr> (value),
+ kind, expr.get_locus ());
+ translated
+ = new HIR::AssignmentExpr (mapping,
+ std::unique_ptr<HIR::Expr> (asignee_expr),
+ std::unique_ptr<HIR::Expr> (operator_expr),
+ expr.get_locus ());
+ }
+
void visit (AST::StructExprStructFields &struct_expr)
{
std::vector<HIR::Attribute> inner_attribs;
@@ -505,6 +630,44 @@ public:
inner_attribs, outer_attribs);
}
+ void visit (AST::GroupedExpr &expr)
+ {
+ std::vector<HIR::Attribute> inner_attribs;
+ std::vector<HIR::Attribute> outer_attribs;
+
+ HIR::Expr *paren_expr
+ = ASTLoweringExpr::translate (expr.get_expr_in_parens ().get ());
+
+ 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::GroupedExpr (mapping, std::unique_ptr<HIR::Expr> (paren_expr),
+ std::move (inner_attribs),
+ std::move (outer_attribs), expr.get_locus ());
+ }
+
+ void visit (AST::FieldAccessExpr &expr)
+ {
+ std::vector<HIR::Attribute> inner_attribs;
+ std::vector<HIR::Attribute> outer_attribs;
+
+ HIR::Expr *receiver
+ = ASTLoweringExpr::translate (expr.get_receiver_expr ().get ());
+
+ 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::FieldAccessExpr (mapping,
+ std::unique_ptr<HIR::Expr> (receiver),
+ expr.get_field_name (),
+ std::move (outer_attribs), expr.get_locus ());
+ }
+
private:
ASTLoweringExpr ()
: translated (nullptr), translated_array_elems (nullptr), terminated (false)
diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h
index 4a5a3fe..ec4ef6b 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -38,10 +38,67 @@ public:
{
ASTLoweringItem resolver;
item->accept_vis (resolver);
+
+ // this is useful for debugging
+ // if (resolver.translated == nullptr)
+ // {
+ // rust_fatal_error (item->get_locus_slow (), "failed to lower: %s",
+ // item->as_string ().c_str ());
+ // return nullptr;
+ // }
+
return resolver.translated;
}
- virtual ~ASTLoweringItem () {}
+ void visit (AST::TupleStruct &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;
+
+ std::vector<HIR::TupleField> fields;
+ struct_decl.iterate ([&] (AST::TupleField &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::TupleField is missing Location info
+ Location field_locus;
+ HIR::TupleField translated_field (mapping,
+ 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::TupleStruct (mapping, std::move (fields),
+ struct_decl.get_identifier (),
+ std::move (generic_params),
+ std::move (where_clause), 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::StructStruct &struct_decl)
{
@@ -51,7 +108,7 @@ public:
HIR::Visibility vis = HIR::Visibility::create_public ();
std::vector<HIR::Attribute> outer_attrs;
- bool is_unit = false;
+ bool is_unit = struct_decl.is_unit_struct ();
std::vector<HIR::StructField> fields;
struct_decl.iterate ([&] (AST::StructField &field) mutable -> bool {
std::vector<HIR::Attribute> outer_attrs;
@@ -190,15 +247,16 @@ public:
= std::unique_ptr<HIR::BlockExpr> (
ASTLoweringBlock::translate (function.get_definition ().get (),
&terminated));
- if (!terminated && function.has_return_type ())
- rust_error_at (function.get_definition ()->get_locus (),
- "missing return");
auto crate_num = mappings->get_current_crate ();
Analysis::NodeMapping mapping (crate_num, function.get_node_id (),
mappings->get_next_hir_id (crate_num),
mappings->get_next_localdef_id (crate_num));
+ mappings->insert_location (crate_num,
+ function_body->get_mappings ().get_hirid (),
+ function.get_locus ());
+
auto fn
= new HIR::Function (mapping, std::move (function_name),
std::move (qualifiers), std::move (generic_params),
@@ -216,8 +274,7 @@ public:
for (auto &param : fn->function_params)
{
mappings->insert_hir_param (mapping.get_crate_num (),
- param.get_mappings ()->get_hirid (),
- &param);
+ param.get_mappings ().get_hirid (), &param);
mappings->insert_location (crate_num, mapping.get_hirid (),
param.get_locus ());
}
diff --git a/gcc/rust/hir/rust-ast-lower-struct-field-expr.h b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h
index 1b444a5..c44c9f9 100644
--- a/gcc/rust/hir/rust-ast-lower-struct-field-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-struct-field-expr.h
@@ -34,10 +34,13 @@ public:
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);
+ compiler.mappings->insert_hir_struct_field (
+ compiler.translated->get_mappings ().get_crate_num (),
+ compiler.translated->get_mappings ().get_hirid (), compiler.translated);
+ compiler.mappings->insert_location (
+ compiler.translated->get_mappings ().get_crate_num (),
+ compiler.translated->get_mappings ().get_hirid (),
+ field->get_locus_slow ());
return compiler.translated;
}
@@ -46,6 +49,10 @@ public:
void visit (AST::StructExprFieldIdentifierValue &field);
+ void visit (AST::StructExprFieldIndexValue &field);
+
+ void visit (AST::StructExprFieldIdentifier &field);
+
private:
ASTLowerStructExprField () : translated (nullptr) {}
diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h
index 2e14ad2..e78ae5a 100644
--- a/gcc/rust/hir/rust-ast-lower-type.h
+++ b/gcc/rust/hir/rust-ast-lower-type.h
@@ -33,12 +33,85 @@ public:
{
ASTLoweringType resolver;
type->accept_vis (resolver);
+
+ resolver.mappings->insert_location (
+ resolver.translated->get_mappings ().get_crate_num (),
+ resolver.translated->get_mappings ().get_hirid (),
+ type->get_locus_slow ());
+
return resolver.translated;
}
- virtual ~ASTLoweringType () {}
+ void visit (AST::BareFunctionType &fntype)
+ {
+ bool is_variadic = false;
+ std::vector<HIR::LifetimeParam> lifetime_params;
+ HIR::FunctionQualifiers qualifiers (
+ HIR::FunctionQualifiers::AsyncConstStatus::NONE, false);
+
+ std::vector<HIR::MaybeNamedParam> named_params;
+ for (auto &param : fntype.get_function_params ())
+ {
+ HIR::MaybeNamedParam::ParamKind kind;
+ switch (param.get_param_kind ())
+ {
+ case AST::MaybeNamedParam::ParamKind::UNNAMED:
+ kind = HIR::MaybeNamedParam::ParamKind::UNNAMED;
+ break;
+ case AST::MaybeNamedParam::ParamKind::IDENTIFIER:
+ kind = HIR::MaybeNamedParam::ParamKind::IDENTIFIER;
+ break;
+ case AST::MaybeNamedParam::ParamKind::WILDCARD:
+ kind = HIR::MaybeNamedParam::ParamKind::WILDCARD;
+ break;
+ }
+
+ HIR::Type *param_type
+ = ASTLoweringType::translate (param.get_type ().get ());
+
+ HIR::MaybeNamedParam p (param.get_name (), kind,
+ std::unique_ptr<HIR::Type> (param_type),
+ param.get_locus ());
+ named_params.push_back (std::move (p));
+ }
+
+ HIR::Type *return_type = nullptr;
+ if (fntype.has_return_type ())
+ {
+ return_type
+ = ASTLoweringType::translate (fntype.get_return_type ().get ());
+ }
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, fntype.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ mappings->get_next_localdef_id (crate_num));
+
+ translated = new HIR::BareFunctionType (
+ std::move (mapping), std::move (lifetime_params), std::move (qualifiers),
+ std::move (named_params), is_variadic,
+ std::unique_ptr<HIR::Type> (return_type), fntype.get_locus ());
+ }
+
+ void visit (AST::TupleType &tuple)
+ {
+ std::vector<std::unique_ptr<HIR::Type> > elems;
+ for (auto &e : tuple.get_elems ())
+ {
+ HIR::Type *t = ASTLoweringType::translate (e.get ());
+ elems.push_back (std::unique_ptr<HIR::Type> (t));
+ }
- virtual void visit (AST::TypePathSegment &segment)
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, tuple.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ mappings->get_next_localdef_id (crate_num));
+
+ translated = new HIR::TupleType (std::move (mapping), std::move (elems),
+ tuple.get_locus ());
+ }
+
+ void visit (AST::TypePathSegment &segment)
{
HIR::PathIdentSegment ident (segment.get_ident_segment ().as_string ());
translated_segment
@@ -47,7 +120,7 @@ public:
segment.get_locus ());
}
- virtual void visit (AST::TypePath &path)
+ void visit (AST::TypePath &path)
{
std::vector<std::unique_ptr<HIR::TypePathSegment> > translated_segments;
@@ -100,10 +173,9 @@ public:
}
private:
- ASTLoweringType () : translated (nullptr) {}
+ ASTLoweringType () : translated (nullptr), translated_segment (nullptr) {}
HIR::Type *translated;
-
HIR::TypePathSegment *translated_segment;
};
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index 4f0d0d0..dac2320 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -89,29 +89,30 @@ ASTLoweringBlock::visit (AST::BlockExpr &expr)
return true;
});
- HIR::ExprWithoutBlock *tail_expr = nullptr;
- if (expr.has_tail_expr () && !block_did_terminate)
- {
- tail_expr = (HIR::ExprWithoutBlock *) ASTLoweringExpr::translate (
- expr.get_tail_expr ().get ());
- }
- else if (expr.has_tail_expr () && block_did_terminate)
+ bool tail_reachable = expr.has_tail_expr () && !block_did_terminate;
+ if (expr.has_tail_expr () && block_did_terminate)
{
// warning unreachable tail expressions
rust_warning_at (expr.get_tail_expr ()->get_locus_slow (), 0,
"unreachable expression");
}
+ HIR::ExprWithoutBlock *tail_expr = nullptr;
+ if (expr.has_tail_expr ())
+ {
+ tail_expr = (HIR::ExprWithoutBlock *) ASTLoweringExpr::translate (
+ expr.get_tail_expr ().get ());
+ }
+
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::BlockExpr (mapping, std::move (block_stmts),
std::unique_ptr<HIR::ExprWithoutBlock> (tail_expr),
- std::move (inner_attribs), std::move (outer_attribs),
- expr.get_locus ());
+ tail_reachable, std::move (inner_attribs),
+ std::move (outer_attribs), expr.get_locus ());
terminated = block_did_terminate || expr.has_tail_expr ();
}
@@ -211,5 +212,34 @@ ASTLowerStructExprField::visit (AST::StructExprFieldIdentifierValue &field)
field.get_locus ());
}
+void
+ASTLowerStructExprField::visit (AST::StructExprFieldIndexValue &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::StructExprFieldIndexValue (mapping, field.get_index (),
+ std::unique_ptr<HIR::Expr> (value),
+ field.get_locus ());
+}
+
+void
+ASTLowerStructExprField::visit (AST::StructExprFieldIdentifier &field)
+{
+ 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::StructExprFieldIdentifier (mapping, field.get_field_name (),
+ 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 11be8b6..69b680d 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -61,7 +61,11 @@ class LiteralExpr : public ExprWithoutBlock
Location locus;
public:
- std::string as_string () const override { return literal.as_string (); }
+ std::string as_string () const override
+ {
+ return "( " + literal.as_string () + " (" + get_mappings ().as_string ()
+ + "))";
+ }
Literal::LitType get_lit_type () const { return literal.get_lit_type (); }
@@ -751,86 +755,6 @@ protected:
}
};
-/* Binary infix compound assignment (arithmetic or logic then assignment)
- * expressions. */
-class CompoundAssignmentExpr : public OperatorExpr
-{
-public:
- enum ExprType
- {
- ADD, // std::ops::AddAssign
- SUBTRACT, // std::ops::SubAssign
- MULTIPLY, // std::ops::MulAssign
- DIVIDE, // std::ops::DivAssign
- MODULUS, // std::ops::RemAssign
- BITWISE_AND, // std::ops::BitAndAssign
- BITWISE_OR, // std::ops::BitOrAssign
- BITWISE_XOR, // std::ops::BitXorAssign
- LEFT_SHIFT, // std::ops::ShlAssign
- RIGHT_SHIFT // std::ops::ShrAssign
- };
-
-private:
- // Note: overloading trait specified in comments
- ExprType expr_type;
- std::unique_ptr<Expr> right_expr;
-
-public:
- std::string as_string () const override;
-
- ExprType get_expr_type () const { return expr_type; }
-
- // Use pointers in constructor to enable polymorphism
- CompoundAssignmentExpr (Analysis::NodeMapping mappings,
- std::unique_ptr<Expr> value_to_assign_to,
- std::unique_ptr<Expr> value_to_assign,
- ExprType expr_kind, Location locus)
- : OperatorExpr (std::move (mappings), std::move (value_to_assign_to),
- std::vector<Attribute> (), locus),
- expr_type (expr_kind), right_expr (std::move (value_to_assign))
- {}
- // outer attributes not allowed
-
- // Have clone in copy constructor
- CompoundAssignmentExpr (CompoundAssignmentExpr const &other)
- : OperatorExpr (other), expr_type (other.expr_type),
- right_expr (other.right_expr->clone_expr ())
- {}
-
- // Overload assignment operator to clone
- CompoundAssignmentExpr &operator= (CompoundAssignmentExpr const &other)
- {
- OperatorExpr::operator= (other);
- // main_or_left_expr = other.main_or_left_expr->clone_expr();
- right_expr = other.right_expr->clone_expr ();
- expr_type = other.expr_type;
- // outer_attrs = other.outer_attrs;
-
- return *this;
- }
-
- // move constructors
- CompoundAssignmentExpr (CompoundAssignmentExpr &&other) = default;
- CompoundAssignmentExpr &operator= (CompoundAssignmentExpr &&other) = default;
-
- void accept_vis (HIRVisitor &vis) override;
-
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- CompoundAssignmentExpr *clone_expr_impl () const override
- {
- return new CompoundAssignmentExpr (*this);
- }
-
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- CompoundAssignmentExpr *clone_expr_without_block_impl () const override
- {
- return new CompoundAssignmentExpr (*this);
- }
-};
-
// Expression in parentheses (i.e. like literally just any 3 + (2 * 6))
class GroupedExpr : public ExprWithoutBlock
{
@@ -880,6 +804,12 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ std::unique_ptr<Expr> &get_expr_in_parens ()
+ {
+ rust_assert (expr_in_parens != nullptr);
+ return expr_in_parens;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1233,6 +1163,17 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ const std::vector<std::unique_ptr<Expr> > &get_tuple_elems () const
+ {
+ return tuple_elems;
+ }
+ std::vector<std::unique_ptr<Expr> > &get_tuple_elems ()
+ {
+ return tuple_elems;
+ }
+
+ bool is_unit () const { return tuple_elems.size () == 0; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1297,6 +1238,12 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ std::unique_ptr<Expr> &get_tuple_expr ()
+ {
+ rust_assert (tuple_expr != nullptr);
+ return tuple_expr;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1473,6 +1420,8 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ Identifier get_field_name () const { return field_name; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1568,6 +1517,8 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ TupleIndex get_tuple_index () const { return index; };
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1642,6 +1593,27 @@ public:
}
}
+ std::vector<std::unique_ptr<StructExprField> > &get_fields ()
+ {
+ return fields;
+ };
+
+ const std::vector<std::unique_ptr<StructExprField> > &get_fields () const
+ {
+ return fields;
+ };
+
+ std::vector<std::unique_ptr<StructExprField> > get_fields_as_owner ()
+ {
+ return std::move (fields);
+ };
+
+ void set_fields_as_owner (
+ std::vector<std::unique_ptr<StructExprField> > new_fields)
+ {
+ fields = std::move (new_fields);
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2353,6 +2325,14 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ std::unique_ptr<Expr> &get_receiver_expr ()
+ {
+ rust_assert (receiver != nullptr);
+ return receiver;
+ }
+
+ Identifier get_field_name () const { return field; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2513,11 +2493,10 @@ class BlockExpr : public ExprWithBlock
public:
std::vector<Attribute> inner_attrs;
- // bool has_statements;
std::vector<std::unique_ptr<Stmt> > statements;
- // bool has_expr;
std::unique_ptr<ExprWithoutBlock> expr; // inlined from Statements
+ bool tail_reachable;
Location locus;
std::string as_string () const override;
@@ -2528,15 +2507,17 @@ public:
// Returns whether the block contains an expression
bool has_expr () const { return expr != nullptr; }
+ bool tail_expr_reachable () const { return tail_reachable; }
+
BlockExpr (Analysis::NodeMapping mappings,
std::vector<std::unique_ptr<Stmt> > block_statements,
- std::unique_ptr<ExprWithoutBlock> block_expr,
+ std::unique_ptr<ExprWithoutBlock> block_expr, bool tail_reachable,
std::vector<Attribute> inner_attribs,
std::vector<Attribute> outer_attribs, Location locus)
: ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
inner_attrs (std::move (inner_attribs)),
statements (std::move (block_statements)), expr (std::move (block_expr)),
- locus (locus)
+ tail_reachable (tail_reachable), locus (locus)
{}
// Copy constructor with clone
diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc
index b935376..b727917 100644
--- a/gcc/rust/hir/tree/rust-hir-full-test.cc
+++ b/gcc/rust/hir/tree/rust-hir-full-test.cc
@@ -2033,67 +2033,6 @@ ErrorPropagationExpr::as_string () const
}
std::string
-CompoundAssignmentExpr::as_string () const
-{
- std::string operator_str;
- operator_str.reserve (1);
-
- // get operator string
- switch (expr_type)
- {
- case ADD:
- operator_str = "+";
- break;
- case SUBTRACT:
- operator_str = "-";
- break;
- case MULTIPLY:
- operator_str = "*";
- break;
- case DIVIDE:
- operator_str = "/";
- break;
- case MODULUS:
- operator_str = "%";
- break;
- case BITWISE_AND:
- operator_str = "&";
- break;
- case BITWISE_OR:
- operator_str = "|";
- break;
- case BITWISE_XOR:
- operator_str = "^";
- break;
- case LEFT_SHIFT:
- operator_str = "<<";
- break;
- case RIGHT_SHIFT:
- operator_str = ">>";
- break;
- default:
- operator_str = "invalid operator. wtf";
- break;
- }
-
- operator_str += "=";
-
- std::string str ("CompoundAssignmentExpr: ");
- if (main_or_left_expr == nullptr || right_expr == nullptr)
- {
- str += "error. this is probably a parsing failure.";
- }
- else
- {
- str += "\n left: " + main_or_left_expr->as_string ();
- str += "\n right: " + right_expr->as_string ();
- str += "\n operator: " + operator_str;
- }
-
- return str;
-}
-
-std::string
ArithmeticOrLogicalExpr::as_string () const
{
std::string operator_str;
@@ -2133,23 +2072,15 @@ ArithmeticOrLogicalExpr::as_string () const
operator_str = ">>";
break;
default:
- operator_str = "invalid operator. wtf";
+ gcc_unreachable ();
break;
}
- std::string str ("ArithmeticOrLogicalExpr: ");
- if (main_or_left_expr == nullptr || right_expr == nullptr)
- {
- str += "error. this is probably a parsing failure.";
- }
- else
- {
- str += main_or_left_expr->as_string () + " ";
- str += operator_str + " ";
- str += right_expr->as_string ();
- }
+ std::string str = main_or_left_expr->as_string () + " ";
+ str += operator_str + " ";
+ str += right_expr->as_string ();
- return str + "::" + get_mappings ().as_string ();
+ return "( " + str + " (" + get_mappings ().as_string () + "))";
}
std::string
@@ -5241,12 +5172,6 @@ AssignmentExpr::accept_vis (HIRVisitor &vis)
}
void
-CompoundAssignmentExpr::accept_vis (HIRVisitor &vis)
-{
- vis.visit (*this);
-}
-
-void
GroupedExpr::accept_vis (HIRVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 69e39c8..e99dd38 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -404,13 +404,13 @@ public:
// A function parameter
struct FunctionParam
{
-public:
std::unique_ptr<Pattern> param_name;
std::unique_ptr<Type> type;
Location locus;
Analysis::NodeMapping mappings;
+public:
FunctionParam (Analysis::NodeMapping mappings,
std::unique_ptr<Pattern> param_name,
std::unique_ptr<Type> param_type, Location locus)
@@ -448,7 +448,7 @@ public:
Type *get_type () { return type.get (); }
- Analysis::NodeMapping *get_mappings () { return &mappings; }
+ Analysis::NodeMapping &get_mappings () { return mappings; }
};
// Visibility of item - if the item has it, then it is some form of public
@@ -1604,7 +1604,9 @@ private:
std::unique_ptr<Type> field_type;
- // should this store location info?
+ Location locus;
+
+ Analysis::NodeMapping mappings;
public:
// Returns whether tuple field has outer attributes.
@@ -1615,16 +1617,18 @@ public:
bool has_visibility () const { return !visibility.is_error (); }
// Complete constructor
- TupleField (std::unique_ptr<Type> field_type, Visibility vis,
+ TupleField (Analysis::NodeMapping mapping, 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_type (std::move (field_type))
+ field_type (std::move (field_type)), locus (locus), mappings (mapping)
{}
// Copy constructor with clone
TupleField (TupleField const &other)
: outer_attrs (other.outer_attrs), visibility (other.visibility),
- field_type (other.field_type->clone_type ())
+ field_type (other.field_type->clone_type ()), locus (other.locus),
+ mappings (other.mappings)
{}
~TupleField () = default;
@@ -1635,6 +1639,8 @@ public:
field_type = other.field_type->clone_type ();
visibility = other.visibility;
outer_attrs = other.outer_attrs;
+ locus = other.locus;
+ mappings = other.mappings;
return *this;
}
@@ -1646,13 +1652,13 @@ public:
// Returns whether tuple field is in an error state.
bool is_error () const { return field_type == nullptr; }
- // Creates an error state tuple field.
- static TupleField create_error ()
- {
- return TupleField (nullptr, Visibility::create_error ());
- }
-
std::string as_string () const;
+
+ Analysis::NodeMapping get_mappings () { return mappings; }
+
+ Location get_locus () const { return locus; }
+
+ std::unique_ptr<HIR::Type> &get_field_type () { return field_type; }
};
// Rust tuple declared using struct keyword HIR node
@@ -1677,6 +1683,18 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ std::vector<TupleField> &get_fields () { return fields; }
+ const std::vector<TupleField> &get_fields () const { return fields; }
+
+ void iterate (std::function<bool (TupleField &)> 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/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h
index f8c851c..ebed119 100644
--- a/gcc/rust/hir/tree/rust-hir-type.h
+++ b/gcc/rust/hir/tree/rust-hir-type.h
@@ -393,6 +393,12 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ std::vector<std::unique_ptr<Type> > &get_elems () { return elems; }
+ const std::vector<std::unique_ptr<Type> > &get_elems () const
+ {
+ return elems;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -785,6 +791,16 @@ public:
}
Location get_locus () const { return locus; }
+
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (param_type != nullptr);
+ return param_type;
+ }
+
+ ParamKind get_param_kind () const { return param_kind; }
+
+ Identifier get_name () const { return name; }
};
/* A function pointer type - can be created via coercion from function items and
@@ -799,9 +815,7 @@ class BareFunctionType : public TypeNoBounds
std::vector<MaybeNamedParam> params;
bool is_variadic;
- // bool has_return_type;
- // BareFunctionReturnType return_type;
- std::unique_ptr<TypeNoBounds> return_type; // inlined version
+ std::unique_ptr<Type> return_type; // inlined version
Location locus;
@@ -816,7 +830,7 @@ public:
std::vector<LifetimeParam> lifetime_params,
FunctionQualifiers qualifiers,
std::vector<MaybeNamedParam> named_params, bool is_variadic,
- std::unique_ptr<TypeNoBounds> type, Location locus)
+ std::unique_ptr<Type> type, Location locus)
: TypeNoBounds (mappings), for_lifetimes (std::move (lifetime_params)),
function_qualifiers (std::move (qualifiers)),
params (std::move (named_params)), is_variadic (is_variadic),
@@ -828,8 +842,7 @@ public:
: TypeNoBounds (other.mappings), for_lifetimes (other.for_lifetimes),
function_qualifiers (other.function_qualifiers), params (other.params),
is_variadic (other.is_variadic),
- return_type (other.return_type->clone_type_no_bounds ()),
- locus (other.locus)
+ return_type (other.return_type->clone_type ()), locus (other.locus)
{}
// Overload assignment operator to deep copy
@@ -840,7 +853,7 @@ public:
function_qualifiers = other.function_qualifiers;
params = other.params;
is_variadic = other.is_variadic;
- return_type = other.return_type->clone_type_no_bounds ();
+ return_type = other.return_type->clone_type ();
locus = other.locus;
return *this;
@@ -856,6 +869,19 @@ public:
void accept_vis (HIRVisitor &vis) override;
+ std::vector<MaybeNamedParam> &get_function_params () { return params; }
+ const std::vector<MaybeNamedParam> &get_function_params () const
+ {
+ return params;
+ }
+
+ // TODO: would a "vis_type" be better?
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h
index abb84f5..7fefb69 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.h
+++ b/gcc/rust/hir/tree/rust-hir-visitor.h
@@ -77,7 +77,6 @@ public:
virtual void visit (LazyBooleanExpr &expr) = 0;
virtual void visit (TypeCastExpr &expr) = 0;
virtual void visit (AssignmentExpr &expr) = 0;
- virtual void visit (CompoundAssignmentExpr &expr) = 0;
virtual void visit (GroupedExpr &expr) = 0;
// virtual void visit(ArrayElems& elems) = 0;
virtual void visit (ArrayElemsValues &elems) = 0;
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index 5d758ee..e4a81c5 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -819,6 +819,9 @@ public:
const Analysis::NodeMapping &get_mappings () const { return mappings; }
+ // Clone function implementation as pure virtual method
+ virtual Expr *clone_expr_impl () const = 0;
+
protected:
// Constructor
Expr (Analysis::NodeMapping mappings,
@@ -826,9 +829,6 @@ protected:
: outer_attrs (std::move (outer_attribs)), mappings (std::move (mappings))
{}
- // Clone function implementation as pure virtual method
- virtual Expr *clone_expr_impl () const = 0;
-
// TODO: think of less hacky way to implement this kind of thing
// Sets outer attributes.
void set_outer_attrs (std::vector<Attribute> outer_attrs_to_set)
@@ -895,7 +895,10 @@ public:
ident (std::move (ident)), locus (locus)
{}
- std::string as_string () const override { return ident; }
+ std::string as_string () const override
+ {
+ return "( " + ident + " (" + get_mappings ().as_string () + "))";
+ }
Location get_locus () const { return locus; }
Location get_locus_slow () const override { return get_locus (); }
@@ -908,6 +911,8 @@ public:
return std::unique_ptr<IdentifierExpr> (clone_identifier_expr_impl ());
}
+ Identifier get_identifier () const { return ident; }
+
protected:
// Clone method implementation
IdentifierExpr *clone_expr_without_block_impl () const override
diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index 4606a6c..6dfaea2 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -466,7 +466,9 @@ Lexer::build_token ()
if (peek_input () == '=')
{
// modulo-assign
+ skip_input ();
current_column += 2;
+
return Token::make (PERCENT_EQ, loc);
}
else
@@ -479,7 +481,9 @@ Lexer::build_token ()
if (peek_input () == '=')
{
// xor-assign?
+ skip_input ();
current_column += 2;
+
return Token::make (CARET_EQ, loc);
}
else
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index a0d2af9..ffe4e91 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -22,8 +22,6 @@ along with GCC; see the file COPYING3. If not see
#include "rust-diagnostics.h"
-#include <algorithm> // for std::find
-
namespace Rust {
// Left binding powers of operations.
enum binding_powers
@@ -12234,10 +12232,9 @@ Parser<ManagedTokenSource>::null_denotation (
// HACK: as struct expressions should always be value expressions,
// cannot be referenced
- ParseRestrictions entered_from_unary
- = {/* can_be_struct_expr = */ false, /* entered_from_unary = */ true};
- /*entered_from_unary.entered_from_unary = true;
- entered_from_unary.can_be_struct_expr = false;*/
+ ParseRestrictions entered_from_unary;
+ entered_from_unary.entered_from_unary = true;
+ entered_from_unary.can_be_struct_expr = false;
if (lexer.peek_token ()->get_id () == MUT)
{
diff --git a/gcc/rust/parse/rust-parse.cc b/gcc/rust/parse/rust-parse.cc
index 62076ee..fdad97c 100644
--- a/gcc/rust/parse/rust-parse.cc
+++ b/gcc/rust/parse/rust-parse.cc
@@ -41,8 +41,6 @@ along with GCC; see the file COPYING3. If not see
#endif
// maybe put these back in if compiling no longer works
-#include <algorithm> // for std::find
-
/* TODO: move non-essential stuff back here from rust-parse-impl.h after
* confirming that it works */
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index 324d820..f62f17c 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -22,6 +22,7 @@
#include "rust-ast-resolve-base.h"
#include "rust-ast-full.h"
#include "rust-ast-resolve-struct-expr-field.h"
+#include "rust-ast-verify-assignee.h"
namespace Rust {
namespace Resolver {
@@ -35,7 +36,19 @@ public:
expr->accept_vis (resolver);
};
- ~ResolveExpr () {}
+ void visit (AST::TupleIndexExpr &expr)
+ {
+ ResolveExpr::go (expr.get_tuple_expr ().get (), expr.get_node_id ());
+ }
+
+ void visit (AST::TupleExpr &expr)
+ {
+ if (expr.is_unit ())
+ return;
+
+ for (auto &elem : expr.get_tuple_elems ())
+ ResolveExpr::go (elem.get (), expr.get_node_id ());
+ }
void visit (AST::PathInExpression &expr)
{
@@ -76,27 +89,39 @@ public:
ResolveExpr::go (p, expr.get_node_id ());
return true;
});
- // resolver->insert_resolved_name(NodeId refId,NodeId defId)
}
void visit (AST::AssignmentExpr &expr)
{
ResolveExpr::go (expr.get_left_expr ().get (), expr.get_node_id ());
ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ());
+
+ // need to verify the assignee
+ VerifyAsignee::go (expr.get_left_expr ().get (), expr.get_node_id ());
}
void visit (AST::IdentifierExpr &expr)
{
- if (!resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node))
+ if (resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node))
+ {
+ resolver->insert_resolved_name (expr.get_node_id (), resolved_node);
+ resolver->insert_new_definition (expr.get_node_id (),
+ Definition{expr.get_node_id (),
+ parent});
+ }
+ else if (resolver->get_type_scope ().lookup (expr.as_string (),
+ &resolved_node))
+ {
+ resolver->insert_resolved_type (expr.get_node_id (), resolved_node);
+ resolver->insert_new_definition (expr.get_node_id (),
+ Definition{expr.get_node_id (),
+ parent});
+ }
+ else
{
rust_error_at (expr.get_locus (), "failed to find name: %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::ArithmeticOrLogicalExpr &expr)
@@ -105,6 +130,15 @@ public:
ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ());
}
+ void visit (AST::CompoundAssignmentExpr &expr)
+ {
+ ResolveExpr::go (expr.get_left_expr ().get (), expr.get_node_id ());
+ ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ());
+
+ // need to verify the assignee
+ VerifyAsignee::go (expr.get_left_expr ().get (), expr.get_node_id ());
+ }
+
void visit (AST::ComparisonExpr &expr)
{
ResolveExpr::go (expr.get_left_expr ().get (), expr.get_node_id ());
@@ -117,6 +151,11 @@ public:
ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ());
}
+ void visit (AST::NegationExpr &expr)
+ {
+ ResolveExpr::go (expr.get_negated_expr ().get (), expr.get_node_id ());
+ }
+
void visit (AST::IfExpr &expr)
{
ResolveExpr::go (expr.get_condition_expr ().get (), expr.get_node_id ());
@@ -168,6 +207,14 @@ public:
{
ResolveExpr::go (&struct_expr.get_struct_name (),
struct_expr.get_node_id ());
+
+ if (struct_expr.has_struct_base ())
+ {
+ AST::StructBase &base = struct_expr.get_struct_base ();
+ ResolveExpr::go (base.get_base_struct ().get (),
+ struct_expr.get_node_id ());
+ }
+
struct_expr.iterate (
[&] (AST::StructExprField *struct_field) mutable -> bool {
ResolveStructExprField::go (struct_field, struct_expr.get_node_id ());
@@ -175,6 +222,16 @@ public:
});
}
+ void visit (AST::GroupedExpr &expr)
+ {
+ ResolveExpr::go (expr.get_expr_in_parens ().get (), expr.get_node_id ());
+ }
+
+ void visit (AST::FieldAccessExpr &expr)
+ {
+ ResolveExpr::go (expr.get_receiver_expr ().get (), expr.get_node_id ());
+ }
+
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 b0b979f..0f45ba0 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ b/gcc/rust/resolve/rust-ast-resolve-item.h
@@ -40,10 +40,20 @@ public:
~ResolveItem () {}
+ void visit (AST::TupleStruct &struct_decl)
+ {
+ struct_decl.iterate ([&] (AST::TupleField &field) mutable -> bool {
+ ResolveType::go (field.get_field_type ().get (),
+ struct_decl.get_node_id ());
+ return true;
+ });
+ }
+
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 ());
+ ResolveType::go (field.get_field_type ().get (),
+ struct_decl.get_node_id ());
return true;
});
}
@@ -52,12 +62,22 @@ public:
{
ResolveType::go (var.get_type ().get (), var.get_node_id ());
ResolveExpr::go (var.get_expr ().get (), var.get_node_id ());
+
+ // the mutability checker needs to verify for immutable decls the number
+ // of assignments are <1. This marks an implicit assignment
+ resolver->mark_assignment_to_decl (var.get_node_id (), var.get_node_id ());
}
void visit (AST::ConstantItem &constant)
{
ResolveType::go (constant.get_type ().get (), constant.get_node_id ());
ResolveExpr::go (constant.get_expr ().get (), constant.get_node_id ());
+
+ // the mutability checker needs to verify for immutable decls the number
+ // of assignments are <1. This marks an implicit assignment
+ resolver->mark_decl_mutability (constant.get_node_id (), false);
+ resolver->mark_assignment_to_decl (constant.get_node_id (),
+ constant.get_node_id ());
}
void visit (AST::Function &function)
@@ -79,6 +99,11 @@ public:
ResolveType::go (param.get_type ().get (), param.get_node_id ());
PatternDeclaration::go (param.get_pattern ().get (),
param.get_node_id ());
+
+ // the mutability checker needs to verify for immutable decls the number
+ // of assignments are <1. This marks an implicit assignment
+ resolver->mark_assignment_to_decl (param.get_pattern ()->get_node_id (),
+ param.get_node_id ());
}
// resolve the function body
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h
index c79f7d3..f7618ab 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.h
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h
@@ -86,6 +86,8 @@ public:
resolver->insert_new_definition (pattern.get_node_id (),
Definition{pattern.get_node_id (),
parent});
+ resolver->mark_decl_mutability (pattern.get_node_id (),
+ pattern.get_is_mut ());
}
private:
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index 6d751e6..8904ce9 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -52,7 +52,13 @@ public:
void visit (AST::LetStmt &stmt)
{
if (stmt.has_init_expr ())
- ResolveExpr::go (stmt.get_init_expr ().get (), stmt.get_node_id ());
+ {
+ ResolveExpr::go (stmt.get_init_expr ().get (), stmt.get_node_id ());
+
+ // mark the assignment
+ resolver->mark_assignment_to_decl (stmt.get_pattern ()->get_node_id (),
+ stmt.get_node_id ());
+ }
PatternDeclaration::go (stmt.get_pattern ().get (), stmt.get_node_id ());
if (stmt.has_type ())
diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h
index c705a03..3916473 100644
--- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h
+++ b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h
@@ -26,8 +26,7 @@ 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:
@@ -41,7 +40,9 @@ public:
void visit (AST::StructExprFieldIdentifierValue &field);
- // TODO
+ void visit (AST::StructExprFieldIndexValue &field);
+
+ void visit (AST::StructExprFieldIdentifier &field);
private:
ResolveStructExprField (NodeId parent) : ResolverBase (parent) {}
diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
index 447fe4b..c3f5e4c 100644
--- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h
+++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
@@ -36,6 +36,13 @@ public:
~ResolveTopLevel () {}
+ void visit (AST::TupleStruct &struct_decl)
+ {
+ resolver->get_type_scope ().insert (struct_decl.get_identifier (),
+ struct_decl.get_node_id (),
+ struct_decl.get_locus ());
+ }
+
void visit (AST::StructStruct &struct_decl)
{
resolver->get_type_scope ().insert (struct_decl.get_identifier (),
@@ -50,6 +57,7 @@ public:
resolver->insert_new_definition (var.get_node_id (),
Definition{var.get_node_id (),
var.get_node_id ()});
+ resolver->mark_decl_mutability (var.get_node_id (), var.is_mutable ());
}
void visit (AST::ConstantItem &constant)
@@ -67,6 +75,9 @@ public:
resolver->get_name_scope ().insert (function.get_function_name (),
function.get_node_id (),
function.get_locus ());
+ resolver->insert_new_definition (function.get_node_id (),
+ Definition{function.get_node_id (),
+ function.get_node_id ()});
// if this does not get a reference it will be determined to be unused
// lets give it a fake reference to itself
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h
index 8ec3a9c..b303ee9 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.h
+++ b/gcc/rust/resolve/rust-ast-resolve-type.h
@@ -31,28 +31,43 @@ public:
static void go (AST::Type *type, NodeId parent)
{
ResolveType resolver (parent);
-
type->accept_vis (resolver);
- if (resolver.resolved_node == UNKNOWN_NODEID)
+ };
+
+ void visit (AST::BareFunctionType &fntype)
+ {
+ for (auto &param : fntype.get_function_params ())
+ ResolveType::go (param.get_type ().get (), fntype.get_node_id ());
+
+ if (fntype.has_return_type ())
+ ResolveType::go (fntype.get_return_type ().get (), fntype.get_node_id ());
+ }
+
+ void visit (AST::TupleType &tuple)
+ {
+ if (tuple.is_unit_type ())
{
- rust_error_at (resolver.locus, "failed to resolve type %s",
- type->as_string ().c_str ());
+ resolved_node = resolver->get_unit_type_node_id ();
+ return;
}
- };
- ~ResolveType () {}
+ for (auto &elem : tuple.get_elems ())
+ ResolveType::go (elem.get (), tuple.get_node_id ());
+ }
void visit (AST::TypePath &path)
{
// this will need changed to handle mod/crate/use globs and look
// at the segments in granularity
- if (resolver->get_type_scope ().lookup (path.as_string (), &resolved_node))
+ if (!resolver->get_type_scope ().lookup (path.as_string (), &resolved_node))
{
- resolver->insert_resolved_type (path.get_node_id (), resolved_node);
- resolver->insert_new_definition (path.get_node_id (),
- Definition{path.get_node_id (),
- parent});
+ rust_error_at (path.get_locus (), "failed to resolve TypePath: %s",
+ path.as_string ().c_str ());
+ return;
}
+ resolver->insert_resolved_type (path.get_node_id (), resolved_node);
+ resolver->insert_new_definition (path.get_node_id (),
+ Definition{path.get_node_id (), parent});
}
void visit (AST::ArrayType &type)
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
index d6eed93..c6d7148 100644
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ b/gcc/rust/resolve/rust-ast-resolve.cc
@@ -113,7 +113,7 @@ Resolver::insert_builtin_types (Rib *r)
Linemap::predeclared_location ());
}
-std::vector<AST::TypePath *> &
+std::vector<AST::Type *> &
Resolver::get_builtin_types ()
{
return builtins;
@@ -146,6 +146,8 @@ Resolver::generate_builtins ()
= new TyTy::FloatType (mappings->get_next_hir_id (), TyTy::FloatType::F32);
auto f64
= new TyTy::FloatType (mappings->get_next_hir_id (), TyTy::FloatType::F64);
+ auto usize = new TyTy::USizeType (mappings->get_next_hir_id ());
+ auto isize = new TyTy::ISizeType (mappings->get_next_hir_id ());
MKBUILTIN_TYPE ("u8", builtins, u8);
MKBUILTIN_TYPE ("u16", builtins, u16);
@@ -160,6 +162,18 @@ Resolver::generate_builtins ()
MKBUILTIN_TYPE ("bool", builtins, rbool);
MKBUILTIN_TYPE ("f32", builtins, f32);
MKBUILTIN_TYPE ("f64", builtins, f64);
+ MKBUILTIN_TYPE ("usize", builtins, usize);
+ MKBUILTIN_TYPE ("isize", builtins, isize);
+
+ // unit type ()
+ TyTy::UnitType *unit_tyty = new TyTy::UnitType (mappings->get_next_hir_id ());
+ std::vector<std::unique_ptr<AST::Type> > elems;
+ AST::TupleType *unit_type
+ = new AST::TupleType (std::move (elems), Linemap::predeclared_location ());
+ builtins.push_back (unit_type);
+ tyctx->insert_builtin (unit_tyty->get_ref (), unit_type->get_node_id (),
+ unit_tyty);
+ set_unit_type_node_id (unit_type->get_node_id ());
}
void
@@ -308,5 +322,20 @@ ResolveStructExprField::visit (AST::StructExprFieldIdentifierValue &field)
ResolveExpr::go (field.get_value ().get (), field.get_node_id ());
}
+void
+ResolveStructExprField::visit (AST::StructExprFieldIndexValue &field)
+{
+ ResolveExpr::go (field.get_value ().get (), field.get_node_id ());
+}
+
+void
+ResolveStructExprField::visit (AST::StructExprFieldIdentifier &field)
+{
+ AST::IdentifierExpr expr (field.get_field_name (), field.get_locus ());
+ expr.set_node_id (field.get_node_id ());
+
+ ResolveExpr::go (&expr, field.get_node_id ());
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-verify-assignee.h b/gcc/rust/resolve/rust-ast-verify-assignee.h
new file mode 100644
index 0000000..6cfe2c2
--- /dev/null
+++ b/gcc/rust/resolve/rust-ast-verify-assignee.h
@@ -0,0 +1,83 @@
+// 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_VERIFY_ASSIGNEE
+#define RUST_AST_VERIFY_ASSIGNEE
+
+#include "rust-ast-resolve-base.h"
+#include "rust-ast-full.h"
+
+namespace Rust {
+namespace Resolver {
+
+class VerifyAsignee : public ResolverBase
+{
+public:
+ static bool go (AST::Expr *assignee, NodeId parent)
+ {
+ VerifyAsignee checker (parent);
+ assignee->accept_vis (checker);
+ if (!checker.ok)
+ rust_error_at (assignee->get_locus_slow (),
+ "invalid left-hand side of assignment");
+ return checker.ok;
+ }
+
+ void visit (AST::ArrayIndexExpr &expr)
+ {
+ expr.get_array_expr ()->accept_vis (*this);
+ }
+
+ void visit (AST::FieldAccessExpr &expr)
+ {
+ expr.get_receiver_expr ()->accept_vis (*this);
+ }
+
+ void visit (AST::TupleIndexExpr &expr)
+ {
+ expr.get_tuple_expr ()->accept_vis (*this);
+ }
+
+ void visit (AST::IdentifierExpr &expr)
+ {
+ if (!resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node))
+ return;
+
+ ok = true;
+ // mark the assignment to the name
+ resolver->mark_assignment_to_decl (resolved_node, parent);
+
+ // check is mutable
+ if (!resolver->decl_is_mutable (resolved_node))
+ {
+ // we only allow a single assignment to immutable decls
+ if (resolver->get_num_assignments_to_decl (resolved_node) > 1)
+ rust_error_at (expr.get_locus (), "cannot assign to immutable");
+ }
+ }
+
+private:
+ VerifyAsignee (NodeId parent) : ResolverBase (parent), ok (false) {}
+
+ bool ok;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_AST_VERIFY_ASSIGNEE
diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h
index 515ebfd..5bc6aba 100644
--- a/gcc/rust/resolve/rust-name-resolver.h
+++ b/gcc/rust/resolve/rust-name-resolver.h
@@ -209,7 +209,7 @@ public:
// these will be required for type resolution passes to
// map back to tyty nodes
- std::vector<AST::TypePath *> &get_builtin_types ();
+ std::vector<AST::Type *> &get_builtin_types ();
void push_new_name_rib (Rib *r);
void push_new_type_rib (Rib *r);
@@ -232,6 +232,40 @@ public:
NodeId get_global_type_node_id () { return global_type_node_id; }
+ void set_unit_type_node_id (NodeId id) { unit_ty_node_id = id; }
+ NodeId get_unit_type_node_id () { return unit_ty_node_id; }
+
+ void mark_decl_mutability (NodeId id, bool mut)
+ {
+ rust_assert (decl_mutability.find (id) == decl_mutability.end ());
+ decl_mutability[id] = mut;
+ }
+
+ bool decl_is_mutable (NodeId id) const
+ {
+ auto it = decl_mutability.find (id);
+ rust_assert (it != decl_mutability.end ());
+ return it->second;
+ }
+
+ void mark_assignment_to_decl (NodeId id, NodeId assignment)
+ {
+ auto it = assignment_to_decl.find (id);
+ if (it == assignment_to_decl.end ())
+ assignment_to_decl[id] = {};
+
+ assignment_to_decl[id].insert (assignment);
+ }
+
+ size_t get_num_assignments_to_decl (NodeId id) const
+ {
+ auto it = assignment_to_decl.find (id);
+ if (it == assignment_to_decl.end ())
+ return 0;
+
+ return it->second.size ();
+ }
+
private:
Resolver ();
@@ -240,12 +274,13 @@ private:
Analysis::Mappings *mappings;
TypeCheckContext *tyctx;
- std::vector<AST::TypePath *> builtins;
+ std::vector<AST::Type *> builtins;
Scope name_scope;
Scope type_scope;
NodeId global_type_node_id;
+ NodeId unit_ty_node_id;
// map a AST Node to a Rib
std::map<NodeId, Rib *> name_ribs;
@@ -265,6 +300,11 @@ private:
// we need two namespaces one for names and ones for types
std::map<NodeId, NodeId> resolved_names;
std::map<NodeId, NodeId> resolved_types;
+
+ // map of resolved names mutability flag
+ std::map<NodeId, bool> decl_mutability;
+ // map of resolved names and set of assignments to the decl
+ std::map<NodeId, std::set<NodeId> > assignment_to_decl;
};
} // namespace Resolver
diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index 210eff3..7b0ccf9 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -98,6 +98,9 @@ public:
// Get the unnamed boolean type.
virtual Btype *bool_type () = 0;
+ // Get the Host pointer size in bits
+ virtual int get_pointer_size () = 0;
+
// Get an unnamed integer type with the given signedness and number
// of bits.
virtual Btype *integer_type (bool is_unsigned, int bits) = 0;
@@ -112,6 +115,9 @@ public:
// Get a pointer type.
virtual Btype *pointer_type (Btype *to_type) = 0;
+ // make type immutable
+ virtual Btype *immutable_type (Btype *base) = 0;
+
// Get a function type. The receiver, parameter, and results are
// generated from the types in the Function_type. The Function_type
// is provided so that the names are available. This should return
@@ -254,6 +260,8 @@ public:
// Create a nil pointer expression.
virtual Bexpression *nil_pointer_expression () = 0;
+ virtual Bexpression *unit_expression () = 0;
+
// Create a reference to a variable.
virtual Bexpression *var_expression (Bvariable *var, Location) = 0;
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index bfa7609..0729b1e 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -165,6 +165,8 @@ public:
Btype *bool_type () { return this->make_type (boolean_type_node); }
+ int get_pointer_size ();
+
Btype *integer_type (bool, int);
Btype *float_type (int);
@@ -173,6 +175,8 @@ public:
Btype *pointer_type (Btype *);
+ Btype *immutable_type (Btype *);
+
Btype *function_type (const Btyped_identifier &,
const std::vector<Btyped_identifier> &,
const std::vector<Btyped_identifier> &, Btype *,
@@ -225,6 +229,8 @@ public:
return this->make_expression (null_pointer_node);
}
+ Bexpression *unit_expression () { return this->make_expression (void_node); }
+
Bexpression *var_expression (Bvariable *var, Location);
Bexpression *indirect_expression (Btype *, Bexpression *expr,
@@ -754,6 +760,12 @@ Gcc_backend::Gcc_backend ()
// Get an unnamed integer type.
+int
+Gcc_backend::get_pointer_size ()
+{
+ return POINTER_SIZE;
+}
+
Btype *
Gcc_backend::integer_type (bool is_unsigned, int bits)
{
@@ -846,6 +858,18 @@ Gcc_backend::pointer_type (Btype *to_type)
return this->make_type (type);
}
+// Get immutable type
+
+Btype *
+Gcc_backend::immutable_type (Btype *base)
+{
+ tree type_tree = base->get_tree ();
+ if (type_tree == error_mark_node)
+ return this->error_type ();
+ tree constified = build_qualified_type (type_tree, TYPE_QUAL_CONST);
+ return this->make_type (constified);
+}
+
// Make a function type.
Btype *
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index c1df913..afc238b 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -34,6 +34,7 @@
#include "rust-ast-resolve.h"
#include "rust-ast-lower.h"
#include "rust-hir-type-check.h"
+#include "rust-tycheck-dump.h"
#include "rust-compile.h"
extern Linemap *
@@ -548,6 +549,10 @@ Session::parse_file (const char *filename)
// type resolve
type_resolution (hir);
+ // FIXME this needs an option of itself
+ auto buf = Resolver::TypeResolverDump::go (hir);
+ fprintf (stderr, "%s\n", buf.c_str ());
+
if (saw_errors ())
return;
diff --git a/gcc/rust/rust-system.h b/gcc/rust/rust-system.h
index 26c9b33..d62e676 100644
--- a/gcc/rust/rust-system.h
+++ b/gcc/rust/rust-system.h
@@ -20,6 +20,7 @@
#ifndef RUST_SYSTEM_H
#define RUST_SYSTEM_H
+#define INCLUDE_ALGORITHM
#include "config.h"
/* Define this so that inttypes.h defines the PRI?64 macros even
@@ -30,7 +31,6 @@
// These must be included before the #poison declarations in system.h.
-#include <algorithm>
#include <string>
#include <list>
#include <map>
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index f2014a1..78f0d0d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -23,7 +23,6 @@
#include "rust-hir-full.h"
#include "rust-tyty.h"
#include "rust-tyty-call.h"
-#include "rust-tyty-resolver.h"
#include "rust-hir-type-check-struct-field.h"
namespace Rust {
@@ -36,20 +35,121 @@ public:
{
TypeCheckExpr resolver (is_final_expr);
expr->accept_vis (resolver);
- if (resolver.infered != nullptr)
- resolver.context->insert_type (expr->get_mappings ().get_hirid (),
- resolver.infered);
+
+ if (resolver.infered == nullptr)
+ {
+ resolver.infered
+ = new TyTy::UnitType (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)
+ {
+ auto resolved = TypeCheckExpr::Resolve (expr.get_tuple_expr ().get ());
+ if (resolved == nullptr)
+ {
+ rust_error_at (expr.get_tuple_expr ()->get_locus_slow (),
+ "failed to resolve TupleIndexExpr receiver");
+ return;
+ }
+
+ 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_slow (),
+ "Expected Tuple or ADT got: %s",
+ resolved->as_string ().c_str ());
+ return;
+ }
+
+ if (resolved->get_kind () == TyTy::TypeKind::TUPLE)
+ {
+ TyTy::TupleType *tuple = (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 = (TyTy::ADTType *) resolved;
+ TupleIndex index = expr.get_tuple_index ();
+ if ((size_t) index >= adt->num_fields ())
+ {
+ rust_error_at (expr.get_locus (), "unknown field at index %i", index);
+ return;
+ }
+
+ auto field_tyty = adt->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->get_field_type ();
+ }
+
+ void 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<HirId> fields;
+ for (auto &elem : expr.get_tuple_elems ())
+ {
+ auto field_ty = TypeCheckExpr::Resolve (elem.get ());
+ fields.push_back (field_ty->get_ref ());
+ }
+ infered = new TyTy::TupleType (expr.get_mappings ().get_hirid (), fields);
+ }
+
void visit (HIR::ReturnExpr &expr)
{
- auto ret = context->peek_return_type ();
- rust_assert (ret != nullptr);
+ auto fn_return_tyty = context->peek_return_type ();
+ rust_assert (fn_return_tyty != nullptr);
auto expr_ty = TypeCheckExpr::Resolve (expr.get_expr ());
- infered = ret->combine (expr_ty);
+ if (expr_ty == nullptr)
+ {
+ rust_error_at (expr.get_locus (),
+ "failed to resolve type for ReturnExpr");
+ return;
+ }
+
+ infered = fn_return_tyty->combine (expr_ty);
+ fn_return_tyty->append_reference (expr_ty->get_ref ());
+ for (auto &ref : infered->get_combined_refs ())
+ fn_return_tyty->append_reference (ref);
}
void visit (HIR::CallExpr &expr)
@@ -58,11 +158,29 @@ public:
auto fn_node_id = fn->get_mappings ().get_nodeid ();
// then lookup the reference_node_id
- NodeId ref_node_id;
- if (!resolver->lookup_resolved_name (fn_node_id, &ref_node_id))
+ NodeId ref_node_id = UNKNOWN_NODEID;
+ if (resolver->lookup_resolved_name (fn_node_id, &ref_node_id))
+ {
+ Definition def;
+ if (!resolver->lookup_definition (ref_node_id, &def))
+ {
+ rust_error_at (expr.get_locus (),
+ "unknown reference for resolved name");
+ return;
+ }
+ ref_node_id = def.parent;
+ }
+ else if (!resolver->lookup_resolved_type (fn_node_id, &ref_node_id))
{
rust_error_at (expr.get_locus (),
- "Failed to lookup reference for node: %s",
+ "Failed to lookup type reference for node: %s",
+ expr.as_string ().c_str ());
+ return;
+ }
+
+ if (ref_node_id == UNKNOWN_NODEID)
+ {
+ rust_error_at (expr.get_locus (), "unresolved node: %s",
expr.as_string ().c_str ());
return;
}
@@ -72,7 +190,8 @@ public:
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");
+ rust_error_at (expr.get_locus (), "reverse lookup failure for node %u",
+ ref_node_id);
return;
}
@@ -87,7 +206,14 @@ public:
return;
}
- infered = TyTy::TypeCheckCallExpr::go (lookup, expr);
+ infered = TyTy::TypeCheckCallExpr::go (lookup, expr, context);
+ if (infered == nullptr)
+ {
+ rust_error_at (expr.get_locus (), "failed to lookup type to CallExpr");
+ return;
+ }
+
+ infered->set_ref (expr.get_mappings ().get_hirid ());
}
void visit (HIR::AssignmentExpr &expr)
@@ -96,9 +222,50 @@ public:
auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
infered = lhs->combine (rhs);
- // need to overrite the lhs type with this combination
- context->insert_type (expr.get_lhs ()->get_mappings ().get_hirid (),
- infered);
+ if (infered == nullptr)
+ {
+ rust_error_at (expr.get_locus (),
+ "failure in TypeInference AssignmentExpr");
+ return;
+ }
+
+ // in the case of declare first for an ADT Type:
+ //
+ // let a;
+ // a = Foo{..}
+ // let b = a.field;
+ //
+ // The lhs will have a TyTy of INFER and so when the declaration is
+ // referenced it will still have an unknown type so we will fail to resolve
+ // FieldAccessExpr
+
+ NodeId ast_node_id = expr.get_lhs ()->get_mappings ().get_nodeid ();
+ NodeId ref_node_id;
+ if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
+ return;
+
+ Definition def;
+ if (!resolver->lookup_definition (ref_node_id, &def))
+ {
+ rust_error_at (expr.get_locus (),
+ "assignment infer - unknown reference");
+ return;
+ }
+
+ HirId ref;
+ if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
+ def.parent, &ref))
+ {
+ rust_error_at (expr.get_locus (),
+ "assignment infer - reverse lookup failure");
+ return;
+ }
+
+ // FIXME free the old one
+ context->insert_type (
+ Analysis::NodeMapping (expr.get_lhs ()->get_mappings ().get_crate_num (),
+ ref_node_id, ref, UNKNOWN_LOCAL_DEFID),
+ infered->clone ());
}
void visit (HIR::IdentifierExpr &expr)
@@ -106,28 +273,39 @@ public:
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))
+ NodeId ref_node_id = UNKNOWN_NODEID;
+ if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
+ {
+ // these ref_node_ids will resolve to a pattern declaration but we are
+ // interested in the definition that this refers to get the parent id
+ Definition def;
+ if (!resolver->lookup_definition (ref_node_id, &def))
+ {
+ rust_error_at (expr.get_locus (),
+ "unknown reference for resolved name");
+ return;
+ }
+ ref_node_id = def.parent;
+ }
+ else if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id))
{
rust_error_at (expr.get_locus (),
- "Failed to lookup reference for node: %s",
+ "Failed to lookup type reference for node: %s",
expr.as_string ().c_str ());
return;
}
- // these ref_node_ids will resolve to a pattern declaration but we are
- // interested in the definition that this refers to get the parent id
- Definition def;
- if (!resolver->lookup_definition (ref_node_id, &def))
+ if (ref_node_id == UNKNOWN_NODEID)
{
- rust_error_at (expr.get_locus (), "unknown reference");
+ 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 (expr.get_mappings ().get_crate_num (),
- def.parent, &ref))
+ ref_node_id, &ref))
{
rust_error_at (expr.get_locus (), "reverse lookup failure");
return;
@@ -143,8 +321,9 @@ public:
return;
}
- // FIXME this needs to be cloned for memory management later on
- infered = lookup;
+ lookup->append_reference (lookup->get_ref ());
+ infered = lookup->clone ();
+ infered->set_ref (expr.get_mappings ().get_hirid ());
}
void visit (HIR::LiteralExpr &expr)
@@ -198,7 +377,10 @@ public:
break;
default:
- ok = context->lookup_builtin ("i32", &infered);
+ ok = true;
+ infered = new TyTy::InferType (
+ expr.get_mappings ().get_hirid (),
+ TyTy::InferType::InferTypeKind::INTEGRAL);
break;
}
rust_assert (ok);
@@ -216,8 +398,12 @@ public:
case CORETYPE_F64:
ok = context->lookup_builtin ("f64", &infered);
break;
+
default:
- ok = context->lookup_builtin ("f32", &infered);
+ ok = true;
+ infered
+ = new TyTy::InferType (expr.get_mappings ().get_hirid (),
+ TyTy::InferType::InferTypeKind::FLOAT);
break;
}
rust_assert (ok);
@@ -234,14 +420,83 @@ public:
gcc_unreachable ();
break;
}
+
+ infered = infered->clone ();
}
void visit (HIR::ArithmeticOrLogicalExpr &expr)
{
auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ());
auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
+ auto combined = lhs->combine (rhs);
- infered = lhs->combine (rhs);
+ // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators
+ switch (expr.get_expr_type ())
+ {
+ // integers or floats
+ case HIR::ArithmeticOrLogicalExpr::ADD:
+ case HIR::ArithmeticOrLogicalExpr::SUBTRACT:
+ case HIR::ArithmeticOrLogicalExpr::MULTIPLY:
+ case HIR::ArithmeticOrLogicalExpr::DIVIDE:
+ case HIR::ArithmeticOrLogicalExpr::MODULUS: {
+ bool valid = (combined->get_kind () == TyTy::TypeKind::INT)
+ || (combined->get_kind () == TyTy::TypeKind::UINT)
+ || (combined->get_kind () == TyTy::TypeKind::FLOAT)
+ || (combined->get_kind () == TyTy::TypeKind::INFER
+ && (((TyTy::InferType *) combined)->get_infer_kind ()
+ == TyTy::InferType::INTEGRAL))
+ || (combined->get_kind () == TyTy::TypeKind::INFER
+ && (((TyTy::InferType *) combined)->get_infer_kind ()
+ == TyTy::InferType::FLOAT));
+ if (!valid)
+ {
+ rust_error_at (expr.get_locus (), "cannot apply operator to %s",
+ combined->as_string ().c_str ());
+ return;
+ }
+ }
+ break;
+
+ // integers or bools
+ case HIR::ArithmeticOrLogicalExpr::BITWISE_AND:
+ case HIR::ArithmeticOrLogicalExpr::BITWISE_OR:
+ case HIR::ArithmeticOrLogicalExpr::BITWISE_XOR: {
+ bool valid = (combined->get_kind () == TyTy::TypeKind::INT)
+ || (combined->get_kind () == TyTy::TypeKind::UINT)
+ || (combined->get_kind () == TyTy::TypeKind::BOOL)
+ || (combined->get_kind () == TyTy::TypeKind::INFER
+ && (((TyTy::InferType *) combined)->get_infer_kind ()
+ == TyTy::InferType::INTEGRAL));
+ if (!valid)
+ {
+ rust_error_at (expr.get_locus (), "cannot apply operator to %s",
+ combined->as_string ().c_str ());
+ return;
+ }
+ }
+ break;
+
+ // integers only
+ case HIR::ArithmeticOrLogicalExpr::LEFT_SHIFT:
+ case HIR::ArithmeticOrLogicalExpr::RIGHT_SHIFT: {
+ bool valid = (combined->get_kind () == TyTy::TypeKind::INT)
+ || (combined->get_kind () == TyTy::TypeKind::UINT)
+ || (combined->get_kind () == TyTy::TypeKind::INFER
+ && (((TyTy::InferType *) combined)->get_infer_kind ()
+ == TyTy::InferType::INTEGRAL));
+ if (!valid)
+ {
+ rust_error_at (expr.get_locus (), "cannot apply operator to %s",
+ combined->as_string ().c_str ());
+ return;
+ }
+ }
+ break;
+ }
+
+ infered = combined;
+ infered->append_reference (lhs->get_ref ());
+ infered->append_reference (rhs->get_ref ());
}
void visit (HIR::ComparisonExpr &expr)
@@ -249,8 +504,14 @@ public:
auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ());
auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
- infered = lhs->combine (rhs);
- // FIXME this will need to turn into bool
+ auto result = lhs->combine (rhs);
+ if (result == nullptr || result->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+
+ // we expect this to be
+ infered = new TyTy::BoolType (expr.get_mappings ().get_hirid ());
+ infered->append_reference (lhs->get_ref ());
+ infered->append_reference (rhs->get_ref ());
}
void visit (HIR::LazyBooleanExpr &expr)
@@ -258,70 +519,182 @@ public:
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.combine (lhs);
+ if (lhs == nullptr || lhs->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+
+ TyTy::BoolType rlhs (expr.get_mappings ().get_hirid ());
+ rhs = elhs.combine (rhs);
+ if (lhs == nullptr || lhs->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+
infered = lhs->combine (rhs);
- // FIXME this will need to turn into bool
+ infered->append_reference (lhs->get_ref ());
+ infered->append_reference (rhs->get_ref ());
+ }
+
+ void visit (HIR::NegationExpr &expr)
+ {
+ auto negated_expr_ty = TypeCheckExpr::Resolve (expr.get_expr ());
+
+ // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators
+ switch (expr.get_negation_type ())
+ {
+ case HIR::NegationExpr::NegationType::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::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 HIR::NegationExpr::NegationType::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)
{
TypeCheckExpr::Resolve (expr.get_if_condition ());
- TypeCheckExpr::Resolve (expr.get_if_block ());
+ auto blk_expr = TypeCheckExpr::Resolve (expr.get_if_block ());
- // if without else always resolves to unit type
- infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ());
+ if (is_final_expr
+ && context->peek_return_type ()->get_kind () != TyTy::TypeKind::UNIT)
+ {
+ auto expected_ty = context->peek_return_type ();
+ infered = expected_ty->combine (blk_expr);
+ }
}
void visit (HIR::IfExprConseqElse &expr)
{
- // this must combine to what the type is expected
- // this might be a parameter or the last expr in an if + else in a BlockExpr
- // then it must resolve to fn return type
- // else its a unit-type
- infered = is_final_expr
- ? context->peek_return_type ()
- : new TyTy::UnitType (expr.get_mappings ().get_hirid ());
+ // check and resolve all types in the conditional var
+ 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 ());
+
+ TyTy::TyBase *if_block_tyty = nullptr;
+ if (expr.get_if_block ()->has_expr ())
+ if_block_tyty
+ = TypeCheckExpr::Resolve (expr.get_if_block ()->expr.get ());
+ else
+ if_block_tyty = if_blk_resolved;
- TypeCheckExpr::Resolve (expr.get_if_condition (), is_final_expr);
- auto if_blk_ty = TypeCheckExpr::Resolve (expr.get_if_block ());
- auto else_blk_ty = TypeCheckExpr::Resolve (expr.get_else_block ());
+ TyTy::TyBase *else_block_tyty = nullptr;
+ if (expr.get_else_block ()->has_expr ())
+ else_block_tyty
+ = TypeCheckExpr::Resolve (expr.get_else_block ()->expr.get ());
+ else
+ else_block_tyty = else_blk_resolved;
- if (is_final_expr)
+ if (context->peek_return_type ()->get_kind () != TyTy::TypeKind::UNIT)
{
- infered = infered->combine (if_blk_ty);
- infered = infered->combine (else_blk_ty);
+ // this must combine to what the type is expected
+ // this might be a parameter or the last expr in an if + else in a
+ // BlockExpr then it must resolve to fn return type else its a unit-type
+ auto expected_ty
+ = is_final_expr
+ ? context->peek_return_type ()
+ : new TyTy::UnitType (expr.get_mappings ().get_hirid ());
+
+ auto if_blk_combined = expected_ty->combine (if_block_tyty);
+ auto else_blk_combined = expected_ty->combine (else_block_tyty);
+
+ infered = if_blk_combined->combine (else_blk_combined);
}
}
void visit (HIR::IfExprConseqIf &expr)
{
TypeCheckExpr::Resolve (expr.get_if_condition ());
- TypeCheckExpr::Resolve (expr.get_if_block ());
- TypeCheckExpr::Resolve (expr.get_conseq_if_expr ());
+ auto if_blk = TypeCheckExpr::Resolve (expr.get_if_block ());
+ auto elif_blk = TypeCheckExpr::Resolve (expr.get_conseq_if_expr ());
- infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ());
+ if (is_final_expr
+ && context->peek_return_type ()->get_kind () != TyTy::TypeKind::UNIT)
+ {
+ auto expected_ty = context->peek_return_type ();
+
+ infered = expected_ty->combine (if_blk);
+ infered = infered->combine (elif_blk);
+ }
}
void visit (HIR::BlockExpr &expr);
void visit (HIR::ArrayIndexExpr &expr)
{
- // FIXME this should be size type
- TyTy::IntType size_ty (expr.get_index_expr ()->get_mappings ().get_hirid (),
- TyTy::IntType::I32);
- auto resolved
- = size_ty.combine (TypeCheckExpr::Resolve (expr.get_index_expr ()));
- rust_assert (resolved != nullptr);
+ TyTy::TyBase *size_ty;
+ if (!context->lookup_builtin ("usize", &size_ty))
+ {
+ rust_error_at (
+ expr.get_locus (),
+ "Failure looking up size type for index in ArrayIndexExpr");
+ return;
+ }
+
+ auto resolved_index_expr
+ = size_ty->combine (TypeCheckExpr::Resolve (expr.get_index_expr ()));
+ if (resolved_index_expr == nullptr)
+ {
+ rust_error_at (expr.get_index_expr ()->get_locus_slow (),
+ "Type Resolver failure in Index for ArrayIndexExpr");
+ return;
+ }
+ context->insert_type (expr.get_index_expr ()->get_mappings (),
+ resolved_index_expr);
+ // resolve the array reference
expr.get_array_expr ()->accept_vis (*this);
- if (infered->get_kind () != TyTy::TypeKind::ARRAY)
+ if (infered == nullptr)
{
- rust_fatal_error (expr.get_array_expr ()->get_locus_slow (),
- "expected an ArrayType for index expression");
+ rust_error_at (expr.get_index_expr ()->get_locus_slow (),
+ "failed to resolve array reference expression");
+ return;
+ }
+ else if (infered->get_kind () != TyTy::TypeKind::ARRAY)
+ {
+ rust_error_at (expr.get_index_expr ()->get_locus_slow (),
+ "expected an ArrayType got [%s]",
+ infered->as_string ().c_str ());
+ infered = nullptr;
return;
}
- // extract the element type out now from the base type
- infered = TyTyExtractorArray::ExtractElementTypeFromArray (infered);
+ TyTy::ArrayType *array_type = (TyTy::ArrayType *) infered;
+ infered = array_type->get_type ()->clone ();
}
void visit (HIR::ArrayExpr &expr)
@@ -349,6 +722,9 @@ public:
{
infered_array_elems = infered_array_elems->combine (types.at (i));
}
+
+ for (auto &elem : types)
+ infered_array_elems->append_reference (elem->get_ref ());
}
void visit (HIR::ArrayElemsCopied &elems)
@@ -361,6 +737,38 @@ public:
infered = TypeCheckStructExpr::Resolve (&struct_expr);
}
+ void visit (HIR::GroupedExpr &expr)
+ {
+ infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get ());
+ }
+
+ void visit (HIR::FieldAccessExpr &expr)
+ {
+ auto struct_base
+ = TypeCheckExpr::Resolve (expr.get_receiver_expr ().get ());
+
+ bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT;
+ if (!is_valid_type)
+ {
+ rust_error_at (expr.get_locus (),
+ "expected ADT or Tuple Type got: [%s]",
+ struct_base->as_string ().c_str ());
+ return;
+ }
+
+ TyTy::ADTType *adt = (TyTy::ADTType *) struct_base;
+ auto resolved = adt->get_field (expr.get_field_name ());
+ if (resolved == nullptr)
+ {
+ 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 = resolved->get_field_type ();
+ }
+
private:
TypeCheckExpr (bool is_final_expr)
: TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr),
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h
index 62320a6..d7f9af1 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.h
@@ -24,44 +24,10 @@
#include "rust-hir-type-check-type.h"
#include "rust-hir-type-check-stmt.h"
#include "rust-tyty-visitor.h"
-#include "rust-tyty-resolver.h"
namespace Rust {
namespace Resolver {
-class ResolveFnType : public TyTy::TyVisitor
-{
-public:
- ResolveFnType (TyTy::TyBase *base) : base (base), state (nullptr) {}
-
- TyTy::TyBase *go ()
- {
- base->accept_vis (*this);
- if (state == nullptr)
- gcc_unreachable ();
-
- return state;
- }
-
- void visit (TyTy::UnitType &type) override { gcc_unreachable (); }
- void visit (TyTy::InferType &type) override { gcc_unreachable (); }
- void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); }
- void visit (TyTy::ADTType &type) override { gcc_unreachable (); }
- void visit (TyTy::ParamType &type) override { gcc_unreachable (); }
- void visit (TyTy::ArrayType &type) override { gcc_unreachable (); }
- void visit (TyTy::BoolType &type) override { gcc_unreachable (); }
- void visit (TyTy::IntType &type) override { gcc_unreachable (); }
- void visit (TyTy::UintType &type) override { gcc_unreachable (); }
- void visit (TyTy::FloatType &type) override { gcc_unreachable (); }
- void visit (TyTy::ErrorType &type) override { gcc_unreachable (); }
-
- void visit (TyTy::FnType &type) override { state = type.return_type (); }
-
-private:
- TyTy::TyBase *base;
- TyTy::TyBase *state;
-};
-
class TypeCheckItem : public TypeCheckBase
{
public:
@@ -73,18 +39,43 @@ public:
void visit (HIR::Function &function)
{
- TyTy::TyBase *fnType;
- if (!context->lookup_type (function.get_mappings ().get_hirid (), &fnType))
+ TyTy::TyBase *lookup;
+ if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup))
{
rust_error_at (function.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
- ResolveFnType resolve_fn_type (fnType);
- context->push_return_type (resolve_fn_type.go ());
+ TyTy::FnType *resolve_fn_type = (TyTy::FnType *) lookup;
+ auto expected_ret_tyty = resolve_fn_type->return_type ();
+ context->push_return_type (expected_ret_tyty);
TypeCheckExpr::Resolve (function.function_body.get ());
+ if (function.function_body->has_expr ())
+ {
+ auto resolved
+ = TypeCheckExpr::Resolve (function.function_body->expr.get ());
+
+ auto ret_resolved = expected_ret_tyty->combine (resolved);
+ if (ret_resolved == nullptr)
+ {
+ rust_error_at (function.function_body->expr->get_locus_slow (),
+ "failed to resolve final expression");
+ return;
+ }
+
+ context->peek_return_type ()->append_reference (
+ ret_resolved->get_ref ());
+ }
context->pop_return_type ();
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
index bf754db..99be0b7 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
@@ -49,10 +49,19 @@ public:
void visit (HIR::LetStmt &stmt)
{
+ infered = new TyTy::UnitType (stmt.get_mappings ().get_hirid ());
+
TyTy::TyBase *init_expr_ty = nullptr;
if (stmt.has_init_expr ())
- init_expr_ty
- = TypeCheckExpr::Resolve (stmt.get_init_expr (), is_final_stmt);
+ {
+ init_expr_ty
+ = TypeCheckExpr::Resolve (stmt.get_init_expr (), is_final_stmt);
+
+ init_expr_ty = init_expr_ty->clone ();
+ auto ref = init_expr_ty->get_ref ();
+ init_expr_ty->set_ref (stmt.get_mappings ().get_hirid ());
+ init_expr_ty->append_reference (ref);
+ }
TyTy::TyBase *specified_ty = nullptr;
if (stmt.has_type ())
@@ -69,35 +78,34 @@ public:
return;
}
- context->insert_type (stmt.get_mappings ().get_hirid (), combined);
+ context->insert_type (stmt.get_mappings (), combined);
}
else
{
// let x:i32;
if (specified_ty != nullptr)
{
- context->insert_type (stmt.get_mappings ().get_hirid (),
- specified_ty);
+ context->insert_type (stmt.get_mappings (), specified_ty);
}
// let x = 123;
else if (init_expr_ty != nullptr)
{
- context->insert_type (stmt.get_mappings ().get_hirid (),
- init_expr_ty);
+ context->insert_type (stmt.get_mappings (), init_expr_ty);
}
// let x;
else
{
- context->insert_type (stmt.get_mappings ().get_hirid (),
- new TyTy::InferType (
- stmt.get_mappings ().get_hirid ()));
+ context->insert_type (
+ stmt.get_mappings (),
+ new TyTy::InferType (stmt.get_mappings ().get_hirid (),
+ TyTy::InferType::InferTypeKind::GENERAL));
}
}
}
private:
TypeCheckStmt (bool is_final_stmt)
- : TypeCheckBase (), is_final_stmt (is_final_stmt)
+ : TypeCheckBase (), infered (nullptr), is_final_stmt (is_final_stmt)
{}
TyTy::TyBase *infered;
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 727569d..98db278 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
@@ -44,6 +44,10 @@ public:
void visit (HIR::StructExprFieldIdentifierValue &field);
+ void visit (HIR::StructExprFieldIndexValue &field);
+
+ void visit (HIR::StructExprFieldIdentifier &field);
+
private:
TypeCheckStructExpr ()
: TypeCheckBase (), resolved (nullptr), struct_path_resolved (nullptr)
@@ -53,6 +57,7 @@ private:
TyTy::ADTType *struct_path_resolved;
TyTy::TyBase *resolved_field;
std::set<std::string> fields_assigned;
+ std::map<size_t, HIR::StructExprField *> adtFieldIndexToField;
};
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
index 34e7020..52b6cde 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
@@ -37,6 +37,30 @@ public:
item->accept_vis (resolver);
}
+ void visit (HIR::TupleStruct &struct_decl)
+ {
+ std::vector<TyTy::StructFieldType *> fields;
+
+ size_t idx = 0;
+ struct_decl.iterate ([&] (HIR::TupleField &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 (),
+ std::to_string (idx), field_type);
+ fields.push_back (ty_field);
+ context->insert_type (field.get_mappings (), ty_field->get_field_type ());
+ idx++;
+ 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 (), type);
+ }
+
void visit (HIR::StructStruct &struct_decl)
{
std::vector<TyTy::StructFieldType *> fields;
@@ -47,8 +71,7 @@ public:
= 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 ());
+ context->insert_type (field.get_mappings (), ty_field->get_field_type ());
return true;
});
@@ -56,7 +79,7 @@ public:
= 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);
+ context->insert_type (struct_decl.get_mappings (), type);
}
void visit (HIR::StaticItem &var)
@@ -64,8 +87,7 @@ public:
TyTy::TyBase *type = TypeCheckType::Resolve (var.get_type ());
TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (var.get_expr ());
- context->insert_type (var.get_mappings ().get_hirid (),
- type->combine (expr_type));
+ context->insert_type (var.get_mappings (), type->combine (expr_type));
}
void visit (HIR::ConstantItem &constant)
@@ -73,8 +95,7 @@ public:
TyTy::TyBase *type = TypeCheckType::Resolve (constant.get_type ());
TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
- context->insert_type (constant.get_mappings ().get_hirid (),
- type->combine (expr_type));
+ context->insert_type (constant.get_mappings (), type->combine (expr_type));
}
void visit (HIR::Function &function)
@@ -83,24 +104,34 @@ public:
if (!function.has_function_return_type ())
ret_type = new TyTy::UnitType (function.get_mappings ().get_hirid ());
else
- ret_type = TypeCheckType::Resolve (function.return_type.get ());
+ {
+ auto resolved = TypeCheckType::Resolve (function.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.return_type->get_mappings ().get_hirid ());
+ }
- std::vector<TyTy::ParamType *> params;
+ std::vector<std::pair<HIR::Pattern *, TyTy::TyBase *> > params;
for (auto &param : function.function_params)
{
// get the name as well required for later on
- auto param_type = TypeCheckType::Resolve (param.type.get ());
- auto param_tyty
- = new TyTy::ParamType (param.get_mappings ()->get_hirid (),
- param.param_name->as_string (), param_type);
- params.push_back (param_tyty);
+ auto param_tyty = TypeCheckType::Resolve (param.get_type ());
+ params.push_back (
+ std::pair<HIR::Pattern *, TyTy::TyBase *> (param.get_param_name (),
+ param_tyty));
- context->insert_type (param.get_mappings ()->get_hirid (), param_tyty);
+ context->insert_type (param.get_mappings (), param_tyty);
}
auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (),
params, ret_type);
- context->insert_type (function.get_mappings ().get_hirid (), fnType);
+ context->insert_type (function.get_mappings (), fnType);
}
private:
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h
index 8ff4c44..2894899 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -40,11 +40,12 @@ public:
void visit (HIR::LiteralExpr &expr)
{
+ auto literal_value = expr.get_literal ();
switch (expr.get_lit_type ())
{
case HIR::Literal::LitType::INT: {
ok = true;
- std::stringstream ss (expr.as_string ());
+ std::stringstream ss (literal_value->as_string ());
ss >> result;
}
break;
@@ -70,18 +71,68 @@ public:
type->accept_vis (resolver);
if (resolver.translated != nullptr)
- resolver.context->insert_type (type->get_mappings ().get_hirid (),
- resolver.translated);
+ {
+ resolver.context->insert_type (type->get_mappings (),
+ resolver.translated);
+ }
return resolver.translated;
}
- void visit (HIR::TypePath &path)
+ void visit (HIR::BareFunctionType &fntype)
{
- // check if this is already defined or not
- if (context->lookup_type (path.get_mappings ().get_hirid (), &translated))
- return;
+ TyTy::TyBase *return_type
+ = fntype.has_return_type ()
+ ? TypeCheckType::Resolve (fntype.get_return_type ().get ())
+ : new TyTy::UnitType (fntype.get_mappings ().get_hirid ());
+
+ std::vector<std::pair<HIR::Pattern *, TyTy::TyBase *> > params;
+ for (auto &param : fntype.get_function_params ())
+ {
+ std::unique_ptr<HIR::Pattern> to_bind;
+
+ bool is_ref = false;
+ bool is_mut = false;
+
+ HIR::Pattern *pattern
+ = new HIR::IdentifierPattern (param.get_name (), param.get_locus (),
+ is_ref, is_mut, std::move (to_bind));
+ TyTy::TyBase *ptype = TypeCheckType::Resolve (param.get_type ().get ());
+ params.push_back (
+ std::pair<HIR::Pattern *, TyTy::TyBase *> (pattern, ptype));
+ }
+
+ translated = new TyTy::FnType (fntype.get_mappings ().get_hirid (),
+ std::move (params), return_type);
+ }
+
+ void visit (HIR::TupleType &tuple)
+ {
+ if (tuple.is_unit_type ())
+ {
+ auto unit_node_id = resolver->get_unit_type_node_id ();
+ if (!context->lookup_builtin (unit_node_id, &translated))
+ {
+ rust_error_at (tuple.get_locus (),
+ "failed to lookup builtin unit type");
+ }
+ return;
+ }
+
+ std::vector<HirId> fields;
+ for (auto &elem : tuple.get_elems ())
+ {
+ auto field_ty = TypeCheckType::Resolve (elem.get ());
+ fields.push_back (field_ty->get_ref ());
+ }
+
+ translated
+ = new TyTy::TupleType (tuple.get_mappings ().get_hirid (), fields);
+ }
+
+ void visit (HIR::TypePath &path)
+ {
// lookup the Node this resolves to
NodeId ref;
if (!resolver->lookup_resolved_type (path.get_mappings ().get_nodeid (),
@@ -98,12 +149,13 @@ public:
{
// we got an HIR node
if (context->lookup_type (hir_lookup, &translated))
- return;
+ {
+ translated = translated->clone ();
+ auto ref = path.get_mappings ().get_hirid ();
+ translated->set_ref (ref);
+ return;
+ }
}
-
- // this might be a struct type (TyTy::ADT) reference
- // TODO
- printf ("UNREACHABLE %s\n", path.as_string ().c_str ());
gcc_unreachable ();
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index 8fa6714..cf3a846 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -34,6 +34,54 @@ TypeResolution::Resolve (HIR::Crate &crate)
for (auto it = crate.items.begin (); it != crate.items.end (); it++)
TypeCheckItem::Resolve (it->get ());
+
+ auto mappings = Analysis::Mappings::get ();
+ auto context = TypeCheckContext::get ();
+
+ context->iterate ([&] (HirId id, TyTy::TyBase *ty) mutable -> bool {
+ // nothing to do
+ if (ty->get_kind () != TyTy::TypeKind::INFER)
+ return true;
+
+ TyTy::InferType *infer_var = (TyTy::InferType *) ty;
+ switch (infer_var->get_infer_kind ())
+ {
+ case TyTy::InferType::GENERAL:
+ rust_error_at (mappings->lookup_location (id),
+ "unable to determine type: %u", id);
+ break;
+
+ case TyTy::InferType::INTEGRAL: {
+ TyTy::TyBase *default_integer;
+ bool ok = context->lookup_builtin ("i32", &default_integer);
+ rust_assert (ok);
+
+ auto result = ty->combine (default_integer);
+ result->set_ref (id);
+ context->insert_type (
+ Analysis::NodeMapping (mappings->get_current_crate (), 0, id,
+ UNKNOWN_LOCAL_DEFID),
+ result);
+ }
+ break;
+
+ case TyTy::InferType::FLOAT: {
+ TyTy::TyBase *default_float;
+ bool ok = context->lookup_builtin ("f32", &default_float);
+ rust_assert (ok);
+
+ auto result = ty->combine (default_float);
+ result->set_ref (id);
+ context->insert_type (
+ Analysis::NodeMapping (mappings->get_current_crate (), 0, id,
+ UNKNOWN_LOCAL_DEFID),
+ result);
+ }
+ break;
+ }
+
+ return true;
+ });
}
// RUST_HIR_TYPE_CHECK_EXPR
@@ -47,7 +95,13 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
bool is_final_stmt = expr.is_final_stmt (s);
bool is_final_expr = is_final_stmt && !expr.has_expr ();
- auto infered = TypeCheckStmt::Resolve (s, is_final_stmt);
+ auto infered = TypeCheckStmt::Resolve (s, is_final_expr);
+ if (infered == nullptr)
+ {
+ rust_error_at (s->get_locus_slow (), "failure to resolve type");
+ return false;
+ }
+
if (is_final_expr)
{
delete block_tyty;
@@ -57,27 +111,21 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
return true;
});
- if (expr.has_expr ())
- {
- auto tail_tyty = TypeCheckExpr::Resolve (expr.expr.get (), true);
-
- delete block_tyty;
- block_tyty = tail_tyty;
- }
+ // tail expression must be checked as part of the caller since
+ // the result of this is very dependant on what we expect it to be
// now that the stmts have been resolved we must resolve the block of locals
// and make sure the variables have been resolved
- auto body_mappings = expr.get_mappings ();
- Rib *rib = nullptr;
- if (!resolver->find_name_rib (body_mappings.get_nodeid (), &rib))
- {
- rust_fatal_error (expr.get_locus (), "failed to lookup locals per block");
- return;
- }
-
- TyTyResolver::Resolve (rib, mappings, resolver, context);
-
- infered = block_tyty;
+ // auto body_mappings = expr.get_mappings ();
+ // Rib *rib = nullptr;
+ // if (!resolver->find_name_rib (body_mappings.get_nodeid (), &rib))
+ // {
+ // rust_fatal_error (expr.get_locus (), "failed to lookup locals per
+ // block"); return;
+ // }
+ // TyTyResolver::Resolve (rib, mappings, resolver, context);
+
+ infered = block_tyty->clone ();
}
// RUST_HIR_TYPE_CHECK_STRUCT_FIELD
@@ -93,6 +141,22 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr)
return;
}
+ resolved = struct_path_resolved;
+ if (struct_expr.has_struct_base ())
+ {
+ TyTy::TyBase *base_resolved
+ = TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get ());
+ resolved = struct_path_resolved->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;
+ }
+ }
+
+ bool ok = true;
struct_expr.iterate ([&] (HIR::StructExprField *field) mutable -> bool {
resolved_field = nullptr;
field->accept_vis (*this);
@@ -100,35 +164,94 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr)
{
rust_fatal_error (field->get_locus (),
"failed to resolve type for field");
+ ok = false;
return false;
}
- context->insert_type (field->get_mappings ().get_hirid (), resolved_field);
+ context->insert_type (field->get_mappings (), resolved_field);
return true;
});
- TyTy::TyBase *expr_type = struct_path_resolved;
- if (struct_expr.has_struct_base ())
+ // something failed setting up the fields
+ if (!ok)
+ return;
+
+ // check the arguments are all assigned and fix up the ordering
+ if (fields_assigned.size () != struct_path_resolved->num_fields ())
{
- TyTy::TyBase *base_resolved
- = TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get ());
- expr_type = expr_type->combine (base_resolved);
- if (resolved == nullptr)
+ if (!struct_expr.has_struct_base ())
{
- rust_fatal_error (
- struct_expr.struct_base->base_struct->get_locus_slow (),
- "incompatible types for base struct reference");
+ rust_error_at (struct_expr.get_locus (),
+ "constructor is missing fields");
return;
}
+ else
+ {
+ // we have a struct base to assign the missing fields from.
+ // the missing fields can be implicit FieldAccessExprs for the value
+ std::set<std::string> missing_fields;
+ struct_path_resolved->iterate_fields (
+ [&] (TyTy::StructFieldType *field) mutable -> bool {
+ auto it = fields_assigned.find (field->get_name ());
+ if (it == fields_assigned.end ())
+ missing_fields.insert (field->get_name ());
+ return true;
+ });
+
+ // we can generate FieldAccessExpr or TupleAccessExpr for the values
+ // of the missing fields.
+ for (auto &missing : missing_fields)
+ {
+ HIR::Expr *receiver
+ = struct_expr.struct_base->base_struct->clone_expr_impl ();
+
+ HIR::StructExprField *implicit_field = nullptr;
+
+ std::vector<HIR::Attribute> outer_attribs;
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (
+ crate_num,
+ struct_expr.struct_base->base_struct->get_mappings ()
+ .get_nodeid (),
+ mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID);
+
+ HIR::Expr *field_value = new HIR::FieldAccessExpr (
+ mapping, std::unique_ptr<HIR::Expr> (receiver), missing,
+ std::move (outer_attribs),
+ struct_expr.struct_base->base_struct->get_locus_slow ());
+
+ implicit_field = new HIR::StructExprFieldIdentifierValue (
+ mapping, missing, std::unique_ptr<HIR::Expr> (field_value),
+ struct_expr.struct_base->base_struct->get_locus_slow ());
+
+ size_t field_index;
+ bool ok = struct_path_resolved->get_field (missing, &field_index);
+ rust_assert (ok);
+
+ adtFieldIndexToField[field_index] = implicit_field;
+ struct_expr.get_fields ().push_back (
+ std::unique_ptr<HIR::StructExprField> (implicit_field));
+ }
+ }
}
- else if (fields_assigned.size () != struct_path_resolved->num_fields ())
+
+ // everything is ok, now we need to ensure all field values are ordered
+ // correctly. The GIMPLE backend uses a simple algorithm that assumes each
+ // assigned field in the constructor is in the same order as the field in the
+ // type
+
+ std::vector<std::unique_ptr<HIR::StructExprField> > expr_fields
+ = struct_expr.get_fields_as_owner ();
+ for (auto &f : expr_fields)
+ f.release ();
+
+ std::vector<std::unique_ptr<HIR::StructExprField> > ordered_fields;
+ for (size_t i = 0; i < adtFieldIndexToField.size (); i++)
{
- rust_fatal_error (struct_expr.get_locus (),
- "some fields are not fully assigned");
- return;
+ ordered_fields.push_back (
+ std::unique_ptr<HIR::StructExprField> (adtFieldIndexToField[i]));
}
-
- resolved = expr_type;
+ struct_expr.set_fields_as_owner (std::move (ordered_fields));
}
void
@@ -187,9 +310,39 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
return;
}
+ size_t field_index;
+ TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ());
+ TyTy::StructFieldType *field_type
+ = struct_path_resolved->get_field (field.field_name, &field_index);
+ 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);
+ adtFieldIndexToField[field_index] = &field;
+ }
+}
+
+void
+TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
+{
+ std::string field_name (std::to_string (field.get_tuple_index ()));
+ auto it = fields_assigned.find (field_name);
+ if (it != fields_assigned.end ())
+ {
+ rust_fatal_error (field.get_locus (), "used more than once");
+ return;
+ }
+
+ size_t field_index;
TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ());
TyTy::StructFieldType *field_type
- = struct_path_resolved->get_field (field.field_name);
+ = struct_path_resolved->get_field (field_name, &field_index);
if (field_type == nullptr)
{
rust_error_at (field.get_locus (), "unknown field");
@@ -198,7 +351,43 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
resolved_field = field_type->get_field_type ()->combine (value);
if (resolved_field != nullptr)
- fields_assigned.insert (field.field_name);
+ {
+ fields_assigned.insert (field_name);
+ adtFieldIndexToField[field_index] = &field;
+ }
+}
+
+void
+TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
+{
+ auto it = fields_assigned.find (field.get_field_name ());
+ if (it != fields_assigned.end ())
+ {
+ rust_fatal_error (field.get_locus (), "used more than once");
+ return;
+ }
+
+ size_t field_index;
+ TyTy::StructFieldType *field_type
+ = struct_path_resolved->get_field (field.get_field_name (), &field_index);
+ if (field_type == nullptr)
+ {
+ rust_error_at (field.get_locus (), "unknown field");
+ return;
+ }
+
+ // we can make the field look like an identifier expr to take advantage of
+ // existing code to figure out the type
+ HIR::IdentifierExpr expr (field.get_mappings (), field.get_field_name (),
+ field.get_locus ());
+ TyTy::TyBase *value = TypeCheckExpr::Resolve (&expr);
+
+ resolved_field = field_type->get_field_type ()->combine (value);
+ if (resolved_field != nullptr)
+ {
+ fields_assigned.insert (field.field_name);
+ adtFieldIndexToField[field_index] = &field;
+ }
}
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index 6deecdd..d033878 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -33,10 +33,11 @@ public:
~TypeCheckContext ();
+ bool lookup_builtin (NodeId id, TyTy::TyBase **type);
bool lookup_builtin (std::string name, TyTy::TyBase **type);
void insert_builtin (HirId id, NodeId ref, TyTy::TyBase *type);
- void insert_type (HirId id, TyTy::TyBase *type);
+ void insert_type (const Analysis::NodeMapping &mappings, TyTy::TyBase *type);
bool lookup_type (HirId id, TyTy::TyBase **type);
void insert_type_by_node_id (NodeId ref, HirId id);
@@ -46,6 +47,15 @@ public:
void push_return_type (TyTy::TyBase *return_type);
void pop_return_type ();
+ void iterate (std::function<bool (HirId, TyTy::TyBase *)> cb)
+ {
+ for (auto it = resolved.begin (); it != resolved.end (); it++)
+ {
+ if (!cb (it->first, it->second))
+ return;
+ }
+ }
+
private:
TypeCheckContext ();
diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h
new file mode 100644
index 0000000..863c2eb
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tycheck-dump.h
@@ -0,0 +1,178 @@
+// 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_TYCHECK_DUMP
+#define RUST_TYCHECK_DUMP
+
+#include "rust-hir-type-check-base.h"
+#include "rust-hir-full.h"
+
+namespace Rust {
+namespace Resolver {
+
+class TypeResolverDump : public TypeCheckBase
+{
+public:
+ static std::string go (HIR::Crate &crate)
+ {
+ TypeResolverDump dumper;
+ for (auto &item : crate.items)
+ item->accept_vis (dumper);
+
+ return dumper.dump;
+ }
+
+ void visit (HIR::Function &function)
+ {
+ dump += indent () + "fn " + function.function_name + " "
+ + type_string (function.get_mappings ()) + "\n";
+ dump += indent () + "{\n";
+
+ HIR::BlockExpr *function_body = function.function_body.get ();
+ function_body->accept_vis (*this);
+
+ dump += indent () + "}\n";
+ }
+
+ void visit (HIR::BlockExpr &expr)
+ {
+ indentation_level++;
+
+ expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool {
+ s->accept_vis (*this);
+ dump += ";\n";
+ return true;
+ });
+
+ if (expr.has_expr () && expr.tail_expr_reachable ())
+ {
+ expr.expr->accept_vis (*this);
+ dump += ";\n";
+ }
+
+ indentation_level--;
+ }
+
+ void visit (HIR::LetStmt &stmt)
+ {
+ dump += indent () + "let " + stmt.get_pattern ()->as_string () + ":"
+ + type_string (stmt.get_mappings ());
+ if (stmt.has_init_expr ())
+ {
+ dump += " = ";
+ stmt.get_init_expr ()->accept_vis (*this);
+ }
+ }
+
+ void visit (HIR::ExprStmtWithBlock &stmt)
+ {
+ dump += indent ();
+ stmt.get_expr ()->accept_vis (*this);
+ }
+
+ void visit (HIR::ExprStmtWithoutBlock &stmt)
+ {
+ dump += indent ();
+ stmt.get_expr ()->accept_vis (*this);
+ }
+
+ void visit (HIR::AssignmentExpr &expr)
+ {
+ expr.get_lhs ()->accept_vis (*this);
+ dump += " = ";
+ expr.get_rhs ()->accept_vis (*this);
+ }
+
+ void visit (HIR::LiteralExpr &expr)
+ {
+ dump += expr.get_literal ()->as_string () + ":"
+ + type_string (expr.get_mappings ());
+ }
+
+ void visit (HIR::IdentifierExpr &expr)
+ {
+ dump += expr.get_identifier () + ":" + type_string (expr.get_mappings ());
+ }
+
+ void visit (HIR::ArrayExpr &expr)
+ {
+ dump += type_string (expr.get_mappings ()) + ":[";
+
+ HIR::ArrayElems *elements = expr.get_internal_elements ();
+ elements->accept_vis (*this);
+
+ dump += "]";
+ }
+
+ void visit (HIR::ArrayElemsValues &elems)
+ {
+ elems.iterate ([&] (HIR::Expr *e) mutable -> bool {
+ e->accept_vis (*this);
+ dump += ",";
+ return true;
+ });
+ }
+
+ void visit (HIR::GroupedExpr &expr)
+ {
+ HIR::Expr *paren_expr = expr.get_expr_in_parens ().get ();
+ dump += "(";
+ paren_expr->accept_vis (*this);
+ dump += ")";
+ }
+
+protected:
+ std::string type_string (const Analysis::NodeMapping &mappings)
+ {
+ TyTy::TyBase *lookup = nullptr;
+ if (!context->lookup_type (mappings.get_hirid (), &lookup))
+ return "<error>";
+
+ std::string buf = "[";
+ for (auto &ref : lookup->get_combined_refs ())
+ {
+ buf += std::to_string (ref);
+ buf += ", ";
+ }
+ buf += "]";
+
+ return "<" + lookup->as_string ()
+ + " RF:" + std::to_string (lookup->get_ref ()) + " TF:"
+ + std::to_string (lookup->get_ty_ref ()) + +" - " + buf + ">";
+ }
+
+ std::string indent ()
+ {
+ std::string buf;
+ for (size_t i = 0; i < indentation_level; ++i)
+ buf += " ";
+
+ return buf;
+ }
+
+private:
+ TypeResolverDump () : TypeCheckBase (), indentation_level (0) {}
+
+ std::string dump;
+ size_t indentation_level;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_TYCHECK_DUMP
diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc
index cd171d1..65c5563 100644
--- a/gcc/rust/typecheck/rust-tyctx.cc
+++ b/gcc/rust/typecheck/rust-tyctx.cc
@@ -36,6 +36,21 @@ TypeCheckContext::TypeCheckContext () {}
TypeCheckContext::~TypeCheckContext () {}
bool
+TypeCheckContext::lookup_builtin (NodeId id, TyTy::TyBase **type)
+{
+ auto ref_it = node_id_refs.find (id);
+ if (ref_it == node_id_refs.end ())
+ return false;
+
+ auto it = resolved.find (ref_it->second);
+ if (it == resolved.end ())
+ return false;
+
+ *type = it->second;
+ return true;
+}
+
+bool
TypeCheckContext::lookup_builtin (std::string name, TyTy::TyBase **type)
{
for (auto &builtin : builtins)
@@ -58,9 +73,13 @@ TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::TyBase *type)
}
void
-TypeCheckContext::insert_type (HirId id, TyTy::TyBase *type)
+TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings,
+ TyTy::TyBase *type)
{
rust_assert (type != nullptr);
+ NodeId ref = mappings.get_nodeid ();
+ HirId id = mappings.get_hirid ();
+ node_id_refs[ref] = id;
resolved[id] = type;
}
diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h
index c3fcb1a..2b3cfb6 100644
--- a/gcc/rust/typecheck/rust-tyty-call.h
+++ b/gcc/rust/typecheck/rust-tyty-call.h
@@ -23,6 +23,7 @@
#include "rust-hir-full.h"
#include "rust-tyty-visitor.h"
#include "rust-tyty.h"
+#include "rust-hir-type-check.h"
namespace Rust {
namespace TyTy {
@@ -30,9 +31,10 @@ namespace TyTy {
class TypeCheckCallExpr : private TyVisitor
{
public:
- static TyBase *go (TyBase *ref, HIR::CallExpr &call)
+ static TyBase *go (TyBase *ref, HIR::CallExpr &call,
+ Resolver::TypeCheckContext *context)
{
- TypeCheckCallExpr checker (call);
+ TypeCheckCallExpr checker (call, context);
ref->accept_vis (checker);
return checker.resolved;
}
@@ -40,23 +42,33 @@ public:
void visit (UnitType &type) override { gcc_unreachable (); }
void visit (InferType &type) override { gcc_unreachable (); }
+ void visit (TupleType &type) override { gcc_unreachable (); }
void visit (StructFieldType &type) override { gcc_unreachable (); }
- void visit (ADTType &type) override { gcc_unreachable (); }
- void visit (ParamType &type) override { gcc_unreachable (); }
void visit (ArrayType &type) override { gcc_unreachable (); }
void visit (BoolType &type) override { gcc_unreachable (); }
void visit (IntType &type) override { gcc_unreachable (); }
void visit (UintType &type) override { gcc_unreachable (); }
void visit (FloatType &type) override { gcc_unreachable (); }
+ void visit (USizeType &type) override { gcc_unreachable (); }
+ void visit (ISizeType &type) override { gcc_unreachable (); }
void visit (ErrorType &type) override { gcc_unreachable (); }
+ // tuple-structs
+ void visit (ADTType &type) override;
+
+ // call fns
void visit (FnType &type) override;
private:
- TypeCheckCallExpr (HIR::CallExpr &c) : resolved (nullptr), call (c) {}
+ TypeCheckCallExpr (HIR::CallExpr &c, Resolver::TypeCheckContext *context)
+ : resolved (nullptr), call (c), context (context),
+ mappings (Analysis::Mappings::get ())
+ {}
TyBase *resolved;
HIR::CallExpr &call;
+ Resolver::TypeCheckContext *context;
+ Analysis::Mappings *mappings;
};
} // namespace TyTy
diff --git a/gcc/rust/typecheck/rust-tyty-resolver.h b/gcc/rust/typecheck/rust-tyty-resolver.h
deleted file mode 100644
index 22c3c91..0000000
--- a/gcc/rust/typecheck/rust-tyty-resolver.h
+++ /dev/null
@@ -1,177 +0,0 @@
-// 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_TYTY_RESOLVER
-#define RUST_TYTY_RESOLVER
-
-#include "rust-system.h"
-#include "rust-diagnostics.h"
-#include "rust-hir-map.h"
-#include "rust-name-resolver.h"
-#include "rust-hir-type-check.h"
-#include "rust-hir-full.h"
-#include "rust-tyty-visitor.h"
-
-namespace Rust {
-namespace Resolver {
-
-class TyTyResolver
-{
-public:
- static void Resolve (Rib *rib, Analysis::Mappings *mappings,
- Resolver *resolver, TypeCheckContext *context)
- {
- TyTyResolver r (mappings, resolver, context);
- r.go (rib);
- }
-
- virtual ~TyTyResolver () {}
-
- void go (Rib *rib)
- {
- rib->iterate_decls ([&] (NodeId decl_node_id, Location) mutable -> bool {
- // type inference in rust means we need to gather and examine all
- // references of this decl and combine each to make sure the type is
- // correctly inferred. Consider the example:
- // let mut x; x = 1;
- // we can only say x is an infer variable then at the assignment
- // we think x must be an integer
-
- std::vector<TyTy::TyBase *> gathered_types;
- rib->iterate_references_for_def (
- decl_node_id, [&] (NodeId ref_node) mutable -> bool {
- HirId hir_node_ref;
- bool ok
- = mappings->lookup_node_to_hir (mappings->get_current_crate (),
- ref_node, &hir_node_ref);
- rust_assert (ok);
-
- TyTy::TyBase *resolved = nullptr;
- if (!context->lookup_type (hir_node_ref, &resolved))
- {
- // this could be an array/adt type
- Definition d;
- bool ok = resolver->lookup_definition (ref_node, &d);
- rust_assert (ok);
-
- ok = mappings->lookup_node_to_hir (mappings->get_current_crate (),
- d.parent, &hir_node_ref);
- rust_assert (ok);
-
- if (!context->lookup_type (hir_node_ref, &resolved))
- {
- rust_fatal_error (
- mappings->lookup_location (hir_node_ref),
- "failed to lookup type for reference at node [%u]",
- hir_node_ref);
- return false;
- }
- }
-
- gathered_types.push_back (resolved);
- return true;
- });
-
- Definition d;
- bool ok = resolver->lookup_definition (decl_node_id, &d);
- rust_assert (ok);
-
- HIR::Stmt *decl = nullptr;
- ok = mappings->resolve_nodeid_to_stmt (d.parent, &decl);
- rust_assert (ok);
-
- TyTy::TyBase *resolved_type = nullptr;
- ok = context->lookup_type (decl->get_mappings ().get_hirid (),
- &resolved_type);
- rust_assert (ok);
-
- if (resolved_type->get_kind () != TyTy::TypeKind::INFER)
- return true;
-
- auto resolved_tyty = resolved_type;
- for (auto it : gathered_types)
- {
- auto combined = resolved_tyty->combine (it);
- if (combined == nullptr)
- break;
-
- resolved_tyty = combined;
- }
-
- // something is not inferred we need to look at all references now
- if (resolved_tyty == nullptr || resolved_tyty->is_unit ())
- {
- rust_fatal_error (decl->get_locus_slow (), "failed to resolve type");
- return false;
- }
-
- // insert the new resolved definition
- context->insert_type (decl->get_mappings ().get_hirid (), resolved_tyty);
- return true;
- });
- }
-
-protected:
-private:
- TyTyResolver (Analysis::Mappings *mappings, Resolver *resolver,
- TypeCheckContext *context)
- : mappings (mappings), resolver (resolver), context (context)
- {}
-
- Analysis::Mappings *mappings;
- Resolver *resolver;
- TypeCheckContext *context;
-};
-
-class TyTyExtractorArray : public TyTy::TyVisitor
-{
-public:
- static TyTy::TyBase *ExtractElementTypeFromArray (TyTy::TyBase *base)
- {
- TyTyExtractorArray e;
- base->accept_vis (e);
- rust_assert (e.extracted != nullptr);
- return e.extracted;
- }
-
- virtual ~TyTyExtractorArray () {}
-
- void visit (TyTy::UnitType &type) override { gcc_unreachable (); }
- void visit (TyTy::InferType &type) override { gcc_unreachable (); }
- void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); }
- void visit (TyTy::ADTType &type) override { gcc_unreachable (); }
- void visit (TyTy::ParamType &type) override { gcc_unreachable (); }
- void visit (TyTy::FnType &type) override { gcc_unreachable (); }
- void visit (TyTy::BoolType &type) override { gcc_unreachable (); }
- void visit (TyTy::IntType &type) override { gcc_unreachable (); }
- void visit (TyTy::UintType &type) override { gcc_unreachable (); }
- void visit (TyTy::FloatType &type) override { gcc_unreachable (); }
- void visit (TyTy::ErrorType &type) override { gcc_unreachable (); }
-
- void visit (TyTy::ArrayType &type) override { extracted = type.get_type (); }
-
-private:
- TyTyExtractorArray () : extracted (nullptr) {}
-
- TyTy::TyBase *extracted;
-};
-
-} // namespace Resolver
-} // namespace Rust
-
-#endif // RUST_TYTY_RESOLVER
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index 677013f..be58805 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -23,6 +23,7 @@
#include "rust-tyty.h"
#include "rust-tyty-visitor.h"
#include "rust-hir-map.h"
+#include "rust-hir-type-check.h"
namespace Rust {
namespace TyTy {
@@ -32,342 +33,702 @@ class BaseRules : public TyVisitor
public:
virtual ~BaseRules () {}
+ TyBase *combine (TyBase *other)
+ {
+ other->accept_vis (*this);
+ if (resolved != nullptr)
+ {
+ resolved->append_reference (base->get_ref ());
+ resolved->append_reference (other->get_ref ());
+ for (auto ref : base->get_combined_refs ())
+ resolved->append_reference (ref);
+ for (auto ref : other->get_combined_refs ())
+ resolved->append_reference (ref);
+
+ bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER;
+ if (result_resolved)
+ {
+ for (auto &ref : resolved->get_combined_refs ())
+ {
+ TyTy::TyBase *ref_tyty = nullptr;
+ bool ok = context->lookup_type (ref, &ref_tyty);
+ if (!ok)
+ continue;
+
+ // if any of the types are inference variables lets fix them
+ if (ref_tyty->get_kind () == TyTy::TypeKind::INFER)
+ {
+ NodeId ref_node_id = UNKNOWN_NODEID;
+ context->insert_type (
+ Analysis::NodeMapping (mappings->get_current_crate (),
+ ref_node_id, ref,
+ UNKNOWN_LOCAL_DEFID),
+ resolved->clone ());
+ }
+ }
+ }
+ }
+ return resolved;
+ }
+
virtual void visit (UnitType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_fatal_error (def_locus, "declared here");
}
- virtual void visit (ADTType &type) override
+ virtual void visit (TupleType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_fatal_error (def_locus, "declared here");
}
- virtual void visit (InferType &type) override
+ virtual void visit (ADTType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_fatal_error (def_locus, "declared here");
}
- virtual void visit (FnType &type) override
+ virtual void visit (InferType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_fatal_error (def_locus, "declared here");
}
- virtual void visit (ParamType &type) override
+ virtual void visit (FnType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_fatal_error (def_locus, "declared here");
}
virtual void visit (ArrayType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_fatal_error (def_locus, "declared here");
}
virtual void visit (BoolType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_fatal_error (def_locus, "declared here");
}
virtual void visit (IntType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_fatal_error (def_locus, "declared here");
}
virtual void visit (UintType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_fatal_error (def_locus, "declared here");
+ }
+
+ virtual void visit (USizeType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ rust_error_at (ref_locus, "expected [%s] got [%s]",
+ base->as_string ().c_str (), type.as_string ().c_str ());
+ }
+
+ virtual void visit (ISizeType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ rust_error_at (ref_locus, "expected [%s] got [%s]",
+ base->as_string ().c_str (), type.as_string ().c_str ());
}
virtual void visit (FloatType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_fatal_error (def_locus, "declared here");
}
virtual void visit (ErrorType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_fatal_error (def_locus, "declared here");
}
virtual void visit (StructFieldType &type) override
{
Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location def_locus = mappings->lookup_location (base->get_ref ());
rust_error_at (ref_locus, "expected [%s] got [%s]",
base->as_string ().c_str (), type.as_string ().c_str ());
- rust_fatal_error (def_locus, "declared here");
}
protected:
BaseRules (TyBase *base)
- : mappings (Analysis::Mappings::get ()), base (base),
- resolved (new ErrorType (base->get_ref ()))
+ : mappings (Analysis::Mappings::get ()),
+ context (Resolver::TypeCheckContext::get ()), base (base),
+ resolved (new ErrorType (base->get_ref (), base->get_ref ()))
{}
Analysis::Mappings *mappings;
+ Resolver::TypeCheckContext *context;
+
TyBase *base;
TyBase *resolved;
};
-class InferRules : protected BaseRules
+class InferRules : public BaseRules
{
public:
InferRules (InferType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
- {
- other->accept_vis (*this);
- return resolved;
- }
-
- // we are an inference variable so this means we can take the other as the
- // type
void visit (UnitType &type) override
{
- resolved = new UnitType (type.get_ref ());
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
}
void visit (BoolType &type) override
{
- resolved = new BoolType (type.get_ref ());
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
}
void visit (IntType &type) override
{
- resolved = new IntType (type.get_ref (), type.get_kind ());
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
+ || (base->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
}
void visit (UintType &type) override
{
- resolved = new UintType (type.get_ref (), type.get_kind ());
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
+ || (base->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
+ }
+
+ void visit (USizeType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
+ || (base->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
+ }
+
+ void visit (ISizeType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
+ || (base->get_infer_kind ()
+ == TyTy::InferType::InferTypeKind::INTEGRAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
+ }
+
+ void visit (FloatType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
+ || (base->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
+ }
+
+ void visit (ArrayType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
+ }
+
+ void visit (ADTType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
+ }
+
+ void visit (TupleType &type) override
+ {
+ bool is_valid
+ = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
+ if (is_valid)
+ {
+ resolved = type.clone ();
+ return;
+ }
+
+ BaseRules::visit (type);
+ }
+
+ void visit (InferType &type) override
+ {
+ switch (base->get_infer_kind ())
+ {
+ case InferType::InferTypeKind::GENERAL:
+ resolved = type.clone ();
+ return;
+
+ case InferType::InferTypeKind::INTEGRAL: {
+ if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
+ {
+ resolved = type.clone ();
+ return;
+ }
+ else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
+ {
+ resolved = base->clone ();
+ return;
+ }
+ }
+ break;
+
+ case InferType::InferTypeKind::FLOAT: {
+ if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
+ {
+ resolved = type.clone ();
+ return;
+ }
+ else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
+ {
+ resolved = base->clone ();
+ return;
+ }
+ }
+ break;
+ }
+
+ BaseRules::visit (type);
}
private:
InferType *base;
};
-class StructFieldTypeRules : protected BaseRules
+class StructFieldTypeRules : public BaseRules
{
public:
StructFieldTypeRules (StructFieldType *base) : BaseRules (base), base (base)
{}
- TyBase *combine (TyBase *other)
+ void visit (StructFieldType &type)
{
- other->accept_vis (*this);
- return resolved;
+ TyBase *ty = base->get_field_type ()->combine (type.get_field_type ());
+ if (ty == nullptr)
+ return;
+
+ resolved = new TyTy::StructFieldType (type.get_ref (), type.get_ty_ref (),
+ type.get_name (), ty);
}
private:
StructFieldType *base;
};
-class UnitRules : protected BaseRules
+class UnitRules : public BaseRules
{
public:
UnitRules (UnitType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
+ void visit (UnitType &type) override
{
- other->accept_vis (*this);
- return resolved;
+ resolved = new UnitType (type.get_ref (), type.get_ty_ref ());
}
- void visit (IntType &type) override { rust_assert (false); }
-
private:
UnitType *base;
};
-class FnRules : protected BaseRules
+class FnRules : public BaseRules
{
public:
FnRules (FnType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
+ void visit (InferType &type) override
{
- other->accept_vis (*this);
- return resolved;
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
}
-private:
- FnType *base;
-};
+ void visit (FnType &type) override
+ {
+ if (base->num_params () != type.num_params ())
+ {
+ BaseRules::visit (type);
+ return;
+ }
-class ParamRules : protected BaseRules
-{
-public:
- ParamRules (ParamType *base) : BaseRules (base), base (base) {}
+ // FIXME add an abstract method for is_equal on TyBase
+ for (size_t i = 0; i < base->num_params (); i++)
+ {
+ auto a = base->param_at (i).second;
+ auto b = type.param_at (i).second;
+
+ auto combined_param = a->combine (b);
+ if (combined_param == nullptr)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+ }
- TyBase *combine (TyBase *other)
- {
- // we only case about the base type of a param
- return base->get_base_type ()->combine (other);
+ auto combined_return
+ = base->get_return_type ()->combine (type.get_return_type ());
+ if (combined_return == nullptr)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
}
private:
- ParamType *base;
+ FnType *base;
};
-class ArrayRules : protected BaseRules
+class ArrayRules : public BaseRules
{
public:
ArrayRules (ArrayType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
- {
- other->accept_vis (*this);
- return resolved;
- }
-
void visit (ArrayType &type) override
{
// check base type
auto base_resolved = base->get_type ()->combine (type.get_type ());
if (base_resolved == nullptr)
- return;
+ {
+ // fixme add error message
+ return;
+ }
// need to check the base types and capacity
if (type.get_capacity () != base->get_capacity ())
{
Location locus = mappings->lookup_location (type.get_ref ());
rust_error_at (locus, "mismatch in array capacity");
+ BaseRules::visit (type);
return;
}
- resolved
- = new ArrayType (type.get_ref (), type.get_capacity (), base_resolved);
+ resolved = new ArrayType (type.get_ref (), type.get_ty_ref (),
+ type.get_capacity (), base_resolved);
}
private:
ArrayType *base;
};
-class BoolRules : protected BaseRules
+class BoolRules : public BaseRules
{
public:
BoolRules (BoolType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
- {
- other->accept_vis (*this);
- return resolved;
- }
-
void visit (BoolType &type) override
{
- resolved = new BoolType (type.get_ref ());
+ resolved = new BoolType (type.get_ref (), type.get_ty_ref ());
}
private:
BoolType *base;
};
-class IntRules : protected BaseRules
+class IntRules : public BaseRules
{
public:
IntRules (IntType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
+ void visit (InferType &type) override
{
- other->accept_vis (*this);
- return resolved;
+ // cant assign a float inference variable
+ if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
}
void visit (IntType &type) override
{
- // FIXME we should look at the IntTypeKind and check if i8 vs i16 etc..
- resolved = new IntType (type.get_ref (), type.get_kind ());
+ if (type.get_kind () != base->get_kind ())
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved
+ = new IntType (type.get_ref (), type.get_ty_ref (), type.get_kind ());
}
private:
IntType *base;
};
-class UintRules : protected BaseRules
+class UintRules : public BaseRules
{
public:
UintRules (UintType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
+ void visit (InferType &type) override
{
- other->accept_vis (*this);
- return resolved;
+ // cant assign a float inference variable
+ if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
}
void visit (UintType &type) override
{
- // FIXME we should look at the IntTypeKind and check if u8 vs u16 etc..
- resolved = new UintType (type.get_ref (), type.get_kind ());
+ if (type.get_kind () != base->get_kind ())
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved
+ = new UintType (type.get_ref (), type.get_ty_ref (), type.get_kind ());
}
private:
UintType *base;
};
-class FloatRules : protected BaseRules
+class FloatRules : public BaseRules
{
public:
FloatRules (FloatType *base) : BaseRules (base), base (base) {}
- TyBase *combine (TyBase *other)
+ void visit (InferType &type) override
{
- other->accept_vis (*this);
- return resolved;
+ if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
}
void visit (FloatType &type) override
{
- // FIXME we should look at the FloatKind and respect it
- resolved = new FloatType (type.get_ref (), type.get_kind ());
+ if (type.get_kind () != base->get_kind ())
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved
+ = new FloatType (type.get_ref (), type.get_ty_ref (), type.get_kind ());
}
private:
FloatType *base;
};
+class ADTRules : public BaseRules
+{
+public:
+ ADTRules (ADTType *base) : BaseRules (base), base (base) {}
+
+ void visit (ADTType &type)
+ {
+ if (base->num_fields () != type.num_fields ())
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ std::vector<TyTy::StructFieldType *> fields;
+ for (size_t i = 0; i < type.num_fields (); ++i)
+ {
+ TyTy::StructFieldType *base_field = base->get_field (i);
+ TyTy::StructFieldType *other_field = type.get_field (i);
+
+ TyBase *combined = base_field->combine (other_field);
+ if (combined == nullptr)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ fields.push_back ((TyTy::StructFieldType *) combined);
+ }
+
+ resolved = new TyTy::ADTType (type.get_ref (), type.get_ty_ref (),
+ type.get_name (), fields);
+ }
+
+private:
+ ADTType *base;
+};
+
+class TupleRules : public BaseRules
+{
+public:
+ TupleRules (TupleType *base) : BaseRules (base), base (base) {}
+
+ void visit (TupleType &type)
+ {
+ if (base->num_fields () != type.num_fields ())
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ std::vector<HirId> fields;
+ for (size_t i = 0; i < base->num_fields (); i++)
+ {
+ TyBase *bo = base->get_field (i);
+ TyBase *fo = type.get_field (i);
+
+ TyBase *combined = bo->combine (fo);
+ if (combined == nullptr)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ fields.push_back (combined->get_ref ());
+ }
+
+ resolved
+ = new TyTy::TupleType (type.get_ref (), type.get_ty_ref (), fields);
+ }
+
+private:
+ TupleType *base;
+};
+
+class USizeRules : public BaseRules
+{
+public:
+ USizeRules (USizeType *base) : BaseRules (base), base (base) {}
+
+ void visit (InferType &type) override
+ {
+ // cant assign a float inference variable
+ if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+ void visit (USizeType &type) override { resolved = type.clone (); }
+
+private:
+ USizeType *base;
+};
+
+class ISizeRules : public BaseRules
+{
+public:
+ ISizeRules (ISizeType *base) : BaseRules (base), base (base) {}
+
+ void visit (InferType &type) override
+ {
+ // cant assign a float inference variable
+ if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ resolved->set_ref (type.get_ref ());
+ }
+
+ void visit (ISizeType &type) override { resolved = type.clone (); }
+
+private:
+ ISizeType *base;
+};
+
} // namespace TyTy
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h
index def43cd..6ae0e80 100644
--- a/gcc/rust/typecheck/rust-tyty-visitor.h
+++ b/gcc/rust/typecheck/rust-tyty-visitor.h
@@ -31,13 +31,15 @@ public:
virtual void visit (InferType &type) = 0;
virtual void visit (StructFieldType &type) = 0;
virtual void visit (ADTType &type) = 0;
+ virtual void visit (TupleType &type) = 0;
virtual void visit (FnType &type) = 0;
- virtual void visit (ParamType &type) = 0;
virtual void visit (ArrayType &type) = 0;
virtual void visit (BoolType &type) = 0;
virtual void visit (IntType &type) = 0;
virtual void visit (UintType &type) = 0;
virtual void visit (FloatType &type) = 0;
+ virtual void visit (USizeType &type) = 0;
+ virtual void visit (ISizeType &type) = 0;
virtual void visit (ErrorType &type) = 0;
};
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 033f839..d506415 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -44,6 +44,12 @@ UnitType::combine (TyBase *other)
return r.combine (other);
}
+TyBase *
+UnitType::clone ()
+{
+ return new UnitType (get_ref (), get_ty_ref (), get_combined_refs ());
+}
+
void
InferType::accept_vis (TyVisitor &vis)
{
@@ -53,7 +59,16 @@ InferType::accept_vis (TyVisitor &vis)
std::string
InferType::as_string () const
{
- return "[_]";
+ switch (infer_kind)
+ {
+ case GENERAL:
+ return "T?";
+ case INTEGRAL:
+ return "<integer>";
+ case FLOAT:
+ return "<float>";
+ }
+ return "<infer::error>";
}
TyBase *
@@ -63,6 +78,13 @@ InferType::combine (TyBase *other)
return r.combine (other);
}
+TyBase *
+InferType::clone ()
+{
+ return new InferType (get_ref (), get_ty_ref (), get_infer_kind (),
+ get_combined_refs ());
+}
+
void
ErrorType::accept_vis (TyVisitor &vis)
{
@@ -78,10 +100,17 @@ ErrorType::as_string () const
TyBase *
ErrorType::combine (TyBase *other)
{
+ // FIXME
// rust_error_at ();
return this;
}
+TyBase *
+ErrorType::clone ()
+{
+ return new ErrorType (get_ref (), get_ty_ref (), get_combined_refs ());
+}
+
void
StructFieldType::accept_vis (TyVisitor &vis)
{
@@ -101,6 +130,14 @@ StructFieldType::combine (TyBase *other)
return r.combine (other);
}
+TyBase *
+StructFieldType::clone ()
+{
+ return new StructFieldType (get_ref (), get_ty_ref (), get_name (),
+ get_field_type ()->clone (),
+ get_combined_refs ());
+}
+
void
ADTType::accept_vis (TyVisitor &vis)
{
@@ -110,17 +147,74 @@ ADTType::accept_vis (TyVisitor &vis)
std::string
ADTType::as_string () const
{
+ if (num_fields () == 0)
+ return identifier;
+
std::string fields_buffer;
for (auto &field : fields)
- fields_buffer += field->as_string () + "\n";
+ fields_buffer += field->as_string () + ", ";
- return identifier + "{\n" + fields_buffer + "\n}";
+ return identifier + "{" + fields_buffer + "}";
}
TyBase *
ADTType::combine (TyBase *other)
{
- return nullptr;
+ ADTRules r (this);
+ return r.combine (other);
+}
+
+TyBase *
+ADTType::clone ()
+{
+ std::vector<StructFieldType *> cloned_fields;
+ for (auto &f : fields)
+ cloned_fields.push_back ((StructFieldType *) f->clone ());
+
+ return new ADTType (get_ref (), get_ty_ref (), get_name (), cloned_fields,
+ get_combined_refs ());
+}
+
+void
+TupleType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+std::string
+TupleType::as_string () const
+{
+ std::string fields_buffer;
+ iterate_fields ([&] (TyBase *field) mutable -> bool {
+ fields_buffer += field->as_string ();
+ fields_buffer += ", ";
+ return true;
+ });
+ return "(" + fields_buffer + ")";
+}
+
+TyBase *
+TupleType::get_field (size_t index) const
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ TyBase *lookup = nullptr;
+ bool ok = context->lookup_type (fields.at (index), &lookup);
+ rust_assert (ok);
+ return lookup;
+}
+
+TyBase *
+TupleType::combine (TyBase *other)
+{
+ TupleRules r (this);
+ return r.combine (other);
+}
+
+TyBase *
+TupleType::clone ()
+{
+ return new TupleType (get_ref (), get_ty_ref (), fields,
+ get_combined_refs ());
}
void
@@ -135,7 +229,9 @@ FnType::as_string () const
std::string params_str = "";
for (auto &param : params)
{
- params_str += param->as_string ();
+ auto pattern = param.first;
+ auto ty = param.second;
+ params_str += pattern->as_string () + " " + ty->as_string ();
params_str += ",";
}
@@ -150,23 +246,16 @@ FnType::combine (TyBase *other)
return r.combine (other);
}
-void
-ParamType::accept_vis (TyVisitor &vis)
-{
- vis.visit (*this);
-}
-
-std::string
-ParamType::as_string () const
-{
- return "(" + identifier + " :" + type->as_string () + ")";
-}
-
TyBase *
-ParamType::combine (TyBase *other)
+FnType::clone ()
{
- ParamRules r (this);
- return r.combine (other);
+ std::vector<std::pair<HIR::Pattern *, TyBase *> > cloned_params;
+ for (auto &p : params)
+ cloned_params.push_back (
+ std::pair<HIR::Pattern *, TyBase *> (p.first, p.second->clone ()));
+
+ return new FnType (get_ref (), get_ty_ref (), cloned_params,
+ get_return_type ()->clone (), get_combined_refs ());
}
void
@@ -178,7 +267,8 @@ ArrayType::accept_vis (TyVisitor &vis)
std::string
ArrayType::as_string () const
{
- return "[" + type->as_string () + ":" + std::to_string (capacity) + "]";
+ return "[" + get_type ()->as_string () + ":" + std::to_string (capacity)
+ + "]";
}
TyBase *
@@ -188,6 +278,23 @@ ArrayType::combine (TyBase *other)
return r.combine (other);
}
+TyBase *
+ArrayType::get_type () const
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ TyBase *lookup = nullptr;
+ bool ok = context->lookup_type (element_type_id, &lookup);
+ rust_assert (ok);
+ return lookup;
+}
+
+TyBase *
+ArrayType::clone ()
+{
+ return new ArrayType (get_ref (), get_ty_ref (), get_capacity (),
+ get_type ()->clone (), get_combined_refs ());
+}
+
void
BoolType::accept_vis (TyVisitor &vis)
{
@@ -207,6 +314,12 @@ BoolType::combine (TyBase *other)
return r.combine (other);
}
+TyBase *
+BoolType::clone ()
+{
+ return new BoolType (get_ref (), get_ty_ref (), get_combined_refs ());
+}
+
void
IntType::accept_vis (TyVisitor &vis)
{
@@ -240,6 +353,13 @@ IntType::combine (TyBase *other)
return r.combine (other);
}
+TyBase *
+IntType::clone ()
+{
+ return new IntType (get_ref (), get_ty_ref (), get_kind (),
+ get_combined_refs ());
+}
+
void
UintType::accept_vis (TyVisitor &vis)
{
@@ -273,6 +393,13 @@ UintType::combine (TyBase *other)
return r.combine (other);
}
+TyBase *
+UintType::clone ()
+{
+ return new UintType (get_ref (), get_ty_ref (), get_kind (),
+ get_combined_refs ());
+}
+
void
FloatType::accept_vis (TyVisitor &vis)
{
@@ -300,37 +427,151 @@ FloatType::combine (TyBase *other)
return r.combine (other);
}
+TyBase *
+FloatType::clone ()
+{
+ return new FloatType (get_ref (), get_ty_ref (), get_kind (),
+ get_combined_refs ());
+}
+
void
-TypeCheckCallExpr::visit (FnType &type)
+USizeType::accept_vis (TyVisitor &vis)
{
- if (call.num_params () != type.num_params ())
+ vis.visit (*this);
+}
+
+std::string
+USizeType::as_string () const
+{
+ return "usize";
+}
+
+TyBase *
+USizeType::combine (TyBase *other)
+{
+ USizeRules r (this);
+ return r.combine (other);
+}
+
+TyBase *
+USizeType::clone ()
+{
+ return new USizeType (get_ref (), get_ty_ref (), get_combined_refs ());
+}
+
+void
+ISizeType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+std::string
+ISizeType::as_string () const
+{
+ return "isize";
+}
+
+TyBase *
+ISizeType::combine (TyBase *other)
+{
+ ISizeRules r (this);
+ return r.combine (other);
+}
+
+TyBase *
+ISizeType::clone ()
+{
+ return new ISizeType (get_ref (), get_ty_ref (), get_combined_refs ());
+}
+
+void
+TypeCheckCallExpr::visit (ADTType &type)
+{
+ if (call.num_params () != type.num_fields ())
{
- rust_error_at (call.get_locus (), "differing number of arguments");
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu",
+ call.num_params (), type.num_fields ());
return;
}
size_t i = 0;
call.iterate_params ([&] (HIR::Expr *p) mutable -> bool {
- TyBase *pt = type.param_at (i);
- auto t = Resolver::TypeCheckExpr::Resolve (p);
- if (t == nullptr)
+ StructFieldType *field = type.get_field (i);
+ TyBase *field_tyty = field->get_field_type ();
+
+ TyBase *arg = Resolver::TypeCheckExpr::Resolve (p);
+ if (arg == nullptr)
{
- rust_error_at (p->get_locus_slow (), "failed to resolve type");
+ rust_error_at (p->get_locus_slow (), "failed to resolve argument type");
return false;
}
- auto res = pt->combine (t);
+ auto res = field_tyty->combine (arg);
if (res == nullptr)
return false;
+ delete res;
i++;
return true;
});
if (i != call.num_params ())
- return;
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu", i,
+ call.num_params ());
+ return;
+ }
+
+ resolved = type.clone ();
+}
+
+void
+TypeCheckCallExpr::visit (FnType &type)
+{
+ if (call.num_params () != type.num_params ())
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu",
+ call.num_params (), type.num_params ());
+ return;
+ }
+
+ size_t i = 0;
+ call.iterate_params ([&] (HIR::Expr *param) mutable -> bool {
+ auto fnparam = type.param_at (i);
+ auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (param);
+ if (argument_expr_tyty == nullptr)
+ {
+ rust_error_at (param->get_locus_slow (),
+ "failed to resolve type for argument expr in CallExpr");
+ return false;
+ }
+
+ auto resolved_argument_type = fnparam.second->combine (argument_expr_tyty);
+ if (resolved_argument_type == nullptr)
+ {
+ rust_error_at (param->get_locus_slow (),
+ "Type Resolution failure on parameter");
+ return false;
+ }
+
+ context->insert_type (param->get_mappings (), resolved_argument_type);
+
+ i++;
+ return true;
+ });
+
+ if (i != call.num_params ())
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu", i,
+ call.num_params ());
+ return;
+ }
- resolved = type.get_return_type ();
+ resolved = type.get_return_type ()->clone ();
}
} // namespace TyTy
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index be7ec0c..860ef96 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -24,6 +24,7 @@
namespace Rust {
namespace TyTy {
+// https://rustc-dev-guide.rust-lang.org/type-inference.html#inference-variables
// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variants
enum TypeKind
{
@@ -42,6 +43,8 @@ enum TypeKind
FLOAT,
UNIT,
FIELD,
+ USIZE,
+ ISIZE,
// there are more to add...
ERROR
};
@@ -54,6 +57,12 @@ public:
HirId get_ref () const { return ref; }
+ void set_ref (HirId id) { ref = id; }
+
+ HirId get_ty_ref () const { return ty_ref; }
+
+ void set_ty_ref (HirId id) { ty_ref = id; }
+
virtual void accept_vis (TyVisitor &vis) = 0;
virtual std::string as_string () const = 0;
@@ -64,17 +73,44 @@ public:
TypeKind get_kind () const { return kind; }
+ virtual TyBase *clone () = 0;
+
+ std::set<HirId> get_combined_refs () { return combined; }
+
+ void append_reference (HirId id) { combined.insert (id); }
+
protected:
- TyBase (HirId ref, TypeKind kind) : kind (kind), ref (ref) {}
+ TyBase (HirId ref, HirId ty_ref, TypeKind kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : kind (kind), ref (ref), ty_ref (ty_ref), combined (refs)
+ {}
TypeKind kind;
HirId ref;
+ HirId ty_ref;
+
+ std::set<HirId> combined;
};
class InferType : public TyBase
{
public:
- InferType (HirId ref) : TyBase (ref, TypeKind::INFER) {}
+ enum InferTypeKind
+ {
+ GENERAL,
+ INTEGRAL,
+ FLOAT
+ };
+
+ InferType (HirId ref, InferTypeKind infer_kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::INFER, refs), infer_kind (infer_kind)
+ {}
+
+ InferType (HirId ref, HirId ty_ref, InferTypeKind infer_kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::INFER, refs), infer_kind (infer_kind)
+ {}
void accept_vis (TyVisitor &vis) override;
@@ -83,12 +119,25 @@ public:
std::string as_string () const override;
TyBase *combine (TyBase *other) override;
+
+ TyBase *clone () final override;
+
+ InferTypeKind get_infer_kind () const { return infer_kind; }
+
+private:
+ InferTypeKind infer_kind;
};
class ErrorType : public TyBase
{
public:
- ErrorType (HirId ref) : TyBase (ref, TypeKind::ERROR) {}
+ ErrorType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::ERROR, refs)
+ {}
+
+ ErrorType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::ERROR, refs)
+ {}
void accept_vis (TyVisitor &vis) override;
@@ -97,12 +146,20 @@ public:
std::string as_string () const override;
TyBase *combine (TyBase *other) override;
+
+ TyBase *clone () final override;
};
class UnitType : public TyBase
{
public:
- UnitType (HirId ref) : TyBase (ref, TypeKind::UNIT) {}
+ UnitType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::UNIT, refs)
+ {}
+
+ UnitType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::UNIT, refs)
+ {}
void accept_vis (TyVisitor &vis) override;
@@ -111,13 +168,21 @@ public:
std::string as_string () const override;
TyBase *combine (TyBase *other) override;
+
+ TyBase *clone () final override;
};
class StructFieldType : public TyBase
{
public:
- StructFieldType (HirId ref, std::string name, TyBase *ty)
- : TyBase (ref, TypeKind::FIELD), name (name), ty (ty)
+ StructFieldType (HirId ref, std::string name, TyBase *ty,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::FIELD, refs), name (name), ty (ty)
+ {}
+
+ StructFieldType (HirId ref, HirId ty_ref, std::string name, TyBase *ty,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::FIELD, refs), name (name), ty (ty)
{}
void accept_vis (TyVisitor &vis) override;
@@ -132,17 +197,24 @@ public:
TyBase *get_field_type () { return ty; }
+ TyBase *clone () final override;
+
private:
std::string name;
TyBase *ty;
};
-class ADTType : public TyBase
+class TupleType : public TyBase
{
public:
- ADTType (HirId ref, std::string identifier,
- std::vector<StructFieldType *> fields)
- : TyBase (ref, TypeKind::ADT), identifier (identifier), fields (fields)
+ TupleType (HirId ref, std::vector<HirId> fields,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::TUPLE, refs), fields (fields)
+ {}
+
+ TupleType (HirId ref, HirId ty_ref, std::vector<HirId> fields,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::TUPLE, refs), fields (fields)
{}
void accept_vis (TyVisitor &vis) override;
@@ -155,50 +227,103 @@ public:
size_t num_fields () const { return fields.size (); }
- StructFieldType *get_field (size_t index) { return fields.at (index); }
+ TyBase *get_field (size_t index) const;
- StructFieldType *get_field (const std::string &lookup)
+ TyBase *clone () final override;
+
+ void iterate_fields (std::function<bool (TyBase *)> cb) const
{
- for (auto &field : fields)
+ for (size_t i = 0; i < num_fields (); i++)
{
- if (field->get_name ().compare (lookup) == 0)
- return field;
+ if (!cb (get_field (i)))
+ return;
}
- return nullptr;
}
private:
- std::string identifier;
- std::vector<StructFieldType *> fields;
+ std::vector<HirId> fields;
};
-class ParamType : public TyBase
+class ADTType : public TyBase
{
public:
- ParamType (HirId ref, std::string identifier, TyBase *type)
- : TyBase (ref, TypeKind::PARAM), identifier (identifier), type (type)
+ ADTType (HirId ref, std::string identifier,
+ std::vector<StructFieldType *> fields,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::ADT, refs), identifier (identifier),
+ fields (fields)
+ {}
+
+ ADTType (HirId ref, HirId ty_ref, std::string identifier,
+ std::vector<StructFieldType *> fields,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::ADT, refs), 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;
- std::string get_identifier () const { return identifier; }
+ size_t num_fields () const { return fields.size (); }
+
+ std::string get_name () const { return identifier; }
+
+ StructFieldType *get_field (size_t index) { return fields.at (index); }
+
+ StructFieldType *get_field (const std::string &lookup,
+ size_t *index = nullptr)
+ {
+ size_t i = 0;
+ for (auto &field : fields)
+ {
+ if (field->get_name ().compare (lookup) == 0)
+ {
+ if (index != nullptr)
+ *index = i;
+ return field;
+ }
+ i++;
+ }
+ return nullptr;
+ }
+
+ TyBase *clone () final override;
+
+ std::vector<StructFieldType *> &get_fields () { return fields; }
+ const std::vector<StructFieldType *> &get_fields () const { return fields; }
- TyBase *get_base_type () { return type; }
+ void iterate_fields (std::function<bool (StructFieldType *)> cb)
+ {
+ for (auto &f : fields)
+ {
+ if (!cb (f))
+ return;
+ }
+ }
private:
std::string identifier;
- TyBase *type;
+ std::vector<StructFieldType *> fields;
};
class FnType : public TyBase
{
public:
- FnType (HirId ref, std::vector<ParamType *> params, TyBase *type)
- : TyBase (ref, TypeKind::FNDEF), params (params), type (type)
+ FnType (HirId ref, std::vector<std::pair<HIR::Pattern *, TyBase *> > params,
+ TyBase *type, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::FNDEF, refs), params (std::move (params)),
+ type (type)
+ {}
+
+ FnType (HirId ref, HirId ty_ref,
+ std::vector<std::pair<HIR::Pattern *, TyBase *> > params,
+ TyBase *type, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::FNDEF, refs), params (params), type (type)
{}
void accept_vis (TyVisitor &vis) override;
@@ -211,20 +336,38 @@ public:
size_t num_params () const { return params.size (); }
- ParamType *param_at (size_t idx) { return params[idx]; }
+ std::vector<std::pair<HIR::Pattern *, TyBase *> > &get_params ()
+ {
+ return params;
+ }
+
+ std::pair<HIR::Pattern *, TyBase *> &param_at (size_t idx)
+ {
+ return params[idx];
+ }
TyBase *get_return_type () { return type; }
+ TyBase *clone () final override;
+
private:
- std::vector<ParamType *> params;
+ std::vector<std::pair<HIR::Pattern *, TyBase *> > params;
TyBase *type;
};
class ArrayType : public TyBase
{
public:
- ArrayType (HirId ref, size_t capacity, TyBase *type)
- : TyBase (ref, TypeKind::ARRAY), capacity (capacity), type (type)
+ ArrayType (HirId ref, size_t capacity, TyBase *type,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::ARRAY, refs), capacity (capacity),
+ element_type_id (type->get_ref ())
+ {}
+
+ ArrayType (HirId ref, HirId ty_ref, size_t capacity, TyBase *type,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::ARRAY, refs), capacity (capacity),
+ element_type_id (type->get_ref ())
{}
void accept_vis (TyVisitor &vis) override;
@@ -235,23 +378,35 @@ public:
size_t get_capacity () const { return capacity; }
- TyBase *get_type () { return type; }
+ HirId element_type_ref () const { return element_type_id; }
+
+ TyBase *get_type () const;
+
+ TyBase *clone () final override;
private:
size_t capacity;
- TyBase *type;
+ HirId element_type_id;
};
class BoolType : public TyBase
{
public:
- BoolType (HirId ref) : TyBase (ref, TypeKind::BOOL) {}
+ BoolType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::BOOL, refs)
+ {}
+
+ BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::BOOL, refs)
+ {}
void accept_vis (TyVisitor &vis) override;
std::string as_string () const override;
TyBase *combine (TyBase *other) override;
+
+ TyBase *clone () final override;
};
class IntType : public TyBase
@@ -266,8 +421,13 @@ public:
I128
};
- IntType (HirId ref, IntKind kind)
- : TyBase (ref, TypeKind::INT), int_kind (kind)
+ IntType (HirId ref, IntKind kind, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::INT, refs), int_kind (kind)
+ {}
+
+ IntType (HirId ref, HirId ty_ref, IntKind kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::INT, refs), int_kind (kind)
{}
void accept_vis (TyVisitor &vis) override;
@@ -278,6 +438,8 @@ public:
IntKind get_kind () const { return int_kind; }
+ TyBase *clone () final override;
+
private:
IntKind int_kind;
};
@@ -294,8 +456,13 @@ public:
U128
};
- UintType (HirId ref, UintKind kind)
- : TyBase (ref, TypeKind::UINT), uint_kind (kind)
+ UintType (HirId ref, UintKind kind, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::UINT, refs), uint_kind (kind)
+ {}
+
+ UintType (HirId ref, HirId ty_ref, UintKind kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::UINT, refs), uint_kind (kind)
{}
void accept_vis (TyVisitor &vis) override;
@@ -306,6 +473,8 @@ public:
UintKind get_kind () const { return uint_kind; }
+ TyBase *clone () final override;
+
private:
UintKind uint_kind;
};
@@ -319,8 +488,14 @@ public:
F64
};
- FloatType (HirId ref, FloatKind kind)
- : TyBase (ref, TypeKind::FLOAT), float_kind (kind)
+ FloatType (HirId ref, FloatKind kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::FLOAT, refs), float_kind (kind)
+ {}
+
+ FloatType (HirId ref, HirId ty_ref, FloatKind kind,
+ std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::FLOAT, refs), float_kind (kind)
{}
void accept_vis (TyVisitor &vis) override;
@@ -331,10 +506,52 @@ public:
FloatKind get_kind () const { return float_kind; }
+ TyBase *clone () final override;
+
private:
FloatKind float_kind;
};
+class USizeType : public TyBase
+{
+public:
+ USizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::USIZE)
+ {}
+
+ USizeType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::USIZE)
+ {}
+
+ void accept_vis (TyVisitor &vis) override;
+
+ std::string as_string () const override;
+
+ TyBase *combine (TyBase *other) override;
+
+ TyBase *clone () final override;
+};
+
+class ISizeType : public TyBase
+{
+public:
+ ISizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ref, TypeKind::ISIZE)
+ {}
+
+ ISizeType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ())
+ : TyBase (ref, ty_ref, TypeKind::ISIZE)
+ {}
+
+ void accept_vis (TyVisitor &vis) override;
+
+ std::string as_string () const override;
+
+ TyBase *combine (TyBase *other) override;
+
+ TyBase *clone () final override;
+};
+
} // namespace TyTy
} // namespace Rust
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 0fea501..925130f 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -159,6 +159,7 @@ Mappings::get_next_hir_id (CrateNum crateNum)
auto id = it->second + 1;
hirIdIter[crateNum] = id;
+ hirNodesWithinCrate[crateNum].insert (id);
return id;
}
@@ -332,7 +333,7 @@ Mappings::insert_hir_param (CrateNum crateNum, HirId id,
rust_assert (lookup_hir_stmt (crateNum, id) == nullptr);
hirParamMappings[crateNum][id] = param;
- nodeIdToHirMappings[crateNum][param->get_mappings ()->get_nodeid ()] = id;
+ nodeIdToHirMappings[crateNum][param->get_mappings ().get_nodeid ()] = id;
}
HIR::FunctionParam *
@@ -350,6 +351,30 @@ Mappings::lookup_hir_param (CrateNum crateNum, HirId id)
}
void
+Mappings::insert_hir_struct_field (CrateNum crateNum, HirId id,
+ HIR::StructExprField *field)
+{
+ rust_assert (lookup_hir_stmt (crateNum, id) == nullptr);
+
+ hirStructFieldMappings[crateNum][id] = field;
+ nodeIdToHirMappings[crateNum][field->get_mappings ().get_nodeid ()] = id;
+}
+
+HIR::StructExprField *
+Mappings::lookup_hir_struct_field (CrateNum crateNum, HirId id)
+{
+ auto it = hirStructFieldMappings.find (crateNum);
+ if (it == hirStructFieldMappings.end ())
+ return nullptr;
+
+ auto iy = it->second.find (id);
+ if (iy == it->second.end ())
+ return nullptr;
+
+ return iy->second;
+}
+
+void
Mappings::insert_local_defid_mapping (CrateNum crateNum, LocalDefId id,
HIR::Item *item)
{
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index a400265..4859d1e 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -121,6 +121,10 @@ public:
void insert_hir_param (CrateNum crateNum, HirId id, HIR::FunctionParam *type);
HIR::FunctionParam *lookup_hir_param (CrateNum crateNum, HirId id);
+ void insert_hir_struct_field (CrateNum crateNum, HirId id,
+ HIR::StructExprField *type);
+ HIR::StructExprField *lookup_hir_struct_field (CrateNum crateNum, HirId id);
+
void walk_local_defids_for_crate (CrateNum crateNum,
std::function<bool (HIR::Item *)> cb);
@@ -139,6 +143,11 @@ public:
return resolve_nodeid_to_stmt (get_current_crate (), id, stmt);
}
+ std::set<HirId> &get_hirids_within_crate (CrateNum crate)
+ {
+ return hirNodesWithinCrate[crate];
+ }
+
private:
Mappings ();
@@ -159,12 +168,17 @@ private:
std::map<CrateNum, std::map<HirId, HIR::Expr *> > hirExprMappings;
std::map<CrateNum, std::map<HirId, HIR::Stmt *> > hirStmtMappings;
std::map<CrateNum, std::map<HirId, HIR::FunctionParam *> > hirParamMappings;
+ std::map<CrateNum, std::map<HirId, HIR::StructExprField *> >
+ hirStructFieldMappings;
// location info
std::map<CrateNum, std::map<NodeId, Location> > locations;
// reverse mappings
std::map<CrateNum, std::map<NodeId, HirId> > nodeIdToHirMappings;
+
+ // all hirid nodes
+ std::map<CrateNum, std::set<HirId> > hirNodesWithinCrate;
};
} // namespace Analysis
diff --git a/gcc/testsuite/rust.test/compilable/arithmetic_expressions1.rs b/gcc/testsuite/rust.test/compilable/arithmetic_expressions1.rs
new file mode 100644
index 0000000..efc63f5
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/arithmetic_expressions1.rs
@@ -0,0 +1,28 @@
+fn main() {
+ let a: i32 = 1;
+ let b: f32 = 5f32;
+ let c: bool = true;
+
+ let a1: i32 = a + 1;
+ let a2: i32 = a - 2;
+ let a3: i32 = a * 3;
+ let a4: i32 = a / 4;
+ let a5: i32 = a % 5;
+
+ let b1: f32 = b + 1f32;
+ let b2: f32 = b - 2f32;
+ let b3: f32 = b * 3f32;
+ let b4: f32 = b / 4f32;
+ // let b5: f32 = b % 5f32;
+
+ let aa1: i32 = a & 1;
+ let aa2: i32 = a | 2;
+ let aa2: i32 = a ^ 3;
+
+ let c1: bool = c & true;
+ let c2: bool = c | false;
+ let c3: bool = c ^ true;
+
+ let aaa1: i32 = a << 1;
+ let aaa2: i32 = a >> 2;
+}
diff --git a/gcc/testsuite/rust.test/compilable/arrays_index2.rs b/gcc/testsuite/rust.test/compilable/arrays_index2.rs
new file mode 100644
index 0000000..f9bee77
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/arrays_index2.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let mut array: [i32; 3] = [0; 3];
+ array[0] = 1;
+}
diff --git a/gcc/testsuite/rust.test/compilable/comparison_expr1.rs b/gcc/testsuite/rust.test/compilable/comparison_expr1.rs
new file mode 100644
index 0000000..d3c5263
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/comparison_expr1.rs
@@ -0,0 +1,34 @@
+fn is_zero(x: i32) -> bool {
+ x == 0
+}
+
+fn is_not_zero(x: i32) -> bool {
+ x != 0
+}
+
+fn is_positive(x: i32) -> bool {
+ x > 0
+}
+
+fn is_negative(x: i32) -> bool {
+ x < 0
+}
+
+fn is_positive_or_zero(x: i32) -> bool {
+ x >= 0
+}
+
+fn is_negative_or_zero(x: i32) -> bool {
+ x <= 0
+}
+
+fn main() {
+ let a: bool = is_zero(1);
+ let b: bool = is_not_zero(2);
+ let c: bool = is_positive(3);
+ let d: bool = is_negative(4);
+ let e: bool = is_positive_or_zero(5);
+ let f: bool = is_negative_or_zero(6);
+ let g: bool = a || b;
+ let h: bool = c && d;
+}
diff --git a/gcc/testsuite/rust.test/compilable/compound_assignment_expr1.rs b/gcc/testsuite/rust.test/compilable/compound_assignment_expr1.rs
new file mode 100644
index 0000000..add4a5f
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/compound_assignment_expr1.rs
@@ -0,0 +1,24 @@
+fn main() {
+ let mut a = 1;
+ let mut b = 2;
+ let mut c = 3;
+ let mut d = 4;
+ let mut e = 5;
+ let mut f = 6;
+ let mut g = 7;
+ let mut h = 8;
+ let mut i = 9;
+ let mut j = 10;
+
+ a += 1;
+ b -= 2;
+ c *= 3;
+ d /= 4;
+ e %= 5;
+ f &= 6;
+ // https://github.com/Rust-GCC/gccrs/issues/173
+ // g |= 7;
+ h ^= 8;
+ i <<= 9;
+ j >>= 10;
+}
diff --git a/gcc/testsuite/rust.test/compilable/forward_decl_2.rs b/gcc/testsuite/rust.test/compilable/forward_decl_2.rs
new file mode 100644
index 0000000..ba9c963
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/forward_decl_2.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let y = x + 1;
+}
+
+static x: i32 = 3;
diff --git a/gcc/testsuite/rust.test/compilable/forward_decl_3.rs b/gcc/testsuite/rust.test/compilable/forward_decl_3.rs
new file mode 100644
index 0000000..257b0f7
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/forward_decl_3.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let struct_test = Foo { one: 1, two: 2 };
+}
+
+struct Foo {
+ one: i32,
+ two: i32,
+}
diff --git a/gcc/testsuite/rust.test/compilable/forward_decl_4.rs b/gcc/testsuite/rust.test/compilable/forward_decl_4.rs
new file mode 100644
index 0000000..dd8a725
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/forward_decl_4.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let mut x = TEST_CONST;
+ x = x + 1;
+
+ let mut y = x + TEST_CONST;
+}
+
+const TEST_CONST: i32 = 10;
diff --git a/gcc/testsuite/rust.test/compilable/function_reference1.rs b/gcc/testsuite/rust.test/compilable/function_reference1.rs
new file mode 100644
index 0000000..604bad0
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/function_reference1.rs
@@ -0,0 +1,8 @@
+fn test(a: i32) -> i32 {
+ a + 1
+}
+
+fn main() {
+ let a = test;
+ let b = a(1);
+}
diff --git a/gcc/testsuite/rust.test/compilable/function_reference2.rs b/gcc/testsuite/rust.test/compilable/function_reference2.rs
new file mode 100644
index 0000000..0b963b2
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/function_reference2.rs
@@ -0,0 +1,8 @@
+fn test(a: i32) -> i32 {
+ a + 1
+}
+
+fn main() {
+ let a: fn(i32) -> i32 = test;
+ let b = a(1);
+}
diff --git a/gcc/testsuite/rust.test/compilable/ints_infer1.rs b/gcc/testsuite/rust.test/compilable/ints_infer1.rs
new file mode 100644
index 0000000..3170c7c
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/ints_infer1.rs
@@ -0,0 +1,18 @@
+const TEST_CONST: i32 = 10;
+
+fn main() {
+ let mut x = TEST_CONST;
+ x = x + 1;
+
+ let mut y = x + TEST_CONST;
+
+ let z = 1u32;
+
+ let a = z;
+
+ let b;
+ b = 1;
+
+ let c;
+ c = a;
+}
diff --git a/gcc/testsuite/rust.test/compilable/parameter_usage1.rs b/gcc/testsuite/rust.test/compilable/parameter_usage1.rs
new file mode 100644
index 0000000..7bba6c6
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/parameter_usage1.rs
@@ -0,0 +1,7 @@
+fn test(a: i32, b: i32) -> i32 {
+ a + b
+}
+
+fn main() {
+ let a = test(1, 4);
+}
diff --git a/gcc/testsuite/rust.test/compilable/parens1.rs b/gcc/testsuite/rust.test/compilable/parens1.rs
new file mode 100644
index 0000000..33d9d86
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/parens1.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let a = 123;
+ let b = a + (a * 2);
+}
diff --git a/gcc/testsuite/rust.test/compilable/recursive_fn1.rs b/gcc/testsuite/rust.test/compilable/recursive_fn1.rs
new file mode 100644
index 0000000..89c21d0
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/recursive_fn1.rs
@@ -0,0 +1,11 @@
+fn gcd(x: i32, y: i32) -> i32 {
+ if y == 0 {
+ x
+ } else {
+ gcd(y, x % y)
+ }
+}
+
+fn main() {
+ let a = gcd(100, 5);
+}
diff --git a/gcc/testsuite/rust.test/compilable/scoping1.rs b/gcc/testsuite/rust.test/compilable/scoping1.rs
index 02b5f93..74af41e 100644
--- a/gcc/testsuite/rust.test/compilable/scoping1.rs
+++ b/gcc/testsuite/rust.test/compilable/scoping1.rs
@@ -1,7 +1,7 @@
fn main() {
let x = 1;
{
- let x = true;
+ let mut x = true;
{
x = false;
}
diff --git a/gcc/testsuite/rust.test/compilable/struct_access1.rs b/gcc/testsuite/rust.test/compilable/struct_access1.rs
new file mode 100644
index 0000000..bc12b93
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/struct_access1.rs
@@ -0,0 +1,10 @@
+struct Foo {
+ one: i32,
+ two: i32,
+}
+
+fn main() {
+ let struct_test = Foo { one: 1, two: 2 };
+ let a = struct_test.one;
+ let b = struct_test.two;
+}
diff --git a/gcc/testsuite/rust.test/compilable/struct_base_init_1.rs b/gcc/testsuite/rust.test/compilable/struct_base_init_1.rs
new file mode 100644
index 0000000..3c0b24a
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/struct_base_init_1.rs
@@ -0,0 +1,12 @@
+struct Foo {
+ a: i32,
+ b: i32,
+}
+
+fn foo() -> Foo {
+ Foo { a: 42, b: 32 }
+}
+
+fn main() {
+ let _f = Foo { a: 10, ..foo() };
+}
diff --git a/gcc/testsuite/rust.test/compilable/struct_init_2.rs b/gcc/testsuite/rust.test/compilable/struct_init_2.rs
new file mode 100644
index 0000000..8d210b8
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/struct_init_2.rs
@@ -0,0 +1,5 @@
+struct Foo(f32, f32);
+
+fn main() {
+ let a = Foo { 0: 10.0, 1: 20.0 };
+}
diff --git a/gcc/testsuite/rust.test/compilable/struct_init_3.rs b/gcc/testsuite/rust.test/compilable/struct_init_3.rs
new file mode 100644
index 0000000..fb1e58e
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/struct_init_3.rs
@@ -0,0 +1,10 @@
+struct Foo {
+ a: i32,
+ b: i32,
+}
+
+fn main() {
+ let a = 1;
+ let b = 2;
+ let c = Foo { a, b };
+}
diff --git a/gcc/testsuite/rust.test/compilable/struct_init_4.rs b/gcc/testsuite/rust.test/compilable/struct_init_4.rs
new file mode 100644
index 0000000..2cc8a19
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/struct_init_4.rs
@@ -0,0 +1,9 @@
+struct Foo {
+ a: i32,
+ b: i32,
+}
+
+fn main() {
+ let a = Foo { a: 1, b: 2 };
+ let b = Foo { a: 3, b: 4, ..a };
+}
diff --git a/gcc/testsuite/rust.test/compilable/struct_init_5.rs b/gcc/testsuite/rust.test/compilable/struct_init_5.rs
new file mode 100644
index 0000000..c79ea71
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/struct_init_5.rs
@@ -0,0 +1,9 @@
+struct Foo {
+ a: i32,
+ b: i32,
+}
+
+fn main() {
+ let a = Foo { a: 1, b: 2 };
+ let b = Foo { ..a };
+}
diff --git a/gcc/testsuite/rust.test/compilable/struct_init_6.rs b/gcc/testsuite/rust.test/compilable/struct_init_6.rs
new file mode 100644
index 0000000..51b90bc
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/struct_init_6.rs
@@ -0,0 +1,9 @@
+struct Foo {
+ a: i32,
+ b: i32,
+}
+
+fn main() {
+ let a = Foo { a: 1, b: 2 };
+ let b = Foo { a: 1, ..a };
+}
diff --git a/gcc/testsuite/rust.test/compilable/struct_init_7.rs b/gcc/testsuite/rust.test/compilable/struct_init_7.rs
new file mode 100644
index 0000000..615eae7
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/struct_init_7.rs
@@ -0,0 +1,9 @@
+struct Foo {
+ a: i32,
+ b: f32,
+}
+
+fn main() {
+ let a = Foo { a: 1, b: 2f32 };
+ let b = Foo { b: 4f32, ..a };
+}
diff --git a/gcc/testsuite/rust.test/compilable/struct_init_8.rs b/gcc/testsuite/rust.test/compilable/struct_init_8.rs
new file mode 100644
index 0000000..e62f40a
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/struct_init_8.rs
@@ -0,0 +1,6 @@
+struct Foo(f32, i32);
+
+fn main() {
+ let a = Foo { 1: 1, 0: 2f32 };
+ let b = Foo { ..a };
+}
diff --git a/gcc/testsuite/rust.test/compilable/tuple1.rs b/gcc/testsuite/rust.test/compilable/tuple1.rs
new file mode 100644
index 0000000..8b89601
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/tuple1.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let a: (i32, bool) = (123, true);
+ let b;
+ b = (456, 5f32);
+}
diff --git a/gcc/testsuite/rust.test/compilable/tuple2.rs b/gcc/testsuite/rust.test/compilable/tuple2.rs
new file mode 100644
index 0000000..51333d8
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/tuple2.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let a = 123;
+ let b = (a,);
+}
diff --git a/gcc/testsuite/rust.test/compilable/tuple3.rs b/gcc/testsuite/rust.test/compilable/tuple3.rs
new file mode 100644
index 0000000..d0fb6fc
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/tuple3.rs
@@ -0,0 +1,9 @@
+fn main() {
+ let a = (1, true);
+
+ let b;
+ let c;
+
+ b = a.0;
+ c = a.1;
+}
diff --git a/gcc/testsuite/rust.test/compilable/tuple_field_access.rs b/gcc/testsuite/rust.test/compilable/tuple_field_access.rs
new file mode 100644
index 0000000..8d1bbe9
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/tuple_field_access.rs
@@ -0,0 +1,6 @@
+struct Foo(i32, i32);
+
+fn main() {
+ let mut a = Foo(1, 2);
+ a.0 = 22;
+}
diff --git a/gcc/testsuite/rust.test/compilable/tuple_struct1.rs b/gcc/testsuite/rust.test/compilable/tuple_struct1.rs
new file mode 100644
index 0000000..65e29f7
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/tuple_struct1.rs
@@ -0,0 +1,5 @@
+struct Foo(i32, i32, bool);
+
+fn main() {
+ let a = Foo(1, 2, true);
+}
diff --git a/gcc/testsuite/rust.test/compilable/tuple_struct2.rs b/gcc/testsuite/rust.test/compilable/tuple_struct2.rs
new file mode 100644
index 0000000..5e0a76e
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/tuple_struct2.rs
@@ -0,0 +1,11 @@
+struct Foo(i32, bool);
+
+fn main() {
+ let a = Foo(1, true);
+
+ let b;
+ let c;
+
+ b = a.0;
+ c = a.1;
+}
diff --git a/gcc/testsuite/rust.test/compilable/type_infer5.rs b/gcc/testsuite/rust.test/compilable/type_infer5.rs
new file mode 100644
index 0000000..65c7058
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/type_infer5.rs
@@ -0,0 +1,11 @@
+struct Foo {
+ a: i32,
+ b: i32,
+}
+
+fn main() {
+ let a;
+ a = Foo { a: 1, b: 2 };
+
+ let b = a.a;
+}
diff --git a/gcc/testsuite/rust.test/compilable/type_infer6.rs b/gcc/testsuite/rust.test/compilable/type_infer6.rs
new file mode 100644
index 0000000..f6eac9e
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/type_infer6.rs
@@ -0,0 +1,12 @@
+fn test(x: u32) -> u32 {
+ return x + 1;
+}
+
+fn main() {
+ let a;
+ a = 1;
+ let b = test(a);
+
+ let c = 1;
+ let d = test(c + 1);
+}
diff --git a/gcc/testsuite/rust.test/compilable/unary_operators.rs b/gcc/testsuite/rust.test/compilable/unary_operators.rs
new file mode 100644
index 0000000..1ed9666
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/unary_operators.rs
@@ -0,0 +1,6 @@
+fn main() {
+ let a: i32 = -1;
+ let b: i32 = 3 - -1;
+ let c: bool = !false;
+ let d: i32 = !3;
+}
diff --git a/gcc/testsuite/rust.test/compilable/unit_type1.rs b/gcc/testsuite/rust.test/compilable/unit_type1.rs
new file mode 100644
index 0000000..ea1ebb3
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/unit_type1.rs
@@ -0,0 +1,6 @@
+fn main() {
+ let a: () = ();
+
+ let b;
+ b = ();
+}
diff --git a/gcc/testsuite/rust.test/compilable/usize1.rs b/gcc/testsuite/rust.test/compilable/usize1.rs
new file mode 100644
index 0000000..0df0a85
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/usize1.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let a = [1, 2, 3];
+ let b: usize = 1;
+ let c = a[b];
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/func2.rs b/gcc/testsuite/rust.test/fail_compilation/func2.rs
new file mode 100644
index 0000000..eae433a
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/func2.rs
@@ -0,0 +1,7 @@
+fn test(a: i32, b: i32) -> i32 {
+ a + b
+}
+
+fn main() {
+ let a = test(1);
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/func3.rs b/gcc/testsuite/rust.test/fail_compilation/func3.rs
new file mode 100644
index 0000000..781caf7
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/func3.rs
@@ -0,0 +1,7 @@
+fn test(a: i32, b: i32) -> i32 {
+ a + b
+}
+
+fn main() {
+ let a = test(1, true);
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/immutable1.rs b/gcc/testsuite/rust.test/fail_compilation/immutable1.rs
new file mode 100644
index 0000000..5713d3b1
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/immutable1.rs
@@ -0,0 +1,5 @@
+static x: i32 = 3;
+
+fn main() {
+ x = 1;
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/immutable2.rs b/gcc/testsuite/rust.test/fail_compilation/immutable2.rs
new file mode 100644
index 0000000..e316e72
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/immutable2.rs
@@ -0,0 +1,5 @@
+const TEST_CONST: i32 = 10;
+
+fn main() {
+ TEST_CONST = 1;
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/immutable3.rs b/gcc/testsuite/rust.test/fail_compilation/immutable3.rs
new file mode 100644
index 0000000..b310193
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/immutable3.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let a = 1;
+ a += 2;
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/immutable4.rs b/gcc/testsuite/rust.test/fail_compilation/immutable4.rs
new file mode 100644
index 0000000..d2e740f
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/immutable4.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let array: [i32; 3] = [0; 3];
+ array[0] = 1;
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/immutable5.rs b/gcc/testsuite/rust.test/fail_compilation/immutable5.rs
new file mode 100644
index 0000000..c442ba5
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/immutable5.rs
@@ -0,0 +1,6 @@
+struct Foo(f32, i32);
+
+fn main() {
+ let a = Foo(1, 2);
+ a.0 = 22;
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err1.rs b/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err1.rs
new file mode 100644
index 0000000..b450e18
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err1.rs
@@ -0,0 +1,12 @@
+fn test(x: i32) -> i32 {
+ if x > 1 {
+ 1
+ } else {
+ 2
+ }
+ 3
+}
+
+fn main() {
+ let a = test(1);
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err2.rs b/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err2.rs
new file mode 100644
index 0000000..b5fbd0a
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err2.rs
@@ -0,0 +1,8 @@
+fn test(x: i32) -> i32 {
+ return 1;
+ true
+}
+
+fn main() {
+ let a = test(1);
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err3.rs b/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err3.rs
new file mode 100644
index 0000000..a83385e
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/implicit_returns_err3.rs
@@ -0,0 +1,9 @@
+fn test(x: i32) -> i32 {
+ if x > 1 {
+ 1
+ }
+}
+
+fn main() {
+ let a = test(9);
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/struct_init1.rs b/gcc/testsuite/rust.test/fail_compilation/struct_init1.rs
new file mode 100644
index 0000000..3eadaef
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/struct_init1.rs
@@ -0,0 +1,8 @@
+struct Foo {
+ a: f32,
+ b: f32,
+}
+
+fn main() {
+ let a = Foo { 0: 10.0, 1: 20.0 };
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/tuple1.rs b/gcc/testsuite/rust.test/fail_compilation/tuple1.rs
new file mode 100644
index 0000000..d551365
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/tuple1.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let a: (i32, bool) = (123, 123);
+ let b;
+ b = (456, 5f32);
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/tuple_struct1.rs b/gcc/testsuite/rust.test/fail_compilation/tuple_struct1.rs
new file mode 100644
index 0000000..0df07d9
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/tuple_struct1.rs
@@ -0,0 +1,8 @@
+struct Foo {
+ one: i32,
+ two: i32,
+}
+
+fn main() {
+ let a = Foo(1, 2);
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/tuple_struct2.rs b/gcc/testsuite/rust.test/fail_compilation/tuple_struct2.rs
new file mode 100644
index 0000000..6c3c0ab
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/tuple_struct2.rs
@@ -0,0 +1,5 @@
+struct Bar(i32, i32, bool);
+
+fn main() {
+ let a = Bar(1, 2);
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/tuple_struct3.rs b/gcc/testsuite/rust.test/fail_compilation/tuple_struct3.rs
new file mode 100644
index 0000000..832df8b
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/tuple_struct3.rs
@@ -0,0 +1,5 @@
+struct Foo(i32, i32, bool);
+
+fn main() {
+ let c = Foo(1, 2f32, true);
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/unary_negation.rs b/gcc/testsuite/rust.test/fail_compilation/unary_negation.rs
new file mode 100644
index 0000000..476b908
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/unary_negation.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let a: i32 = -1;
+ let b: i32 = 3 - -1;
+ let c: bool = !false;
+ let d: i32 = !3;
+
+ let e: f32 = -true;
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/unary_not.rs b/gcc/testsuite/rust.test/fail_compilation/unary_not.rs
new file mode 100644
index 0000000..f358f0e
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/unary_not.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let a: i32 = -1;
+ let b: i32 = 3 - -1;
+ let c: bool = !false;
+ let d: i32 = !3;
+
+ let e: f32 = !5f32;
+}
diff --git a/gcc/testsuite/rust.test/fail_compilation/usize1.rs b/gcc/testsuite/rust.test/fail_compilation/usize1.rs
new file mode 100644
index 0000000..92393e7
--- /dev/null
+++ b/gcc/testsuite/rust.test/fail_compilation/usize1.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let a = [1, 2, 3];
+ let b: u32 = 1;
+ let c = a[b];
+}