diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2021-02-02 17:13:10 +0800 |
---|---|---|
committer | SimplyTheOther <simplytheother@gmail.com> | 2021-02-02 17:13:10 +0800 |
commit | 61b498895bcc0d99f00f0a89707d068d08e14246 (patch) | |
tree | 86a866a4467c6612ad1b8b68e6395f20aeb2daf6 | |
parent | 3a0c8ca2156038b726e2689e9b46be4d8c40c55f (diff) | |
parent | e0e49f434423def63312084b04ea0e60e7787e27 (diff) | |
download | gcc-61b498895bcc0d99f00f0a89707d068d08e14246.zip gcc-61b498895bcc0d99f00f0a89707d068d08e14246.tar.gz gcc-61b498895bcc0d99f00f0a89707d068d08e14246.tar.bz2 |
Merge with upstream
114 files changed, 3975 insertions, 1041 deletions
@@ -5,6 +5,8 @@ # GCC Rust  +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 ¶m_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 ¶ms : 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 ¶m : fn->function_params) { mappings->insert_hir_param (mapping.get_crate_num (), - param.get_mappings ()->get_hirid (), - ¶m); + param.get_mappings ().get_hirid (), ¶m); 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 ¶m : 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 ¶m : 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 ¶m : 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 ¶m : 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 ¶m : 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 *> ¶m_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]; +} |