diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2021-02-04 12:43:59 +0800 |
---|---|---|
committer | SimplyTheOther <simplytheother@gmail.com> | 2021-02-04 12:43:59 +0800 |
commit | 7c7c76f27f6ab999ec8fa299bde8911911fa7d90 (patch) | |
tree | e432cd20f59552da34313060fbcbd87e0ef9728a | |
parent | 877e7ac6c72608950fbe2ffde04142bbfb01b29d (diff) | |
parent | 9abf0733814c5e4131b96afb1c0abad68f4cf4ef (diff) | |
download | gcc-7c7c76f27f6ab999ec8fa299bde8911911fa7d90.zip gcc-7c7c76f27f6ab999ec8fa299bde8911911fa7d90.tar.gz gcc-7c7c76f27f6ab999ec8fa299bde8911911fa7d90.tar.bz2 |
Merge branch 'master' of https://github.com/redbrain/gccrs
42 files changed, 1111 insertions, 316 deletions
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index ddeb176..faecfba 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1323,6 +1323,8 @@ public: virtual void mark_for_strip () = 0; virtual bool is_marked_for_strip () const = 0; + + virtual Location get_locus_slow () const = 0; }; // Abstract base class for items used in a trait impl @@ -1547,6 +1549,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + Location get_locus () const { return locus; } + + Location get_locus_slow () const override { return get_locus (); } + protected: MacroInvocationSemi *clone_macro_invocation_semi_impl () const { diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 6de37f6..9437f21 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -698,6 +698,8 @@ class Method : public InherentImplItem, public TraitImplItem Location locus; + NodeId node_id; + public: // Returns whether the method is in an error state. bool is_error () const @@ -746,7 +748,8 @@ public: function_params (std::move (function_params)), return_type (std::move (return_type)), where_clause (std::move (where_clause)), - function_body (std::move (function_body)), locus (locus) + function_body (std::move (function_body)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // TODO: add constructor with less fields @@ -769,6 +772,8 @@ public: generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); + + node_id = other.node_id; } // Overloaded assignment operator to clone @@ -799,6 +804,8 @@ public: for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); + node_id = other.node_id; + return *this; } @@ -860,6 +867,14 @@ public: return where_clause; } + Identifier get_method_name () const { return method_name; } + + NodeId get_node_id () const { return node_id; } + + Location get_locus () const { return locus; } + + Location get_locus_slow () const override { return get_locus (); } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1505,6 +1520,8 @@ public: Location get_locus () const { return locus; } + Location get_locus_slow () const override { return get_locus (); } + void accept_vis (ASTVisitor &vis) override; // Invalid if block is null, so base stripping on that. @@ -2538,6 +2555,8 @@ public: Location get_locus () const { return locus; } + Location get_locus_slow () const override { return get_locus (); } + void accept_vis (ASTVisitor &vis) override; // Invalid if type or expression are null, so base stripping on that. diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index 6410fd4..fdc5ad9 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -51,7 +51,6 @@ public: // virtual void visit(TraitItem& trait_item) {} // virtual void visit(InherentImplItem& inherent_impl_item) {} // virtual void visit(TraitImplItem& trait_impl_item) {} - virtual void visit (HIR::MacroInvocationSemi ¯o) {} // rust-path.h virtual void visit (HIR::PathInExpression &path) {} diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 81d7786..ccff51a 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -481,6 +481,11 @@ public: expr.get_locus ()); } + void visit (HIR::PathInExpression &expr) + { + translated = ResolvePathRef::Compile (&expr, ctx); + } + private: CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h new file mode 100644 index 0000000..fe2abf1 --- /dev/null +++ b/gcc/rust/backend/rust-compile-implitem.h @@ -0,0 +1,264 @@ +// 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_IMPLITEM_H +#define RUST_COMPILE_IMPLITEM_H + +#include "rust-compile-base.h" +#include "rust-compile-tyty.h" +#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 { + +class CompileInherentImplItem : public HIRCompileBase +{ +public: + static void Compile (HIR::Type *base, HIR::InherentImplItem *item, + Context *ctx, bool compile_fns) + { + CompileInherentImplItem compiler (base, ctx, compile_fns); + item->accept_vis (compiler); + } + + void visit (HIR::ConstantItem &constant) + { + TyTy::TyBase *resolved_type = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (constant.get_mappings ().get_hirid (), + &resolved_type); + rust_assert (ok); + + ::Btype *type = TyTyResolveCompile::compile (ctx, resolved_type); + Bexpression *value = CompileExpr::Compile (constant.get_expr (), ctx); + + std::string ident = base->as_string () + "::" + constant.get_identifier (); + Bexpression *const_expr = ctx->get_backend ()->named_constant_expression ( + type, constant.get_identifier (), value, constant.get_locus ()); + + ctx->push_const (const_expr); + ctx->insert_const_decl (constant.get_mappings ().get_hirid (), const_expr); + } + + 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; + if (ctx->lookup_function_decl (function.get_mappings ().get_hirid (), + &lookup)) + { + // has this been added to the list then it must be finished + if (ctx->function_completed (lookup)) + return; + } + + TyTy::TyBase *fntype_tyty; + if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (), + &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 + ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); + + unsigned int flags = 0; + bool is_main_fn = function.function_name.compare ("main") == 0; + + std::string fn_identifier + = base->as_string () + "::" + function.function_name; + + // if its the main fn or pub visibility mark its as DECL_PUBLIC + // please see https://github.com/Rust-GCC/gccrs/pull/137 + if (is_main_fn || function.has_visibility ()) + flags |= Backend::function_is_visible; + + std::string asm_name = fn_identifier; + if (!is_main_fn) + { + // FIXME need name mangling + asm_name = "__" + function.function_name; + } + + Bfunction *fndecl + = ctx->get_backend ()->function (compiled_fn_type, fn_identifier, + asm_name, flags, function.get_locus ()); + ctx->insert_function_decl (function.get_mappings ().get_hirid (), fndecl); + + // setup the params + + TyTy::TyBase *tyret = fntype->return_type (); + std::vector<Bvariable *> param_vars; + + size_t i = 0; + for (auto &it : fntype->get_params ()) + { + 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)) + { + rust_fatal_error (function.get_locus (), + "failed to setup parameter variables"); + return; + } + + // lookup locals + auto block_expr = function.function_body.get (); + auto body_mappings = block_expr->get_mappings (); + + Resolver::Rib *rib = nullptr; + if (!ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), + &rib)) + { + rust_fatal_error (function.get_locus (), + "failed to setup locals per block"); + return; + } + + std::vector<Bvariable *> locals; + rib->iterate_decls ([&] (NodeId n, Location) mutable -> bool { + Resolver::Definition d; + bool ok = ctx->get_resolver ()->lookup_definition (n, &d); + rust_assert (ok); + + HIR::Stmt *decl = nullptr; + ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl); + rust_assert (ok); + + Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx); + locals.push_back (compiled); + + return true; + }); + + bool toplevel_item + = function.get_mappings ().get_local_defid () != UNKNOWN_LOCAL_DEFID; + Bblock *enclosing_scope + = toplevel_item ? NULL : ctx->peek_enclosing_scope (); + + HIR::BlockExpr *function_body = function.function_body.get (); + Location start_location = function_body->get_locus (); + Location end_location = function_body->get_closing_locus (); + + Bblock *code_block + = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, + start_location, end_location); + ctx->push_block (code_block); + + Bvariable *return_address = nullptr; + if (function.has_function_return_type ()) + { + Btype *return_type = TyTyResolveCompile::compile (ctx, tyret); + + bool address_is_taken = false; + Bstatement *ret_var_stmt = nullptr; + + return_address = ctx->get_backend ()->temporary_variable ( + fndecl, code_block, return_type, NULL, address_is_taken, + function.get_locus (), &ret_var_stmt); + + ctx->add_statement (ret_var_stmt); + } + + ctx->push_fn (fndecl, return_address); + + // compile the block + function_body->iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { + CompileStmt::Compile (s, ctx); + return true; + }); + + 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 + Bexpression *compiled_expr + = CompileExpr::Compile (function_body->expr.get (), ctx); + rust_assert (compiled_expr != nullptr); + + auto fncontext = ctx->peek_fn (); + + std::vector<Bexpression *> retstmts; + retstmts.push_back (compiled_expr); + auto s = ctx->get_backend ()->return_statement ( + fncontext.fndecl, retstmts, function_body->expr->get_locus_slow ()); + ctx->add_statement (s); + } + + ctx->pop_block (); + auto body = ctx->get_backend ()->block_statement (code_block); + if (!ctx->get_backend ()->function_set_body (fndecl, body)) + { + rust_error_at (function.get_locus (), "failed to set body to function"); + return; + } + + ctx->pop_fn (); + + ctx->push_function (fndecl); + } + +private: + CompileInherentImplItem (HIR::Type *base, Context *ctx, bool compile_fns) + : HIRCompileBase (ctx), base (base), compile_fns (compile_fns) + {} + + HIR::Type *base; + bool compile_fns; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_IMPLITEM_H diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 1bb7c91..83e4451 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -21,6 +21,7 @@ #include "rust-compile-base.h" #include "rust-compile-tyty.h" +#include "rust-compile-implitem.h" #include "rust-compile-var-decl.h" #include "rust-compile-stmt.h" #include "rust-compile-expr.h" @@ -300,6 +301,13 @@ public: ctx->push_function (fndecl); } + void visit (HIR::InherentImpl &impl_block) + { + for (auto &impl_item : impl_block.get_impl_items ()) + CompileInherentImplItem::Compile (impl_block.get_type ().get (), + impl_item.get (), ctx, compile_fns); + } + private: CompileItem (Context *ctx, bool compile_fns) : HIRCompileBase (ctx), compile_fns (compile_fns) diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 818d5cb..de325fa 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -55,6 +55,10 @@ ResolvePathRef::visit (HIR::PathInExpression &expr) return; } + // might be a constant + if (ctx->lookup_const_decl (ref, &resolved)) + return; + // this might be a variable reference or a function reference Bvariable *var = nullptr; if (ctx->lookup_var_decl (ref, &var)) diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index 06ea5a9..e701b15 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -38,8 +38,6 @@ public: return compiler.translated; } - virtual ~CompileVarDecl () {} - void visit (HIR::LetStmt &stmt) { locus = stmt.get_locus (); diff --git a/gcc/rust/hir/README.md b/gcc/rust/hir/README.md deleted file mode 100644 index 550d104..0000000 --- a/gcc/rust/hir/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# GCCRS HIR - -Working with the AST has proved to become difficult. To overcome non lexical scoping -a toplevel scan pass was added to provide lookups for functioins. To get ready for the -gimple conversion pass, type resolution scanned blocks to create the list of locals per -block. Type Conversion had to create awkward getters/setters on LetStmts to have a Type or -InferedType which was more of a hack that what should really be there. ArrayExprs get checked -and create their own type to be checked against a possible LetStmt type. All of these things -started to become hard to manage. - -HIR from the RFC defines how they create lookups and IDs for all the nodes which solves the toplevel -scan pass. The lowering to HIR allows for cleanup in how types are resolved. Without using -the HIR and IDs implementing the shadowing rules was going to become very difficult. - - -## IMPL: - -* AST-lower - move down to HIR classes - generate mappings and IDs - -* Name Resolution - Check for path segments naming and map to HirIDS - This should in theory map for example a call expression to already have the HirID to the function ready - Dyn dispatch may need some help here if its a method the receiver could be bound the local name hirid - the resoltion would need to be fixed up in type resolution pass - -* Expand - Gather locals per block and fix up returns is it possible to generate return expressions - at this pass? - -* Type Resolution - Port over work from AST Type resolver - generate mir from this pass? - - -For now this can then port over to the existing GIMPLE conversion faily easily. But after more -of the core data structures work MIR will be needed for all the glue that will need to be generated. - - -## Returns - -looks like its implemented by an implicit mutable return variable for the function. If were processing -a block expression and the last element on the block is an expression we can try to bind it to the mutable -return variable. diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h new file mode 100644 index 0000000..dab3208 --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-implitem.h @@ -0,0 +1,156 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_LOWER_IMPLITEM_H +#define RUST_AST_LOWER_IMPLITEM_H + +#include "rust-diagnostics.h" +#include "rust-ast-lower-type.h" +#include "rust-ast-lower-stmt.h" +#include "rust-ast-lower-expr.h" +#include "rust-ast-lower-pattern.h" +#include "rust-ast-lower-block.h" + +namespace Rust { +namespace HIR { + +class ASTLowerImplItem : public ASTLoweringBase +{ +public: + static HIR::InherentImplItem *translate (AST::InherentImplItem *item) + { + ASTLowerImplItem resolver; + item->accept_vis (resolver); + rust_assert (resolver.translated != nullptr); + return resolver.translated; + } + + void visit (AST::ConstantItem &constant) + { + std::vector<HIR::Attribute> outer_attrs; + HIR::Visibility vis = HIR::Visibility::create_public (); + + HIR::Type *type = ASTLoweringType::translate (constant.get_type ().get ()); + HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, constant.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated = new HIR::ConstantItem (mapping, constant.get_identifier (), + vis, std::unique_ptr<HIR::Type> (type), + std::unique_ptr<HIR::Expr> (expr), + outer_attrs, constant.get_locus ()); + + mappings->insert_hir_implitem (mapping.get_crate_num (), + mapping.get_hirid (), translated); + mappings->insert_location (crate_num, mapping.get_hirid (), + constant.get_locus ()); + } + + void visit (AST::Function &function) + { + // ignore for now and leave empty + std::vector<std::unique_ptr<HIR::GenericParam> > generic_params; + std::vector<HIR::Attribute> outer_attrs; + std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items; + HIR::WhereClause where_clause (std::move (where_clause_items)); + HIR::FunctionQualifiers qualifiers ( + HIR::FunctionQualifiers::AsyncConstStatus::NONE, false); + HIR::Visibility vis = HIR::Visibility::create_public (); + + // need + Identifier function_name = function.get_function_name (); + Location locus = function.get_locus (); + + std::unique_ptr<HIR::Type> return_type + = function.has_return_type () ? std::unique_ptr<HIR::Type> ( + ASTLoweringType::translate (function.get_return_type ().get ())) + : nullptr; + + std::vector<HIR::FunctionParam> function_params; + for (auto ¶m : function.get_function_params ()) + { + auto translated_pattern = std::unique_ptr<HIR::Pattern> ( + ASTLoweringPattern::translate (param.get_pattern ().get ())); + auto translated_type = std::unique_ptr<HIR::Type> ( + ASTLoweringType::translate (param.get_type ().get ())); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, param.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + auto hir_param + = HIR::FunctionParam (mapping, std::move (translated_pattern), + std::move (translated_type), + param.get_locus ()); + function_params.push_back (hir_param); + } + + bool terminated = false; + std::unique_ptr<HIR::BlockExpr> function_body + = std::unique_ptr<HIR::BlockExpr> ( + ASTLoweringBlock::translate (function.get_definition ().get (), + &terminated)); + + 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), + std::move (function_params), std::move (return_type), + std::move (where_clause), std::move (function_body), + std::move (vis), std::move (outer_attrs), locus); + + mappings->insert_hir_implitem (mapping.get_crate_num (), + mapping.get_hirid (), fn); + mappings->insert_location (crate_num, mapping.get_hirid (), + function.get_locus ()); + + // add the mappings for the function params at the end + for (auto ¶m : fn->function_params) + { + mappings->insert_hir_param (mapping.get_crate_num (), + param.get_mappings ().get_hirid (), ¶m); + mappings->insert_location (crate_num, mapping.get_hirid (), + param.get_locus ()); + } + + translated = fn; + } + +private: + ASTLowerImplItem () : translated (nullptr) {} + + HIR::InherentImplItem *translated; +}; + +} // namespace HIR + +} // namespace Rust + +#endif // RUST_AST_LOWER_IMPLITEM_H diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index ec4ef6b..1e48e82 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -23,6 +23,7 @@ #include "rust-ast-lower-base.h" #include "rust-ast-lower-type.h" +#include "rust-ast-lower-implitem.h" #include "rust-ast-lower-stmt.h" #include "rust-ast-lower-expr.h" #include "rust-ast-lower-pattern.h" @@ -282,6 +283,46 @@ public: translated = fn; } + void visit (AST::InherentImpl &impl_block) + { + std::vector<HIR::Attribute> inner_attrs; + std::vector<HIR::Attribute> outer_attrs; + 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 (); + HIR::Type *trait_type + = ASTLoweringType::translate (impl_block.get_type ().get ()); + + std::vector<std::unique_ptr<HIR::InherentImplItem> > impl_items; + for (auto &impl_item : impl_block.get_impl_items ()) + { + HIR::InherentImplItem *lowered + = ASTLowerImplItem::translate (impl_item.get ()); + impl_items.push_back (std::unique_ptr<HIR::InherentImplItem> (lowered)); + } + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, impl_block.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + translated + = new HIR::InherentImpl (mapping, std::move (impl_items), + std::move (generic_params), + std::unique_ptr<HIR::Type> (trait_type), + where_clause, vis, std::move (inner_attrs), + std::move (outer_attrs), + impl_block.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 (), + impl_block.get_locus ()); + } + private: ASTLoweringItem () : translated (nullptr) {} diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index dac2320..c1ea01a 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -18,6 +18,7 @@ #include "rust-ast-lower.h" #include "rust-ast-lower-item.h" +#include "rust-ast-lower-implitem.h" #include "rust-ast-lower-expr.h" #include "rust-ast-lower-block.h" diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h index 02b9f03..8295e89 100644 --- a/gcc/rust/hir/tree/rust-hir-full-decls.h +++ b/gcc/rust/hir/tree/rust-hir-full-decls.h @@ -53,7 +53,6 @@ class MacroItem; class TraitItem; class InherentImplItem; class TraitImplItem; -class MacroInvocationSemi; struct Crate; class PathExpr; diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc index b727917..8502c9c 100644 --- a/gcc/rust/hir/tree/rust-hir-full-test.cc +++ b/gcc/rust/hir/tree/rust-hir-full-test.cc @@ -1377,47 +1377,6 @@ TypeAlias::as_string () const } std::string -MacroInvocationSemi::as_string () const -{ - // get outer attrs - std::string str = MacroItem::as_string (); - - str += "\n" + path.as_string () + "!"; - - std::string tok_trees; - if (token_trees.empty ()) - { - tok_trees = "none"; - } - else - { - auto i = token_trees.begin (); - auto e = token_trees.end (); - - // DEBUG: null pointer check - if (i == e) - { - fprintf (stderr, - "something really terrible has gone wrong - null pointer " - "token tree in macro invocation semi."); - return "nullptr_POINTER_MARK"; - } - - std::string s; - for (; i != e; i++) - { - s += (*i)->as_string (); - if (e != i + 1) - s += ", "; - } - - tok_trees += get_string_in_delims (s, delim_type); - } - - return str; -} - -std::string ExternBlock::as_string () const { std::string str = VisItem::as_string (); @@ -5046,12 +5005,6 @@ LifetimeParam::accept_vis (HIRVisitor &vis) } void -MacroInvocationSemi::accept_vis (HIRVisitor &vis) -{ - vis.visit (*this); -} - -void PathInExpression::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 e99dd38..e90dbb4 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -27,7 +27,6 @@ namespace HIR { // forward decls class BlockExpr; class TypePath; -class MacroInvocationSemi; // A type generic parameter (as opposed to a lifetime generic parameter) class TypeParam : public GenericParam @@ -569,6 +568,8 @@ class Method : public InherentImplItem, public TraitImplItem std::unique_ptr<BlockExpr> expr; + Analysis::NodeMapping mappings; + Location locus; public: @@ -588,14 +589,15 @@ public: bool has_visibility () const { return !vis.is_error (); } // Mega-constructor with all possible fields - Method (Identifier method_name, FunctionQualifiers qualifiers, + Method (Analysis::NodeMapping mappings, Identifier method_name, + FunctionQualifiers qualifiers, std::vector<std::unique_ptr<GenericParam> > generic_params, SelfParam self_param, std::vector<FunctionParam> function_params, std::unique_ptr<Type> return_type, WhereClause where_clause, std::unique_ptr<BlockExpr> function_body, Visibility vis, std::vector<Attribute> outer_attrs, Location locus = Location ()) - : outer_attrs (std::move (outer_attrs)), vis (std::move (vis)), - qualifiers (std::move (qualifiers)), + : mappings (mappings), outer_attrs (std::move (outer_attrs)), + vis (std::move (vis)), qualifiers (std::move (qualifiers)), method_name (std::move (method_name)), generic_params (std::move (generic_params)), self_param (std::move (self_param)), @@ -609,9 +611,10 @@ public: // Copy constructor with clone Method (Method const &other) - : outer_attrs (other.outer_attrs), vis (other.vis), - qualifiers (other.qualifiers), method_name (other.method_name), - self_param (other.self_param), function_params (other.function_params), + : mappings (other.mappings), outer_attrs (other.outer_attrs), + vis (other.vis), qualifiers (other.qualifiers), + method_name (other.method_name), self_param (other.self_param), + function_params (other.function_params), return_type (other.return_type->clone_type ()), where_clause (other.where_clause), expr (other.expr->clone_block_expr ()), locus (other.locus) @@ -624,6 +627,7 @@ public: // Overloaded assignment operator to clone Method &operator= (Method const &other) { + mappings = other.mappings; method_name = other.method_name; outer_attrs = other.outer_attrs; vis = other.vis; @@ -650,6 +654,13 @@ public: void accept_vis (HIRVisitor &vis) override; + Analysis::NodeMapping get_mappings () const { return mappings; }; + + Analysis::NodeMapping get_impl_mappings () const override + { + return get_mappings (); + }; + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1267,6 +1278,11 @@ public: void accept_vis (HIRVisitor &vis) override; + Analysis::NodeMapping get_impl_mappings () const override + { + return get_mappings (); + }; + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2096,6 +2112,11 @@ public: std::string get_identifier () { return identifier; } + Analysis::NodeMapping get_impl_mappings () const override + { + return get_mappings (); + }; + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2767,6 +2788,8 @@ public: Location get_locus () const { return locus; } + std::unique_ptr<Type> &get_type () { return trait_type; }; + protected: // Mega-constructor Impl (Analysis::NodeMapping mappings, @@ -2864,6 +2887,16 @@ public: void accept_vis (HIRVisitor &vis) override; + std::vector<std::unique_ptr<InherentImplItem> > &get_impl_items () + { + return impl_items; + }; + + const std::vector<std::unique_ptr<InherentImplItem> > &get_impl_items () const + { + return impl_items; + }; + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -3300,7 +3333,6 @@ protected: // Replaced with forward decls - defined in "rust-macro.h" class MacroItem; -class MacroInvocationSemi; class MacroRulesDefinition; } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-macro.h b/gcc/rust/hir/tree/rust-hir-macro.h index 84b4914..13f0d22 100644 --- a/gcc/rust/hir/tree/rust-hir-macro.h +++ b/gcc/rust/hir/tree/rust-hir-macro.h @@ -25,7 +25,6 @@ namespace Rust { namespace HIR { // Decls as definitions moved to rust-ast.h class MacroItem; -class MacroInvocationSemi; enum MacroFragSpec { diff --git a/gcc/rust/hir/tree/rust-hir-stmt.h b/gcc/rust/hir/tree/rust-hir-stmt.h index be4ff7d..3384aaa 100644 --- a/gcc/rust/hir/tree/rust-hir-stmt.h +++ b/gcc/rust/hir/tree/rust-hir-stmt.h @@ -233,9 +233,6 @@ protected: } }; -/* Replaced definition of MacroInvocationSemi with forward decl - defined in - * rust-macro.h */ -class MacroInvocationSemi; } // namespace HIR } // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h index 7fefb69..a7b9791 100644 --- a/gcc/rust/hir/tree/rust-hir-visitor.h +++ b/gcc/rust/hir/tree/rust-hir-visitor.h @@ -52,7 +52,6 @@ public: // virtual void visit(TraitItem& trait_item) = 0; // virtual void visit(InherentImplItem& inherent_impl_item) = 0; // virtual void visit(TraitImplItem& trait_impl_item) = 0; - virtual void visit (MacroInvocationSemi ¯o) = 0; // rust-path.h virtual void visit (PathInExpression &path) = 0; diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index e4a81c5..6fd6297 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -1256,6 +1256,8 @@ public: virtual std::string as_string () const = 0; virtual void accept_vis (HIRVisitor &vis) = 0; + + virtual Analysis::NodeMapping get_impl_mappings () const = 0; }; // Abstract base class for items used in a trait impl @@ -1278,122 +1280,6 @@ public: virtual void accept_vis (HIRVisitor &vis) = 0; }; -/* A macro invocation item (or statement) HIR node (i.e. semi-coloned macro - * invocation) */ -class MacroInvocationSemi : public MacroItem, - public TraitItem, - public InherentImplItem, - public TraitImplItem -{ - SimplePath path; - // all delim types except curly must have invocation end with a semicolon - DelimType delim_type; - std::vector<std::unique_ptr<TokenTree> > token_trees; - Location locus; - -public: - std::string as_string () const override; - - MacroInvocationSemi (Analysis::NodeMapping mappings, SimplePath macro_path, - DelimType delim_type, - std::vector<std::unique_ptr<TokenTree> > token_trees, - std::vector<Attribute> outer_attribs, Location locus) - : MacroItem (std::move (mappings), std::move (outer_attribs)), - path (std::move (macro_path)), delim_type (delim_type), - token_trees (std::move (token_trees)), locus (locus) - {} - /* TODO: possible issue with Item and TraitItem hierarchies both having outer - * attributes - * - storage inefficiency at least. - * Best current idea is to make Item preferred and have TraitItem get virtual - * functions for attributes or something. Or just redo the "composition" - * approach, but then this prevents polymorphism and would entail redoing - * quite a bit of the parser. */ - - // Move constructors - MacroInvocationSemi (MacroInvocationSemi &&other) = default; - MacroInvocationSemi &operator= (MacroInvocationSemi &&other) = default; - - void accept_vis (HIRVisitor &vis) override; - - // Clones this macro invocation semi. - std::unique_ptr<MacroInvocationSemi> clone_macro_invocation_semi () const - { - return std::unique_ptr<MacroInvocationSemi> ( - clone_macro_invocation_semi_impl ()); - } - -protected: - // Copy constructor with vector clone - MacroInvocationSemi (MacroInvocationSemi const &other) - : MacroItem (other), TraitItem (other), InherentImplItem (other), - TraitImplItem (other), path (other.path), delim_type (other.delim_type), - locus (other.locus) - { - token_trees.reserve (other.token_trees.size ()); - for (const auto &e : other.token_trees) - token_trees.push_back (e->clone_token_tree ()); - } - - // Overloaded assignment operator to vector clone - MacroInvocationSemi &operator= (MacroInvocationSemi const &other) - { - MacroItem::operator= (other); - TraitItem::operator= (other); - InherentImplItem::operator= (other); - TraitImplItem::operator= (other); - path = other.path; - delim_type = other.delim_type; - locus = other.locus; - - token_trees.reserve (other.token_trees.size ()); - for (const auto &e : other.token_trees) - token_trees.push_back (e->clone_token_tree ()); - - return *this; - } - - MacroInvocationSemi *clone_macro_invocation_semi_impl () const - { - return new MacroInvocationSemi (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - MacroInvocationSemi *clone_item_impl () const override - { - return clone_macro_invocation_semi_impl (); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - MacroInvocationSemi *clone_inherent_impl_item_impl () const override - { - return clone_macro_invocation_semi_impl (); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - MacroInvocationSemi *clone_trait_impl_item_impl () const override - { - return clone_macro_invocation_semi_impl (); - } - - // FIXME: remove if item impl virtual override works properly - // Use covariance to implement clone function as returning this object rather - // than base - /*MacroInvocationSemi* clone_statement_impl() const override { - return clone_macro_invocation_semi_impl (); - }*/ - - /* Use covariance to implement clone function as returning this object rather - * than base */ - MacroInvocationSemi *clone_trait_item_impl () const override - { - return clone_macro_invocation_semi_impl (); - } -}; - // A crate HIR object - holds all the data for a single compilation unit struct Crate { diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h new file mode 100644 index 0000000..74f2cdc --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-implitem.h @@ -0,0 +1,82 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_IMPLITEM_H +#define RUST_AST_RESOLVE_IMPLITEM_H + +#include "rust-ast-resolve-base.h" +#include "rust-ast-resolve-type.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Resolver { + +class ResolveToplevelImplItem : public ResolverBase +{ +public: + static void go (AST::InherentImplItem *item, AST::Type *base) + { + ResolveToplevelImplItem resolver (base); + item->accept_vis (resolver); + }; + + void visit (AST::ConstantItem &constant) + { + std::string identifier + = base->as_string () + "::" + constant.get_identifier (); + resolver->get_name_scope ().insert (identifier, constant.get_node_id (), + constant.get_locus ()); + resolver->insert_new_definition (constant.get_node_id (), + Definition{constant.get_node_id (), + constant.get_node_id ()}); + } + + void visit (AST::Function &function) + { + std::string identifier + = base->as_string () + "::" + function.get_function_name (); + resolver->get_name_scope ().insert (identifier, function.get_node_id (), + function.get_locus ()); + resolver->insert_new_definition (function.get_node_id (), + Definition{function.get_node_id (), + function.get_node_id ()}); + } + + void visit (AST::Method &method) + { + std::string identifier + = base->as_string () + "::" + method.get_method_name (); + resolver->get_name_scope ().insert (identifier, method.get_node_id (), + method.get_locus ()); + resolver->insert_new_definition (method.get_node_id (), + Definition{method.get_node_id (), + method.get_node_id ()}); + } + +private: + ResolveToplevelImplItem (AST::Type *base) + : ResolverBase (UNKNOWN_NODEID), base (base) + {} + + AST::Type *base; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_IMPLITEM_H diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index 0f45ba0..74b5f8d 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -117,6 +117,12 @@ public: resolver->get_type_scope ().pop (); } + void visit (AST::InherentImpl &impl_block) + { + for (auto &impl_item : impl_block.get_impl_items ()) + impl_item->accept_vis (*this); + } + private: ResolveItem () : ResolverBase (UNKNOWN_NODEID) {} }; diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index c3f5e4c..7ca8275 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -20,6 +20,8 @@ #define RUST_AST_RESOLVE_TOPLEVEL_H #include "rust-ast-resolve-base.h" +#include "rust-ast-resolve-type.h" +#include "rust-ast-resolve-implitem.h" #include "rust-ast-full.h" namespace Rust { @@ -34,8 +36,6 @@ public: item->accept_vis (resolver); }; - ~ResolveTopLevel () {} - void visit (AST::TupleStruct &struct_decl) { resolver->get_type_scope ().insert (struct_decl.get_identifier (), @@ -88,6 +88,17 @@ public: } } + void visit (AST::InherentImpl &impl_block) + { + if (!ResolveType::go (impl_block.get_type ().get (), + impl_block.get_node_id ())) + return; + + for (auto &impl_item : impl_block.get_impl_items ()) + ResolveToplevelImplItem::go (impl_item.get (), + impl_block.get_type ().get ()); + } + private: ResolveTopLevel () : ResolverBase (UNKNOWN_NODEID) {} }; diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index b303ee9..258524b 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -28,14 +28,19 @@ namespace Resolver { class ResolveType : public ResolverBase { public: - static void go (AST::Type *type, NodeId parent) + static bool go (AST::Type *type, NodeId parent) { ResolveType resolver (parent); type->accept_vis (resolver); + if (!resolver.ok) + rust_error_at (type->get_locus_slow (), "unresolved type"); + + return resolver.ok; }; void visit (AST::BareFunctionType &fntype) { + ok = true; for (auto ¶m : fntype.get_function_params ()) ResolveType::go (param.get_type ().get (), fntype.get_node_id ()); @@ -45,6 +50,7 @@ public: void visit (AST::TupleType &tuple) { + ok = true; if (tuple.is_unit_type ()) { resolved_node = resolver->get_unit_type_node_id (); @@ -65,6 +71,8 @@ public: path.as_string ().c_str ()); return; } + + ok = true; resolver->insert_resolved_type (path.get_node_id (), resolved_node); resolver->insert_new_definition (path.get_node_id (), Definition{path.get_node_id (), parent}); @@ -76,7 +84,9 @@ public: } private: - ResolveType (NodeId parent) : ResolverBase (parent) {} + ResolveType (NodeId parent) : ResolverBase (parent), ok (false) {} + + bool ok; }; } // namespace Resolver diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index afc238b..281049d 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -550,8 +550,8 @@ Session::parse_file (const char *filename) type_resolution (hir); // FIXME this needs an option of itself - auto buf = Resolver::TypeResolverDump::go (hir); - fprintf (stderr, "%s\n", buf.c_str ()); + // auto buf = Resolver::TypeResolverDump::go (hir); + // fprintf (stderr, "%s\n", buf.c_str ()); if (saw_errors ()) return; diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h index 78afff9..8de1474 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.h +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -55,7 +55,6 @@ public: // virtual void visit(TraitItem& trait_item) {} // virtual void visit(InherentImplItem& inherent_impl_item) {} // virtual void visit(TraitImplItem& trait_impl_item) {} - virtual void visit (HIR::MacroInvocationSemi ¯o) {} // rust-path.h virtual void visit (HIR::PathInExpression &path) {} diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 78f0d0d..82977e4 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -37,10 +37,7 @@ public: expr->accept_vis (resolver); if (resolver.infered == nullptr) - { - resolver.infered - = new TyTy::UnitType (expr->get_mappings ().get_hirid ()); - } + return new TyTy::ErrorType (expr->get_mappings ().get_hirid ()); auto ref = expr->get_mappings ().get_hirid (); resolver.infered->set_ref (ref); @@ -428,73 +425,19 @@ public: { auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); - auto combined = lhs->combine (rhs); - // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators - switch (expr.get_expr_type ()) + bool valid_lhs = validate_arithmetic_type (lhs, expr.get_expr_type ()); + bool valid_rhs = validate_arithmetic_type (rhs, expr.get_expr_type ()); + bool valid = valid_lhs && valid_rhs; + if (!valid) { - // 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; + rust_error_at (expr.get_locus (), + "cannot apply this operator to types %s and %s", + lhs->as_string ().c_str (), rhs->as_string ().c_str ()); + return; } - infered = combined; + infered = lhs->combine (rhs); infered->append_reference (lhs->get_ref ()); infered->append_reference (rhs->get_ref ()); } @@ -594,7 +537,10 @@ public: { auto expected_ty = context->peek_return_type (); infered = expected_ty->combine (blk_expr); + return; } + + infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } void visit (HIR::IfExprConseqElse &expr) @@ -633,7 +579,10 @@ public: auto else_blk_combined = expected_ty->combine (else_block_tyty); infered = if_blk_combined->combine (else_blk_combined); + return; } + + infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } void visit (HIR::IfExprConseqIf &expr) @@ -649,7 +598,10 @@ public: infered = expected_ty->combine (if_blk); infered = infered->combine (elif_blk); + return; } + + infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } void visit (HIR::BlockExpr &expr); @@ -769,12 +721,86 @@ public: infered = resolved->get_field_type (); } + void visit (HIR::PathInExpression &expr) + { + NodeId ast_node_id = expr.get_mappings ().get_nodeid (); + + // then lookup the reference_node_id + NodeId ref_node_id; + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + { + if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id)) + { + rust_error_at (expr.get_locus (), + "Failed to lookup reference for node: %s", + expr.as_string ().c_str ()); + return; + } + } + + // node back to HIR + HirId ref; + if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), + ref_node_id, &ref)) + { + rust_error_at (expr.get_locus (), "reverse lookup failure"); + return; + } + + context->lookup_type (ref, &infered); + } + private: TypeCheckExpr (bool is_final_expr) : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr), is_final_expr (is_final_expr) {} + bool + validate_arithmetic_type (TyTy::TyBase *type, + HIR::ArithmeticOrLogicalExpr::ExprType expr_type) + { + // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators + // this will change later when traits are added + switch (expr_type) + { + case HIR::ArithmeticOrLogicalExpr::ADD: + case HIR::ArithmeticOrLogicalExpr::SUBTRACT: + case HIR::ArithmeticOrLogicalExpr::MULTIPLY: + case HIR::ArithmeticOrLogicalExpr::DIVIDE: + case HIR::ArithmeticOrLogicalExpr::MODULUS: + return (type->get_kind () == TyTy::TypeKind::INT) + || (type->get_kind () == TyTy::TypeKind::UINT) + || (type->get_kind () == TyTy::TypeKind::FLOAT) + || (type->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) type)->get_infer_kind () + == TyTy::InferType::INTEGRAL)) + || (type->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) type)->get_infer_kind () + == TyTy::InferType::FLOAT)); + + // integers or bools + case HIR::ArithmeticOrLogicalExpr::BITWISE_AND: + case HIR::ArithmeticOrLogicalExpr::BITWISE_OR: + case HIR::ArithmeticOrLogicalExpr::BITWISE_XOR: + return (type->get_kind () == TyTy::TypeKind::INT) + || (type->get_kind () == TyTy::TypeKind::UINT) + || (type->get_kind () == TyTy::TypeKind::BOOL) + || (type->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) type)->get_infer_kind () + == TyTy::InferType::INTEGRAL)); + + // integers only + case HIR::ArithmeticOrLogicalExpr::LEFT_SHIFT: + case HIR::ArithmeticOrLogicalExpr::RIGHT_SHIFT: + return (type->get_kind () == TyTy::TypeKind::INT) + || (type->get_kind () == TyTy::TypeKind::UINT) + || (type->get_kind () == TyTy::TypeKind::INFER + && (((TyTy::InferType *) type)->get_infer_kind () + == TyTy::InferType::INTEGRAL)); + } + } + TyTy::TyBase *infered; TyTy::TyBase *infered_array_elems; diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h new file mode 100644 index 0000000..abaee73 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -0,0 +1,149 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_IMPLITEM_H +#define RUST_HIR_TYPE_CHECK_IMPLITEM_H + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-type.h" +#include "rust-hir-type-check-expr.h" +#include "rust-tyty.h" + +namespace Rust { +namespace Resolver { + +class TypeCheckTopLevelImplItem : public TypeCheckBase +{ +public: + static void Resolve (HIR::InherentImplItem *item) + { + TypeCheckTopLevelImplItem resolver; + item->accept_vis (resolver); + } + + void visit (HIR::ConstantItem &constant) + { + TyTy::TyBase *type = TypeCheckType::Resolve (constant.get_type ()); + TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); + + context->insert_type (constant.get_mappings (), type->combine (expr_type)); + } + + void visit (HIR::Function &function) + { + TyTy::TyBase *ret_type = nullptr; + if (!function.has_function_return_type ()) + ret_type = new TyTy::UnitType (function.get_mappings ().get_hirid ()); + else + { + 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<std::pair<HIR::Pattern *, TyTy::TyBase *> > params; + for (auto ¶m : function.function_params) + { + // get the name as well required for later on + auto param_tyty = TypeCheckType::Resolve (param.get_type ()); + params.push_back ( + std::pair<HIR::Pattern *, TyTy::TyBase *> (param.get_param_name (), + 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 (), fnType); + } + +private: + TypeCheckTopLevelImplItem () : TypeCheckBase () {} +}; + +class TypeCheckImplItem : public TypeCheckBase +{ +public: + static void Resolve (HIR::InherentImplItem *item, TyTy::TyBase *self) + { + TypeCheckImplItem resolver (self); + item->accept_vis (resolver); + } + + void visit (HIR::Function &function) + { + 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 + 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 (); + } + +private: + TypeCheckImplItem (TyTy::TyBase *self) : TypeCheckBase (), self (self) {} + + TyTy::TyBase *self; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_IMPLITEM_H diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index d7f9af1..571d998 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -21,6 +21,7 @@ #include "rust-hir-type-check-base.h" #include "rust-hir-full.h" +#include "rust-hir-type-check-implitem.h" #include "rust-hir-type-check-type.h" #include "rust-hir-type-check-stmt.h" #include "rust-tyty-visitor.h" @@ -37,6 +38,21 @@ public: item->accept_vis (resolver); } + void visit (HIR::InherentImpl &impl_block) + { + TyTy::TyBase *self = nullptr; + if (!context->lookup_type ( + impl_block.get_type ()->get_mappings ().get_hirid (), &self)) + { + rust_error_at (impl_block.get_locus (), + "failed to resolve Self for InherentImpl"); + return; + } + + for (auto &impl_item : impl_block.get_impl_items ()) + TypeCheckImplItem::Resolve (impl_item.get (), self); + } + void visit (HIR::Function &function) { TyTy::TyBase *lookup; diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index 99be0b7..e04284e 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -56,6 +56,8 @@ public: { init_expr_ty = TypeCheckExpr::Resolve (stmt.get_init_expr (), is_final_stmt); + if (init_expr_ty == nullptr) + return; init_expr_ty = init_expr_ty->clone (); auto ref = init_expr_ty->get_ref (); diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 52b6cde..46b3b0f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -21,6 +21,7 @@ #include "rust-hir-type-check-base.h" #include "rust-hir-full.h" +#include "rust-hir-type-check-implitem.h" #include "rust-hir-type-check-type.h" #include "rust-hir-type-check-expr.h" #include "rust-tyty.h" @@ -134,6 +135,15 @@ public: context->insert_type (function.get_mappings (), fnType); } + void visit (HIR::InherentImpl &impl_block) + { + TypeCheckType::Resolve (impl_block.get_type ().get ()); + for (auto &impl_item : impl_block.get_impl_items ()) + { + TypeCheckTopLevelImplItem::Resolve (impl_item.get ()); + } + } + private: TypeCheckTopLevel () : TypeCheckBase () {} }; diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index cf3a846..416cd89 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -23,6 +23,9 @@ #include "rust-hir-type-check-expr.h" #include "rust-hir-type-check-struct-field.h" +extern bool +saw_errors (void); + namespace Rust { namespace Resolver { @@ -32,13 +35,26 @@ TypeResolution::Resolve (HIR::Crate &crate) for (auto it = crate.items.begin (); it != crate.items.end (); it++) TypeCheckTopLevel::Resolve (it->get ()); + if (saw_errors ()) + return; + for (auto it = crate.items.begin (); it != crate.items.end (); it++) TypeCheckItem::Resolve (it->get ()); + if (saw_errors ()) + return; + auto mappings = Analysis::Mappings::get (); auto context = TypeCheckContext::get (); context->iterate ([&] (HirId id, TyTy::TyBase *ty) mutable -> bool { + if (ty->get_kind () == TyTy::TypeKind::ERROR) + { + rust_error_at (mappings->lookup_location (id), + "failure in type resolution"); + return false; + } + // nothing to do if (ty->get_kind () != TyTy::TypeKind::INFER) return true; diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h index 863c2eb..0d8fffc 100644 --- a/gcc/rust/typecheck/rust-tycheck-dump.h +++ b/gcc/rust/typecheck/rust-tycheck-dump.h @@ -37,6 +37,30 @@ public: return dumper.dump; } + void visit (HIR::InherentImpl &impl_block) + { + dump += indent () + "impl " + + type_string (impl_block.get_type ()->get_mappings ()) + " {\n"; + indentation_level++; + + for (auto &impl_item : impl_block.get_impl_items ()) + { + impl_item->accept_vis (*this); + dump += "\n"; + } + + indentation_level--; + dump += indent () + "}\n"; + } + + void visit (HIR::ConstantItem &constant) + { + dump += indent () + "constant " + constant.get_identifier () + ":" + + type_string (constant.get_mappings ()) + " = "; + constant.get_expr ()->accept_vis (*this); + dump += ";\n"; + } + void visit (HIR::Function &function) { dump += indent () + "fn " + function.function_name + " " @@ -54,6 +78,7 @@ public: indentation_level++; expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { + dump += indent (); s->accept_vis (*this); dump += ";\n"; return true; @@ -61,6 +86,7 @@ public: if (expr.has_expr () && expr.tail_expr_reachable ()) { + dump += indent (); expr.expr->accept_vis (*this); dump += ";\n"; } @@ -70,7 +96,7 @@ public: void visit (HIR::LetStmt &stmt) { - dump += indent () + "let " + stmt.get_pattern ()->as_string () + ":" + dump += "let " + stmt.get_pattern ()->as_string () + ":" + type_string (stmt.get_mappings ()); if (stmt.has_init_expr ()) { @@ -81,13 +107,11 @@ public: 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); } @@ -136,6 +160,11 @@ public: dump += ")"; } + void visit (HIR::PathInExpression &expr) + { + dump += type_string (expr.get_mappings ()); + } + protected: std::string type_string (const Analysis::NodeMapping &mappings) { @@ -152,6 +181,7 @@ protected: buf += "]"; return "<" + lookup->as_string () + + " HIRID: " + std::to_string (mappings.get_hirid ()) + " RF:" + std::to_string (lookup->get_ref ()) + " TF:" + std::to_string (lookup->get_ty_ref ()) + +" - " + buf + ">"; } diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 925130f..eb55581 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -259,6 +259,30 @@ Mappings::lookup_hir_item (CrateNum crateNum, HirId id) } void +Mappings::insert_hir_implitem (CrateNum crateNum, HirId id, + HIR::InherentImplItem *item) +{ + rust_assert (lookup_hir_implitem (crateNum, id) == nullptr); + + hirImplItemMappings[crateNum][id] = item; + nodeIdToHirMappings[crateNum][item->get_impl_mappings ().get_nodeid ()] = id; +} + +HIR::InherentImplItem * +Mappings::lookup_hir_implitem (CrateNum crateNum, HirId id) +{ + auto it = hirImplItemMappings.find (crateNum); + if (it == hirImplItemMappings.end ()) + return nullptr; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return nullptr; + + return iy->second; +} + +void Mappings::insert_hir_expr (CrateNum crateNum, HirId id, HIR::Expr *expr) { hirExprMappings[crateNum][id] = expr; diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 4859d1e..f81cee6 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -109,6 +109,10 @@ public: void insert_hir_item (CrateNum crateNum, HirId id, HIR::Item *item); HIR::Item *lookup_hir_item (CrateNum crateNum, HirId id); + void insert_hir_implitem (CrateNum crateNum, HirId id, + HIR::InherentImplItem *item); + HIR::InherentImplItem *lookup_hir_implitem (CrateNum crateNum, HirId id); + void insert_hir_expr (CrateNum crateNum, HirId id, HIR::Expr *expr); HIR::Expr *lookup_hir_expr (CrateNum crateNum, HirId id); @@ -170,6 +174,8 @@ private: std::map<CrateNum, std::map<HirId, HIR::FunctionParam *> > hirParamMappings; std::map<CrateNum, std::map<HirId, HIR::StructExprField *> > hirStructFieldMappings; + std::map<CrateNum, std::map<HirId, HIR::InherentImplItem *> > + hirImplItemMappings; // location info std::map<CrateNum, std::map<NodeId, Location> > locations; diff --git a/gcc/testsuite/rust.test/compilable/impl_block1.rs b/gcc/testsuite/rust.test/compilable/impl_block1.rs new file mode 100644 index 0000000..d67afa1 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/impl_block1.rs @@ -0,0 +1,23 @@ +struct Foo(i32, bool); + +impl Foo { + fn new(a: i32, b: bool) -> Foo { + Foo(a, b) + } + + fn test2() -> i32 { + test_forward_decl() + } +} + +fn test_forward_decl() -> i32 { + 123 +} + +fn main() { + let a; + a = Foo::new(1, true); + + let b; + b = Foo::test2(); +} diff --git a/gcc/testsuite/rust.test/compilable/impl_block2.rs b/gcc/testsuite/rust.test/compilable/impl_block2.rs new file mode 100644 index 0000000..0ed592d --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/impl_block2.rs @@ -0,0 +1,28 @@ +struct Foo(i32, bool); + +impl Foo { + const number: i32 = 456; + + fn new(a: i32, b: bool) -> Foo { + Foo(a, b) + } + + fn test2() -> i32 { + test_forward_decl() + } +} + +fn test_forward_decl() -> i32 { + 123 +} + +fn main() { + let a; + a = Foo::new(1, true); + + let b; + b = Foo::test2(); + + let c; + c = Foo::new(Foo::number, true); +} diff --git a/gcc/testsuite/rust.test/compilable/integer_inference_var1.rs b/gcc/testsuite/rust.test/compilable/integer_inference_var1.rs new file mode 100644 index 0000000..ccee06a --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/integer_inference_var1.rs @@ -0,0 +1,6 @@ +const TEST_CONST: i32 = 10; + +fn main() { + let a; + a = TEST_CONST; +} diff --git a/gcc/testsuite/rust.test/compilable/integer_inference_var2.rs b/gcc/testsuite/rust.test/compilable/integer_inference_var2.rs new file mode 100644 index 0000000..2209e93 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/integer_inference_var2.rs @@ -0,0 +1,6 @@ +fn main() { + let a = 1u32; + + let b; + b = a; +} diff --git a/gcc/testsuite/rust.test/compilable/integer_inference_var3.rs b/gcc/testsuite/rust.test/compilable/integer_inference_var3.rs new file mode 100644 index 0000000..858c5d3 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/integer_inference_var3.rs @@ -0,0 +1,10 @@ +fn test(a: u32) -> u32 { + a + 1 +} + +fn main() { + let param; + param = 123; + + let a = test(param); +} diff --git a/gcc/testsuite/rust.test/compilable/integer_inference_var4.rs b/gcc/testsuite/rust.test/compilable/integer_inference_var4.rs new file mode 100644 index 0000000..136d818 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/integer_inference_var4.rs @@ -0,0 +1,4 @@ +fn main() { + let a; + a = 1; +} diff --git a/gcc/testsuite/rust.test/compilable/integer_inference_var5.rs b/gcc/testsuite/rust.test/compilable/integer_inference_var5.rs new file mode 100644 index 0000000..6b97de5 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/integer_inference_var5.rs @@ -0,0 +1,23 @@ +const TEST_CONST: i32 = 10; + +fn test(x: u32) -> u32 { + x + 1 +} + +fn main() { + let x = TEST_CONST; + + let a = 1u32; + let b = a; + + let c; + c = 1; + + let d; + d = b; + + let param; + param = 123; + + let test_call = test(param); +} diff --git a/gcc/testsuite/rust.test/compilable/ints_infer1.rs b/gcc/testsuite/rust.test/compilable/ints_infer1.rs deleted file mode 100644 index 3170c7c..0000000 --- a/gcc/testsuite/rust.test/compilable/ints_infer1.rs +++ /dev/null @@ -1,18 +0,0 @@ -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; -} |