diff options
Diffstat (limited to 'gcc')
55 files changed, 2075 insertions, 867 deletions
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 74a6473..511c30d 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -2399,9 +2399,9 @@ public: void iterate_params (std::function<bool (Expr *)> cb) { - for (auto it = params.begin (); it != params.end (); it++) + for (auto ¶m : params) { - if (!cb (it->get ())) + if (!cb (param.get ())) return; } } @@ -2504,6 +2504,15 @@ public: void mark_for_strip () override { receiver = nullptr; } bool is_marked_for_strip () const override { return receiver == nullptr; } + void iterate_params (std::function<bool (Expr *)> cb) + { + for (auto ¶m : params) + { + if (!cb (param.get ())) + return; + } + } + // TODO: this mutable getter seems really dodgy. Think up better way. const std::vector<std::unique_ptr<Expr> > &get_params () const { diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 9437f21..a6f5398 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -366,12 +366,14 @@ private: // bool has_type; // only possible if not ref std::unique_ptr<Type> type; + NodeId node_id; + Location locus; // Unrestricted constructor used for error state SelfParam (Lifetime lifetime, bool has_ref, bool is_mut, Type *type) : has_ref (has_ref), is_mut (is_mut), lifetime (std::move (lifetime)), - type (type) + type (type), node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // this is ok as no outside classes can ever call this @@ -401,20 +403,23 @@ public: // Type-based self parameter (not ref, no lifetime) SelfParam (std::unique_ptr<Type> type, bool is_mut, Location locus) : has_ref (false), is_mut (is_mut), lifetime (Lifetime::error ()), - type (std::move (type)), locus (locus) + type (std::move (type)), + node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus) {} // Lifetime-based self parameter (is ref, no type) SelfParam (Lifetime lifetime, bool is_mut, Location locus) : has_ref (true), is_mut (is_mut), lifetime (std::move (lifetime)), - locus (locus) + node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus) {} // Copy constructor requires clone SelfParam (SelfParam const &other) : has_ref (other.has_ref), is_mut (other.is_mut), lifetime (other.lifetime), + node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (other.locus) { + node_id = other.node_id; if (other.type != nullptr) type = other.type->clone_type (); } @@ -426,6 +431,7 @@ public: has_ref = other.has_ref; lifetime = other.lifetime; locus = other.locus; + node_id = other.node_id; if (other.type != nullptr) type = other.type->clone_type (); @@ -443,6 +449,13 @@ public: Location get_locus () const { return locus; } + bool get_has_ref () const { return has_ref; }; + bool get_is_mut () const { return is_mut; } + + Lifetime get_lifetime () const { return lifetime; } + + NodeId get_node_id () const { return node_id; } + // TODO: is this better? Or is a "vis_block" better? std::unique_ptr<Type> &get_type () { diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index e89fc62..049aaf0 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -78,7 +78,7 @@ class IdentifierPattern : public Pattern Location locus; public: - std::string as_string () const; + std::string as_string () const override; // Returns whether the IdentifierPattern has a pattern to bind. bool has_pattern_to_bind () const { return to_bind != nullptr; } @@ -91,6 +91,15 @@ public: is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus) {} + IdentifierPattern (NodeId node_id, Identifier ident, Location locus, + bool is_ref = false, bool is_mut = false, + std::unique_ptr<Pattern> to_bind = nullptr) + : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), + is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus) + { + this->node_id = node_id; + } + // Copy constructor with clone IdentifierPattern (IdentifierPattern const &other) : variable_ident (other.variable_ident), is_ref (other.is_ref), diff --git a/gcc/rust/backend/cscope.h b/gcc/rust/backend/cscope.h deleted file mode 100644 index 3ba837c..0000000 --- a/gcc/rust/backend/cscope.h +++ /dev/null @@ -1,160 +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/>. - -#pragma once - -#include "rust-system.h" -#include "rust-backend.h" -#include "scope.h" - -namespace Rust { -namespace Compile { - -class Scope -{ -public: - Scope (Backend *backend) : backend (backend) {} - - ~Scope () {} - - void Push () - { - fndecls.Push (); - vars.Push (); - types.Push (); - structDecls.Push (); - } - - void Pop () - { - fndecls.Pop (); - vars.Pop (); - types.Pop (); - structDecls.Pop (); - } - - void PushCurrentFunction (std::string name, Bfunction *fn, Btype *retType, - Bvariable *retDecl) - { - fns.push_back (fn); - fnRetType.push_back (retType); - fnRetDecl.push_back (retDecl); - } - - Bfunction *PopCurrentFunction () - { - auto ret = fns.back (); - fns.pop_back (); - fnRetType.pop_back (); - fnRetDecl.pop_back (); - return ret; - } - - Bfunction *GetCurrentFndecl () { return fns.back (); } - - Btype *GetCurrentFnRetType () { return fnRetType.back (); } - - Bvariable *GetCurrentFnRetDecl () { return fnRetDecl.back (); } - - Btype *GetFnRetType (Bfunction *fn) - { - auto it = fnRetTypeMapping.find (fn); - if (it == fnRetTypeMapping.end ()) - { - return NULL; - } - return it->second; - } - - void PushBlock (Bblock *block) - { - blocks.push_back (block); - std::vector<Bstatement *> empty; - context.push_back (empty); - } - - Bblock *PopBlock () - { - auto ret = blocks.back (); - blocks.pop_back (); - - auto stmts = context.back (); - context.pop_back (); - - backend->block_add_statements (ret, stmts); - - return ret; - } - - Bblock *CurBlock () { return blocks.back (); } - - void AddStatement (Bstatement *stmt) { context.back ().push_back (stmt); } - - void InsertStructDecl (std::string name, AST::StructStruct *decl) - { - structDecls.Insert (name, decl); - } - - bool LookupStructDecl (std::string name, AST::StructStruct **decl) - { - return structDecls.Lookup (name, decl); - } - - void InsertFunction (std::string name, Bfunction *fn, Btype *retType) - { - fndecls.Insert (name, fn); - fnRetTypeMapping[fn] = retType; - } - - bool LookupFunction (std::string name, Bfunction **fn) - { - return fndecls.Lookup (name, fn); - } - - void InsertType (std::string name, Btype *type) { types.Insert (name, type); } - - bool LookupType (std::string name, Btype **type) - { - return types.Lookup (name, type); - } - - void InsertVar (std::string name, Bvariable *var) { vars.Insert (name, var); } - - bool LookupVar (std::string name, Bvariable **var) - { - return vars.Lookup (name, var); - } - -private: - Backend *backend; - - ::std::vector<Bfunction *> fns; - ::std::vector<Bblock *> blocks; - ::std::vector< ::std::vector<Bstatement *> > context; - ::std::vector< ::Btype *> fnRetType; - ::std::vector< ::Bvariable *> fnRetDecl; - ::std::map<Bfunction *, Btype *> fnRetTypeMapping; - - Analysis::Scope<Bfunction *> fndecls; - Analysis::Scope<Bvariable *> vars; - Analysis::Scope<Btype *> types; - Analysis::Scope<AST::StructStruct *> structDecls; -}; - -} // namespace Compile -} // namespace Rust diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index fdc5ad9..ec7c13a 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -237,9 +237,13 @@ public: protected: HIRCompileBase (Context *ctx) : ctx (ctx) {} + Context *ctx; + Context *get_context () { return ctx; } - Context *ctx; + void compile_function_body (Bfunction *fndecl, + std::unique_ptr<HIR::BlockExpr> &function_body, + bool has_return_type); }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-block.h b/gcc/rust/backend/rust-compile-block.h index b17fb05..879e32d 100644 --- a/gcc/rust/backend/rust-compile-block.h +++ b/gcc/rust/backend/rust-compile-block.h @@ -28,35 +28,35 @@ namespace Compile { class CompileBlock : public HIRCompileBase { public: - static Bblock *compile (HIR::BlockExpr *expr, Context *ctx) + static Bblock *compile (HIR::BlockExpr *expr, Context *ctx, Bvariable *result) { - CompileBlock compiler (ctx); + CompileBlock compiler (ctx, result); expr->accept_vis (compiler); return compiler.translated; } - ~CompileBlock () {} - void visit (HIR::BlockExpr &expr); private: - CompileBlock (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} + CompileBlock (Context *ctx, Bvariable *result) + : HIRCompileBase (ctx), translated (nullptr), result (result) + {} Bblock *translated; + Bvariable *result; }; class CompileConditionalBlocks : public HIRCompileBase { public: - static Bstatement *compile (HIR::IfExpr *expr, Context *ctx) + static Bstatement *compile (HIR::IfExpr *expr, Context *ctx, + Bvariable *result) { - CompileConditionalBlocks resolver (ctx); + CompileConditionalBlocks resolver (ctx, result); expr->accept_vis (resolver); return resolver.translated; } - ~CompileConditionalBlocks () {} - void visit (HIR::IfExpr &expr); void visit (HIR::IfExprConseqElse &expr); @@ -64,46 +64,47 @@ public: void visit (HIR::IfExprConseqIf &expr); private: - CompileConditionalBlocks (Context *ctx) - : HIRCompileBase (ctx), translated (nullptr) + CompileConditionalBlocks (Context *ctx, Bvariable *result) + : HIRCompileBase (ctx), translated (nullptr), result (result) {} Bstatement *translated; + Bvariable *result; }; class CompileExprWithBlock : public HIRCompileBase { public: - static Bstatement *compile (HIR::ExprWithBlock *expr, Context *ctx) + static Bstatement *compile (HIR::ExprWithBlock *expr, Context *ctx, + Bvariable *result) { - CompileExprWithBlock resolver (ctx); + CompileExprWithBlock resolver (ctx, result); expr->accept_vis (resolver); return resolver.translated; } - ~CompileExprWithBlock () {} - void visit (HIR::IfExpr &expr) { - translated = CompileConditionalBlocks::compile (&expr, ctx); + translated = CompileConditionalBlocks::compile (&expr, ctx, result); } void visit (HIR::IfExprConseqElse &expr) { - translated = CompileConditionalBlocks::compile (&expr, ctx); + translated = CompileConditionalBlocks::compile (&expr, ctx, result); } void visit (HIR::IfExprConseqIf &expr) { - translated = CompileConditionalBlocks::compile (&expr, ctx); + translated = CompileConditionalBlocks::compile (&expr, ctx, result); } private: - CompileExprWithBlock (Context *ctx) - : HIRCompileBase (ctx), translated (nullptr) + CompileExprWithBlock (Context *ctx, Bvariable *result) + : HIRCompileBase (ctx), translated (nullptr), result (result) {} Bstatement *translated; + Bvariable *result; }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 034568f..25c9b89 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -110,6 +110,11 @@ public: return scope_stack.back (); } + void add_statement_to_enclosing_scope (Bstatement *stmt) + { + statements.at (statements.size () - 2).push_back (stmt); + } + void add_statement (Bstatement *stmt) { statements.back ().push_back (stmt); } void insert_var_decl (HirId id, ::Bvariable *decl) @@ -222,11 +227,11 @@ public: virtual ~TyTyResolveCompile () {} - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } + void visit (TyTy::ErrorType &) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } + void visit (TyTy::InferType &) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } + void visit (TyTy::StructFieldType &) override { gcc_unreachable (); } void visit (TyTy::FnType &type) override { @@ -261,7 +266,7 @@ public: ctx->get_mappings ()->lookup_location (type.get_ref ())); } - void visit (TyTy::UnitType &type) override + void visit (TyTy::UnitType &) override { translated = ctx->get_backend ()->void_type (); } @@ -278,8 +283,7 @@ public: { TyTy::StructFieldType *field = type.get_field (i); Btype *compiled_field_ty - = TyTyCompile::compile (ctx->get_backend (), - field->get_field_type ()); + = TyTyResolveCompile::compile (ctx, field->get_field_type ()); Backend::Btyped_identifier f (field->get_name (), compiled_field_ty, ctx->get_mappings ()->lookup_location ( diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index ccff51a..b823d29 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -99,6 +99,8 @@ public: void visit (HIR::CallExpr &expr); + void visit (HIR::MethodCallExpr &expr); + void visit (HIR::IdentifierExpr &expr) { // need to look up the reference for this identifier @@ -409,27 +411,71 @@ public: void visit (HIR::IfExpr &expr) { - auto stmt = CompileConditionalBlocks::compile (&expr, ctx); + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr); ctx->add_statement (stmt); } void visit (HIR::IfExprConseqElse &expr) { - auto stmt = CompileConditionalBlocks::compile (&expr, ctx); + // this can be a return expression + TyTy::TyBase *if_type = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &if_type)) + { + rust_error_at (expr.get_locus (), + "failed to lookup type of IfExprConseqElse"); + return; + } + + fncontext fnctx = ctx->peek_fn (); + Bblock *enclosing_scope = ctx->peek_enclosing_scope (); + Btype *block_type = TyTyResolveCompile::compile (ctx, if_type); + + bool is_address_taken = false; + Bstatement *ret_var_stmt = nullptr; + Bvariable *tmp = ctx->get_backend ()->temporary_variable ( + fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, + expr.get_locus (), &ret_var_stmt); + ctx->add_statement (ret_var_stmt); + + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp); ctx->add_statement (stmt); + + translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); } void visit (HIR::IfExprConseqIf &expr) { - auto stmt = CompileConditionalBlocks::compile (&expr, ctx); + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr); ctx->add_statement (stmt); } void visit (HIR::BlockExpr &expr) { - auto code_block = CompileBlock::compile (&expr, ctx); + TyTy::TyBase *block_tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &block_tyty)) + { + rust_error_at (expr.get_locus (), "failed to lookup type of BlockExpr"); + return; + } + + fncontext fnctx = ctx->peek_fn (); + Bblock *enclosing_scope = ctx->peek_enclosing_scope (); + Btype *block_type = TyTyResolveCompile::compile (ctx, block_tyty); + + bool is_address_taken = false; + Bstatement *ret_var_stmt = nullptr; + Bvariable *tmp = ctx->get_backend ()->temporary_variable ( + fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, + expr.get_locus (), &ret_var_stmt); + ctx->add_statement (ret_var_stmt); + + auto code_block = CompileBlock::compile (&expr, ctx, tmp); auto block_stmt = ctx->get_backend ()->block_statement (code_block); ctx->add_statement (block_stmt); + + translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); } void visit (HIR::StructExprStructFields &struct_expr) diff --git a/gcc/rust/backend/rust-compile-fnparam.h b/gcc/rust/backend/rust-compile-fnparam.h index cf6e6f7..1ea0c9f 100644 --- a/gcc/rust/backend/rust-compile-fnparam.h +++ b/gcc/rust/backend/rust-compile-fnparam.h @@ -61,6 +61,22 @@ private: ::Bvariable *translated; }; +class CompileSelfParam : public HIRCompileBase +{ +public: + static Bvariable *compile (Context *ctx, Bfunction *fndecl, + HIR::SelfParam &self, Btype *decl_type, + Location locus) + { + if (!self.get_is_mut ()) + decl_type = ctx->get_backend ()->immutable_type (decl_type); + + return ctx->get_backend ()->parameter_variable (fndecl, "self", decl_type, + false /* address_taken */, + locus); + } +}; + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h index fe2abf1..6d180c8 100644 --- a/gcc/rust/backend/rust-compile-implitem.h +++ b/gcc/rust/backend/rust-compile-implitem.h @@ -32,10 +32,10 @@ namespace Compile { class CompileInherentImplItem : public HIRCompileBase { public: - static void Compile (HIR::Type *base, HIR::InherentImplItem *item, + static void Compile (TyTy::TyBase *self, HIR::InherentImplItem *item, Context *ctx, bool compile_fns) { - CompileInherentImplItem compiler (base, ctx, compile_fns); + CompileInherentImplItem compiler (self, ctx, compile_fns); item->accept_vis (compiler); } @@ -50,7 +50,7 @@ public: ::Btype *type = TyTyResolveCompile::compile (ctx, resolved_type); Bexpression *value = CompileExpr::Compile (constant.get_expr (), ctx); - std::string ident = base->as_string () + "::" + constant.get_identifier (); + std::string ident = self->as_string () + "::" + constant.get_identifier (); Bexpression *const_expr = ctx->get_backend ()->named_constant_expression ( type, constant.get_identifier (), value, constant.get_locus ()); @@ -78,7 +78,8 @@ public: if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (), &fntype_tyty)) { - rust_fatal_error (function.locus, "failed to lookup function type"); + rust_fatal_error (function.get_locus (), + "failed to lookup function type"); return; } @@ -93,23 +94,15 @@ public: ::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; + = self->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 ()) + if (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 ()); @@ -213,34 +206,219 @@ public: ctx->push_fn (fndecl, return_address); - // compile the block - function_body->iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { - CompileStmt::Compile (s, ctx); + compile_function_body (fndecl, function.function_body, + function.has_function_return_type ()); + + 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); + } + + void visit (HIR::Method &method) + { + 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 (method.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 (method.get_mappings ().get_hirid (), + &fntype_tyty)) + { + rust_fatal_error (method.get_locus (), + "failed to lookup function type"); + return; + } + + if (fntype_tyty->get_kind () != TyTy::TypeKind::FNDEF) + { + rust_error_at (method.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; + std::string fn_identifier + = self->as_string () + "::" + method.get_method_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 (method.has_visibility ()) + flags |= Backend::function_is_visible; + + std::string asm_name = fn_identifier; + Bfunction *fndecl + = ctx->get_backend ()->function (compiled_fn_type, fn_identifier, + asm_name, flags, method.get_locus ()); + ctx->insert_function_decl (method.get_mappings ().get_hirid (), fndecl); + + // setup the params + TyTy::TyBase *tyret = fntype->return_type (); + std::vector<Bvariable *> param_vars; + + // insert self + TyTy::TyBase *self_tyty_lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + method.get_self_param ().get_mappings ().get_hirid (), + &self_tyty_lookup)) + { + rust_error_at (method.get_self_param ().get_locus (), + "failed to lookup self param type"); + return; + } + + Btype *self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup); + if (self_type == nullptr) + { + rust_error_at (method.get_self_param ().get_locus (), + "failed to compile self param type"); + return; + } + + Bvariable *compiled_self_param + = CompileSelfParam::compile (ctx, fndecl, method.get_self_param (), + self_type, + method.get_self_param ().get_locus ()); + if (compiled_self_param == nullptr) + { + rust_error_at (method.get_self_param ().get_locus (), + "failed to compile self param variable"); + return; + } + + param_vars.push_back (compiled_self_param); + ctx->insert_var_decl (method.get_self_param ().get_mappings ().get_hirid (), + compiled_self_param); + + // offset from + 1 for the TyTy::FnType being used + size_t i = 1; + for (auto referenced_param : method.get_function_params ()) + { + auto tyty_param = fntype->param_at (i); + auto param_tyty = tyty_param.second; + + auto compiled_param_type + = TyTyResolveCompile::compile (ctx, param_tyty); + if (compiled_param_type == nullptr) + { + rust_error_at (referenced_param.get_locus (), + "failed to compile parameter type"); + return; + } + + 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 (method.get_locus (), + "failed to setup parameter variables"); + return; + } + + // lookup locals + auto block_expr = method.get_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 (method.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; }); - if (function_body->has_expr () && function_body->tail_expr_reachable ()) + bool toplevel_item + = method.get_mappings ().get_local_defid () != UNKNOWN_LOCAL_DEFID; + Bblock *enclosing_scope + = toplevel_item ? NULL : ctx->peek_enclosing_scope (); + + HIR::BlockExpr *function_body = method.get_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 (method.has_function_return_type ()) { - // 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); + 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, + method.get_locus (), &ret_var_stmt); + + ctx->add_statement (ret_var_stmt); } + ctx->push_fn (fndecl, return_address); + + compile_function_body (fndecl, method.get_function_body (), + method.has_function_return_type ()); + 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"); + rust_error_at (method.get_locus (), "failed to set body to function"); return; } @@ -250,11 +428,11 @@ public: } private: - CompileInherentImplItem (HIR::Type *base, Context *ctx, bool compile_fns) - : HIRCompileBase (ctx), base (base), compile_fns (compile_fns) + CompileInherentImplItem (TyTy::TyBase *self, Context *ctx, bool compile_fns) + : HIRCompileBase (ctx), self (self), compile_fns (compile_fns) {} - HIR::Type *base; + TyTy::TyBase *self; bool compile_fns; }; diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 83e4451..7f93af9f 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -265,28 +265,8 @@ public: 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); - } + compile_function_body (fndecl, function.function_body, + function.has_function_return_type ()); ctx->pop_block (); auto body = ctx->get_backend ()->block_statement (code_block); @@ -297,15 +277,23 @@ public: } ctx->pop_fn (); - ctx->push_function (fndecl); } void visit (HIR::InherentImpl &impl_block) { + TyTy::TyBase *self_lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + impl_block.get_type ()->get_mappings ().get_hirid (), &self_lookup)) + { + rust_error_at (impl_block.get_locus (), + "failed to resolve type of impl"); + return; + } + for (auto &impl_item : impl_block.get_impl_items ()) - CompileInherentImplItem::Compile (impl_block.get_type ().get (), - impl_item.get (), ctx, compile_fns); + CompileInherentImplItem::Compile (self_lookup, impl_item.get (), ctx, + compile_fns); } private: diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h index c52f605..d021240e4 100644 --- a/gcc/rust/backend/rust-compile-stmt.h +++ b/gcc/rust/backend/rust-compile-stmt.h @@ -29,37 +29,24 @@ namespace Compile { class CompileStmt : public HIRCompileBase { public: - static void Compile (HIR::Stmt *stmt, Context *ctx) + static Bexpression *Compile (HIR::Stmt *stmt, Context *ctx) { CompileStmt compiler (ctx); stmt->accept_vis (compiler); rust_assert (compiler.ok); + return compiler.translated; } - virtual ~CompileStmt () {} - void visit (HIR::ExprStmtWithBlock &stmt) { ok = true; - auto translated = CompileExpr::Compile (stmt.get_expr (), ctx); - - // these can be null - if (translated == nullptr) - return; - - gcc_unreachable (); + translated = CompileExpr::Compile (stmt.get_expr (), ctx); } void visit (HIR::ExprStmtWithoutBlock &stmt) { ok = true; - auto translated = CompileExpr::Compile (stmt.get_expr (), ctx); - - // these can be null - if (translated == nullptr) - return; - - gcc_unreachable (); + translated = CompileExpr::Compile (stmt.get_expr (), ctx); } void visit (HIR::LetStmt &stmt) @@ -99,9 +86,12 @@ public: } private: - CompileStmt (Context *ctx) : HIRCompileBase (ctx), ok (false) {} + CompileStmt (Context *ctx) + : HIRCompileBase (ctx), ok (false), translated (nullptr) + {} bool ok; + Bexpression *translated; }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index 2c54b17..0629cbe 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -44,22 +44,19 @@ public: ~TyTyCompile () {} - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } + void visit (TyTy::ErrorType &) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } + void visit (TyTy::InferType &) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } + void visit (TyTy::StructFieldType &) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } + void visit (TyTy::ADTType &) override { gcc_unreachable (); } - void visit (TyTy::TupleType &type) override { gcc_unreachable (); } + void visit (TyTy::TupleType &) override { gcc_unreachable (); } - void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } + void visit (TyTy::ArrayType &) override { gcc_unreachable (); } - void visit (TyTy::UnitType &type) override - { - translated = backend->void_type (); - } + void visit (TyTy::UnitType &) override { translated = backend->void_type (); } void visit (TyTy::FnType &type) override { @@ -93,7 +90,7 @@ public: mappings->lookup_location (type.get_ref ())); } - void visit (TyTy::BoolType &type) override + void visit (TyTy::BoolType &) override { translated = backend->named_type ("bool", backend->bool_type (), Linemap::predeclared_location ()); @@ -190,14 +187,14 @@ public: gcc_unreachable (); } - void visit (TyTy::USizeType &type) override + void visit (TyTy::USizeType &) override { translated = backend->named_type ( "usize", backend->integer_type (true, backend->get_pointer_size ()), Linemap::predeclared_location ()); } - void visit (TyTy::ISizeType &type) override + void visit (TyTy::ISizeType &) override { translated = backend->named_type ( "isize", backend->integer_type (false, backend->get_pointer_size ()), diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index ce6d827..0b83c72 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -95,6 +95,83 @@ CompileExpr::visit (HIR::CallExpr &expr) } } +void +CompileExpr::visit (HIR::MethodCallExpr &expr) +{ + // lookup the resolved name + NodeId resolved_node_id = UNKNOWN_NODEID; + if (!ctx->get_resolver ()->lookup_resolved_name ( + expr.get_mappings ().get_nodeid (), &resolved_node_id)) + { + rust_error_at (expr.get_locus (), "failed to lookup resolved MethodCall"); + return; + } + + // reverse lookup + HirId ref; + if (!ctx->get_mappings ()->lookup_node_to_hir ( + expr.get_mappings ().get_crate_num (), resolved_node_id, &ref)) + { + rust_fatal_error (expr.get_locus (), "reverse lookup failure"); + return; + } + + // lookup compiled functions + Bfunction *fn = nullptr; + if (!ctx->lookup_function_decl (ref, &fn)) + { + // this might fail because its a forward decl so we can attempt to + // resolve it now + HIR::InherentImplItem *resolved_item + = ctx->get_mappings ()->lookup_hir_implitem ( + expr.get_mappings ().get_crate_num (), ref); + if (resolved_item == nullptr) + { + rust_error_at (expr.get_locus (), "failed to lookup forward decl"); + return; + } + + TyTy::TyBase *self_type = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + expr.get_receiver ()->get_mappings ().get_hirid (), &self_type)) + { + rust_error_at (expr.get_locus (), + "failed to resolve type for self param"); + return; + } + + CompileInherentImplItem::Compile (self_type, resolved_item, ctx, true); + if (!ctx->lookup_function_decl (ref, &fn)) + { + rust_error_at (expr.get_locus (), "forward decl was not compiled"); + return; + } + } + + Bexpression *fn_expr + = ctx->get_backend ()->function_code_expression (fn, expr.get_locus ()); + + std::vector<Bexpression *> args; + + // method receiver + Bexpression *self = CompileExpr::Compile (expr.get_receiver ().get (), ctx); + rust_assert (self != nullptr); + args.push_back (self); + + // normal 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_expr, args, + nullptr, expr.get_locus ()); +} + // rust-compile-block.h void @@ -135,10 +212,30 @@ CompileBlock::visit (HIR::BlockExpr &expr) start_location, end_location); ctx->push_block (new_block); - expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { - CompileStmt::Compile (s, ctx); - return true; - }); + for (auto &s : expr.get_statements ()) + { + auto compiled_expr = CompileStmt::Compile (s.get (), ctx); + if (compiled_expr == nullptr) + continue; + + if (result == nullptr) + { + Bstatement *final_stmt + = ctx->get_backend ()->expression_statement (fnctx.fndecl, + compiled_expr); + ctx->add_statement (final_stmt); + } + else + { + Bexpression *result_reference + = ctx->get_backend ()->var_expression (result, + s->get_locus_slow ()); + + Bstatement *assignment = ctx->get_backend ()->assignment_statement ( + fnctx.fndecl, result_reference, compiled_expr, expr.get_locus ()); + ctx->add_statement (assignment); + } + } if (expr.has_expr () && expr.tail_expr_reachable ()) { @@ -147,14 +244,22 @@ CompileBlock::visit (HIR::BlockExpr &expr) Bexpression *compiled_expr = CompileExpr::Compile (expr.expr.get (), ctx); rust_assert (compiled_expr != nullptr); - auto fncontext = ctx->peek_fn (); + if (result == nullptr) + { + Bstatement *final_stmt + = ctx->get_backend ()->expression_statement (fnctx.fndecl, + compiled_expr); + ctx->add_statement (final_stmt); + } + else + { + Bexpression *result_reference = ctx->get_backend ()->var_expression ( + result, expr.get_final_expr ()->get_locus_slow ()); - std::vector<Bexpression *> retstmts; - retstmts.push_back (compiled_expr); - auto s - = ctx->get_backend ()->return_statement (fncontext.fndecl, retstmts, - expr.expr->get_locus_slow ()); - ctx->add_statement (s); + Bstatement *assignment = ctx->get_backend ()->assignment_statement ( + fnctx.fndecl, result_reference, compiled_expr, expr.get_locus ()); + ctx->add_statement (assignment); + } } ctx->pop_block (); @@ -168,7 +273,8 @@ CompileConditionalBlocks::visit (HIR::IfExpr &expr) Bfunction *fndecl = fnctx.fndecl; Bexpression *condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx); - Bblock *then_block = CompileBlock::compile (expr.get_if_block (), ctx); + Bblock *then_block + = CompileBlock::compile (expr.get_if_block (), ctx, result); translated = ctx->get_backend ()->if_statement (fndecl, condition_expr, then_block, @@ -182,8 +288,10 @@ CompileConditionalBlocks::visit (HIR::IfExprConseqElse &expr) Bfunction *fndecl = fnctx.fndecl; Bexpression *condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx); - Bblock *then_block = CompileBlock::compile (expr.get_if_block (), ctx); - Bblock *else_block = CompileBlock::compile (expr.get_else_block (), ctx); + Bblock *then_block + = CompileBlock::compile (expr.get_if_block (), ctx, result); + Bblock *else_block + = CompileBlock::compile (expr.get_else_block (), ctx, result); translated = ctx->get_backend ()->if_statement (fndecl, condition_expr, then_block, @@ -197,7 +305,8 @@ CompileConditionalBlocks::visit (HIR::IfExprConseqIf &expr) Bfunction *fndecl = fnctx.fndecl; Bexpression *condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx); - Bblock *then_block = CompileBlock::compile (expr.get_if_block (), ctx); + Bblock *then_block + = CompileBlock::compile (expr.get_if_block (), ctx, result); // else block std::vector<Bvariable *> locals; @@ -210,7 +319,8 @@ CompileConditionalBlocks::visit (HIR::IfExprConseqIf &expr) ctx->push_block (else_block); Bstatement *else_stmt_decl - = CompileConditionalBlocks::compile (expr.get_conseq_if_expr (), ctx); + = CompileConditionalBlocks::compile (expr.get_conseq_if_expr (), ctx, + result); ctx->add_statement (else_stmt_decl); ctx->pop_block (); @@ -244,5 +354,64 @@ CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field) translated = CompileExpr::Compile (&expr, ctx); } +// Shared methods in compilation + +void +HIRCompileBase::compile_function_body ( + Bfunction *fndecl, std::unique_ptr<HIR::BlockExpr> &function_body, + bool has_return_type) +{ + for (auto &s : function_body->get_statements ()) + { + auto compiled_expr = CompileStmt::Compile (s.get (), ctx); + if (compiled_expr != nullptr) + { + if (has_return_type) + { + std::vector<Bexpression *> retstmts; + retstmts.push_back (compiled_expr); + + auto ret + = ctx->get_backend ()->return_statement (fndecl, retstmts, + s->get_locus_slow ()); + ctx->add_statement (ret); + } + else + { + Bstatement *final_stmt + = ctx->get_backend ()->expression_statement (fndecl, + compiled_expr); + ctx->add_statement (final_stmt); + } + } + } + + 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); + + if (has_return_type) + { + std::vector<Bexpression *> retstmts; + retstmts.push_back (compiled_expr); + + auto ret = ctx->get_backend ()->return_statement ( + fndecl, retstmts, + function_body->get_final_expr ()->get_locus_slow ()); + ctx->add_statement (ret); + } + else + { + Bstatement *final_stmt + = ctx->get_backend ()->expression_statement (fndecl, compiled_expr); + ctx->add_statement (final_stmt); + } + } +} + } // 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 fc18e27..cd1863f 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -238,6 +238,35 @@ public: expr.get_locus ()); } + void visit (AST::MethodCallExpr &expr) + { + std::vector<HIR::Attribute> outer_attribs; + + HIR::PathExprSegment method_path ( + expr.get_method_name ().get_ident_segment ().as_string (), + expr.get_method_name ().get_locus ()); + + HIR::Expr *receiver + = ASTLoweringExpr::translate (expr.get_receiver_expr ().get ()); + + std::vector<std::unique_ptr<HIR::Expr> > params; + expr.iterate_params ([&] (AST::Expr *p) mutable -> bool { + auto trans = ASTLoweringExpr::translate (p); + params.push_back (std::unique_ptr<HIR::Expr> (trans)); + return true; + }); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping ( + crate_num, UNKNOWN_NODEID /* this can map back to the AST*/, + mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::MethodCallExpr (mapping, std::unique_ptr<HIR::Expr> (receiver), + method_path, std::move (params), + std::move (outer_attribs), expr.get_locus ()); + } + void visit (AST::AssignmentExpr &expr) { HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ()); diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h index dab3208..de4d55d 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.h +++ b/gcc/rust/hir/rust-ast-lower-implitem.h @@ -40,6 +40,21 @@ public: return resolver.translated; } + HIR::SelfParam lower_self (AST::SelfParam &self) + { + HIR::Type *type = self.has_type () + ? ASTLoweringType::translate (self.get_type ().get ()) + : nullptr; + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, self.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + return HIR::SelfParam (mapping, std::unique_ptr<HIR::Type> (type), + self.get_is_mut (), self.get_locus ()); + } + void visit (AST::ConstantItem &constant) { std::vector<HIR::Attribute> outer_attrs; @@ -143,6 +158,91 @@ public: translated = fn; } + void visit (AST::Method &method) + { + // 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 method_name = method.get_method_name (); + Location locus = method.get_locus (); + + HIR::SelfParam self_param = lower_self (method.get_self_param ()); + + std::unique_ptr<HIR::Type> return_type + = method.has_return_type () ? std::unique_ptr<HIR::Type> ( + ASTLoweringType::translate (method.get_return_type ().get ())) + : nullptr; + + std::vector<HIR::FunctionParam> function_params; + for (auto ¶m : method.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> method_body + = std::unique_ptr<HIR::BlockExpr> ( + ASTLoweringBlock::translate (method.get_definition ().get (), + &terminated)); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, method.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + auto mth + = new HIR::Method (mapping, std::move (method_name), + std::move (qualifiers), std::move (generic_params), + std::move (self_param), std::move (function_params), + std::move (return_type), std::move (where_clause), + std::move (method_body), std::move (vis), + std::move (outer_attrs), locus); + + mappings->insert_hir_implitem (mapping.get_crate_num (), + mapping.get_hirid (), mth); + mappings->insert_location (crate_num, mapping.get_hirid (), + method.get_locus ()); + + // insert mappings for self + mappings->insert_hir_self_param (crate_num, + self_param.get_mappings ().get_hirid (), + &self_param); + mappings->insert_location (crate_num, + self_param.get_mappings ().get_hirid (), + self_param.get_locus ()); + + // add the mappings for the function params at the end + for (auto ¶m : mth->get_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 = mth; + } + private: ASTLowerImplItem () : translated (nullptr) {} diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 69b680d..d4af3c2 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2177,9 +2177,9 @@ public: void iterate_params (std::function<bool (Expr *)> cb) { - for (auto it = params.begin (); it != params.end (); it++) + for (auto ¶m : params) { - if (!cb (it->get ())) + if (!cb (param.get ())) return; } } @@ -2261,6 +2261,27 @@ public: void accept_vis (HIRVisitor &vis) override; + std::unique_ptr<Expr> &get_receiver () { return receiver; } + + PathExprSegment get_method_name () const { return method_name; }; + + std::vector<std::unique_ptr<Expr> > &get_params () { return params; } + const std::vector<std::unique_ptr<Expr> > &get_params () const + { + return params; + } + + size_t num_params () const { return params.size (); } + + void iterate_params (std::function<bool (Expr *)> cb) + { + for (auto ¶m : params) + { + if (!cb (param.get ())) + return; + } + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2585,6 +2606,10 @@ public: return statements[statements.size () - 1]->get_locus_slow (); } + std::unique_ptr<ExprWithoutBlock> &get_final_expr () { return expr; } + + std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc index 8502c9c..e4fa39a 100644 --- a/gcc/rust/hir/tree/rust-hir-full-test.cc +++ b/gcc/rust/hir/tree/rust-hir-full-test.cc @@ -676,7 +676,7 @@ Method::as_string () const } str += "\n Block expr (body): \n "; - str += expr->as_string (); + str += function_body->as_string (); return str; } diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index e90dbb4..4ab23e1 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -297,10 +297,13 @@ private: Location locus; + Analysis::NodeMapping mappings; + // Unrestricted constructor used for error state - SelfParam (Lifetime lifetime, bool has_ref, bool is_mut, Type *type) + SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime, bool has_ref, + bool is_mut, Type *type) : has_ref (has_ref), is_mut (is_mut), lifetime (std::move (lifetime)), - type (type) + type (type), mappings (mappings) {} // this is ok as no outside classes can ever call this @@ -319,21 +322,23 @@ public: } // Type-based self parameter (not ref, no lifetime) - SelfParam (std::unique_ptr<Type> type, bool is_mut, Location locus) + SelfParam (Analysis::NodeMapping mappings, std::unique_ptr<Type> type, + bool is_mut, Location locus) : has_ref (false), is_mut (is_mut), lifetime (Lifetime::error ()), - type (std::move (type)), locus (locus) + type (std::move (type)), locus (locus), mappings (mappings) {} // Lifetime-based self parameter (is ref, no type) - SelfParam (Lifetime lifetime, bool is_mut, Location locus) + SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime, bool is_mut, + Location locus) : has_ref (true), is_mut (is_mut), lifetime (std::move (lifetime)), - locus (locus) + locus (locus), mappings (mappings) {} // Copy constructor requires clone SelfParam (SelfParam const &other) : has_ref (other.has_ref), is_mut (other.is_mut), lifetime (other.lifetime), - locus (other.locus) + locus (other.locus), mappings (other.mappings) { if (other.type != nullptr) type = other.type->clone_type (); @@ -348,6 +353,7 @@ public: has_ref = other.has_ref; lifetime = other.lifetime; locus = other.locus; + mappings = other.mappings; return *this; } @@ -359,6 +365,18 @@ public: std::string as_string () const; Location get_locus () const { return locus; } + + bool get_has_ref () const { return has_ref; }; + bool get_is_mut () const { return is_mut; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Type> &get_type () + { + rust_assert (has_type ()); + return type; + } + + Analysis::NodeMapping get_mappings () { return mappings; } }; // Qualifiers for function, i.e. const, unsafe, extern etc. @@ -542,6 +560,8 @@ protected: // A method (function belonging to a type) class Method : public InherentImplItem, public TraitImplItem { + Analysis::NodeMapping mappings; + // moved from impl items for consistency std::vector<Attribute> outer_attrs; Visibility vis; @@ -566,9 +586,7 @@ class Method : public InherentImplItem, public TraitImplItem // bool has_where_clause; WhereClause where_clause; - std::unique_ptr<BlockExpr> expr; - - Analysis::NodeMapping mappings; + std::unique_ptr<BlockExpr> function_body; Location locus; @@ -603,8 +621,8 @@ public: self_param (std::move (self_param)), function_params (std::move (function_params)), return_type (std::move (return_type)), - where_clause (std::move (where_clause)), expr (std::move (function_body)), - locus (locus) + where_clause (std::move (where_clause)), + function_body (std::move (function_body)), locus (locus) {} // TODO: add constructor with less fields @@ -616,7 +634,8 @@ public: 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 ()), + where_clause (other.where_clause), + function_body (other.function_body->clone_block_expr ()), locus (other.locus) { generic_params.reserve (other.generic_params.size ()); @@ -636,7 +655,7 @@ public: function_params = other.function_params; return_type = other.return_type->clone_type (); where_clause = other.where_clause; - expr = other.expr->clone_block_expr (); + function_body = other.function_body->clone_block_expr (); locus = other.locus; generic_params.reserve (other.generic_params.size ()); @@ -661,6 +680,58 @@ public: return get_mappings (); }; + // Returns whether function has return type - if not, it is void. + bool has_function_return_type () const { return return_type != nullptr; } + + std::vector<FunctionParam> &get_function_params () { return function_params; } + const std::vector<FunctionParam> &get_function_params () const + { + return function_params; + } + + std::vector<std::unique_ptr<GenericParam> > &get_generic_params () + { + return generic_params; + } + const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const + { + return generic_params; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<BlockExpr> &get_definition () + { + rust_assert (function_body != nullptr); + return function_body; + } + + SelfParam &get_self_param () { return self_param; } + const SelfParam &get_self_param () const { return self_param; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Type> &get_return_type () + { + rust_assert (has_return_type ()); + return return_type; + } + + // TODO: is this better? Or is a "vis_block" better? + WhereClause &get_where_clause () + { + rust_assert (has_where_clause ()); + return where_clause; + } + + Identifier get_method_name () const { return method_name; } + + Location get_locus () const { return locus; } + + std::unique_ptr<BlockExpr> &get_function_body () { return function_body; } + const std::unique_ptr<BlockExpr> &get_function_body () const + { + return function_body; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index 1bba506..9a772f0 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -228,6 +228,8 @@ public: std::string as_string () const; Location get_locus () const { return locus; } + + PathIdentSegment get_segment () const { return segment_name; } }; // HIR node representing a pattern that involves a "path" - abstract base class diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h index cc60055..16334bd 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -21,7 +21,6 @@ #include "rust-ast-visitor.h" #include "rust-name-resolver.h" - #include "rust-diagnostics.h" #include "rust-location.h" @@ -33,210 +32,181 @@ class ResolverBase : public AST::ASTVisitor public: virtual ~ResolverBase () {} - // visitor impl - // rust-ast.h - // virtual void visit(AttrInput& attr_input); - // virtual void visit(TokenTree& token_tree); - // virtual void visit(MacroMatch& macro_match); - virtual void visit (AST::Token &tok) {} - virtual void visit (AST::DelimTokenTree &delim_tok_tree) {} - virtual void visit (AST::AttrInputMetaItemContainer &input) {} - // virtual void visit(MetaItem& meta_item) {} - // void vsit(Stmt& stmt) {} - // virtual void visit(Expr& expr) {} - virtual void visit (AST::IdentifierExpr &ident_expr) {} - // virtual void visit(Pattern& pattern) {} - // virtual void visit(Type& type) {} - // virtual void visit(TypeParamBound& type_param_bound) {} - virtual void visit (AST::Lifetime &lifetime) {} - // virtual void visit(GenericParam& generic_param) {} - virtual void visit (AST::LifetimeParam &lifetime_param) {} - // virtual void visit(TraitItem& trait_item) {} - // virtual void visit(InherentImplItem& inherent_impl_item) {} - // virtual void visit(TraitImplItem& trait_impl_item) {} - virtual void visit (AST::MacroInvocationSemi ¯o) {} - - // rust-path.h - virtual void visit (AST::PathInExpression &path) {} - virtual void visit (AST::TypePathSegment &segment) {} - virtual void visit (AST::TypePathSegmentGeneric &segment) {} - virtual void visit (AST::TypePathSegmentFunction &segment) {} - virtual void visit (AST::TypePath &path) {} - virtual void visit (AST::QualifiedPathInExpression &path) {} - virtual void visit (AST::QualifiedPathInType &path) {} - - // rust-expr.h - virtual void visit (AST::LiteralExpr &expr) {} - virtual void visit (AST::AttrInputLiteral &attr_input) {} - virtual void visit (AST::MetaItemLitExpr &meta_item) {} - virtual void visit (AST::MetaItemPathLit &meta_item) {} - virtual void visit (AST::BorrowExpr &expr) {} - virtual void visit (AST::DereferenceExpr &expr) {} - virtual void visit (AST::ErrorPropagationExpr &expr) {} - virtual void visit (AST::NegationExpr &expr) {} - virtual void visit (AST::ArithmeticOrLogicalExpr &expr) {} - virtual void visit (AST::ComparisonExpr &expr) {} - virtual void visit (AST::LazyBooleanExpr &expr) {} - virtual void visit (AST::TypeCastExpr &expr) {} - virtual void visit (AST::AssignmentExpr &expr) {} - virtual void visit (AST::CompoundAssignmentExpr &expr) {} - virtual void visit (AST::GroupedExpr &expr) {} - // virtual void visit(ArrayElems& elems) {} - virtual void visit (AST::ArrayElemsValues &elems) {} - virtual void visit (AST::ArrayElemsCopied &elems) {} - virtual void visit (AST::ArrayExpr &expr) {} - virtual void visit (AST::ArrayIndexExpr &expr) {} - virtual void visit (AST::TupleExpr &expr) {} - virtual void visit (AST::TupleIndexExpr &expr) {} - virtual void visit (AST::StructExprStruct &expr) {} - // virtual void visit(StructExprField& field) {} - virtual void visit (AST::StructExprFieldIdentifier &field) {} - virtual void visit (AST::StructExprFieldIdentifierValue &field) {} - virtual void visit (AST::StructExprFieldIndexValue &field) {} - virtual void visit (AST::StructExprStructFields &expr) {} - virtual void visit (AST::StructExprStructBase &expr) {} - virtual void visit (AST::StructExprTuple &expr) {} - virtual void visit (AST::StructExprUnit &expr) {} - // virtual void visit(EnumExprField& field) {} - virtual void visit (AST::EnumExprFieldIdentifier &field) {} - virtual void visit (AST::EnumExprFieldIdentifierValue &field) {} - virtual void visit (AST::EnumExprFieldIndexValue &field) {} - virtual void visit (AST::EnumExprStruct &expr) {} - virtual void visit (AST::EnumExprTuple &expr) {} - virtual void visit (AST::EnumExprFieldless &expr) {} - virtual void visit (AST::CallExpr &expr) {} - virtual void visit (AST::MethodCallExpr &expr) {} - virtual void visit (AST::FieldAccessExpr &expr) {} - virtual void visit (AST::ClosureExprInner &expr) {} - virtual void visit (AST::BlockExpr &expr) {} - virtual void visit (AST::ClosureExprInnerTyped &expr) {} - virtual void visit (AST::ContinueExpr &expr) {} - virtual void visit (AST::BreakExpr &expr) {} - virtual void visit (AST::RangeFromToExpr &expr) {} - virtual void visit (AST::RangeFromExpr &expr) {} - virtual void visit (AST::RangeToExpr &expr) {} - virtual void visit (AST::RangeFullExpr &expr) {} - virtual void visit (AST::RangeFromToInclExpr &expr) {} - virtual void visit (AST::RangeToInclExpr &expr) {} - virtual void visit (AST::ReturnExpr &expr) {} - virtual void visit (AST::UnsafeBlockExpr &expr) {} - virtual void visit (AST::LoopExpr &expr) {} - virtual void visit (AST::WhileLoopExpr &expr) {} - virtual void visit (AST::WhileLetLoopExpr &expr) {} - virtual void visit (AST::ForLoopExpr &expr) {} - virtual void visit (AST::IfExpr &expr) {} - virtual void visit (AST::IfExprConseqElse &expr) {} - virtual void visit (AST::IfExprConseqIf &expr) {} - virtual void visit (AST::IfExprConseqIfLet &expr) {} - virtual void visit (AST::IfLetExpr &expr) {} - virtual void visit (AST::IfLetExprConseqElse &expr) {} - virtual void visit (AST::IfLetExprConseqIf &expr) {} - virtual void visit (AST::IfLetExprConseqIfLet &expr) {} - // virtual void visit(MatchCase& match_case) {} - // virtual void visit (AST::MatchCaseBlockExpr &match_case) {} - // virtual void visit (AST::MatchCaseExpr &match_case) {} - virtual void visit (AST::MatchExpr &expr) {} - virtual void visit (AST::AwaitExpr &expr) {} - virtual void visit (AST::AsyncBlockExpr &expr) {} - - // rust-item.h - virtual void visit (AST::TypeParam ¶m) {} - // virtual void visit(WhereClauseItem& item) {} - virtual void visit (AST::LifetimeWhereClauseItem &item) {} - virtual void visit (AST::TypeBoundWhereClauseItem &item) {} - virtual void visit (AST::Method &method) {} - virtual void visit (AST::ModuleBodied &module) {} - virtual void visit (AST::ModuleNoBody &module) {} - virtual void visit (AST::ExternCrate &crate) {} - // virtual void visit(UseTree& use_tree) {} - virtual void visit (AST::UseTreeGlob &use_tree) {} - virtual void visit (AST::UseTreeList &use_tree) {} - virtual void visit (AST::UseTreeRebind &use_tree) {} - virtual void visit (AST::UseDeclaration &use_decl) {} - virtual void visit (AST::Function &function) {} - virtual void visit (AST::TypeAlias &type_alias) {} - virtual void visit (AST::StructStruct &struct_item) {} - virtual void visit (AST::TupleStruct &tuple_struct) {} - virtual void visit (AST::EnumItem &item) {} - virtual void visit (AST::EnumItemTuple &item) {} - virtual void visit (AST::EnumItemStruct &item) {} - virtual void visit (AST::EnumItemDiscriminant &item) {} - virtual void visit (AST::Enum &enum_item) {} - virtual void visit (AST::Union &union_item) {} - virtual void visit (AST::ConstantItem &const_item) {} - virtual void visit (AST::StaticItem &static_item) {} - virtual void visit (AST::TraitItemFunc &item) {} - virtual void visit (AST::TraitItemMethod &item) {} - virtual void visit (AST::TraitItemConst &item) {} - virtual void visit (AST::TraitItemType &item) {} - virtual void visit (AST::Trait &trait) {} - virtual void visit (AST::InherentImpl &impl) {} - virtual void visit (AST::TraitImpl &impl) {} - // virtual void visit(ExternalItem& item) {} - virtual void visit (AST::ExternalStaticItem &item) {} - virtual void visit (AST::ExternalFunctionItem &item) {} - virtual void visit (AST::ExternBlock &block) {} - - // rust-macro.h - virtual void visit (AST::MacroMatchFragment &match) {} - virtual void visit (AST::MacroMatchRepetition &match) {} - virtual void visit (AST::MacroMatcher &matcher) {} - virtual void visit (AST::MacroRulesDefinition &rules_def) {} - virtual void visit (AST::MacroInvocation ¯o_invoc) {} - virtual void visit (AST::MetaItemPath &meta_item) {} - virtual void visit (AST::MetaItemSeq &meta_item) {} - virtual void visit (AST::MetaWord &meta_item) {} - virtual void visit (AST::MetaNameValueStr &meta_item) {} - virtual void visit (AST::MetaListPaths &meta_item) {} - virtual void visit (AST::MetaListNameValueStr &meta_item) {} - - // rust-pattern.h - virtual void visit (AST::LiteralPattern &pattern) {} - virtual void visit (AST::IdentifierPattern &pattern) {} - virtual void visit (AST::WildcardPattern &pattern) {} - // virtual void visit(RangePatternBound& bound) {} - virtual void visit (AST::RangePatternBoundLiteral &bound) {} - virtual void visit (AST::RangePatternBoundPath &bound) {} - virtual void visit (AST::RangePatternBoundQualPath &bound) {} - virtual void visit (AST::RangePattern &pattern) {} - virtual void visit (AST::ReferencePattern &pattern) {} - // virtual void visit(StructPatternField& field) {} - virtual void visit (AST::StructPatternFieldTuplePat &field) {} - virtual void visit (AST::StructPatternFieldIdentPat &field) {} - virtual void visit (AST::StructPatternFieldIdent &field) {} - virtual void visit (AST::StructPattern &pattern) {} - // virtual void visit(TupleStructItems& tuple_items) {} - virtual void visit (AST::TupleStructItemsNoRange &tuple_items) {} - virtual void visit (AST::TupleStructItemsRange &tuple_items) {} - virtual void visit (AST::TupleStructPattern &pattern) {} - // virtual void visit(TuplePatternItems& tuple_items) {} - virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) {} - virtual void visit (AST::TuplePatternItemsRanged &tuple_items) {} - virtual void visit (AST::TuplePattern &pattern) {} - virtual void visit (AST::GroupedPattern &pattern) {} - virtual void visit (AST::SlicePattern &pattern) {} - - // rust-stmt.h - virtual void visit (AST::EmptyStmt &stmt) {} - virtual void visit (AST::LetStmt &stmt) {} - virtual void visit (AST::ExprStmtWithoutBlock &stmt) {} - virtual void visit (AST::ExprStmtWithBlock &stmt) {} - - // rust-type.h - virtual void visit (AST::TraitBound &bound) {} - virtual void visit (AST::ImplTraitType &type) {} - virtual void visit (AST::TraitObjectType &type) {} - virtual void visit (AST::ParenthesisedType &type) {} - virtual void visit (AST::ImplTraitTypeOneBound &type) {} - virtual void visit (AST::TraitObjectTypeOneBound &type) {} - virtual void visit (AST::TupleType &type) {} - virtual void visit (AST::NeverType &type) {} - virtual void visit (AST::RawPointerType &type) {} - virtual void visit (AST::ReferenceType &type) {} - virtual void visit (AST::ArrayType &type) {} - virtual void visit (AST::SliceType &type) {} - virtual void visit (AST::InferredType &type) {} - virtual void visit (AST::BareFunctionType &type) {} + void visit (AST::Token &) {} + void visit (AST::DelimTokenTree &) {} + void visit (AST::AttrInputMetaItemContainer &) {} + void visit (AST::IdentifierExpr &) {} + void visit (AST::Lifetime &) {} + void visit (AST::LifetimeParam &) {} + void visit (AST::MacroInvocationSemi &) {} + void visit (AST::PathInExpression &) {} + void visit (AST::TypePathSegment &) {} + void visit (AST::TypePathSegmentGeneric &) {} + void visit (AST::TypePathSegmentFunction &) {} + void visit (AST::TypePath &) {} + void visit (AST::QualifiedPathInExpression &) {} + void visit (AST::QualifiedPathInType &) {} + void visit (AST::LiteralExpr &) {} + void visit (AST::AttrInputLiteral &) {} + void visit (AST::MetaItemLitExpr &) {} + void visit (AST::MetaItemPathLit &) {} + void visit (AST::BorrowExpr &) {} + void visit (AST::DereferenceExpr &) {} + void visit (AST::ErrorPropagationExpr &) {} + void visit (AST::NegationExpr &) {} + void visit (AST::ArithmeticOrLogicalExpr &) {} + void visit (AST::ComparisonExpr &) {} + void visit (AST::LazyBooleanExpr &) {} + void visit (AST::TypeCastExpr &) {} + void visit (AST::AssignmentExpr &) {} + void visit (AST::CompoundAssignmentExpr &) {} + void visit (AST::GroupedExpr &) {} + void visit (AST::ArrayElemsValues &) {} + void visit (AST::ArrayElemsCopied &) {} + void visit (AST::ArrayExpr &) {} + void visit (AST::ArrayIndexExpr &) {} + void visit (AST::TupleExpr &) {} + void visit (AST::TupleIndexExpr &) {} + void visit (AST::StructExprStruct &) {} + void visit (AST::StructExprFieldIdentifier &) {} + void visit (AST::StructExprFieldIdentifierValue &) {} + void visit (AST::StructExprFieldIndexValue &) {} + void visit (AST::StructExprStructFields &) {} + void visit (AST::StructExprStructBase &) {} + void visit (AST::StructExprTuple &) {} + void visit (AST::StructExprUnit &) {} + void visit (AST::EnumExprFieldIdentifier &) {} + void visit (AST::EnumExprFieldIdentifierValue &) {} + void visit (AST::EnumExprFieldIndexValue &) {} + void visit (AST::EnumExprStruct &) {} + void visit (AST::EnumExprTuple &) {} + void visit (AST::EnumExprFieldless &) {} + void visit (AST::CallExpr &) {} + void visit (AST::MethodCallExpr &) {} + void visit (AST::FieldAccessExpr &) {} + void visit (AST::ClosureExprInner &) {} + void visit (AST::BlockExpr &) {} + void visit (AST::ClosureExprInnerTyped &) {} + void visit (AST::ContinueExpr &) {} + void visit (AST::BreakExpr &) {} + void visit (AST::RangeFromToExpr &) {} + void visit (AST::RangeFromExpr &) {} + void visit (AST::RangeToExpr &) {} + void visit (AST::RangeFullExpr &) {} + void visit (AST::RangeFromToInclExpr &) {} + void visit (AST::RangeToInclExpr &) {} + void visit (AST::ReturnExpr &) {} + void visit (AST::UnsafeBlockExpr &) {} + void visit (AST::LoopExpr &) {} + void visit (AST::WhileLoopExpr &) {} + void visit (AST::WhileLetLoopExpr &) {} + void visit (AST::ForLoopExpr &) {} + void visit (AST::IfExpr &) {} + void visit (AST::IfExprConseqElse &) {} + void visit (AST::IfExprConseqIf &) {} + void visit (AST::IfExprConseqIfLet &) {} + void visit (AST::IfLetExpr &) {} + void visit (AST::IfLetExprConseqElse &) {} + void visit (AST::IfLetExprConseqIf &) {} + void visit (AST::IfLetExprConseqIfLet &) {} + + void visit (AST::MatchExpr &) {} + void visit (AST::AwaitExpr &) {} + void visit (AST::AsyncBlockExpr &) {} + + void visit (AST::TypeParam &) {} + + void visit (AST::LifetimeWhereClauseItem &) {} + void visit (AST::TypeBoundWhereClauseItem &) {} + void visit (AST::Method &) {} + void visit (AST::ModuleBodied &) {} + void visit (AST::ModuleNoBody &) {} + void visit (AST::ExternCrate &) {} + + void visit (AST::UseTreeGlob &) {} + void visit (AST::UseTreeList &) {} + void visit (AST::UseTreeRebind &) {} + void visit (AST::UseDeclaration &) {} + void visit (AST::Function &) {} + void visit (AST::TypeAlias &) {} + void visit (AST::StructStruct &) {} + void visit (AST::TupleStruct &) {} + void visit (AST::EnumItem &) {} + void visit (AST::EnumItemTuple &) {} + void visit (AST::EnumItemStruct &) {} + void visit (AST::EnumItemDiscriminant &) {} + void visit (AST::Enum &) {} + void visit (AST::Union &) {} + void visit (AST::ConstantItem &) {} + void visit (AST::StaticItem &) {} + void visit (AST::TraitItemFunc &) {} + void visit (AST::TraitItemMethod &) {} + void visit (AST::TraitItemConst &) {} + void visit (AST::TraitItemType &) {} + void visit (AST::Trait &) {} + void visit (AST::InherentImpl &) {} + void visit (AST::TraitImpl &) {} + + void visit (AST::ExternalStaticItem &) {} + void visit (AST::ExternalFunctionItem &) {} + void visit (AST::ExternBlock &) {} + + void visit (AST::MacroMatchFragment &) {} + void visit (AST::MacroMatchRepetition &) {} + void visit (AST::MacroMatcher &) {} + void visit (AST::MacroRulesDefinition &) {} + void visit (AST::MacroInvocation &) {} + void visit (AST::MetaItemPath &) {} + void visit (AST::MetaItemSeq &) {} + void visit (AST::MetaWord &) {} + void visit (AST::MetaNameValueStr &) {} + void visit (AST::MetaListPaths &) {} + void visit (AST::MetaListNameValueStr &) {} + + void visit (AST::LiteralPattern &) {} + void visit (AST::IdentifierPattern &) {} + void visit (AST::WildcardPattern &) {} + + void visit (AST::RangePatternBoundLiteral &) {} + void visit (AST::RangePatternBoundPath &) {} + void visit (AST::RangePatternBoundQualPath &) {} + void visit (AST::RangePattern &) {} + void visit (AST::ReferencePattern &) {} + + void visit (AST::StructPatternFieldTuplePat &) {} + void visit (AST::StructPatternFieldIdentPat &) {} + void visit (AST::StructPatternFieldIdent &) {} + void visit (AST::StructPattern &) {} + + void visit (AST::TupleStructItemsNoRange &) {} + void visit (AST::TupleStructItemsRange &) {} + void visit (AST::TupleStructPattern &) {} + + void visit (AST::TuplePatternItemsMultiple &) {} + void visit (AST::TuplePatternItemsRanged &) {} + void visit (AST::TuplePattern &) {} + void visit (AST::GroupedPattern &) {} + void visit (AST::SlicePattern &) {} + + void visit (AST::EmptyStmt &) {} + void visit (AST::LetStmt &) {} + void visit (AST::ExprStmtWithoutBlock &) {} + void visit (AST::ExprStmtWithBlock &) {} + + void visit (AST::TraitBound &) {} + void visit (AST::ImplTraitType &) {} + void visit (AST::TraitObjectType &) {} + void visit (AST::ParenthesisedType &) {} + void visit (AST::ImplTraitTypeOneBound &) {} + void visit (AST::TraitObjectTypeOneBound &) {} + void visit (AST::TupleType &) {} + void visit (AST::NeverType &) {} + void visit (AST::RawPointerType &) {} + void visit (AST::ReferenceType &) {} + void visit (AST::ArrayType &) {} + void visit (AST::SliceType &) {} + void visit (AST::InferredType &) {} + void visit (AST::BareFunctionType &) {} protected: ResolverBase (NodeId parent) diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index f62f17c..d563f93 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -91,6 +91,15 @@ public: }); } + void visit (AST::MethodCallExpr &expr) + { + ResolveExpr::go (expr.get_receiver_expr ().get (), expr.get_node_id ()); + expr.iterate_params ([&] (AST::Expr *p) mutable -> bool { + ResolveExpr::go (p, expr.get_node_id ()); + return true; + }); + } + void visit (AST::AssignmentExpr &expr) { ResolveExpr::go (expr.get_left_expr ().get (), expr.get_node_id ()); diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h index 74f2cdc..9cbef53 100644 --- a/gcc/rust/resolve/rust-ast-resolve-implitem.h +++ b/gcc/rust/resolve/rust-ast-resolve-implitem.h @@ -39,8 +39,12 @@ public: { std::string identifier = base->as_string () + "::" + constant.get_identifier (); - resolver->get_name_scope ().insert (identifier, constant.get_node_id (), - constant.get_locus ()); + resolver->get_name_scope ().insert ( + identifier, constant.get_node_id (), constant.get_locus (), false, + [&] (std::string, NodeId, Location locus) -> void { + rust_error_at (constant.get_locus (), "redefined multiple times"); + rust_error_at (locus, "was defined here"); + }); resolver->insert_new_definition (constant.get_node_id (), Definition{constant.get_node_id (), constant.get_node_id ()}); @@ -50,8 +54,12 @@ public: { std::string identifier = base->as_string () + "::" + function.get_function_name (); - resolver->get_name_scope ().insert (identifier, function.get_node_id (), - function.get_locus ()); + resolver->get_name_scope ().insert ( + identifier, function.get_node_id (), function.get_locus (), false, + [&] (std::string, NodeId, Location locus) -> void { + rust_error_at (function.get_locus (), "redefined multiple times"); + rust_error_at (locus, "was defined here"); + }); resolver->insert_new_definition (function.get_node_id (), Definition{function.get_node_id (), function.get_node_id ()}); @@ -61,8 +69,12 @@ public: { std::string identifier = base->as_string () + "::" + method.get_method_name (); - resolver->get_name_scope ().insert (identifier, method.get_node_id (), - method.get_locus ()); + resolver->get_name_scope ().insert ( + identifier, method.get_node_id (), method.get_locus (), false, + [&] (std::string, NodeId, Location locus) -> void { + rust_error_at (method.get_locus (), "redefined multiple times"); + rust_error_at (locus, "was defined here"); + }); resolver->insert_new_definition (method.get_node_id (), Definition{method.get_node_id (), method.get_node_id ()}); diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index 74b5f8d..8b6227e 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -24,7 +24,6 @@ #include "rust-ast-resolve-type.h" #include "rust-ast-resolve-pattern.h" #include "rust-ast-resolve-stmt.h" -#include "rust-ast-resolve-unused.h" namespace Rust { namespace Resolver { @@ -110,17 +109,76 @@ public: ResolveExpr::go (function.get_definition ().get (), function.get_node_id ()); - ScanUnused::Scan (resolver->get_name_scope ().peek ()); - ScanUnused::Scan (resolver->get_type_scope ().peek ()); - resolver->get_name_scope ().pop (); resolver->get_type_scope ().pop (); } void visit (AST::InherentImpl &impl_block) { + NodeId resolved_node = ResolveType::go (impl_block.get_type ().get (), + impl_block.get_node_id ()); + if (resolved_node == UNKNOWN_NODEID) + return; + + resolver->get_type_scope ().insert ( + "Self", resolved_node, impl_block.get_type ()->get_locus_slow ()); + for (auto &impl_item : impl_block.get_impl_items ()) impl_item->accept_vis (*this); + + resolver->get_type_scope ().peek ()->clear_name ("Self", resolved_node); + } + + void visit (AST::Method &method) + { + if (method.has_return_type ()) + ResolveType::go (method.get_return_type ().get (), method.get_node_id ()); + + NodeId scope_node_id = method.get_node_id (); + resolver->get_name_scope ().push (scope_node_id); + resolver->get_type_scope ().push (scope_node_id); + resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); + + // self turns into self: Self as a function param + AST::SelfParam &self_param = method.get_self_param (); + AST::IdentifierPattern self_pattern ( + self_param.get_node_id (), "self", self_param.get_locus (), + self_param.get_has_ref (), self_param.get_is_mut (), + std::unique_ptr<AST::Pattern> (nullptr)); + + std::vector<std::unique_ptr<AST::TypePathSegment> > segments; + segments.push_back (std::unique_ptr<AST::TypePathSegment> ( + new AST::TypePathSegment ("Self", false, self_param.get_locus ()))); + + AST::TypePath self_type_path (std::move (segments), + self_param.get_locus ()); + + ResolveType::go (&self_type_path, self_param.get_node_id ()); + PatternDeclaration::go (&self_pattern, self_param.get_node_id ()); + + resolver->mark_assignment_to_decl (self_pattern.get_node_id (), + self_pattern.get_node_id ()); + + // we make a new scope so the names of parameters are resolved and shadowed + // correctly + for (auto ¶m : method.get_function_params ()) + { + 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 + ResolveExpr::go (method.get_definition ().get (), method.get_node_id ()); + + resolver->get_name_scope ().pop (); + resolver->get_type_scope ().pop (); } private: diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index 7ca8275..2e4e8e7 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -38,22 +38,34 @@ public: void visit (AST::TupleStruct &struct_decl) { - resolver->get_type_scope ().insert (struct_decl.get_identifier (), - struct_decl.get_node_id (), - struct_decl.get_locus ()); + resolver->get_type_scope ().insert ( + struct_decl.get_identifier (), struct_decl.get_node_id (), + struct_decl.get_locus (), false, + [&] (std::string, NodeId, Location locus) -> void { + rust_error_at (struct_decl.get_locus (), "redefined multiple times"); + rust_error_at (locus, "was defined here"); + }); } void visit (AST::StructStruct &struct_decl) { - resolver->get_type_scope ().insert (struct_decl.get_identifier (), - struct_decl.get_node_id (), - struct_decl.get_locus ()); + resolver->get_type_scope ().insert ( + struct_decl.get_identifier (), struct_decl.get_node_id (), + struct_decl.get_locus (), false, + [&] (std::string, NodeId, Location locus) -> void { + rust_error_at (struct_decl.get_locus (), "redefined multiple times"); + rust_error_at (locus, "was defined here"); + }); } void visit (AST::StaticItem &var) { - resolver->get_name_scope ().insert (var.get_identifier (), - var.get_node_id (), var.get_locus ()); + resolver->get_name_scope ().insert ( + var.get_identifier (), var.get_node_id (), var.get_locus (), false, + [&] (std::string, NodeId, Location locus) -> void { + rust_error_at (var.get_locus (), "redefined multiple times"); + rust_error_at (locus, "was defined here"); + }); resolver->insert_new_definition (var.get_node_id (), Definition{var.get_node_id (), var.get_node_id ()}); @@ -62,9 +74,13 @@ public: void visit (AST::ConstantItem &constant) { - resolver->get_name_scope ().insert (constant.get_identifier (), - constant.get_node_id (), - constant.get_locus ()); + resolver->get_name_scope ().insert ( + constant.get_identifier (), constant.get_node_id (), + constant.get_locus (), false, + [&] (std::string, NodeId, Location locus) -> void { + rust_error_at (constant.get_locus (), "redefined multiple times"); + rust_error_at (locus, "was defined here"); + }); resolver->insert_new_definition (constant.get_node_id (), Definition{constant.get_node_id (), constant.get_node_id ()}); @@ -72,9 +88,13 @@ public: void visit (AST::Function &function) { - resolver->get_name_scope ().insert (function.get_function_name (), - function.get_node_id (), - function.get_locus ()); + resolver->get_name_scope ().insert ( + function.get_function_name (), function.get_node_id (), + function.get_locus (), false, + [&] (std::string, NodeId, Location locus) -> void { + rust_error_at (function.get_locus (), "redefined multiple times"); + rust_error_at (locus, "was defined here"); + }); resolver->insert_new_definition (function.get_node_id (), Definition{function.get_node_id (), function.get_node_id ()}); @@ -90,10 +110,6 @@ 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 ()); diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 258524b..ec8ee87 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -28,14 +28,14 @@ namespace Resolver { class ResolveType : public ResolverBase { public: - static bool go (AST::Type *type, NodeId parent) + static NodeId 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; + return resolver.resolved_node; }; void visit (AST::BareFunctionType &fntype) diff --git a/gcc/rust/resolve/rust-ast-resolve-unused.h b/gcc/rust/resolve/rust-ast-resolve-unused.h index 08b2db1..928cf11 100644 --- a/gcc/rust/resolve/rust-ast-resolve-unused.h +++ b/gcc/rust/resolve/rust-ast-resolve-unused.h @@ -24,10 +24,10 @@ namespace Rust { namespace Resolver { -class ScanUnused : public ResolverBase +class ScanUnused { public: - static void Scan (Rib *r) + static void ScanRib (Rib *r) { r->iterate_decls ([&] (NodeId decl_node_id, Location locus) -> bool { if (!r->have_references_for_node (decl_node_id)) @@ -37,6 +37,13 @@ public: return true; }); } + + static void Scan () + { + auto resolver = Resolver::get (); + resolver->iterate_name_ribs ([&] (Rib *r) -> void { ScanRib (r); }); + resolver->iterate_type_ribs ([&] (Rib *r) -> void { ScanRib (r); }); + } }; } // namespace Resolver diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 6731f13..d514132 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -22,7 +22,6 @@ #include "rust-ast-resolve-toplevel.h" #include "rust-ast-resolve-item.h" #include "rust-ast-resolve-expr.h" -#include "rust-ast-resolve-unused.h" #define MKBUILTIN_TYPE(_X, _R, _TY) \ do \ @@ -110,7 +109,8 @@ Resolver::insert_builtin_types (Rib *r) auto builtins = get_builtin_types (); for (auto &builtin : builtins) r->insert_name (builtin->as_string (), builtin->get_node_id (), - Linemap::predeclared_location ()); + Linemap::predeclared_location (), false, + [] (std::string, NodeId, Location) -> void {}); } std::vector<AST::Type *> & @@ -283,9 +283,6 @@ NameResolution::go (AST::Crate &crate) // next we can drill down into the items and their scopes for (auto it = crate.items.begin (); it != crate.items.end (); it++) ResolveItem::go (it->get ()); - - ScanUnused::Scan (resolver->get_name_scope ().peek ()); - ScanUnused::Scan (resolver->get_type_scope ().peek ()); } // rust-ast-resolve-expr.h @@ -307,9 +304,6 @@ ResolveExpr::visit (AST::BlockExpr &expr) if (expr.has_tail_expr ()) ResolveExpr::go (expr.get_tail_expr ().get (), expr.get_node_id ()); - ScanUnused::Scan (resolver->get_name_scope ().peek ()); - ScanUnused::Scan (resolver->get_type_scope ().peek ()); - resolver->get_name_scope ().pop (); resolver->get_type_scope ().pop (); } diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h index 5bc6aba..ea0e4f5 100644 --- a/gcc/rust/resolve/rust-name-resolver.h +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -37,8 +37,25 @@ public: ~Rib () {} - void insert_name (std::string ident, NodeId id, Location locus) + void insert_name (std::string ident, NodeId id, Location locus, bool shadow, + std::function<void (std::string, NodeId, Location)> dup_cb) { + auto it = mappings.find (ident); + bool already_exists = it != mappings.end (); + if (already_exists && !shadow) + { + for (auto &decl : decls_within_rib) + { + if (decl.first == it->second) + { + dup_cb (ident, it->second, decl.second); + return; + } + } + dup_cb (ident, it->second, locus); + return; + } + mappings[ident] = id; decls_within_rib.insert (std::pair<NodeId, Location> (id, locus)); references[id] = {}; @@ -54,6 +71,19 @@ public: return true; } + void clear_name (std::string ident, NodeId id) + { + mappings.erase (ident); + for (auto &it : decls_within_rib) + { + if (it.first == id) + { + decls_within_rib.erase (it); + break; + } + } + } + CrateNum get_crate_num () const { return crate_num; } NodeId get_node_id () const { return node_id; } @@ -117,9 +147,16 @@ public: Scope (CrateNum crate_num) : crate_num (crate_num) {} ~Scope () {} + void insert (std::string ident, NodeId id, Location locus, bool shadow, + std::function<void (std::string, NodeId, Location)> dup_cb) + { + peek ()->insert_name (ident, id, locus, shadow, dup_cb); + } + void insert (std::string ident, NodeId id, Location locus) { - peek ()->insert_name (ident, id, locus); + peek ()->insert_name (ident, id, locus, true, + [] (std::string, NodeId, Location) -> void {}); } bool lookup (std::string ident, NodeId *id) @@ -266,6 +303,23 @@ public: return it->second.size (); } + void iterate_name_ribs (std::function<void (Rib *)> cb) + { + for (auto it = name_ribs.begin (); it != name_ribs.end (); it++) + cb (it->second); + } + + void iterate_type_ribs (std::function<void (Rib *)> cb) + { + for (auto it = type_ribs.begin (); it != type_ribs.end (); it++) + { + if (it->first == global_type_node_id) + continue; + + cb (it->second); + } + } + private: Resolver (); diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index dcdbd49..1d31135 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -35,6 +35,7 @@ #include "rust-ast-lower.h" #include "rust-hir-type-check.h" #include "rust-tycheck-dump.h" +#include "rust-ast-resolve-unused.h" #include "rust-compile.h" extern Linemap * @@ -527,9 +528,7 @@ Session::parse_file (const char *filename) } // resolution pipeline stage - resolution (parsed_crate); - fprintf (stderr, "\033[0;31mSUCCESSFULLY FINISHED RESOLUTION \n\033[0m"); - + Resolver::NameResolution::Resolve (parsed_crate); if (options.dump_option == CompileOptions::RESOLUTION_DUMP) { // TODO: what do I dump here? resolved names? AST with resolved names? @@ -539,7 +538,7 @@ Session::parse_file (const char *filename) return; // lower AST to HIR - HIR::Crate hir = lower_ast (parsed_crate); + HIR::Crate hir = HIR::ASTLowering::Resolve (parsed_crate); if (options.dump_option == CompileOptions::HIR_DUMP) { fprintf (stderr, "%s", hir.as_string ().c_str ()); @@ -550,11 +549,17 @@ Session::parse_file (const char *filename) return; // type resolve - type_resolution (hir); + Resolver::TypeResolution::Resolve (hir); + if (options.dump_option == CompileOptions::TYPE_RESOLUTION_DUMP) + { + auto buf = Resolver::TypeResolverDump::go (hir); + fprintf (stderr, "%s\n", buf.c_str ()); + return; + } - // FIXME this needs an option of itself - // auto buf = Resolver::TypeResolverDump::go (hir); - // fprintf (stderr, "%s\n", buf.c_str ()); + // scan unused has to be done after type resolution since methods are resolved + // at that point + Resolver::ScanUnused::Scan (); if (saw_errors ()) return; @@ -792,31 +797,6 @@ Session::expansion (AST::Crate &crate) } void -Session::resolution (AST::Crate &crate) -{ - fprintf (stderr, "started name resolution\n"); - Resolver::NameResolution::Resolve (crate); - fprintf (stderr, "finished name resolution\n"); -} - -HIR::Crate -Session::lower_ast (AST::Crate &crate) -{ - fprintf (stderr, "started lowering AST\n"); - auto hir = HIR::ASTLowering::Resolve (crate); - fprintf (stderr, "finished lowering AST\n"); - return hir; -} - -void -Session::type_resolution (HIR::Crate &crate) -{ - fprintf (stderr, "started type resolution\n"); - Resolver::TypeResolution::Resolve (crate); - fprintf (stderr, "finished type resolution\n"); -} - -void TargetOptions::dump_target_options () const { fprintf (stderr, diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index 4836cc8..07d5461 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -177,7 +177,8 @@ struct CompileOptions RESOLUTION_DUMP, TARGET_OPTION_DUMP, HIR_DUMP, - // TODO: add more? + TYPE_RESOLUTION_DUMP, + } dump_option; /* configuration options - actually useful for conditional compilation and @@ -204,8 +205,6 @@ struct Session // backend linemap Linemap *linemap; - // TODO: replace raw pointers with smart pointers? - public: /* Initialise compiler session. Corresponds to langhook grs_langhook_init(). * Note that this is called after option handling. */ @@ -217,7 +216,6 @@ public: void init_options (); private: - // TODO: should this be private or public? void parse_file (const char *filename); bool enable_dump (std::string arg); @@ -232,23 +230,16 @@ private: * (top-level inner attribute creation from command line arguments), setting * options maybe, registering lints maybe, loading plugins maybe. */ void register_plugins (AST::Crate &crate); + /* Injection pipeline stage. TODO maybe move to another object? Maybe have * some lint checks (in future, obviously), register builtin macros, crate * injection. */ void injection (AST::Crate &crate); + /* Expansion pipeline stage. TODO maybe move to another object? Expands all * macros, maybe build test harness in future, AST validation, maybe create * macro crate (if not rustdoc).*/ void expansion (AST::Crate &crate); - /* Resolution pipeline stage. TODO maybe move to another object. - * Performs name resolution and type resolution, maybe complete gated - * feature checking, maybe create buffered lints in future. */ - void resolution (AST::Crate &crate); - /* This lowers the AST down to HIR and assigns all mappings from AST - * NodeIds back to HirIds */ - HIR::Crate lower_ast (AST::Crate &crate); - /* This adds the type resolution process */ - void type_resolution (HIR::Crate &crate); }; } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-method-resolve.h b/gcc/rust/typecheck/rust-hir-method-resolve.h new file mode 100644 index 0000000..9a6c76f --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-method-resolve.h @@ -0,0 +1,95 @@ +// 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_METHOD_RESOLVE_H +#define RUST_HIR_METHOD_RESOLVE_H + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-tyty.h" + +namespace Rust { +namespace Resolver { + +class MethodResolution : public TypeCheckBase +{ +public: + static std::vector<HIR::Method *> Probe (TyTy::TyBase *receiver, + HIR::PathExprSegment method_name) + { + MethodResolution probe (receiver, method_name); + + // lookup impl items for this crate and find all methods that can resolve to + // this receiver + probe.mappings->iterate_impl_items ( + [&] (HirId id, HIR::InherentImplItem *item) mutable -> bool { + item->accept_vis (probe); + return true; + }); + + return probe.probed; + } + + void visit (HIR::Method &method) + { + TyTy::TyBase *self_lookup = nullptr; + if (!context->lookup_type ( + method.get_self_param ().get_mappings ().get_hirid (), &self_lookup)) + { + rust_error_at (method.get_self_param ().get_locus (), + "failed to lookup lookup self type in MethodProbe"); + return; + } + + // are the names the same + HIR::PathIdentSegment seg = method_name.get_segment (); + if (seg.as_string ().compare (method.get_method_name ()) != 0) + { + // if the method name does not match then this is not a valid match + return; + } + + // FIXME this can be simplified with + // https://github.com/Rust-GCC/gccrs/issues/187 + auto combined = receiver->combine (self_lookup); + if (combined == nullptr) + { + // incompatible self argument then this is not a valid method for this + // receiver + return; + } + delete combined; + + probed.push_back (&method); + } + +private: + MethodResolution (TyTy::TyBase *receiver, HIR::PathExprSegment method_name) + : TypeCheckBase (), receiver (receiver), method_name (method_name) + {} + + TyTy::TyBase *receiver; + HIR::PathExprSegment method_name; + + std::vector<HIR::Method *> probed; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_METHOD_RESOLVE_H diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h index 8de1474..6906878 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.h +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -34,209 +34,186 @@ class TypeCheckBase : public HIR::HIRVisitor public: virtual ~TypeCheckBase () {} - // visitor impl - // rust-ast.h - // virtual void visit(AttrInput& attr_input); - // virtual void visit(TokenTree& token_tree); - // virtual void visit(MacroMatch& macro_match); - virtual void visit (HIR::Token &tok) {} - virtual void visit (HIR::DelimTokenTree &delim_tok_tree) {} - virtual void visit (HIR::AttrInputMetaItemContainer &input) {} - // virtual void visit(MetaItem& meta_item) {} - // void vsit(Stmt& stmt) {} - // virtual void visit(Expr& expr) {} - virtual void visit (HIR::IdentifierExpr &ident_expr) {} - // virtual void visit(Pattern& pattern) {} - // virtual void visit(Type& type) {} - // virtual void visit(TypeParamBound& type_param_bound) {} - virtual void visit (HIR::Lifetime &lifetime) {} - // virtual void visit(GenericParam& generic_param) {} - virtual void visit (HIR::LifetimeParam &lifetime_param) {} - // virtual void visit(TraitItem& trait_item) {} - // virtual void visit(InherentImplItem& inherent_impl_item) {} - // virtual void visit(TraitImplItem& trait_impl_item) {} - - // rust-path.h - virtual void visit (HIR::PathInExpression &path) {} - virtual void visit (HIR::TypePathSegment &segment) {} - virtual void visit (HIR::TypePathSegmentGeneric &segment) {} - virtual void visit (HIR::TypePathSegmentFunction &segment) {} - virtual void visit (HIR::TypePath &path) {} - virtual void visit (HIR::QualifiedPathInExpression &path) {} - virtual void visit (HIR::QualifiedPathInType &path) {} - - // rust-expr.h - virtual void visit (HIR::LiteralExpr &expr) {} - virtual void visit (HIR::AttrInputLiteral &attr_input) {} - virtual void visit (HIR::MetaItemLitExpr &meta_item) {} - virtual void visit (HIR::MetaItemPathLit &meta_item) {} - virtual void visit (HIR::BorrowExpr &expr) {} - virtual void visit (HIR::DereferenceExpr &expr) {} - virtual void visit (HIR::ErrorPropagationExpr &expr) {} - virtual void visit (HIR::NegationExpr &expr) {} - virtual void visit (HIR::ArithmeticOrLogicalExpr &expr) {} - virtual void visit (HIR::ComparisonExpr &expr) {} - virtual void visit (HIR::LazyBooleanExpr &expr) {} - virtual void visit (HIR::TypeCastExpr &expr) {} - virtual void visit (HIR::AssignmentExpr &expr) {} - virtual void visit (HIR::CompoundAssignmentExpr &expr) {} - virtual void visit (HIR::GroupedExpr &expr) {} - // virtual void visit(ArrayElems& elems) {} - virtual void visit (HIR::ArrayElemsValues &elems) {} - virtual void visit (HIR::ArrayElemsCopied &elems) {} - virtual void visit (HIR::ArrayExpr &expr) {} - virtual void visit (HIR::ArrayIndexExpr &expr) {} - virtual void visit (HIR::TupleExpr &expr) {} - virtual void visit (HIR::TupleIndexExpr &expr) {} - virtual void visit (HIR::StructExprStruct &expr) {} - // virtual void visit(StructExprField& field) {} - virtual void visit (HIR::StructExprFieldIdentifier &field) {} - virtual void visit (HIR::StructExprFieldIdentifierValue &field) {} - virtual void visit (HIR::StructExprFieldIndexValue &field) {} - virtual void visit (HIR::StructExprStructFields &expr) {} - virtual void visit (HIR::StructExprStructBase &expr) {} - virtual void visit (HIR::StructExprTuple &expr) {} - virtual void visit (HIR::StructExprUnit &expr) {} - // virtual void visit(EnumExprField& field) {} - virtual void visit (HIR::EnumExprFieldIdentifier &field) {} - virtual void visit (HIR::EnumExprFieldIdentifierValue &field) {} - virtual void visit (HIR::EnumExprFieldIndexValue &field) {} - virtual void visit (HIR::EnumExprStruct &expr) {} - virtual void visit (HIR::EnumExprTuple &expr) {} - virtual void visit (HIR::EnumExprFieldless &expr) {} - virtual void visit (HIR::CallExpr &expr) {} - virtual void visit (HIR::MethodCallExpr &expr) {} - virtual void visit (HIR::FieldAccessExpr &expr) {} - virtual void visit (HIR::ClosureExprInner &expr) {} - virtual void visit (HIR::BlockExpr &expr) {} - virtual void visit (HIR::ClosureExprInnerTyped &expr) {} - virtual void visit (HIR::ContinueExpr &expr) {} - virtual void visit (HIR::BreakExpr &expr) {} - virtual void visit (HIR::RangeFromToExpr &expr) {} - virtual void visit (HIR::RangeFromExpr &expr) {} - virtual void visit (HIR::RangeToExpr &expr) {} - virtual void visit (HIR::RangeFullExpr &expr) {} - virtual void visit (HIR::RangeFromToInclExpr &expr) {} - virtual void visit (HIR::RangeToInclExpr &expr) {} - virtual void visit (HIR::ReturnExpr &expr) {} - virtual void visit (HIR::UnsafeBlockExpr &expr) {} - virtual void visit (HIR::LoopExpr &expr) {} - virtual void visit (HIR::WhileLoopExpr &expr) {} - virtual void visit (HIR::WhileLetLoopExpr &expr) {} - virtual void visit (HIR::ForLoopExpr &expr) {} - virtual void visit (HIR::IfExpr &expr) {} - virtual void visit (HIR::IfExprConseqElse &expr) {} - virtual void visit (HIR::IfExprConseqIf &expr) {} - virtual void visit (HIR::IfExprConseqIfLet &expr) {} - virtual void visit (HIR::IfLetExpr &expr) {} - virtual void visit (HIR::IfLetExprConseqElse &expr) {} - virtual void visit (HIR::IfLetExprConseqIf &expr) {} - virtual void visit (HIR::IfLetExprConseqIfLet &expr) {} - // virtual void visit(MatchCase& match_case) {} - // virtual void visit (HIR::MatchCaseBlockExpr &match_case) {} - // virtual void visit (HIR::MatchCaseExpr &match_case) {} - virtual void visit (HIR::MatchExpr &expr) {} - virtual void visit (HIR::AwaitExpr &expr) {} - virtual void visit (HIR::AsyncBlockExpr &expr) {} - - // rust-item.h - virtual void visit (HIR::TypeParam ¶m) {} - // virtual void visit(WhereClauseItem& item) {} - virtual void visit (HIR::LifetimeWhereClauseItem &item) {} - virtual void visit (HIR::TypeBoundWhereClauseItem &item) {} - virtual void visit (HIR::Method &method) {} - virtual void visit (HIR::ModuleBodied &module) {} - virtual void visit (HIR::ModuleNoBody &module) {} - virtual void visit (HIR::ExternCrate &crate) {} - // virtual void visit(UseTree& use_tree) {} - virtual void visit (HIR::UseTreeGlob &use_tree) {} - virtual void visit (HIR::UseTreeList &use_tree) {} - virtual void visit (HIR::UseTreeRebind &use_tree) {} - virtual void visit (HIR::UseDeclaration &use_decl) {} - virtual void visit (HIR::Function &function) {} - virtual void visit (HIR::TypeAlias &type_alias) {} - virtual void visit (HIR::StructStruct &struct_item) {} - virtual void visit (HIR::TupleStruct &tuple_struct) {} - virtual void visit (HIR::EnumItem &item) {} - virtual void visit (HIR::EnumItemTuple &item) {} - virtual void visit (HIR::EnumItemStruct &item) {} - virtual void visit (HIR::EnumItemDiscriminant &item) {} - virtual void visit (HIR::Enum &enum_item) {} - virtual void visit (HIR::Union &union_item) {} - virtual void visit (HIR::ConstantItem &const_item) {} - virtual void visit (HIR::StaticItem &static_item) {} - virtual void visit (HIR::TraitItemFunc &item) {} - virtual void visit (HIR::TraitItemMethod &item) {} - virtual void visit (HIR::TraitItemConst &item) {} - virtual void visit (HIR::TraitItemType &item) {} - virtual void visit (HIR::Trait &trait) {} - virtual void visit (HIR::InherentImpl &impl) {} - virtual void visit (HIR::TraitImpl &impl) {} - // virtual void visit(ExternalItem& item) {} - virtual void visit (HIR::ExternalStaticItem &item) {} - virtual void visit (HIR::ExternalFunctionItem &item) {} - virtual void visit (HIR::ExternBlock &block) {} - - // rust-macro.h - virtual void visit (HIR::MacroMatchFragment &match) {} - virtual void visit (HIR::MacroMatchRepetition &match) {} - virtual void visit (HIR::MacroMatcher &matcher) {} - virtual void visit (HIR::MacroRulesDefinition &rules_def) {} - virtual void visit (HIR::MacroInvocation ¯o_invoc) {} - virtual void visit (HIR::MetaItemPath &meta_item) {} - virtual void visit (HIR::MetaItemSeq &meta_item) {} - virtual void visit (HIR::MetaWord &meta_item) {} - virtual void visit (HIR::MetaNameValueStr &meta_item) {} - virtual void visit (HIR::MetaListPaths &meta_item) {} - virtual void visit (HIR::MetaListNameValueStr &meta_item) {} - - // rust-pattern.h - virtual void visit (HIR::LiteralPattern &pattern) {} - virtual void visit (HIR::IdentifierPattern &pattern) {} - virtual void visit (HIR::WildcardPattern &pattern) {} - // virtual void visit(RangePatternBound& bound) {} - virtual void visit (HIR::RangePatternBoundLiteral &bound) {} - virtual void visit (HIR::RangePatternBoundPath &bound) {} - virtual void visit (HIR::RangePatternBoundQualPath &bound) {} - virtual void visit (HIR::RangePattern &pattern) {} - virtual void visit (HIR::ReferencePattern &pattern) {} - // virtual void visit(StructPatternField& field) {} - virtual void visit (HIR::StructPatternFieldTuplePat &field) {} - virtual void visit (HIR::StructPatternFieldIdentPat &field) {} - virtual void visit (HIR::StructPatternFieldIdent &field) {} - virtual void visit (HIR::StructPattern &pattern) {} - // virtual void visit(TupleStructItems& tuple_items) {} - virtual void visit (HIR::TupleStructItemsNoRange &tuple_items) {} - virtual void visit (HIR::TupleStructItemsRange &tuple_items) {} - virtual void visit (HIR::TupleStructPattern &pattern) {} - // virtual void visit(TuplePatternItems& tuple_items) {} - virtual void visit (HIR::TuplePatternItemsMultiple &tuple_items) {} - virtual void visit (HIR::TuplePatternItemsRanged &tuple_items) {} - virtual void visit (HIR::TuplePattern &pattern) {} - virtual void visit (HIR::GroupedPattern &pattern) {} - virtual void visit (HIR::SlicePattern &pattern) {} - - // rust-stmt.h - virtual void visit (HIR::EmptyStmt &stmt) {} - virtual void visit (HIR::LetStmt &stmt) {} - virtual void visit (HIR::ExprStmtWithoutBlock &stmt) {} - virtual void visit (HIR::ExprStmtWithBlock &stmt) {} - - // rust-type.h - virtual void visit (HIR::TraitBound &bound) {} - virtual void visit (HIR::ImplTraitType &type) {} - virtual void visit (HIR::TraitObjectType &type) {} - virtual void visit (HIR::ParenthesisedType &type) {} - virtual void visit (HIR::ImplTraitTypeOneBound &type) {} - virtual void visit (HIR::TraitObjectTypeOneBound &type) {} - virtual void visit (HIR::TupleType &type) {} - virtual void visit (HIR::NeverType &type) {} - virtual void visit (HIR::RawPointerType &type) {} - virtual void visit (HIR::ReferenceType &type) {} - virtual void visit (HIR::ArrayType &type) {} - virtual void visit (HIR::SliceType &type) {} - virtual void visit (HIR::InferredType &type) {} - virtual void visit (HIR::BareFunctionType &type) {} + virtual void visit (HIR::Token &) override {} + virtual void visit (HIR::DelimTokenTree &) override {} + virtual void visit (HIR::AttrInputMetaItemContainer &) override {} + virtual void visit (HIR::IdentifierExpr &) override {} + virtual void visit (HIR::Lifetime &) override {} + virtual void visit (HIR::LifetimeParam &) override {} + virtual void visit (HIR::PathInExpression &) override {} + virtual void visit (HIR::TypePathSegment &) override {} + virtual void visit (HIR::TypePathSegmentGeneric &) override {} + virtual void visit (HIR::TypePathSegmentFunction &) override {} + virtual void visit (HIR::TypePath &) override {} + virtual void visit (HIR::QualifiedPathInExpression &) override {} + virtual void visit (HIR::QualifiedPathInType &) override {} + + virtual void visit (HIR::LiteralExpr &) override {} + virtual void visit (HIR::AttrInputLiteral &) override {} + virtual void visit (HIR::MetaItemLitExpr &) override {} + virtual void visit (HIR::MetaItemPathLit &) override {} + virtual void visit (HIR::BorrowExpr &) override {} + virtual void visit (HIR::DereferenceExpr &) override {} + virtual void visit (HIR::ErrorPropagationExpr &) override {} + virtual void visit (HIR::NegationExpr &) override {} + virtual void visit (HIR::ArithmeticOrLogicalExpr &) override {} + virtual void visit (HIR::ComparisonExpr &) override {} + virtual void visit (HIR::LazyBooleanExpr &) override {} + virtual void visit (HIR::TypeCastExpr &) override {} + virtual void visit (HIR::AssignmentExpr &) override {} + + virtual void visit (HIR::GroupedExpr &) override {} + + virtual void visit (HIR::ArrayElemsValues &) override {} + virtual void visit (HIR::ArrayElemsCopied &) override {} + virtual void visit (HIR::ArrayExpr &) override {} + virtual void visit (HIR::ArrayIndexExpr &) override {} + virtual void visit (HIR::TupleExpr &) override {} + virtual void visit (HIR::TupleIndexExpr &) override {} + virtual void visit (HIR::StructExprStruct &) override {} + + virtual void visit (HIR::StructExprFieldIdentifier &) override {} + virtual void visit (HIR::StructExprFieldIdentifierValue &) override {} + + virtual void visit (HIR::StructExprFieldIndexValue &) override {} + virtual void visit (HIR::StructExprStructFields &) override {} + virtual void visit (HIR::StructExprStructBase &) override {} + virtual void visit (HIR::StructExprTuple &) override {} + virtual void visit (HIR::StructExprUnit &) override {} + + virtual void visit (HIR::EnumExprFieldIdentifier &) override {} + virtual void visit (HIR::EnumExprFieldIdentifierValue &) override {} + + virtual void visit (HIR::EnumExprFieldIndexValue &) override {} + virtual void visit (HIR::EnumExprStruct &) override {} + virtual void visit (HIR::EnumExprTuple &) override {} + virtual void visit (HIR::EnumExprFieldless &) override {} + virtual void visit (HIR::CallExpr &) override {} + virtual void visit (HIR::MethodCallExpr &) override {} + virtual void visit (HIR::FieldAccessExpr &) override {} + virtual void visit (HIR::ClosureExprInner &) override {} + virtual void visit (HIR::BlockExpr &) override {} + virtual void visit (HIR::ClosureExprInnerTyped &) override {} + virtual void visit (HIR::ContinueExpr &) override {} + virtual void visit (HIR::BreakExpr &) override {} + virtual void visit (HIR::RangeFromToExpr &) override {} + virtual void visit (HIR::RangeFromExpr &) override {} + virtual void visit (HIR::RangeToExpr &) override {} + virtual void visit (HIR::RangeFullExpr &) override {} + virtual void visit (HIR::RangeFromToInclExpr &) override {} + virtual void visit (HIR::RangeToInclExpr &) override {} + virtual void visit (HIR::ReturnExpr &) override {} + virtual void visit (HIR::UnsafeBlockExpr &) override {} + virtual void visit (HIR::LoopExpr &) override {} + virtual void visit (HIR::WhileLoopExpr &) override {} + virtual void visit (HIR::WhileLetLoopExpr &) override {} + virtual void visit (HIR::ForLoopExpr &) override {} + virtual void visit (HIR::IfExpr &) override {} + virtual void visit (HIR::IfExprConseqElse &) override {} + virtual void visit (HIR::IfExprConseqIf &) override {} + virtual void visit (HIR::IfExprConseqIfLet &) override {} + virtual void visit (HIR::IfLetExpr &) override {} + virtual void visit (HIR::IfLetExprConseqElse &) override {} + virtual void visit (HIR::IfLetExprConseqIf &) override {} + virtual void visit (HIR::IfLetExprConseqIfLet &) override {} + + virtual void visit (HIR::MatchExpr &) override {} + virtual void visit (HIR::AwaitExpr &) override {} + virtual void visit (HIR::AsyncBlockExpr &) override {} + + virtual void visit (HIR::TypeParam &) override {} + + virtual void visit (HIR::LifetimeWhereClauseItem &) override {} + virtual void visit (HIR::TypeBoundWhereClauseItem &) override {} + virtual void visit (HIR::Method &) override {} + virtual void visit (HIR::ModuleBodied &) override {} + virtual void visit (HIR::ModuleNoBody &) override {} + virtual void visit (HIR::ExternCrate &) override {} + + virtual void visit (HIR::UseTreeGlob &) override {} + virtual void visit (HIR::UseTreeList &) override {} + virtual void visit (HIR::UseTreeRebind &) override {} + virtual void visit (HIR::UseDeclaration &) override {} + virtual void visit (HIR::Function &) override {} + virtual void visit (HIR::TypeAlias &) override {} + virtual void visit (HIR::StructStruct &) override {} + virtual void visit (HIR::TupleStruct &) override {} + virtual void visit (HIR::EnumItem &) override {} + virtual void visit (HIR::EnumItemTuple &) override {} + virtual void visit (HIR::EnumItemStruct &) override {} + virtual void visit (HIR::EnumItemDiscriminant &) override {} + virtual void visit (HIR::Enum &) override {} + virtual void visit (HIR::Union &) override {} + virtual void visit (HIR::ConstantItem &) override {} + virtual void visit (HIR::StaticItem &) override {} + virtual void visit (HIR::TraitItemFunc &) override {} + virtual void visit (HIR::TraitItemMethod &) override {} + virtual void visit (HIR::TraitItemConst &) override {} + virtual void visit (HIR::TraitItemType &) override {} + virtual void visit (HIR::Trait &) override {} + virtual void visit (HIR::InherentImpl &) override {} + virtual void visit (HIR::TraitImpl &) override {} + + virtual void visit (HIR::ExternalStaticItem &) override {} + virtual void visit (HIR::ExternalFunctionItem &) override {} + virtual void visit (HIR::ExternBlock &) override {} + + virtual void visit (HIR::MacroMatchFragment &) override {} + virtual void visit (HIR::MacroMatchRepetition &) override {} + virtual void visit (HIR::MacroMatcher &) override {} + virtual void visit (HIR::MacroRulesDefinition &) override {} + virtual void visit (HIR::MacroInvocation &) override {} + virtual void visit (HIR::MetaItemPath &) override {} + virtual void visit (HIR::MetaItemSeq &) override {} + virtual void visit (HIR::MetaWord &) override {} + virtual void visit (HIR::MetaNameValueStr &) override {} + virtual void visit (HIR::MetaListPaths &) override {} + virtual void visit (HIR::MetaListNameValueStr &) override {} + + virtual void visit (HIR::LiteralPattern &) override {} + virtual void visit (HIR::IdentifierPattern &) override {} + virtual void visit (HIR::WildcardPattern &) override {} + + virtual void visit (HIR::RangePatternBoundLiteral &) override {} + virtual void visit (HIR::RangePatternBoundPath &) override {} + virtual void visit (HIR::RangePatternBoundQualPath &) override {} + virtual void visit (HIR::RangePattern &) override {} + virtual void visit (HIR::ReferencePattern &) override {} + + virtual void visit (HIR::StructPatternFieldTuplePat &) override {} + virtual void visit (HIR::StructPatternFieldIdentPat &) override {} + virtual void visit (HIR::StructPatternFieldIdent &) override {} + virtual void visit (HIR::StructPattern &) override {} + + virtual void visit (HIR::TupleStructItemsNoRange &) override {} + virtual void visit (HIR::TupleStructItemsRange &) override {} + virtual void visit (HIR::TupleStructPattern &) override {} + + virtual void visit (HIR::TuplePatternItemsMultiple &) override {} + virtual void visit (HIR::TuplePatternItemsRanged &) override {} + virtual void visit (HIR::TuplePattern &) override {} + virtual void visit (HIR::GroupedPattern &) override {} + virtual void visit (HIR::SlicePattern &) override {} + + virtual void visit (HIR::EmptyStmt &) override {} + virtual void visit (HIR::LetStmt &) override {} + virtual void visit (HIR::ExprStmtWithoutBlock &) override {} + virtual void visit (HIR::ExprStmtWithBlock &) override {} + + virtual void visit (HIR::TraitBound &) override {} + virtual void visit (HIR::ImplTraitType &) override {} + virtual void visit (HIR::TraitObjectType &) override {} + virtual void visit (HIR::ParenthesisedType &) override {} + virtual void visit (HIR::ImplTraitTypeOneBound &) override {} + virtual void visit (HIR::TraitObjectTypeOneBound &) override {} + virtual void visit (HIR::TupleType &) override {} + virtual void visit (HIR::NeverType &) override {} + virtual void visit (HIR::RawPointerType &) override {} + virtual void visit (HIR::ReferenceType &) override {} + virtual void visit (HIR::ArrayType &) override {} + virtual void visit (HIR::SliceType &) override {} + virtual void visit (HIR::InferredType &) override {} + virtual void visit (HIR::BareFunctionType &) override {} protected: TypeCheckBase () diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 82977e4..e6cca19 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -24,6 +24,7 @@ #include "rust-tyty.h" #include "rust-tyty-call.h" #include "rust-hir-type-check-struct-field.h" +#include "rust-hir-method-resolve.h" namespace Rust { namespace Resolver { @@ -37,7 +38,10 @@ public: expr->accept_vis (resolver); if (resolver.infered == nullptr) - return new TyTy::ErrorType (expr->get_mappings ().get_hirid ()); + { + rust_error_at (expr->get_locus_slow (), "failed to resolve expression"); + return new TyTy::ErrorType (expr->get_mappings ().get_hirid ()); + } auto ref = expr->get_mappings ().get_hirid (); resolver.infered->set_ref (ref); @@ -196,9 +200,8 @@ public: TyTy::TyBase *lookup; if (!context->lookup_type (ref, &lookup)) { - // FIXME we need to be able to lookup the location info for the - // reference here - rust_error_at (expr.get_locus (), "consider giving this a type: %s", + rust_error_at (mappings->lookup_location (ref), + "failed to lookup type for CallExpr: %s", expr.as_string ().c_str ()); return; } @@ -213,6 +216,65 @@ public: infered->set_ref (expr.get_mappings ().get_hirid ()); } + void visit (HIR::MethodCallExpr &expr) + { + auto receiver_tyty = TypeCheckExpr::Resolve (expr.get_receiver ().get ()); + if (receiver_tyty == nullptr) + { + rust_error_at (expr.get_receiver ()->get_locus_slow (), + "failed to resolve receiver in MethodCallExpr"); + return; + } + + // https://doc.rust-lang.org/reference/expressions/method-call-expr.html + // method resolution is complex in rust once we start handling generics and + // traits. For now we only support looking up the valid name in impl blocks + // which is simple. There will need to be adjustments to ensure we can turn + // the receiver into borrowed references etc + + auto probes + = MethodResolution::Probe (receiver_tyty, expr.get_method_name ()); + if (probes.size () == 0) + { + rust_error_at (expr.get_locus (), + "failed to resolve the PathExprSegment to any Method"); + return; + } + else if (probes.size () > 1) + { + rust_error_at ( + expr.get_locus (), + "Generics and Traits are not implemented yet for MethodCall"); + return; + } + + auto resolved_method = probes.at (0); + TyTy::TyBase *lookup; + if (!context->lookup_type (resolved_method->get_mappings ().get_hirid (), + &lookup)) + { + rust_error_at (resolved_method->get_locus (), + "failed to lookup type for CallExpr: %s", + expr.as_string ().c_str ()); + return; + } + + infered = TyTy::TypeCheckMethodCallExpr::go (lookup, expr, context); + if (infered == nullptr) + { + rust_error_at (expr.get_locus (), + "failed to lookup type to MethodCallExpr"); + return; + } + + infered->set_ref (expr.get_mappings ().get_hirid ()); + + // set up the resolved name on the path + resolver->insert_resolved_name ( + expr.get_mappings ().get_nodeid (), + resolved_method->get_mappings ().get_nodeid ()); + } + void visit (HIR::AssignmentExpr &expr) { auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); @@ -313,7 +375,7 @@ public: if (!context->lookup_type (ref, &lookup)) { rust_error_at (mappings->lookup_location (ref), - "consider giving this a type: %s", + "Failed to resolve IdentifierExpr type: %s", expr.as_string ().c_str ()); return; } @@ -703,7 +765,7 @@ public: if (!is_valid_type) { rust_error_at (expr.get_locus (), - "expected ADT or Tuple Type got: [%s]", + "expected algebraic data type got: [%s]", struct_base->as_string ().c_str ()); return; } @@ -747,7 +809,11 @@ public: return; } - context->lookup_type (ref, &infered); + if (!context->lookup_type (ref, &infered)) + { + rust_error_at (expr.get_locus (), + "failed to resolve PathInExpression type"); + } } private: @@ -799,6 +865,7 @@ private: && (((TyTy::InferType *) type)->get_infer_kind () == TyTy::InferType::INTEGRAL)); } + gcc_unreachable (); } TyTy::TyBase *infered; diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index abaee73..c8d161a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -31,9 +31,9 @@ namespace Resolver { class TypeCheckTopLevelImplItem : public TypeCheckBase { public: - static void Resolve (HIR::InherentImplItem *item) + static void Resolve (HIR::InherentImplItem *item, TyTy::TyBase *self) { - TypeCheckTopLevelImplItem resolver; + TypeCheckTopLevelImplItem resolver (self); item->accept_vis (resolver); } @@ -81,8 +81,62 @@ public: context->insert_type (function.get_mappings (), fnType); } + void visit (HIR::Method &method) + { + TyTy::TyBase *ret_type = nullptr; + if (!method.has_function_return_type ()) + ret_type = new TyTy::UnitType (method.get_mappings ().get_hirid ()); + else + { + auto resolved + = TypeCheckType::Resolve (method.get_return_type ().get ()); + if (resolved == nullptr) + { + rust_error_at (method.get_locus (), + "failed to resolve return type"); + return; + } + + ret_type = resolved->clone (); + ret_type->set_ref ( + method.get_return_type ()->get_mappings ().get_hirid ()); + } + + // hold all the params to the fndef + std::vector<std::pair<HIR::Pattern *, TyTy::TyBase *> > params; + + // add the self param at the front + HIR::SelfParam &self_param = method.get_self_param (); + HIR::IdentifierPattern *self_pattern + = new HIR::IdentifierPattern ("self", self_param.get_locus (), + self_param.get_has_ref (), + self_param.get_is_mut (), + std::unique_ptr<HIR::Pattern> (nullptr)); + context->insert_type (self_param.get_mappings (), self->clone ()); + params.push_back ( + std::pair<HIR::Pattern *, TyTy::TyBase *> (self_pattern, self->clone ())); + + for (auto ¶m : method.get_function_params ()) + { + // get the name as well required for later on + auto param_tyty = TypeCheckType::Resolve (param.get_type ()); + params.push_back ( + std::pair<HIR::Pattern *, TyTy::TyBase *> (param.get_param_name (), + param_tyty)); + + context->insert_type (param.get_mappings (), param_tyty); + } + + auto fnType = new TyTy::FnType (method.get_mappings ().get_hirid (), params, + ret_type); + context->insert_type (method.get_mappings (), fnType); + } + private: - TypeCheckTopLevelImplItem () : TypeCheckBase () {} + TypeCheckTopLevelImplItem (TyTy::TyBase *self) : TypeCheckBase (), self (self) + {} + + TyTy::TyBase *self; }; class TypeCheckImplItem : public TypeCheckBase @@ -99,7 +153,7 @@ public: TyTy::TyBase *lookup; if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup)) { - rust_error_at (function.locus, "failed to lookup function type"); + rust_error_at (function.get_locus (), "failed to lookup function type"); return; } @@ -137,6 +191,49 @@ public: context->pop_return_type (); } + void visit (HIR::Method &method) + { + TyTy::TyBase *lookup; + if (!context->lookup_type (method.get_mappings ().get_hirid (), &lookup)) + { + rust_error_at (method.get_locus (), "failed to lookup function type"); + return; + } + + if (lookup->get_kind () != TyTy::TypeKind::FNDEF) + { + rust_error_at (method.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 (method.get_function_body ().get ()); + if (method.get_function_body ()->has_expr ()) + { + auto resolved + = TypeCheckExpr::Resolve (method.get_function_body ()->expr.get ()); + + auto ret_resolved = expected_ret_tyty->combine (resolved); + if (ret_resolved == nullptr) + { + rust_error_at (method.get_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) {} diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 571d998..06be1ac 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -38,7 +38,7 @@ public: item->accept_vis (resolver); } - void visit (HIR::InherentImpl &impl_block) + void visit (HIR::InherentImpl &impl_block) override { TyTy::TyBase *self = nullptr; if (!context->lookup_type ( @@ -53,7 +53,7 @@ public: TypeCheckImplItem::Resolve (impl_item.get (), self); } - void visit (HIR::Function &function) + void visit (HIR::Function &function) override { TyTy::TyBase *lookup; if (!context->lookup_type (function.get_mappings ().get_hirid (), &lookup)) diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 46b3b0f..61823bf 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -137,11 +137,15 @@ public: void visit (HIR::InherentImpl &impl_block) { - TypeCheckType::Resolve (impl_block.get_type ().get ()); - for (auto &impl_item : impl_block.get_impl_items ()) + auto self = TypeCheckType::Resolve (impl_block.get_type ().get ()); + if (self == nullptr) { - TypeCheckTopLevelImplItem::Resolve (impl_item.get ()); + rust_error_at (impl_block.get_locus (), "failed to resolve impl type"); + return; } + + for (auto &impl_item : impl_block.get_impl_items ()) + TypeCheckTopLevelImplItem::Resolve (impl_item.get (), self); } private: diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 416cd89..681d023 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -127,19 +127,12 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) return true; }); - // 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); + if (expr.has_expr ()) + { + delete block_tyty; + + block_tyty = TypeCheckExpr::Resolve (expr.get_final_expr ().get (), true); + } infered = block_tyty->clone (); } diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h index 0d8fffc..9d882fb 100644 --- a/gcc/rust/typecheck/rust-tycheck-dump.h +++ b/gcc/rust/typecheck/rust-tycheck-dump.h @@ -37,7 +37,7 @@ public: return dumper.dump; } - void visit (HIR::InherentImpl &impl_block) + void visit (HIR::InherentImpl &impl_block) override { dump += indent () + "impl " + type_string (impl_block.get_type ()->get_mappings ()) + " {\n"; @@ -53,7 +53,7 @@ public: dump += indent () + "}\n"; } - void visit (HIR::ConstantItem &constant) + void visit (HIR::ConstantItem &constant) override { dump += indent () + "constant " + constant.get_identifier () + ":" + type_string (constant.get_mappings ()) + " = "; @@ -61,7 +61,7 @@ public: dump += ";\n"; } - void visit (HIR::Function &function) + void visit (HIR::Function &function) override { dump += indent () + "fn " + function.function_name + " " + type_string (function.get_mappings ()) + "\n"; @@ -73,7 +73,19 @@ public: dump += indent () + "}\n"; } - void visit (HIR::BlockExpr &expr) + void visit (HIR::Method &method) override + { + dump += indent () + "fn " + method.get_method_name () + " " + + type_string (method.get_mappings ()) + "\n"; + dump += indent () + "{\n"; + + HIR::BlockExpr *function_body = method.get_function_body ().get (); + function_body->accept_vis (*this); + + dump += indent () + "}\n"; + } + + void visit (HIR::BlockExpr &expr) override { indentation_level++; @@ -94,7 +106,7 @@ public: indentation_level--; } - void visit (HIR::LetStmt &stmt) + void visit (HIR::LetStmt &stmt) override { dump += "let " + stmt.get_pattern ()->as_string () + ":" + type_string (stmt.get_mappings ()); @@ -105,35 +117,35 @@ public: } } - void visit (HIR::ExprStmtWithBlock &stmt) + void visit (HIR::ExprStmtWithBlock &stmt) override { stmt.get_expr ()->accept_vis (*this); } - void visit (HIR::ExprStmtWithoutBlock &stmt) + void visit (HIR::ExprStmtWithoutBlock &stmt) override { stmt.get_expr ()->accept_vis (*this); } - void visit (HIR::AssignmentExpr &expr) + void visit (HIR::AssignmentExpr &expr) override { expr.get_lhs ()->accept_vis (*this); dump += " = "; expr.get_rhs ()->accept_vis (*this); } - void visit (HIR::LiteralExpr &expr) + void visit (HIR::LiteralExpr &expr) override { dump += expr.get_literal ()->as_string () + ":" + type_string (expr.get_mappings ()); } - void visit (HIR::IdentifierExpr &expr) + void visit (HIR::IdentifierExpr &expr) override { dump += expr.get_identifier () + ":" + type_string (expr.get_mappings ()); } - void visit (HIR::ArrayExpr &expr) + void visit (HIR::ArrayExpr &expr) override { dump += type_string (expr.get_mappings ()) + ":["; @@ -143,7 +155,7 @@ public: dump += "]"; } - void visit (HIR::ArrayElemsValues &elems) + void visit (HIR::ArrayElemsValues &elems) override { elems.iterate ([&] (HIR::Expr *e) mutable -> bool { e->accept_vis (*this); @@ -152,7 +164,7 @@ public: }); } - void visit (HIR::GroupedExpr &expr) + void visit (HIR::GroupedExpr &expr) override { HIR::Expr *paren_expr = expr.get_expr_in_parens ().get (); dump += "("; @@ -160,7 +172,7 @@ public: dump += ")"; } - void visit (HIR::PathInExpression &expr) + void visit (HIR::PathInExpression &expr) override { dump += type_string (expr.get_mappings ()); } diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index 2b3cfb6..82b070f 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -38,7 +38,6 @@ public: ref->accept_vis (checker); return checker.resolved; } - ~TypeCheckCallExpr () {} void visit (UnitType &type) override { gcc_unreachable (); } void visit (InferType &type) override { gcc_unreachable (); } @@ -71,6 +70,47 @@ private: Analysis::Mappings *mappings; }; +class TypeCheckMethodCallExpr : private TyVisitor +{ +public: + static TyBase *go (TyBase *ref, HIR::MethodCallExpr &call, + Resolver::TypeCheckContext *context) + { + TypeCheckMethodCallExpr checker (call, context); + ref->accept_vis (checker); + return checker.resolved; + } + + 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 (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 (); } + void visit (ADTType &type) override { gcc_unreachable (); }; + + // call fns + void visit (FnType &type) override; + +private: + TypeCheckMethodCallExpr (HIR::MethodCallExpr &c, + Resolver::TypeCheckContext *context) + : resolved (nullptr), call (c), context (context), + mappings (Analysis::Mappings::get ()) + {} + + TyBase *resolved; + HIR::MethodCallExpr &call; + Resolver::TypeCheckContext *context; + Analysis::Mappings *mappings; +}; + } // namespace TyTy } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index d506415..8b04209 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -147,14 +147,15 @@ ADTType::accept_vis (TyVisitor &vis) std::string ADTType::as_string () const { - if (num_fields () == 0) - return identifier; + // if (num_fields () == 0) + // return identifier; - std::string fields_buffer; - for (auto &field : fields) - fields_buffer += field->as_string () + ", "; + // std::string fields_buffer; + // for (auto &field : fields) + // fields_buffer += field->as_string () + ", "; - return identifier + "{" + fields_buffer + "}"; + // return identifier + "{" + fields_buffer + "}"; + return identifier; } TyBase * @@ -574,5 +575,56 @@ TypeCheckCallExpr::visit (FnType &type) resolved = type.get_return_type ()->clone (); } +// method call checker + +void +TypeCheckMethodCallExpr::visit (FnType &type) +{ + // +1 for the receiver self + size_t num_args_to_call = call.num_params () + 1; + if (num_args_to_call != 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 = 1; + 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 != num_args_to_call) + { + rust_error_at (call.get_locus (), + "unexpected number of arguments %lu expected %lu", i, + call.num_params ()); + return; + } + + resolved = type.get_return_type ()->clone (); +} + } // namespace TyTy } // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index eb55581..8a15631 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -375,6 +375,30 @@ Mappings::lookup_hir_param (CrateNum crateNum, HirId id) } void +Mappings::insert_hir_self_param (CrateNum crateNum, HirId id, + HIR::SelfParam *param) +{ + rust_assert (lookup_hir_stmt (crateNum, id) == nullptr); + + hirSelfParamMappings[crateNum][id] = param; + nodeIdToHirMappings[crateNum][param->get_mappings ().get_nodeid ()] = id; +} + +HIR::SelfParam * +Mappings::lookup_hir_self_param (CrateNum crateNum, HirId id) +{ + auto it = hirSelfParamMappings.find (crateNum); + if (it == hirSelfParamMappings.end ()) + return nullptr; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return nullptr; + + return iy->second; +} + +void Mappings::insert_hir_struct_field (CrateNum crateNum, HirId id, HIR::StructExprField *field) { diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index f81cee6..0d625f6 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -125,6 +125,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_self_param (CrateNum crateNum, HirId id, + HIR::SelfParam *type); + HIR::SelfParam *lookup_hir_self_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); @@ -152,6 +156,20 @@ public: return hirNodesWithinCrate[crate]; } + void + iterate_impl_items (std::function<bool (HirId, HIR::InherentImplItem *)> cb) + { + for (auto it = hirImplItemMappings.begin (); + it != hirImplItemMappings.end (); it++) + { + for (auto iy = it->second.begin (); iy != it->second.end (); iy++) + { + if (!cb (iy->first, iy->second)) + return; + } + } + } + private: Mappings (); @@ -176,6 +194,7 @@ private: hirStructFieldMappings; std::map<CrateNum, std::map<HirId, HIR::InherentImplItem *> > hirImplItemMappings; + std::map<CrateNum, std::map<HirId, HIR::SelfParam *> > hirSelfParamMappings; // location info std::map<CrateNum, std::map<NodeId, Location> > locations; diff --git a/gcc/testsuite/rust.test/compilable/block_expr1.rs b/gcc/testsuite/rust.test/compilable/block_expr1.rs new file mode 100644 index 0000000..fe63252 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/block_expr1.rs @@ -0,0 +1,27 @@ +fn test3(x: i32) -> i32 { + if x > 1 { + 5 + } else { + 0 + } +} + +fn test5(x: i32) -> i32 { + if x > 1 { + if x == 5 { + 7 + } else { + 9 + } + } else { + 0 + } +} + +fn main() { + let call3: i32 = { test3(3) + 2 }; + let call5 = { + let a = test5(5); + a + 1 + }; +} diff --git a/gcc/testsuite/rust.test/compilable/impl_block3.rs b/gcc/testsuite/rust.test/compilable/impl_block3.rs new file mode 100644 index 0000000..3093a6c --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/impl_block3.rs @@ -0,0 +1,31 @@ +struct Point { + x: f64, + y: f64, +} + +impl Point { + fn origin() -> Point { + Point { x: 0.0, y: 0.0 } + } + + fn new(x: f64, y: f64) -> Point { + Point { x: x, y: y } + } +} + +struct Rectangle { + p1: Point, + p2: Point, +} + +impl Rectangle { + fn from(p1: Point, p2: Point) -> Self { + Self { p1, p2 } + } +} + +fn main() { + let p1 = Point::origin(); + let p2 = Point::new(3.0, 4.0); + let rect = Rectangle::from(p1, p2); +} diff --git a/gcc/testsuite/rust.test/compilable/methods1.rs b/gcc/testsuite/rust.test/compilable/methods1.rs new file mode 100644 index 0000000..cffa02e --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/methods1.rs @@ -0,0 +1,39 @@ +struct Point { + x: f64, + y: f64, +} + +impl Point { + fn origin() -> Point { + Point { x: 0.0, y: 0.0 } + } + + fn new(x: f64, y: f64) -> Point { + Point { x: x, y: y } + } +} + +struct Rectangle { + p1: Point, + p2: Point, +} + +impl Rectangle { + fn from(p1: Point, p2: Point) -> Self { + Self { p1, p2 } + } + + fn sum_x(self) -> f64 { + let p1 = self.p1; + let p2 = self.p2; + p1.x + p2.x + } +} + +fn main() { + let p1 = Point::origin(); + let p2 = Point::new(3.0, 4.0); + let rect = Rectangle::from(p1, p2); + + let sum = rect.sum_x(); +} diff --git a/gcc/testsuite/rust.test/compilable/methods2.rs b/gcc/testsuite/rust.test/compilable/methods2.rs new file mode 100644 index 0000000..96a3211 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/methods2.rs @@ -0,0 +1,41 @@ +struct Point { + x: f64, + y: f64, +} + +impl Point { + fn origin() -> Point { + Point { x: 0.0, y: 0.0 } + } + + fn new(x: f64, y: f64) -> Point { + Point { x: x, y: y } + } +} + +struct Rectangle { + p1: Point, + p2: Point, +} + +impl Rectangle { + fn from(p1: Point, p2: Point) -> Self { + Self { p1, p2 } + } +} + +fn main() { + let p1 = Point::origin(); + let p2 = Point::new(3.0, 4.0); + let rect = Rectangle::from(p1, p2); + + let sum = rect.sum_x(); +} + +impl Rectangle { + fn sum_x(self) -> f64 { + let p1 = self.p1; + let p2 = self.p2; + p1.x + p2.x + } +} diff --git a/gcc/testsuite/rust.test/compilable/name_resolve1.rs b/gcc/testsuite/rust.test/compilable/name_resolve1.rs new file mode 100644 index 0000000..817f48b --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/name_resolve1.rs @@ -0,0 +1,23 @@ +struct Foo(i32, bool); + +impl Foo { + fn new(a: i32, b: bool) -> Foo { + Foo(a, b) + } + + fn test() -> i32 { + test() + } +} + +fn test() -> i32 { + 123 +} + +fn main() { + let a; + a = Foo::new(1, true); + + let b; + b = Foo::test(); +} diff --git a/gcc/testsuite/rust.test/compilable/nested_struct1.rs b/gcc/testsuite/rust.test/compilable/nested_struct1.rs new file mode 100644 index 0000000..3880be0 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/nested_struct1.rs @@ -0,0 +1,17 @@ +struct Point { + x: f64, + y: f64, +} + +struct Rectangle { + p1: Point, + p2: Point, +} + +fn main() { + let p1 = Point { x: 0.0, y: 0.0 }; + let p2 = Point { x: 2.0, y: 4.0 }; + let rect = Rectangle { p1, p2 }; + + let a = rect.p1.x; +} diff --git a/gcc/testsuite/rust.test/compilable/self_type1.rs b/gcc/testsuite/rust.test/compilable/self_type1.rs new file mode 100644 index 0000000..373d6dd --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/self_type1.rs @@ -0,0 +1,12 @@ +struct Foo(i32, bool); + +impl Foo { + fn new(a: i32, b: bool) -> Self { + Self(a, b) + } +} + +fn main() { + let a; + a = Foo::new(1, true); +} diff --git a/gcc/testsuite/rust.test/fail_compilation/redef_error1.rs b/gcc/testsuite/rust.test/fail_compilation/redef_error1.rs new file mode 100644 index 0000000..9acdf5f --- /dev/null +++ b/gcc/testsuite/rust.test/fail_compilation/redef_error1.rs @@ -0,0 +1,8 @@ +struct S1 { + x: f64, + y: f64, +} + +struct S1(i32, bool); + +fn main() {} diff --git a/gcc/testsuite/rust.test/fail_compilation/redef_error2.rs b/gcc/testsuite/rust.test/fail_compilation/redef_error2.rs new file mode 100644 index 0000000..c04d2cf --- /dev/null +++ b/gcc/testsuite/rust.test/fail_compilation/redef_error2.rs @@ -0,0 +1,4 @@ +const TEST: i32 = 2; +const TEST: f32 = 3.0; + +fn main() {} diff --git a/gcc/testsuite/rust.test/fail_compilation/redef_error3.rs b/gcc/testsuite/rust.test/fail_compilation/redef_error3.rs new file mode 100644 index 0000000..9ffa4e5 --- /dev/null +++ b/gcc/testsuite/rust.test/fail_compilation/redef_error3.rs @@ -0,0 +1,9 @@ +fn test() -> bool { + true +} + +fn test() -> i32 { + 123 +} + +fn main() {} diff --git a/gcc/testsuite/rust.test/fail_compilation/redef_error4.rs b/gcc/testsuite/rust.test/fail_compilation/redef_error4.rs new file mode 100644 index 0000000..5b20e1b --- /dev/null +++ b/gcc/testsuite/rust.test/fail_compilation/redef_error4.rs @@ -0,0 +1,27 @@ +struct Foo(i32, bool); + +impl Foo { + fn new(a: i32, b: bool) -> Foo { + Foo(a, b) + } + + fn test() -> i32 { + test() + } + + fn test() -> bool { + true + } +} + +fn test() -> i32 { + 123 +} + +fn main() { + let a; + a = Foo::new(1, true); + + let b; + b = Foo::test(); +} diff --git a/gcc/testsuite/rust.test/fail_compilation/redef_error5.rs b/gcc/testsuite/rust.test/fail_compilation/redef_error5.rs new file mode 100644 index 0000000..342a67e --- /dev/null +++ b/gcc/testsuite/rust.test/fail_compilation/redef_error5.rs @@ -0,0 +1,8 @@ +struct Foo(i32, bool); + +impl Foo { + const TEST: i32 = 123; + const TEST: bool = false; +} + +fn main() {} |