From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7905) id 0CFBB3857B8E; Tue, 16 Jan 2024 18:17:53 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0CFBB3857B8E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1705429073; bh=NE1KlCHD+XP0L0PK0biYrGF3Gv/B+gqAd7pc96C4QSc=; h=From:To:Subject:Date:From; b=pmHI5Myew3uJXZrx57rxoobBpitHOlkTW/lQG1fqiqlDDUe0a7KIZQvGHMwxr4QOJ 952nx9cTHG+V7qYvuaxh+lr4/c7Q2D0wLTC4e7YC1fpZHrL9Wk5q62+0+WgVsFAWpk WY6PMv7M+jMW69rcnW8uvdC9GHjdXHBY+Ocbi81Y= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Arthur Cohen To: gcc-cvs@gcc.gnu.org Subject: [gcc r14-8149] gccrs: Rework function special parameters X-Act-Checkin: gcc X-Git-Author: Pierre-Emmanuel Patry X-Git-Refname: refs/heads/trunk X-Git-Oldrev: bbb2472501f71a1a9eabed4e345b4202ebd81ec1 X-Git-Newrev: 513b0154ab1f00e92d2072a5858f585510599b9b Message-Id: <20240116181753.0CFBB3857B8E@sourceware.org> Date: Tue, 16 Jan 2024 18:17:53 +0000 (GMT) List-Id: https://gcc.gnu.org/g:513b0154ab1f00e92d2072a5858f585510599b9b commit r14-8149-g513b0154ab1f00e92d2072a5858f585510599b9b Author: Pierre-Emmanuel Patry Date: Sun Nov 12 21:44:07 2023 +0100 gccrs: Rework function special parameters Make self param and variadic param Param, introduce Param class and make function parameters param too. Self can now be represented as a standard parameter and is thus no longer required as a separate function attribute. Prevent self pointers and allow self in standard functions during parsing so they could be rejected at a later stage. gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Add visitor for VariadicParam and remove Self parameter visitor from Function visit. * expand/rust-cfg-strip.cc (CfgStrip::maybe_strip_self_param): Remove function. (CfgStrip::maybe_strip_trait_method_decl): Remove self parameter visit. (CfgStrip::maybe_strip_function_params): Handle new function parameters. (CfgStrip::visit): Handle VariadicParam, SelfParam and FunctionParam. * expand/rust-expand-visitor.cc (ExpandVisitor::expand_self_param): Remove function. (ExpandVisitor::expand_trait_method_decl): Do not visit self parameter. (ExpandVisitor::visit): Add visit for VariadicParam, FunctionParam and SelfParam. (ExpandVisitor::expand_function_params): Visit parameters instead. * expand/rust-expand-visitor.h: Update function prototypes. * resolve/rust-ast-resolve-item.cc (ResolveItem::visit): Update visit with new parameters. (ResolveTraitItems::visit): Likewise. * resolve/rust-early-name-resolver.cc (EarlyNameResolver::visit): Update visit functions with the new visitor functions for VariadicParam SelfParam and FunctionParam. * resolve/rust-early-name-resolver.h: Update function prototypes. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Update visitor according to the new function parameter structures. * ast/rust-ast-visitor.h: Update prototypes and add visitor virtual functions for SelfParam, FunctionParam and VariadicParam. * ast/rust-ast.cc (Function::Function): Move constructor in implementation instead of header. (Function::operator=): Likewise. (Function::as_string): Update function with pointer dereference. (VariadicParam::as_string): Likewise. (TraitFunctionDecl::as_string): Likewise. (TraitMethodDecl::as_string): Likewise. (FunctionParam::accept_vis): Add function for visitor. (SelfParam::accept_vis): Likewise. (VariadicParam::accept_vis): Likewise. (TraitItemFunc::TraitItemFunc): Move constructor to implementation file. (TraitItemFunc::operator=): Likewise. (TraitItemMethod::TraitItemMethod): Likewise. (TraitItemMethod::operator=): Likewise. * ast/rust-item.h (class Function): Remove self optional member. (class TraitMethodDecl): Likewise. (class TraitFunctionDecl): Likewise. (class Param): Add abstract parameter class. (class SelfParam): Inherit from Param and remove parameter common members. (class FunctionParam): Likewise. (class VariadicParam): Likewise. (struct Visibility): Move structure declaration. (class VisItem): Likewise. * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add a self parameter check during AST validation. * checks/errors/rust-ast-validation.h: Add function prototype. * expand/rust-derive-clone.cc (DeriveClone::clone_fn): Update function constructor. * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_self): Rework function for the new parameters. (ASTLoweringBase::visit): Add visit functions for VariadicParam, FunctionParam and SelfParam. * hir/rust-ast-lower-base.h: Update function prototypes. * parse/rust-parse-impl.h (Parser::parse_function): Update function according to new function representation. (Parser::parse_function_param): Return vector of abstract param instead of FunctionParam. (Parser::parse_method): Update according to new representation. (Parser::parse_trait_item): Likewise. (Parser::parse_self_param): Error out with self pointers and prevent the lexer from eating regular function parameters. Update return type. * parse/rust-parse.h: Update function return types. * ast/rust-ast-collector.h: Add VariadicParam visit prototype. * ast/rust-ast.h (struct Visibility): Move struct declaration. (class VisItem): Likewise. * ast/rust-expr.h: Update included files. * checks/errors/rust-feature-gate.h: Add visitor functions for SelfParam, FunctionParam and VariadicParam. * expand/rust-cfg-strip.h: Update function prototypes. * expand/rust-derive.h: Likewise. * hir/rust-ast-lower-implitem.h: Handle special arguments. * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise. * metadata/rust-export-metadata.cc (ExportContext::emit_function): Likewise. * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Add visitor functions. * resolve/rust-ast-resolve-base.h: Update prototypes. * resolve/rust-ast-resolve-stmt.h: Handle new parameter kind. * resolve/rust-default-resolver.cc (DefaultResolver::visit): Likewise. * resolve/rust-default-resolver.h: Update prototype. * util/rust-attributes.cc (AttributeChecker::visit): Add visitor functions for SelfParam and VariadicParam. * util/rust-attributes.h: Add visit prototypes. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/ast/rust-ast-collector.cc | 27 +- gcc/rust/ast/rust-ast-collector.h | 1 + gcc/rust/ast/rust-ast-visitor.cc | 26 +- gcc/rust/ast/rust-ast-visitor.h | 10 +- gcc/rust/ast/rust-ast.cc | 146 ++++++- gcc/rust/ast/rust-ast.h | 167 ++++++++ gcc/rust/ast/rust-expr.h | 1 + gcc/rust/ast/rust-item.h | 549 +++++++++----------------- gcc/rust/checks/errors/rust-ast-validation.cc | 15 + gcc/rust/checks/errors/rust-ast-validation.h | 1 + gcc/rust/checks/errors/rust-feature-gate.h | 3 + gcc/rust/expand/rust-cfg-strip.cc | 95 +++-- gcc/rust/expand/rust-cfg-strip.h | 7 +- gcc/rust/expand/rust-derive-clone.cc | 15 +- gcc/rust/expand/rust-derive.h | 3 + gcc/rust/expand/rust-expand-visitor.cc | 45 +-- gcc/rust/expand/rust-expand-visitor.h | 7 +- gcc/rust/hir/rust-ast-lower-base.cc | 37 +- gcc/rust/hir/rust-ast-lower-base.h | 5 +- gcc/rust/hir/rust-ast-lower-implitem.h | 45 ++- gcc/rust/hir/rust-ast-lower-item.cc | 15 +- gcc/rust/metadata/rust-export-metadata.cc | 17 +- gcc/rust/parse/rust-parse-impl.h | 283 ++++++------- gcc/rust/parse/rust-parse.h | 30 +- gcc/rust/resolve/rust-ast-resolve-base.cc | 12 + gcc/rust/resolve/rust-ast-resolve-base.h | 3 + gcc/rust/resolve/rust-ast-resolve-item.cc | 143 ++++--- gcc/rust/resolve/rust-ast-resolve-stmt.h | 26 +- gcc/rust/resolve/rust-default-resolver.cc | 34 +- gcc/rust/resolve/rust-default-resolver.h | 3 + gcc/rust/resolve/rust-early-name-resolver.cc | 38 +- gcc/rust/resolve/rust-early-name-resolver.h | 4 + gcc/rust/util/rust-attributes.cc | 12 + gcc/rust/util/rust-attributes.h | 3 + 34 files changed, 1089 insertions(+), 739 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 83260720aff..05c9630bf52 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -16,6 +16,7 @@ // along with GCC; see the file COPYING3. If not see // . #include "rust-ast-collector.h" +#include "rust-item.h" namespace Rust { namespace AST { @@ -190,6 +191,17 @@ TokenCollector::visit (FunctionParam ¶m) } } +void +TokenCollector::visit (VariadicParam ¶m) +{ + if (param.has_pattern ()) + { + visit (param.get_pattern ()); + push (Rust::Token::make (COLON, UNDEF_LOCATION)); + } + push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION)); +} + void TokenCollector::visit (Attribute &attrib) { @@ -1783,13 +1795,6 @@ TokenCollector::visit (Function &function) push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); - if (function.has_self_param ()) - { - visit (function.get_self_param ()); - if (!function.get_function_params ().empty ()) - push (Rust::Token::make (COMMA, UNDEF_LOCATION)); - } - visit_items_joined_by_separator (function.get_function_params ()); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); @@ -2069,13 +2074,7 @@ TokenCollector::visit (TraitItemMethod &item) push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); - visit (method.get_self_param ()); - - if (!method.get_function_params ().empty ()) - { - push (Rust::Token::make (COMMA, UNDEF_LOCATION)); - visit_items_joined_by_separator (method.get_function_params (), COMMA); - } + visit_items_joined_by_separator (method.get_function_params (), COMMA); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index 47655286dd9..20ffd8e65ab 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -163,6 +163,7 @@ public: void visit (Literal &lit, location_t locus = UNDEF_LOCATION); void visit (FunctionParam ¶m); + void visit (VariadicParam ¶m); void visit (Attribute &attrib); void visit (Visibility &vis); void visit (std::vector> ¶ms); diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index b4d1011a03e..d8395820892 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -707,12 +707,6 @@ void DefaultASTVisitor::visit (AST::FunctionQualifiers &qualifiers) {} -void -DefaultASTVisitor::visit (AST::SelfParam &self) -{ - visit (self.get_lifetime ()); -} - void DefaultASTVisitor::visit (AST::WhereClause &where) { @@ -726,7 +720,18 @@ DefaultASTVisitor::visit (AST::FunctionParam ¶m) if (param.has_name ()) visit (param.get_pattern ()); - if (!param.is_variadic ()) + visit (param.get_type ()); +} + +void +DefaultASTVisitor::visit (AST::SelfParam ¶m) +{ + visit_outer_attrs (param); + + if (param.has_lifetime ()) + visit (param.get_lifetime ()); + + if (param.has_type ()) visit (param.get_type ()); } @@ -1438,6 +1443,13 @@ DefaultASTVisitor::visit (AST::BareFunctionType &type) visit (type.get_return_type ()); } +void +DefaultASTVisitor::visit (AST::VariadicParam ¶m) +{ + if (param.has_pattern ()) + visit (param.get_pattern ()); +} + void ContextualASTVisitor::visit (AST::Crate &crate) { diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index d6340e745c9..e5be44157ed 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -23,6 +23,7 @@ // full include not required - only forward decls #include "rust-ast-full-decls.h" #include "rust-ast.h" +#include "rust-item.h" #include "rust-system.h" namespace Rust { @@ -129,6 +130,10 @@ public: // rust-item.h virtual void visit (TypeParam ¶m) = 0; + virtual void visit (SelfParam ¶m) = 0; + virtual void visit (FunctionParam ¶m) = 0; + virtual void visit (VariadicParam ¶m) = 0; + // virtual void visit(WhereClauseItem& item) = 0; virtual void visit (LifetimeWhereClauseItem &item) = 0; virtual void visit (TypeBoundWhereClauseItem &item) = 0; @@ -386,6 +391,9 @@ protected: virtual void visit (AST::SliceType &type) override; virtual void visit (AST::InferredType &type) override; virtual void visit (AST::BareFunctionType &type) override; + virtual void visit (AST::SelfParam &self) override; + virtual void visit (AST::FunctionParam ¶m) override; + virtual void visit (AST::VariadicParam ¶m) override; template void visit (T &node); @@ -406,9 +414,7 @@ protected: virtual void visit (AST::MatchArm &arm); virtual void visit (AST::Visibility &vis); virtual void visit (AST::FunctionQualifiers &qualifiers); - virtual void visit (AST::SelfParam &self); virtual void visit (AST::WhereClause &where); - virtual void visit (AST::FunctionParam ¶m); virtual void visit (AST::StructField &field); virtual void visit (AST::TupleField &field); virtual void visit (AST::TraitFunctionDecl &decl); diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index cc0d6ec996f..43820d38e28 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -1090,6 +1090,62 @@ Union::as_string () const return str; } +Function::Function (Function const &other) + : VisItem (other), qualifiers (other.qualifiers), + function_name (other.function_name), where_clause (other.where_clause), + locus (other.locus), is_default (other.is_default) +{ + // guard to prevent null dereference (always required) + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + + // guard to prevent null dereference (only required if error state) + if (other.function_body != nullptr) + function_body = other.function_body->clone_block_expr (); + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + function_params.reserve (other.function_params.size ()); + for (const auto &e : other.function_params) + function_params.push_back (e->clone_param ()); +} + +Function & +Function::operator= (Function const &other) +{ + VisItem::operator= (other); + function_name = other.function_name; + qualifiers = other.qualifiers; + where_clause = other.where_clause; + // visibility = other.visibility->clone_visibility(); + // outer_attrs = other.outer_attrs; + locus = other.locus; + is_default = other.is_default; + + // guard to prevent null dereference (always required) + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + else + return_type = nullptr; + + // guard to prevent null dereference (only required if error state) + if (other.function_body != nullptr) + function_body = other.function_body->clone_block_expr (); + else + function_body = nullptr; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + function_params.reserve (other.function_params.size ()); + for (const auto &e : other.function_params) + function_params.push_back (e->clone_param ()); + + return *this; +} std::string Function::as_string () const { @@ -1149,7 +1205,7 @@ Function::as_string () const str += "("; for (; i != e; i++) { - str += (*i).as_string (); + str += (*i)->as_string (); if (e != i + 1) str += ", "; } @@ -2245,6 +2301,33 @@ FunctionParam::as_string () const return param_name->as_string () + " : " + type->as_string (); } +void +FunctionParam::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void +SelfParam::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void +VariadicParam::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +std::string +VariadicParam::as_string () const +{ + if (has_pattern ()) + return get_pattern ()->as_string () + " : ..."; + else + return "..."; +} + std::string FunctionQualifiers::as_string () const { @@ -3013,6 +3096,33 @@ NamedFunctionParam::as_string () const return str; } +TraitItemFunc::TraitItemFunc (TraitItemFunc const &other) + : TraitItem (other.locus), outer_attrs (other.outer_attrs), decl (other.decl) +{ + node_id = other.node_id; + + // guard to prevent null dereference + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); +} + +TraitItemFunc & +TraitItemFunc::operator= (TraitItemFunc const &other) +{ + TraitItem::operator= (other); + outer_attrs = other.outer_attrs; + decl = other.decl; + locus = other.locus; + node_id = other.node_id; + + // guard to prevent null dereference + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + else + block_expr = nullptr; + + return *this; +} std::string TraitItemFunc::as_string () const { @@ -3062,7 +3172,7 @@ TraitFunctionDecl::as_string () const if (has_params ()) { for (const auto ¶m : function_params) - str += "\n " + param.as_string (); + str += "\n " + param->as_string (); } else { @@ -3084,6 +3194,34 @@ TraitFunctionDecl::as_string () const return str; } +TraitItemMethod::TraitItemMethod (TraitItemMethod const &other) + : TraitItem (other.locus), outer_attrs (other.outer_attrs), decl (other.decl) +{ + node_id = other.node_id; + + // guard to prevent null dereference + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); +} + +TraitItemMethod & +TraitItemMethod::operator= (TraitItemMethod const &other) +{ + TraitItem::operator= (other); + outer_attrs = other.outer_attrs; + decl = other.decl; + locus = other.locus; + node_id = other.node_id; + + // guard to prevent null dereference + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + else + block_expr = nullptr; + + return *this; +} + std::string TraitItemMethod::as_string () const { @@ -3129,13 +3267,11 @@ TraitMethodDecl::as_string () const } } - str += "\n Self param: " + self_param.as_string (); - str += "\n Function params: "; if (has_params ()) { for (const auto ¶m : function_params) - str += "\n " + param.as_string (); + str += "\n " + param->as_string (); } else { diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 938268dd83a..67ae92fb42d 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1042,6 +1042,173 @@ protected: Item *clone_stmt_impl () const final override { return clone_item_impl (); } }; +// Visibility of item - if the item has it, then it is some form of public +struct Visibility +{ +public: + enum VisType + { + PRIV, + PUB, + PUB_CRATE, + PUB_SELF, + PUB_SUPER, + PUB_IN_PATH + }; + +private: + VisType vis_type; + // Only assigned if vis_type is IN_PATH + SimplePath in_path; + location_t locus; + + // should this store location info? + +public: + // Creates a Visibility - TODO make constructor protected or private? + Visibility (VisType vis_type, SimplePath in_path, location_t locus) + : vis_type (vis_type), in_path (std::move (in_path)), locus (locus) + {} + + VisType get_vis_type () const { return vis_type; } + + // Returns whether visibility is in an error state. + bool is_error () const + { + return vis_type == PUB_IN_PATH && in_path.is_empty (); + } + + // Returns whether a visibility has a path + bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; } + + // Returns whether visibility is public or not. + bool is_public () const { return vis_type != PRIV && !is_error (); } + + location_t get_locus () const { return locus; } + + // empty? + // Creates an error visibility. + static Visibility create_error () + { + return Visibility (PUB_IN_PATH, SimplePath::create_empty (), + UNDEF_LOCATION); + } + + // Unique pointer custom clone function + /*std::unique_ptr clone_visibility() const { + return std::unique_ptr(clone_visibility_impl()); + }*/ + + /* TODO: think of a way to only allow valid Visibility states - polymorphism + * is one idea but may be too resource-intensive. */ + + // Creates a public visibility with no further features/arguments. + // empty? + static Visibility create_public (location_t pub_vis_location) + { + return Visibility (PUB, SimplePath::create_empty (), pub_vis_location); + } + + // Creates a public visibility with crate-relative paths + static Visibility create_crate (location_t crate_tok_location, + location_t crate_vis_location) + { + return Visibility (PUB_CRATE, + SimplePath::from_str ("crate", crate_tok_location), + crate_vis_location); + } + + // Creates a public visibility with self-relative paths + static Visibility create_self (location_t self_tok_location, + location_t self_vis_location) + { + return Visibility (PUB_SELF, + SimplePath::from_str ("self", self_tok_location), + self_vis_location); + } + + // Creates a public visibility with parent module-relative paths + static Visibility create_super (location_t super_tok_location, + location_t super_vis_location) + { + return Visibility (PUB_SUPER, + SimplePath::from_str ("super", super_tok_location), + super_vis_location); + } + + // Creates a private visibility + static Visibility create_private () + { + return Visibility (PRIV, SimplePath::create_empty (), UNDEF_LOCATION); + } + + // Creates a public visibility with a given path or whatever. + static Visibility create_in_path (SimplePath in_path, + location_t in_path_vis_location) + { + return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location); + } + + std::string as_string () const; + const SimplePath &get_path () const { return in_path; } + SimplePath &get_path () { return in_path; } + +protected: + // Clone function implementation - not currently virtual but may be if + // polymorphism used + /*virtual*/ Visibility *clone_visibility_impl () const + { + return new Visibility (*this); + } +}; +// Item that supports visibility - abstract base class +class VisItem : public Item +{ + Visibility visibility; + std::vector outer_attrs; + +protected: + // Visibility constructor + VisItem (Visibility visibility, + std::vector outer_attrs = std::vector ()) + : visibility (std::move (visibility)), outer_attrs (std::move (outer_attrs)) + {} + + // Visibility copy constructor + VisItem (VisItem const &other) + : visibility (other.visibility), outer_attrs (other.outer_attrs) + {} + + // Overload assignment operator to clone + VisItem &operator= (VisItem const &other) + { + visibility = other.visibility; + outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + VisItem (VisItem &&other) = default; + VisItem &operator= (VisItem &&other) = default; + +public: + /* Does the item have some kind of public visibility (non-default + * visibility)? */ + bool has_visibility () const { return visibility.is_public (); } + + std::string as_string () const override; + + // TODO: this mutable getter seems really dodgy. Think up better way. + Visibility &get_visibility () { return visibility; } + const Visibility &get_visibility () const { return visibility; } + + std::vector &get_outer_attrs () override { return outer_attrs; } + const std::vector &get_outer_attrs () const override + { + return outer_attrs; + } +}; // forward decl of ExprWithoutBlock class ExprWithoutBlock; diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 4dc240c4aa7..4830ae0d2d3 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -3,6 +3,7 @@ #include "rust-ast.h" #include "rust-path.h" +#include "rust-macro.h" #include "rust-operators.h" namespace Rust { diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 6d9791e7de7..8b53bc63a83 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -20,6 +20,8 @@ #define RUST_AST_ITEM_H #include "rust-ast.h" +#include "rust-hir-map.h" +#include "rust-mapping-common.h" #include "rust-path.h" #include "rust-common.h" #include "rust-expr.h" @@ -376,8 +378,46 @@ public: } }; +// Abstract class Param +class Param : public Visitable +{ +public: + Param (std::vector outer_attrs, location_t locus) + : outer_attrs (std::move (outer_attrs)), locus (locus), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} + + virtual ~Param () = default; + + std::unique_ptr clone_param () const + { + return std::unique_ptr (clone_param_impl ()); + } + + virtual bool is_variadic () const { return false; } + + virtual bool is_self () const { return false; } + + NodeId get_node_id () const { return node_id; } + + location_t get_locus () const { return locus; } + + std::vector get_outer_attrs () const { return outer_attrs; } + + std::vector &get_outer_attrs () { return outer_attrs; } + + virtual Param *clone_param_impl () const = 0; + + virtual std::string as_string () const = 0; + +protected: + std::vector outer_attrs; + location_t locus; + NodeId node_id; +}; + // A self parameter in a method -class SelfParam +class SelfParam : public Param { bool has_ref; bool is_mut; @@ -387,14 +427,10 @@ class SelfParam // bool has_type; // only possible if not ref std::unique_ptr type; - NodeId node_id; - - location_t 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), node_id (Analysis::Mappings::get ()->get_next_node_id ()) + : Param ({}, UNDEF_LOCATION), has_ref (has_ref), is_mut (is_mut), + lifetime (std::move (lifetime)), type (type) {} // this is ok as no outside classes can ever call this @@ -423,22 +459,20 @@ public: // Type-based self parameter (not ref, no lifetime) SelfParam (std::unique_ptr type, bool is_mut, location_t locus) - : has_ref (false), is_mut (is_mut), lifetime (Lifetime::error ()), - type (std::move (type)), - node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus) + : Param ({}, locus), has_ref (false), is_mut (is_mut), + lifetime (Lifetime::error ()), type (std::move (type)) {} // Lifetime-based self parameter (is ref, no type) SelfParam (Lifetime lifetime, bool is_mut, location_t locus) - : has_ref (true), is_mut (is_mut), lifetime (std::move (lifetime)), - node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus) + : Param ({}, locus), has_ref (true), is_mut (is_mut), + lifetime (std::move (lifetime)) {} // 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) + : Param (other.get_outer_attrs (), other.get_locus ()), + has_ref (other.has_ref), is_mut (other.is_mut), lifetime (other.lifetime) { node_id = other.node_id; if (other.type != nullptr) @@ -453,6 +487,7 @@ public: lifetime = other.lifetime; locus = other.locus; node_id = other.node_id; + outer_attrs = other.outer_attrs; if (other.type != nullptr) type = other.type->clone_type (); @@ -466,10 +501,12 @@ public: SelfParam (SelfParam &&other) = default; SelfParam &operator= (SelfParam &&other) = default; - std::string as_string () const; + std::string as_string () const override; location_t get_locus () const { return locus; } + bool is_self () const override { return true; } + bool get_has_ref () const { return has_ref; }; bool get_is_mut () const { return is_mut; } @@ -484,6 +521,13 @@ public: rust_assert (has_type ()); return type; } + + void accept_vis (ASTVisitor &vis) override; + + SelfParam *clone_param_impl () const override + { + return new SelfParam (*this); + } }; // Qualifiers for function, i.e. const, unsafe, extern etc. @@ -521,41 +565,84 @@ public: location_t get_locus () const { return locus; } }; -// A function parameter -class FunctionParam +class VariadicParam : public Param { - std::vector outer_attrs; - location_t locus; std::unique_ptr param_name; - std::unique_ptr type; - bool variadic; public: - FunctionParam (std::unique_ptr param_name, - std::unique_ptr param_type, + VariadicParam (std::unique_ptr param_name, std::vector outer_attrs, location_t locus) - : outer_attrs (std::move (outer_attrs)), locus (locus), - param_name (std::move (param_name)), type (std::move (param_type)), - variadic (false), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + : Param (std::move (outer_attrs), std::move (locus)), + param_name (std::move (param_name)) {} - FunctionParam (std::vector outer_attrs, location_t locus) - : outer_attrs (std::move (outer_attrs)), locus (locus), - param_name (nullptr), type (nullptr), variadic (true), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + VariadicParam (std::vector outer_attrs, location_t locus) + : Param (std::move (outer_attrs), std::move (locus)), param_name (nullptr) {} + VariadicParam (VariadicParam const &other) + : Param (other.get_outer_attrs (), other.locus) + { + if (other.param_name != nullptr) + param_name = other.param_name->clone_pattern (); + } + + VariadicParam &operator= (VariadicParam const &other) + { + outer_attrs = other.outer_attrs; + locus = other.locus; + node_id = other.node_id; + if (other.param_name != nullptr) + param_name = other.param_name->clone_pattern (); + else + param_name = nullptr; + + return *this; + } + + bool is_variadic () const override { return true; } + + VariadicParam *clone_param_impl () const override + { + return new VariadicParam (*this); + } + + std::unique_ptr &get_pattern () + { + rust_assert (param_name != nullptr); + return param_name; + } + + const std::unique_ptr &get_pattern () const + { + rust_assert (param_name != nullptr); + return param_name; + } + + bool has_pattern () const { return param_name != nullptr; } + + void accept_vis (ASTVisitor &vis) override; + + std::string as_string () const override; +}; + +// A function parameter +class FunctionParam : public Param +{ + std::unique_ptr param_name; + std::unique_ptr type; + +public: FunctionParam (std::unique_ptr param_name, + std::unique_ptr param_type, std::vector outer_attrs, location_t locus) - : outer_attrs (std::move (outer_attrs)), locus (locus), - param_name (std::move (param_name)), type (nullptr), variadic (true), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + : Param (std::move (outer_attrs), locus), + param_name (std::move (param_name)), type (std::move (param_type)) {} // Copy constructor uses clone FunctionParam (FunctionParam const &other) - : locus (other.locus), variadic (other.variadic), node_id (other.node_id) + : Param (other.get_outer_attrs (), other.locus) { // guard to prevent nullptr dereference if (other.param_name != nullptr) @@ -569,7 +656,6 @@ public: { locus = other.locus; node_id = other.node_id; - variadic = other.variadic; // guard to prevent nullptr dereference if (other.param_name != nullptr) @@ -589,13 +675,7 @@ public: FunctionParam &operator= (FunctionParam &&other) = default; // Returns whether FunctionParam is in an invalid state. - bool is_error () const - { - if (variadic) - return false; - else - return param_name == nullptr || type == nullptr; - } + bool is_error () const { return param_name == nullptr || type == nullptr; } // Creates an error FunctionParam. static FunctionParam create_error () @@ -603,9 +683,7 @@ public: return FunctionParam (nullptr, nullptr, {}, UNDEF_LOCATION); } - std::string as_string () const; - - location_t get_locus () const { return locus; } + std::string as_string () const override; // TODO: seems kinda dodgy. Think of better way. std::vector &get_outer_attrs () { return outer_attrs; } @@ -627,181 +705,12 @@ public: return type; } - bool is_variadic () const { return variadic; } - - NodeId get_node_id () const { return node_id; } - -protected: - NodeId node_id; -}; - -// Visibility of item - if the item has it, then it is some form of public -struct Visibility -{ -public: - enum VisType - { - PRIV, - PUB, - PUB_CRATE, - PUB_SELF, - PUB_SUPER, - PUB_IN_PATH - }; - -private: - VisType vis_type; - // Only assigned if vis_type is IN_PATH - SimplePath in_path; - location_t locus; - - // should this store location info? - -public: - // Creates a Visibility - TODO make constructor protected or private? - Visibility (VisType vis_type, SimplePath in_path, location_t locus) - : vis_type (vis_type), in_path (std::move (in_path)), locus (locus) - {} - - VisType get_vis_type () const { return vis_type; } - - // Returns whether visibility is in an error state. - bool is_error () const - { - return vis_type == PUB_IN_PATH && in_path.is_empty (); - } - - // Returns whether a visibility has a path - bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; } - - // Returns whether visibility is public or not. - bool is_public () const { return vis_type != PRIV && !is_error (); } - - location_t get_locus () const { return locus; } - - // empty? - // Creates an error visibility. - static Visibility create_error () + FunctionParam *clone_param_impl () const override { - return Visibility (PUB_IN_PATH, SimplePath::create_empty (), - UNDEF_LOCATION); + return new FunctionParam (*this); } - // Unique pointer custom clone function - /*std::unique_ptr clone_visibility() const { - return std::unique_ptr(clone_visibility_impl()); - }*/ - - /* TODO: think of a way to only allow valid Visibility states - polymorphism - * is one idea but may be too resource-intensive. */ - - // Creates a public visibility with no further features/arguments. - // empty? - static Visibility create_public (location_t pub_vis_location) - { - return Visibility (PUB, SimplePath::create_empty (), pub_vis_location); - } - - // Creates a public visibility with crate-relative paths - static Visibility create_crate (location_t crate_tok_location, - location_t crate_vis_location) - { - return Visibility (PUB_CRATE, - SimplePath::from_str ("crate", crate_tok_location), - crate_vis_location); - } - - // Creates a public visibility with self-relative paths - static Visibility create_self (location_t self_tok_location, - location_t self_vis_location) - { - return Visibility (PUB_SELF, - SimplePath::from_str ("self", self_tok_location), - self_vis_location); - } - - // Creates a public visibility with parent module-relative paths - static Visibility create_super (location_t super_tok_location, - location_t super_vis_location) - { - return Visibility (PUB_SUPER, - SimplePath::from_str ("super", super_tok_location), - super_vis_location); - } - - // Creates a private visibility - static Visibility create_private () - { - return Visibility (PRIV, SimplePath::create_empty (), UNDEF_LOCATION); - } - - // Creates a public visibility with a given path or whatever. - static Visibility create_in_path (SimplePath in_path, - location_t in_path_vis_location) - { - return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location); - } - - std::string as_string () const; - const SimplePath &get_path () const { return in_path; } - SimplePath &get_path () { return in_path; } - -protected: - // Clone function implementation - not currently virtual but may be if - // polymorphism used - /*virtual*/ Visibility *clone_visibility_impl () const - { - return new Visibility (*this); - } -}; - -// Item that supports visibility - abstract base class -class VisItem : public Item -{ - Visibility visibility; - std::vector outer_attrs; - -protected: - // Visibility constructor - VisItem (Visibility visibility, - std::vector outer_attrs = std::vector ()) - : visibility (std::move (visibility)), outer_attrs (std::move (outer_attrs)) - {} - - // Visibility copy constructor - VisItem (VisItem const &other) - : visibility (other.visibility), outer_attrs (other.outer_attrs) - {} - - // Overload assignment operator to clone - VisItem &operator= (VisItem const &other) - { - visibility = other.visibility; - outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - VisItem (VisItem &&other) = default; - VisItem &operator= (VisItem &&other) = default; - -public: - /* Does the item have some kind of public visibility (non-default - * visibility)? */ - bool has_visibility () const { return visibility.is_public (); } - - std::string as_string () const override; - - // TODO: this mutable getter seems really dodgy. Think up better way. - Visibility &get_visibility () { return visibility; } - const Visibility &get_visibility () const { return visibility; } - - std::vector &get_outer_attrs () override { return outer_attrs; } - const std::vector &get_outer_attrs () const override - { - return outer_attrs; - } + void accept_vis (ASTVisitor &vis) override; }; // Rust module item - abstract base class @@ -1372,8 +1281,7 @@ class Function : public VisItem, public InherentImplItem, public TraitImplItem FunctionQualifiers qualifiers; Identifier function_name; std::vector> generic_params; - tl::optional self_param; - std::vector function_params; + std::vector> function_params; std::unique_ptr return_type; WhereClause where_clause; std::unique_ptr function_body; @@ -1395,13 +1303,15 @@ public: // Returns whether function has a where clause. bool has_where_clause () const { return !where_clause.is_empty (); } - bool has_self_param () const { return self_param.has_value (); } + bool has_self_param () const + { + return function_params.size () > 0 && function_params[0]->is_self (); + } // Mega-constructor with all possible fields Function (Identifier function_name, FunctionQualifiers qualifiers, std::vector> generic_params, - tl::optional self_param, - std::vector function_params, + std::vector> function_params, std::unique_ptr return_type, WhereClause where_clause, std::unique_ptr function_body, Visibility vis, std::vector outer_attrs, location_t locus, @@ -1410,7 +1320,6 @@ public: qualifiers (std::move (qualifiers)), function_name (std::move (function_name)), generic_params (std::move (generic_params)), - self_param (std::move (self_param)), function_params (std::move (function_params)), return_type (std::move (return_type)), where_clause (std::move (where_clause)), @@ -1421,58 +1330,10 @@ public: // TODO: add constructor with less fields // Copy constructor with clone - Function (Function const &other) - : VisItem (other), qualifiers (other.qualifiers), - function_name (other.function_name), self_param (other.self_param), - function_params (other.function_params), - where_clause (other.where_clause), locus (other.locus), - is_default (other.is_default) - { - // guard to prevent null dereference (always required) - if (other.return_type != nullptr) - return_type = other.return_type->clone_type (); - - // guard to prevent null dereference (only required if error state) - if (other.function_body != nullptr) - function_body = other.function_body->clone_block_expr (); - - generic_params.reserve (other.generic_params.size ()); - for (const auto &e : other.generic_params) - generic_params.push_back (e->clone_generic_param ()); - } + Function (Function const &other); // Overloaded assignment operator to clone - Function &operator= (Function const &other) - { - VisItem::operator= (other); - function_name = other.function_name; - qualifiers = other.qualifiers; - self_param = other.self_param; - function_params = other.function_params; - where_clause = other.where_clause; - // visibility = other.visibility->clone_visibility(); - // outer_attrs = other.outer_attrs; - locus = other.locus; - is_default = other.is_default; - - // guard to prevent null dereference (always required) - if (other.return_type != nullptr) - return_type = other.return_type->clone_type (); - else - return_type = nullptr; - - // guard to prevent null dereference (only required if error state) - if (other.function_body != nullptr) - function_body = other.function_body->clone_block_expr (); - else - function_body = nullptr; - - generic_params.reserve (other.generic_params.size ()); - for (const auto &e : other.generic_params) - generic_params.push_back (e->clone_generic_param ()); - - return *this; - } + Function &operator= (Function const &other); // move constructors Function (Function &&other) = default; @@ -1485,7 +1346,7 @@ public: bool is_variadic () const { return function_params.size () != 0 - && function_params.back ().is_variadic (); + && function_params.back ()->is_variadic (); } // Invalid if block is null, so base stripping on that. @@ -1495,8 +1356,11 @@ public: return function_body == nullptr; } - std::vector &get_function_params () { return function_params; } - const std::vector &get_function_params () const + std::vector> &get_function_params () + { + return function_params; + } + const std::vector> &get_function_params () const { return function_params; } @@ -1533,15 +1397,15 @@ public: return return_type; } - SelfParam &get_self_param () + std::unique_ptr &get_self_param () { rust_assert (has_self_param ()); - return self_param.value (); + return function_params[0]; } - const SelfParam &get_self_param () const + const std::unique_ptr &get_self_param () const { rust_assert (has_self_param ()); - return self_param.value (); + return function_params[0]; } protected: @@ -2668,7 +2532,7 @@ class TraitFunctionDecl // bool has_params; // FunctionParams function_params; - std::vector function_params; // inlined + std::vector> function_params; // inlined // bool has_return_type; std::unique_ptr return_type; @@ -2696,7 +2560,7 @@ public: // Mega-constructor TraitFunctionDecl (Identifier function_name, FunctionQualifiers qualifiers, std::vector> generic_params, - std::vector function_params, + std::vector> function_params, std::unique_ptr return_type, WhereClause where_clause) : qualifiers (std::move (qualifiers)), @@ -2710,7 +2574,7 @@ public: // Copy constructor with clone TraitFunctionDecl (TraitFunctionDecl const &other) : qualifiers (other.qualifiers), function_name (other.function_name), - function_params (other.function_params), where_clause (other.where_clause) + where_clause (other.where_clause) { // guard to prevent nullptr dereference if (other.return_type != nullptr) @@ -2719,6 +2583,10 @@ public: generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); + + function_params.reserve (other.function_params.size ()); + for (const auto &e : other.function_params) + function_params.push_back (e->clone_param ()); } ~TraitFunctionDecl () = default; @@ -2728,7 +2596,6 @@ public: { function_name = other.function_name; qualifiers = other.qualifiers; - function_params = other.function_params; where_clause = other.where_clause; // guard to prevent nullptr dereference @@ -2741,6 +2608,10 @@ public: for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); + function_params.reserve (other.function_params.size ()); + for (const auto &e : other.function_params) + function_params.push_back (e->clone_param ()); + return *this; } @@ -2755,8 +2626,11 @@ public: bool is_marked_for_strip () const { return function_name.empty (); } // TODO: this mutable getter seems really dodgy. Think up better way. - std::vector &get_function_params () { return function_params; } - const std::vector &get_function_params () const + std::vector> &get_function_params () + { + return function_params; + } + const std::vector> &get_function_params () const { return function_params; } @@ -2798,34 +2672,11 @@ public: {} // Copy constructor with clone - TraitItemFunc (TraitItemFunc const &other) - : TraitItem (other.locus), outer_attrs (other.outer_attrs), - decl (other.decl) - { - node_id = other.node_id; - - // guard to prevent null dereference - if (other.block_expr != nullptr) - block_expr = other.block_expr->clone_block_expr (); - } + TraitItemFunc (TraitItemFunc const &other); // Overloaded assignment operator to clone - TraitItemFunc &operator= (TraitItemFunc const &other) - { - TraitItem::operator= (other); - outer_attrs = other.outer_attrs; - decl = other.decl; - locus = other.locus; - node_id = other.node_id; - - // guard to prevent null dereference - if (other.block_expr != nullptr) - block_expr = other.block_expr->clone_block_expr (); - else - block_expr = nullptr; - return *this; - } + TraitItemFunc &operator= (TraitItemFunc const &other); // move constructors TraitItemFunc (TraitItemFunc &&other) = default; @@ -2875,11 +2726,9 @@ class TraitMethodDecl // Generics generic_params; std::vector> generic_params; // inlined - SelfParam self_param; - // bool has_params; // FunctionParams function_params; - std::vector function_params; // inlined + std::vector> function_params; // inlined // bool has_return_type; std::unique_ptr return_type; @@ -2907,13 +2756,11 @@ public: // Mega-constructor TraitMethodDecl (Identifier function_name, FunctionQualifiers qualifiers, std::vector> generic_params, - SelfParam self_param, - std::vector function_params, + std::vector> function_params, std::unique_ptr return_type, WhereClause where_clause) : qualifiers (std::move (qualifiers)), function_name (std::move (function_name)), generic_params (std::move (generic_params)), - self_param (std::move (self_param)), function_params (std::move (function_params)), return_type (std::move (return_type)), where_clause (std::move (where_clause)) @@ -2922,7 +2769,6 @@ public: // Copy constructor with clone TraitMethodDecl (TraitMethodDecl const &other) : qualifiers (other.qualifiers), function_name (other.function_name), - self_param (other.self_param), function_params (other.function_params), where_clause (other.where_clause) { // guard to prevent nullptr dereference @@ -2932,6 +2778,10 @@ public: generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); + + function_params.reserve (other.function_params.size ()); + for (const auto &e : other.function_params) + function_params.push_back (e->clone_param ()); } ~TraitMethodDecl () = default; @@ -2941,8 +2791,6 @@ public: { function_name = other.function_name; qualifiers = other.qualifiers; - self_param = other.self_param; - function_params = other.function_params; where_clause = other.where_clause; // guard to prevent nullptr dereference @@ -2955,6 +2803,10 @@ public: for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); + function_params.reserve (other.function_params.size ()); + for (const auto &e : other.function_params) + function_params.push_back (e->clone_param ()); + return *this; } @@ -2969,8 +2821,11 @@ public: bool is_marked_for_strip () const { return function_name.empty (); } // TODO: this mutable getter seems really dodgy. Think up better way. - std::vector &get_function_params () { return function_params; } - const std::vector &get_function_params () const + std::vector> &get_function_params () + { + return function_params; + } + const std::vector> &get_function_params () const { return function_params; } @@ -2990,8 +2845,21 @@ public: // TODO: is this better? Or is a "vis_block" better? WhereClause &get_where_clause () { return where_clause; } - SelfParam &get_self_param () { return self_param; } - const SelfParam &get_self_param () const { return self_param; } + bool has_self () const + { + return !function_params.empty () && function_params[0]->is_self (); + } + + std::unique_ptr &get_self_param () + { + rust_assert (has_self ()); + return function_params[0]; + } + const std::unique_ptr &get_self_param () const + { + rust_assert (has_self ()); + return function_params[0]; + } FunctionQualifiers get_qualifiers () const { return qualifiers; } @@ -3016,34 +2884,9 @@ public: {} // Copy constructor with clone - TraitItemMethod (TraitItemMethod const &other) - : TraitItem (other.locus), outer_attrs (other.outer_attrs), - decl (other.decl) - { - node_id = other.node_id; - - // guard to prevent null dereference - if (other.block_expr != nullptr) - block_expr = other.block_expr->clone_block_expr (); - } - + TraitItemMethod (TraitItemMethod const &other); // Overloaded assignment operator to clone - TraitItemMethod &operator= (TraitItemMethod const &other) - { - TraitItem::operator= (other); - outer_attrs = other.outer_attrs; - decl = other.decl; - locus = other.locus; - node_id = other.node_id; - - // guard to prevent null dereference - if (other.block_expr != nullptr) - block_expr = other.block_expr->clone_block_expr (); - else - block_expr = nullptr; - - return *this; - } + TraitItemMethod &operator= (TraitItemMethod const &other); // move constructors TraitItemMethod (TraitItemMethod &&other) = default; diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index a903297d19b..f6ce45eacca 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -81,4 +81,19 @@ ASTValidation::visit (AST::ExternalFunctionItem &item) AST::ContextualASTVisitor::visit (item); } +void +ASTValidation::visit (AST::Function &function) +{ + std::set valid_context + = {Context::INHERENT_IMPL, Context::TRAIT_IMPL}; + + if (valid_context.find (context.back ()) == valid_context.end () + && function.has_self_param ()) + rust_error_at ( + function.get_self_param ()->get_locus (), + "% parameter is only allowed in associated functions"); + + AST::ContextualASTVisitor::visit (function); +} + } // namespace Rust diff --git a/gcc/rust/checks/errors/rust-ast-validation.h b/gcc/rust/checks/errors/rust-ast-validation.h index 6028b21ff00..44995eb1fbc 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.h +++ b/gcc/rust/checks/errors/rust-ast-validation.h @@ -37,6 +37,7 @@ public: virtual void visit (AST::Lifetime &lifetime); virtual void visit (AST::LoopLabel &label); virtual void visit (AST::ExternalFunctionItem &item); + virtual void visit (AST::Function &function); }; } // namespace Rust diff --git a/gcc/rust/checks/errors/rust-feature-gate.h b/gcc/rust/checks/errors/rust-feature-gate.h index de0170e9d03..1ebd3c9e05f 100644 --- a/gcc/rust/checks/errors/rust-feature-gate.h +++ b/gcc/rust/checks/errors/rust-feature-gate.h @@ -183,6 +183,9 @@ public: void visit (AST::SliceType &type) override {} void visit (AST::InferredType &type) override {} void visit (AST::BareFunctionType &type) override {} + void visit (AST::FunctionParam ¶m) override {} + void visit (AST::VariadicParam ¶m) override {} + void visit (AST::SelfParam ¶m) override {} private: void gate (Feature::Name name, location_t loc, const std::string &error_msg); diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index 9ef2468ecf6..fd115654618 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -218,34 +218,37 @@ CfgStrip::maybe_strip_tuple_fields (std::vector &fields) } void -CfgStrip::maybe_strip_function_params (std::vector ¶ms) +CfgStrip::maybe_strip_function_params ( + std::vector> ¶ms) { for (auto it = params.begin (); it != params.end ();) { - auto ¶m = *it; - - auto ¶m_attrs = param.get_outer_attrs (); - expand_cfg_attrs (param_attrs); - if (fails_cfg_with_expand (param_attrs)) + if (!(*it)->is_self () && !(*it)->is_variadic ()) { - it = params.erase (it); - continue; - } + auto param = static_cast (it->get ()); - // TODO: should an unwanted strip lead to break out of loop? - auto &pattern = param.get_pattern (); - pattern->accept_vis (*this); - if (pattern->is_marked_for_strip ()) - rust_error_at (pattern->get_locus (), - "cannot strip pattern in this position"); + auto ¶m_attrs = param->get_outer_attrs (); + expand_cfg_attrs (param_attrs); + if (fails_cfg_with_expand (param_attrs)) + { + it = params.erase (it); + continue; + } - auto &type = param.get_type (); - type->accept_vis (*this); + // TODO: should an unwanted strip lead to break out of loop? + auto &pattern = param->get_pattern (); + pattern->accept_vis (*this); + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus (), + "cannot strip pattern in this position"); - if (type->is_marked_for_strip ()) - rust_error_at (type->get_locus (), - "cannot strip type in this position"); + auto &type = param->get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus (), + "cannot strip type in this position"); + } // increment ++it; } @@ -359,22 +362,6 @@ CfgStrip::CfgStrip::maybe_strip_closure_params ( } } -void -CfgStrip::maybe_strip_self_param (AST::SelfParam &self_param) -{ - if (self_param.has_type ()) - { - auto &type = self_param.get_type (); - type->accept_vis (*this); - - if (type->is_marked_for_strip ()) - rust_error_at (type->get_locus (), - "cannot strip type in this position"); - } - /* TODO: maybe check for invariants being violated - e.g. both type and - * lifetime? */ -} - void CfgStrip::maybe_strip_where_clause (AST::WhereClause &where_clause) { @@ -415,11 +402,6 @@ CfgStrip::maybe_strip_trait_method_decl (AST::TraitMethodDecl &decl) for (auto ¶m : decl.get_generic_params ()) param->accept_vis (*this); - /* assuming you can't strip self param - wouldn't be a method - * anymore. spec allows outer attrs on self param, but doesn't - * specify whether cfg is used. */ - maybe_strip_self_param (decl.get_self_param ()); - /* strip function parameters if required - this is specifically * allowed by spec */ maybe_strip_function_params (decl.get_function_params ()); @@ -2029,13 +2011,6 @@ CfgStrip::visit (AST::Function &function) for (auto ¶m : function.get_generic_params ()) param->accept_vis (*this); - /* assuming you can't strip self param - wouldn't be a method - * anymore. spec allows outer attrs on self param, but doesn't - * specify whether cfg is used. */ - // TODO: verify this - if (function.has_self_param ()) - maybe_strip_self_param (function.get_self_param ()); - /* strip function parameters if required - this is specifically * allowed by spec */ maybe_strip_function_params (function.get_function_params ()); @@ -3167,4 +3142,28 @@ CfgStrip::visit (AST::BareFunctionType &type) // no where clause, apparently } +void +CfgStrip::visit (AST::VariadicParam &type) +{} + +void +CfgStrip::visit (AST::FunctionParam &type) +{} + +void +CfgStrip::visit (AST::SelfParam ¶m) +{ + if (param.has_type ()) + { + auto &type = param.get_type (); + type->accept_vis (*this); + + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus (), + "cannot strip type in this position"); + } + /* TODO: maybe check for invariants being violated - e.g. both type and + * lifetime? */ +} + } // namespace Rust diff --git a/gcc/rust/expand/rust-cfg-strip.h b/gcc/rust/expand/rust-cfg-strip.h index a06026e1c0a..32dbee6f780 100644 --- a/gcc/rust/expand/rust-cfg-strip.h +++ b/gcc/rust/expand/rust-cfg-strip.h @@ -18,6 +18,7 @@ #include "rust-ast-visitor.h" #include "rust-ast.h" +#include "rust-item.h" namespace Rust { // Visitor used to maybe_strip attributes. @@ -32,7 +33,8 @@ public: void maybe_strip_struct_fields (std::vector &fields); void maybe_strip_tuple_fields (std::vector &fields); - void maybe_strip_function_params (std::vector ¶ms); + void maybe_strip_function_params ( + std::vector> ¶ms); void maybe_strip_generic_args (AST::GenericArgs &args); void maybe_strip_qualified_path_type (AST::QualifiedPathType &path_type); void maybe_strip_closure_params (std::vector ¶ms); @@ -222,5 +224,8 @@ public: void visit (AST::SliceType &type) override; void visit (AST::InferredType &) override; void visit (AST::BareFunctionType &type) override; + void visit (AST::VariadicParam &type) override; + void visit (AST::FunctionParam &type) override; + void visit (AST::SelfParam &type) override; }; } // namespace Rust diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc index 28ce402dde7..cc198eecf5d 100644 --- a/gcc/rust/expand/rust-derive-clone.cc +++ b/gcc/rust/expand/rust-derive-clone.cc @@ -17,6 +17,7 @@ // . #include "rust-derive-clone.h" +#include "rust-item.h" namespace Rust { namespace AST { @@ -50,13 +51,17 @@ DeriveClone::clone_fn (std::unique_ptr &&clone_expr) loc, loc)); auto big_self_type = builder.single_type_path ("Self"); + std::unique_ptr self (new SelfParam (Lifetime::error (), + /* is_mut */ false, loc)); + + std::vector> params; + params.push_back (std::move (self)); + return std::unique_ptr ( new Function ({"clone"}, builder.fn_qualifiers (), /* generics */ {}, - tl::optional (tl::in_place, Lifetime::error (), - /* is_mut */ false, loc), - /* function params */ {}, std::move (big_self_type), - WhereClause::create_empty (), std::move (block), - Visibility::create_private (), {}, loc)); + /* function params */ std::move (params), + std::move (big_self_type), WhereClause::create_empty (), + std::move (block), Visibility::create_private (), {}, loc)); } /** diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h index 915c0545cbe..d5c8b44442d 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -220,6 +220,9 @@ private: virtual void visit (SliceType &type) override final{}; virtual void visit (InferredType &type) override final{}; virtual void visit (BareFunctionType &type) override final{}; + virtual void visit (SelfParam ¶m) override final{}; + virtual void visit (FunctionParam ¶m) override final{}; + virtual void visit (VariadicParam ¶m) override final{}; }; } // namespace AST diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index 0dd6f592dba..3f598b7f21c 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -373,12 +373,11 @@ ExpandVisitor::expand_tuple_fields (std::vector &fields) // FIXME: This can definitely be refactored with the method above void -ExpandVisitor::expand_function_params (std::vector ¶ms) +ExpandVisitor::expand_function_params ( + std::vector> ¶ms) { - for (auto ¶m : params) - { - maybe_expand_type (param.get_type ()); - } + for (auto &p : params) + visit (p); } void @@ -431,16 +430,6 @@ ExpandVisitor::expand_closure_params (std::vector ¶ms) } } -void -ExpandVisitor::expand_self_param (AST::SelfParam &self_param) -{ - if (self_param.has_type ()) - maybe_expand_type (self_param.get_type ()); - - /* TODO: maybe check for invariants being violated - e.g. both type and - * lifetime? */ -} - void ExpandVisitor::expand_where_clause (AST::WhereClause &where_clause) { @@ -472,11 +461,6 @@ ExpandVisitor::expand_trait_method_decl (AST::TraitMethodDecl &decl) for (auto ¶m : decl.get_generic_params ()) visit (param); - /* assuming you can't strip self param - wouldn't be a method - * anymore. spec allows outer attrs on self param, but doesn't - * specify whether cfg is used. */ - expand_self_param (decl.get_self_param ()); - /* strip function parameters if required - this is specifically * allowed by spec */ expand_function_params (decl.get_function_params ()); @@ -1022,8 +1006,6 @@ ExpandVisitor::visit (AST::Function &function) for (auto ¶m : function.get_generic_params ()) visit (param); - if (function.has_self_param ()) - expand_self_param (function.get_self_param ()); expand_function_params (function.get_function_params ()); if (function.has_return_type ()) @@ -1566,6 +1548,25 @@ ExpandVisitor::visit (AST::BareFunctionType &type) visit (type.get_return_type ()); } +void +ExpandVisitor::visit (AST::VariadicParam ¶m) +{} + +void +ExpandVisitor::visit (AST::FunctionParam ¶m) +{ + maybe_expand_type (param.get_type ()); +} + +void +ExpandVisitor::visit (AST::SelfParam ¶m) +{ + /* TODO: maybe check for invariants being violated - e.g. both type and + * lifetime? */ + if (param.has_type ()) + maybe_expand_type (param.get_type ()); +} + template void ExpandVisitor::expand_inner_attribute (T &item, AST::SimplePath &path) diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h index d7612acd385..74f2673655f 100644 --- a/gcc/rust/expand/rust-expand-visitor.h +++ b/gcc/rust/expand/rust-expand-visitor.h @@ -67,7 +67,8 @@ public: * Expand all macro invocations in lieu of types within a list of function * parameters */ - void expand_function_params (std::vector ¶ms); + void + expand_function_params (std::vector> ¶ms); /** * Expand all macro invocations in lieu of types within a list of generic @@ -82,7 +83,6 @@ public: // FIXME: Add documentation void expand_closure_params (std::vector ¶ms); - void expand_self_param (AST::SelfParam &self_param); void expand_where_clause (AST::WhereClause &where_clause); void expand_trait_function_decl (AST::TraitFunctionDecl &decl); void expand_trait_method_decl (AST::TraitMethodDecl &decl); @@ -347,6 +347,9 @@ public: void visit (AST::SliceType &type) override; void visit (AST::InferredType &) override; void visit (AST::BareFunctionType &type) override; + void visit (AST::VariadicParam &type) override; + void visit (AST::FunctionParam &type) override; + void visit (AST::SelfParam &type) override; template void expand_inner_attribute (T &item, AST::SimplePath &Path); diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index 1343a53667c..f5eed256a5e 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -21,6 +21,8 @@ #include "rust-ast-lower-pattern.h" #include "rust-ast-lower-extern.h" #include "rust-attribute-values.h" +#include "rust-item.h" +#include "rust-system.h" namespace Rust { namespace HIR { @@ -515,6 +517,18 @@ void ASTLoweringBase::visit (AST::BareFunctionType &) {} +void +ASTLoweringBase::visit (AST::FunctionParam ¶m) +{} + +void +ASTLoweringBase::visit (AST::VariadicParam ¶m) +{} + +void +ASTLoweringBase::visit (AST::SelfParam ¶m) +{} + HIR::Lifetime ASTLoweringBase::lower_lifetime (AST::Lifetime &lifetime) { @@ -629,28 +643,31 @@ ASTLoweringBase::lower_generic_args (AST::GenericArgs &args) } HIR::SelfParam -ASTLoweringBase::lower_self (AST::SelfParam &self) +ASTLoweringBase::lower_self (std::unique_ptr ¶m) { + rust_assert (param->is_self ()); + + auto self = static_cast (param.get ()); auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, self.get_node_id (), + Analysis::NodeMapping mapping (crate_num, self->get_node_id (), mappings->get_next_hir_id (crate_num), mappings->get_next_localdef_id (crate_num)); - if (self.has_type ()) + if (self->has_type ()) { - HIR::Type *type = ASTLoweringType::translate (self.get_type ().get ()); + HIR::Type *type = ASTLoweringType::translate (self->get_type ().get ()); return HIR::SelfParam (mapping, std::unique_ptr (type), - self.get_is_mut (), self.get_locus ()); + self->get_is_mut (), self->get_locus ()); } - else if (!self.get_has_ref ()) + else if (!self->get_has_ref ()) { return HIR::SelfParam (mapping, std::unique_ptr (nullptr), - self.get_is_mut (), self.get_locus ()); + self->get_is_mut (), self->get_locus ()); } - AST::Lifetime l = self.get_lifetime (); - return HIR::SelfParam (mapping, lower_lifetime (l), self.get_is_mut (), - self.get_locus ()); + AST::Lifetime l = self->get_lifetime (); + return HIR::SelfParam (mapping, lower_lifetime (l), self->get_is_mut (), + self->get_locus ()); } HIR::Type * diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index 1bb2731b860..d52afd3421f 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -251,6 +251,9 @@ public: virtual void visit (AST::SliceType &type); virtual void visit (AST::InferredType &type); virtual void visit (AST::BareFunctionType &type); + virtual void visit (AST::FunctionParam ¶m); + virtual void visit (AST::VariadicParam ¶m); + virtual void visit (AST::SelfParam ¶m); protected: ASTLoweringBase () @@ -274,7 +277,7 @@ protected: HIR::GenericArgsBinding lower_binding (AST::GenericArgsBinding &binding); - HIR::SelfParam lower_self (AST::SelfParam &self); + HIR::SelfParam lower_self (std::unique_ptr &self); HIR::Type *lower_type_no_bounds (AST::TypeNoBounds *type); diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h index 490676a55de..096a30e1e42 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.h +++ b/gcc/rust/hir/rust-ast-lower-implitem.h @@ -23,6 +23,7 @@ #include "rust-ast-lower-expr.h" #include "rust-ast-lower-pattern.h" #include "rust-ast-lower-block.h" +#include "rust-item.h" namespace Rust { namespace HIR { @@ -141,22 +142,26 @@ public: : nullptr; std::vector function_params; - for (auto ¶m : function.get_function_params ()) + for (auto &p : function.get_function_params ()) { + if (p->is_self () || p->is_variadic ()) + continue; + auto param = static_cast (p.get ()); + auto translated_pattern = std::unique_ptr ( - ASTLoweringPattern::translate (param.get_pattern ().get ())); + ASTLoweringPattern::translate (param->get_pattern ().get ())); auto translated_type = std::unique_ptr ( - ASTLoweringType::translate (param.get_type ().get ())); + ASTLoweringType::translate (param->get_type ().get ())); auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, param.get_node_id (), + 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 ()); + param->get_locus ()); function_params.push_back (std::move (hir_param)); } @@ -255,22 +260,27 @@ public: : nullptr; std::vector function_params; - for (auto ¶m : ref.get_function_params ()) + for (auto &p : ref.get_function_params ()) { + if (p->is_variadic () || p->is_self ()) + continue; + + auto param = static_cast (p.get ()); + auto translated_pattern = std::unique_ptr ( - ASTLoweringPattern::translate (param.get_pattern ().get ())); + ASTLoweringPattern::translate (param->get_pattern ().get ())); auto translated_type = std::unique_ptr ( - ASTLoweringType::translate (param.get_type ().get ())); + ASTLoweringType::translate (param->get_type ().get ())); auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, param.get_node_id (), + 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 ()); + param->get_locus ()); function_params.push_back (std::move (hir_param)); } @@ -329,22 +339,27 @@ public: HIR::SelfParam self_param = lower_self (ref.get_self_param ()); std::vector function_params; - for (auto ¶m : ref.get_function_params ()) + for (auto &p : ref.get_function_params ()) { + if (p->is_variadic () || p->is_self ()) + continue; + + auto param = static_cast (p.get ()); + auto translated_pattern = std::unique_ptr ( - ASTLoweringPattern::translate (param.get_pattern ().get ())); + ASTLoweringPattern::translate (param->get_pattern ().get ())); auto translated_type = std::unique_ptr ( - ASTLoweringType::translate (param.get_type ().get ())); + ASTLoweringType::translate (param->get_type ().get ())); auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, param.get_node_id (), + 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 ()); + param->get_locus ()); function_params.push_back (hir_param); } diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc index 6d91c23e8d2..8d6ab7cd350 100644 --- a/gcc/rust/hir/rust-ast-lower-item.cc +++ b/gcc/rust/hir/rust-ast-lower-item.cc @@ -26,6 +26,7 @@ #include "rust-ast-lower-expr.h" #include "rust-ast-lower-pattern.h" #include "rust-ast-lower-block.h" +#include "rust-item.h" namespace Rust { namespace HIR { @@ -420,21 +421,25 @@ ASTLoweringItem::visit (AST::Function &function) : nullptr; std::vector function_params; - for (auto ¶m : function.get_function_params ()) + for (auto &p : function.get_function_params ()) { + if (p->is_variadic () || p->is_self ()) + continue; + auto param = static_cast (p.get ()); + auto translated_pattern = std::unique_ptr ( - ASTLoweringPattern::translate (param.get_pattern ().get ())); + ASTLoweringPattern::translate (param->get_pattern ().get ())); auto translated_type = std::unique_ptr ( - ASTLoweringType::translate (param.get_type ().get ())); + ASTLoweringType::translate (param->get_type ().get ())); auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, param.get_node_id (), + 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 ()); + std::move (translated_type), param->get_locus ()); function_params.push_back (std::move (hir_param)); } diff --git a/gcc/rust/metadata/rust-export-metadata.cc b/gcc/rust/metadata/rust-export-metadata.cc index 73c3abfe0a2..a946c67422d 100644 --- a/gcc/rust/metadata/rust-export-metadata.cc +++ b/gcc/rust/metadata/rust-export-metadata.cc @@ -22,9 +22,11 @@ #include "rust-hir-map.h" #include "rust-ast-dump.h" #include "rust-abi.h" +#include "rust-item.h" #include "rust-object-export.h" #include "md5.h" +#include "rust-system.h" namespace Rust { namespace Metadata { @@ -107,15 +109,18 @@ ExportContext::emit_function (const HIR::Function &fn) } std::vector function_params; - for (AST::FunctionParam ¶m : function.get_function_params ()) + for (auto &p : function.get_function_params ()) { - std::string name = param.get_pattern ()->as_string (); + if (p->is_variadic () || p->is_self ()) + rust_unreachable (); + auto param = static_cast (p.get ()); + std::string name = param->get_pattern ()->as_string (); std::unique_ptr param_type - = param.get_type ()->clone_type (); + = param->get_type ()->clone_type (); - AST::NamedFunctionParam p (name, std::move (param_type), {}, - param.get_locus ()); - function_params.push_back (std::move (p)); + AST::NamedFunctionParam np (name, std::move (param_type), {}, + param->get_locus ()); + function_params.push_back (std::move (np)); } AST::ExternalItem *external_item diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 21795bb4ca0..0e50c9eb17a 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -2879,12 +2879,21 @@ Parser::parse_function (AST::Visibility vis, return nullptr; } + std::unique_ptr initial_param = parse_self_param (); + if (initial_param != nullptr) + skip_token (COMMA); + // parse function parameters (only if next token isn't right paren) - std::vector function_params; + std::vector> function_params; + if (lexer.peek_token ()->get_id () != RIGHT_PAREN) function_params = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; }); + if (initial_param != nullptr) + function_params.insert (function_params.begin (), + std::move (initial_param)); + if (!skip_token (RIGHT_PAREN)) { Error error (lexer.peek_token ()->get_locus (), @@ -2907,11 +2916,10 @@ Parser::parse_function (AST::Visibility vis, return std::unique_ptr ( new AST::Function (std::move (function_name), std::move (qualifiers), - std::move (generic_params), - tl::optional (), - std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (block_expr), - std::move (vis), std::move (outer_attrs), locus)); + std::move (generic_params), std::move (function_params), + std::move (return_type), std::move (where_clause), + std::move (block_expr), std::move (vis), + std::move (outer_attrs), locus)); } // Parses function or method qualifiers (i.e. const, unsafe, and extern). @@ -3525,18 +3533,18 @@ Parser::parse_type_param () * has end token handling. */ template template -std::vector +std::vector> Parser::parse_function_params (EndTokenPred is_end_token) { - std::vector params; + std::vector> params; if (is_end_token (lexer.peek_token ()->get_id ())) return params; - AST::FunctionParam initial_param = parse_function_param (); + auto initial_param = parse_function_param (); // Return empty parameter list if no parameter there - if (initial_param.is_error ()) + if (initial_param == nullptr) { // TODO: is this an error? return params; @@ -3558,15 +3566,15 @@ Parser::parse_function_params (EndTokenPred is_end_token) break; // now, as right paren would break, function param is required - AST::FunctionParam param = parse_function_param (); - if (param.is_error ()) + auto param = parse_function_param (); + if (param == nullptr) { Error error (lexer.peek_token ()->get_locus (), "failed to parse function param (in function params)"); add_error (std::move (error)); // skip somewhere? - return std::vector (); + return std::vector> (); } params.push_back (std::move (param)); @@ -3581,7 +3589,7 @@ Parser::parse_function_params (EndTokenPred is_end_token) /* Parses a single regular (i.e. non-generic) parameter in a function or * method, i.e. the "name: type" bit. Also handles it not existing. */ template -AST::FunctionParam +std::unique_ptr Parser::parse_function_param () { // parse outer attributes if they exist @@ -3593,7 +3601,8 @@ Parser::parse_function_param () if (lexer.peek_token ()->get_id () == ELLIPSIS) // Unnamed variadic { lexer.skip_token (); // Skip ellipsis - return AST::FunctionParam (std::move (outer_attrs), locus); + return Rust::make_unique ( + AST::VariadicParam (std::move (outer_attrs), locus)); } std::unique_ptr param_pattern = parse_pattern (); @@ -3602,32 +3611,32 @@ Parser::parse_function_param () if (param_pattern == nullptr) { // skip after something - return AST::FunctionParam::create_error (); + return nullptr; } if (!skip_token (COLON)) { // skip after something - return AST::FunctionParam::create_error (); + return nullptr; } if (lexer.peek_token ()->get_id () == ELLIPSIS) // Named variadic { lexer.skip_token (); // Skip ellipsis - return AST::FunctionParam (std::move (param_pattern), - std::move (outer_attrs), locus); + return Rust::make_unique ( + AST::VariadicParam (std::move (param_pattern), std::move (outer_attrs), + locus)); } else { std::unique_ptr param_type = parse_type (); if (param_type == nullptr) { - // skip? - return AST::FunctionParam::create_error (); + return nullptr; } - return AST::FunctionParam (std::move (param_pattern), - std::move (param_type), - std::move (outer_attrs), locus); + return Rust::make_unique ( + AST::FunctionParam (std::move (param_pattern), std::move (param_type), + std::move (outer_attrs), locus)); } } @@ -5051,13 +5060,14 @@ Parser::parse_trait_item () /* now for function vs method disambiguation - method has opening * "self" param */ - AST::SelfParam self_param = parse_self_param (); + std::unique_ptr initial_param = parse_self_param (); /* FIXME: ensure that self param doesn't accidently consume tokens for * a function */ bool is_method = false; - if (!self_param.is_error ()) + if (initial_param != nullptr) { - is_method = true; + if (initial_param->is_self ()) + is_method = true; /* skip comma so function and method regular params can be parsed * in same way */ @@ -5066,7 +5076,7 @@ Parser::parse_trait_item () } // parse trait function params - std::vector function_params + std::vector> function_params = parse_function_params ( [] (TokenId id) { return id == RIGHT_PAREN; }); @@ -5076,6 +5086,10 @@ Parser::parse_trait_item () return nullptr; } + if (initial_param != nullptr) + function_params.insert (function_params.begin (), + std::move (initial_param)); + // parse return type (optional) std::unique_ptr return_type = parse_function_return_type (); @@ -5114,7 +5128,6 @@ Parser::parse_trait_item () AST::TraitMethodDecl method_decl (std::move (ident), std::move (qualifiers), std::move (generic_params), - std::move (self_param), std::move (function_params), std::move (return_type), std::move (where_clause)); @@ -5592,14 +5605,15 @@ Parser::parse_inherent_impl_function_or_method ( // now for function vs method disambiguation - method has opening "self" // param - AST::SelfParam self_param = parse_self_param (); + std::unique_ptr initial_param = parse_self_param (); /* FIXME: ensure that self param doesn't accidently consume tokens for a * function one idea is to lookahead up to 4 tokens to see whether self is * one of them */ bool is_method = false; - if (!self_param.is_error ()) + if (initial_param != nullptr) { - is_method = true; + if (initial_param->is_self ()) + is_method = true; /* skip comma so function and method regular params can be parsed in * same way */ @@ -5608,9 +5622,13 @@ Parser::parse_inherent_impl_function_or_method ( } // parse trait function params - std::vector function_params + std::vector> function_params = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; }); + if (initial_param != nullptr) + function_params.insert (function_params.begin (), + std::move (initial_param)); + if (!skip_token (RIGHT_PAREN)) { skip_after_end_block (); @@ -5650,18 +5668,18 @@ Parser::parse_inherent_impl_function_or_method ( // do actual if instead of ternary for return value optimisation if (is_method) { - return std::unique_ptr (new AST::Function ( - std::move (ident), std::move (qualifiers), std::move (generic_params), - tl::optional (tl::in_place, std::move (self_param)), - std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (body), std::move (vis), - std::move (outer_attrs), locus)); + return std::unique_ptr ( + new AST::Function (std::move (ident), std::move (qualifiers), + std::move (generic_params), + std::move (function_params), std::move (return_type), + std::move (where_clause), std::move (body), + std::move (vis), std::move (outer_attrs), locus)); } else { return std::unique_ptr ( new AST::Function (std::move (ident), std::move (qualifiers), - std::move (generic_params), tl::nullopt, + std::move (generic_params), std::move (function_params), std::move (return_type), std::move (where_clause), std::move (body), std::move (vis), std::move (outer_attrs), locus)); @@ -5795,13 +5813,14 @@ Parser::parse_trait_impl_function_or_method ( // now for function vs method disambiguation - method has opening "self" // param - AST::SelfParam self_param = parse_self_param (); + std::unique_ptr initial_param = parse_self_param (); // FIXME: ensure that self param doesn't accidently consume tokens for a // function bool is_method = false; - if (!self_param.is_error ()) + if (initial_param != nullptr) { - is_method = true; + if (initial_param->is_self ()) + is_method = true; // skip comma so function and method regular params can be parsed in // same way @@ -5819,7 +5838,7 @@ Parser::parse_trait_impl_function_or_method ( "started to parse function params in function or method trait impl item"); // parse trait function params (only if next token isn't right paren) - std::vector function_params; + std::vector> function_params; if (lexer.peek_token ()->get_id () != RIGHT_PAREN) { function_params @@ -5838,6 +5857,10 @@ Parser::parse_trait_impl_function_or_method ( } } + if (initial_param != nullptr) + function_params.insert (function_params.begin (), + std::move (initial_param)); + // DEBUG rust_debug ("successfully parsed function params in function or method " "trait impl item"); @@ -5886,24 +5909,12 @@ Parser::parse_trait_impl_function_or_method ( return nullptr; } - // do actual if instead of ternary for return value optimisation - if (is_method) - { - return std::unique_ptr (new AST::Function ( - std::move (ident), std::move (qualifiers), std::move (generic_params), - tl::optional (tl::in_place, std::move (self_param)), - std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (body), std::move (vis), - std::move (outer_attrs), locus, is_default)); - } - else - { - return std::unique_ptr (new AST::Function ( - std::move (ident), std::move (qualifiers), std::move (generic_params), - tl::nullopt, std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (body), std::move (vis), - std::move (outer_attrs), locus, is_default)); - } + return std::unique_ptr ( + new AST::Function (std::move (ident), std::move (qualifiers), + std::move (generic_params), std::move (function_params), + std::move (return_type), std::move (where_clause), + std::move (body), std::move (vis), + std::move (outer_attrs), locus, is_default)); } // Parses an extern block of declarations. @@ -7097,7 +7108,7 @@ Parser::parse_qualified_path_in_type () // Parses a self param. Also handles self param not existing. template -AST::SelfParam +std::unique_ptr Parser::parse_self_param () { bool has_reference = false; @@ -7105,6 +7116,42 @@ Parser::parse_self_param () location_t locus = lexer.peek_token ()->get_locus (); + // TODO: Feels off, find a better way to clearly express this + std::vector> ptrs + = {{ASTERISK, SELF} /* *self */, + {ASTERISK, CONST, SELF} /* *const self */, + {ASTERISK, MUT, SELF} /* *mut self */}; + + for (auto &s : ptrs) + { + size_t i = 0; + for (i = 0; i > s.size (); i++) + if (lexer.peek_token (i)->get_id () != s[i]) + break; + if (i == s.size ()) + rust_error_at (lexer.peek_token ()->get_locus (), + "cannot pass % by raw pointer"); + } + + // Trying to find those patterns: + // + // &'lifetime mut self + // &'lifetime self + // & mut self + // & self + // mut self + // self + // + // If not found, it is probably a function, exit and let function parsing + // handle it. + bool is_self = false; + for (size_t i = 0; i < 5; i++) + if (lexer.peek_token (i)->get_id () == SELF) + is_self = true; + + if (!is_self) + return nullptr; + // test if self is a reference parameter if (lexer.peek_token ()->get_id () == AMP) { @@ -7124,7 +7171,7 @@ Parser::parse_self_param () add_error (std::move (error)); // skip after somewhere? - return AST::SelfParam::create_error (); + return nullptr; } } } @@ -7142,7 +7189,7 @@ Parser::parse_self_param () if (self_tok->get_id () != SELF) { // skip after somewhere? - return AST::SelfParam::create_error (); + return nullptr; } lexer.skip_token (); @@ -7161,7 +7208,7 @@ Parser::parse_self_param () add_error (std::move (error)); // skip after somewhere? - return AST::SelfParam::create_error (); + return nullptr; } } @@ -7174,114 +7221,20 @@ Parser::parse_self_param () add_error (std::move (error)); // skip after somewhere? - return AST::SelfParam::create_error (); + return nullptr; } if (has_reference) { - return AST::SelfParam (std::move (lifetime), has_mut, locus); + return Rust::make_unique (std::move (lifetime), has_mut, + locus); } else { // note that type may be nullptr here and that's fine - return AST::SelfParam (std::move (type), has_mut, locus); - } -} - -/* Parses a method. Note that this function is probably useless because using - * lookahead to determine whether a function is a method is a PITA (maybe not - * even doable), so most places probably parse a "function or method" and then - * resolve it into whatever it is afterward. As such, this is only here for - * algorithmically defining the grammar rule. */ -template -std::unique_ptr -Parser::parse_method () -{ - location_t locus = lexer.peek_token ()->get_locus (); - /* Note: as a result of the above, this will not attempt to disambiguate a - * function parse qualifiers */ - AST::FunctionQualifiers qualifiers = parse_function_qualifiers (); - - skip_token (FN_TOK); - - const_TokenPtr ident_tok = expect_token (IDENTIFIER); - if (ident_tok == nullptr) - { - skip_after_next_block (); - return nullptr; + return Rust::make_unique (std::move (type), has_mut, + locus); } - Identifier method_name{ident_tok}; - - // parse generic params - if exist - std::vector> generic_params - = parse_generic_params_in_angles (); - - if (!skip_token (LEFT_PAREN)) - { - Error error (lexer.peek_token ()->get_locus (), - "method missing opening parentheses before parameter list"); - add_error (std::move (error)); - - skip_after_next_block (); - return nullptr; - } - - // parse self param - AST::SelfParam self_param = parse_self_param (); - if (self_param.is_error ()) - { - Error error (lexer.peek_token ()->get_locus (), - "could not parse self param in method"); - add_error (std::move (error)); - - skip_after_next_block (); - return nullptr; - } - - // skip comma if it exists - if (lexer.peek_token ()->get_id () == COMMA) - lexer.skip_token (); - - // parse function parameters - std::vector function_params - = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; }); - - if (!skip_token (RIGHT_PAREN)) - { - Error error (lexer.peek_token ()->get_locus (), - "method declaration missing closing parentheses after " - "parameter list"); - add_error (std::move (error)); - - skip_after_next_block (); - return nullptr; - } - - // parse function return type - if exists - std::unique_ptr return_type = parse_function_return_type (); - - // parse where clause - if exists - AST::WhereClause where_clause = parse_where_clause (); - - // parse block expression - std::unique_ptr block_expr = parse_block_expr (); - if (block_expr == nullptr) - { - Error error (lexer.peek_token ()->get_locus (), - "method declaration missing block expression"); - add_error (std::move (error)); - - skip_after_end_block (); - return nullptr; - } - - // does not parse visibility, but this method isn't used, so doesn't matter - return std::unique_ptr (new AST::Function ( - std::move (method_name), std::move (qualifiers), std::move (generic_params), - tl::optional (tl::in_place, std::move (self_param)), - std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (block_expr), - AST::Visibility::create_error (), AST::AttrVec (), locus)); } /* Parses an expression or macro statement. */ diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 3ff9b99caed..9e924e0015c 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -164,7 +164,7 @@ public: std::unique_ptr parse_inherent_impl_item (); std::unique_ptr parse_trait_impl_item (); AST::PathInExpression parse_path_in_expression (); - std::vector > parse_lifetime_params (); + std::vector> parse_lifetime_params (); AST::Visibility parse_visibility (); std::unique_ptr parse_identifier_pattern (); std::unique_ptr parse_identifier_or_keyword_token (); @@ -246,17 +246,17 @@ private: std::unique_ptr parse_function (AST::Visibility vis, AST::AttrVec outer_attrs); AST::FunctionQualifiers parse_function_qualifiers (); - std::vector > + std::vector> parse_generic_params_in_angles (); template - std::vector > + std::vector> parse_generic_params (EndTokenPred is_end_token); template std::unique_ptr parse_generic_param (EndTokenPred is_end_token); template - std::vector > + std::vector> parse_lifetime_params (EndTokenPred is_end_token); std::vector parse_lifetime_params_objs (); template @@ -268,15 +268,15 @@ private: std::string error_msg = "failed to parse generic param in generic params") -> std::vector; AST::LifetimeParam parse_lifetime_param (); - std::vector > parse_type_params (); + std::vector> parse_type_params (); template - std::vector > + std::vector> parse_type_params (EndTokenPred is_end_token); std::unique_ptr parse_type_param (); template - std::vector + std::vector> parse_function_params (EndTokenPred is_end_token); - AST::FunctionParam parse_function_param (); + std::unique_ptr parse_function_param (); std::unique_ptr parse_function_return_type (); AST::WhereClause parse_where_clause (); std::unique_ptr parse_where_clause_item (); @@ -286,9 +286,9 @@ private: parse_type_bound_where_clause_item (); std::vector parse_for_lifetimes (); template - std::vector > + std::vector> parse_type_param_bounds (EndTokenPred is_end_token); - std::vector > parse_type_param_bounds (); + std::vector> parse_type_param_bounds (); std::unique_ptr parse_type_param_bound (); std::unique_ptr parse_trait_bound (); std::vector parse_lifetime_bounds (); @@ -317,9 +317,9 @@ private: AST::TupleField parse_tuple_field (); std::unique_ptr parse_enum (AST::Visibility vis, AST::AttrVec outer_attrs); - std::vector > parse_enum_items (); + std::vector> parse_enum_items (); template - std::vector > + std::vector> parse_enum_items (EndTokenPred is_end_token); std::unique_ptr parse_enum_item (); std::unique_ptr parse_union (AST::Visibility vis, @@ -334,7 +334,7 @@ private: parse_trait_type (AST::AttrVec outer_attrs); std::unique_ptr parse_trait_const (AST::AttrVec outer_attrs); - AST::SelfParam parse_self_param (); + std::unique_ptr parse_self_param (); std::unique_ptr parse_impl (AST::Visibility vis, AST::AttrVec outer_attrs); std::unique_ptr @@ -594,7 +594,7 @@ private: parse_match_expr (AST::AttrVec outer_attrs = AST::AttrVec (), location_t pratt_parsed_loc = UNKNOWN_LOCATION); AST::MatchArm parse_match_arm (); - std::vector > + std::vector> parse_match_arm_patterns (TokenId end_token_id); std::unique_ptr parse_labelled_loop_expr (const_TokenPtr tok, AST::AttrVec outer_attrs @@ -692,7 +692,7 @@ public: // Parse items without parsing an entire crate. This function is the main // parsing loop of AST::Crate::parse_crate(). - std::vector > parse_items (); + std::vector> parse_items (); // Main entry point for parser. std::unique_ptr parse_crate (); diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc index 34ebbc7dfba..1283d77d22b 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ b/gcc/rust/resolve/rust-ast-resolve-base.cc @@ -646,5 +646,17 @@ void ResolverBase::visit (AST::BareFunctionType &) {} +void +ResolverBase::visit (AST::SelfParam &) +{} + +void +ResolverBase::visit (AST::VariadicParam &) +{} + +void +ResolverBase::visit (AST::FunctionParam &) +{} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h index f9ae7011eae..78830498771 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -196,6 +196,9 @@ public: void visit (AST::SliceType &); void visit (AST::InferredType &); void visit (AST::BareFunctionType &); + void visit (AST::FunctionParam ¶m); + void visit (AST::VariadicParam ¶m); + void visit (AST::SelfParam ¶m); protected: ResolverBase () diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index 4c6958d0b81..1fc6b920c5e 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -17,11 +17,13 @@ // . #include "rust-ast-resolve-item.h" +#include "rust-ast-full-decls.h" #include "rust-ast-resolve-toplevel.h" #include "rust-ast-resolve-type.h" #include "rust-ast-resolve-pattern.h" #include "rust-ast-resolve-path.h" +#include "rust-item.h" #include "selftest.h" namespace Rust { @@ -87,11 +89,26 @@ ResolveTraitItems::visit (AST::TraitItemFunc &func) // we make a new scope so the names of parameters are resolved and shadowed // correctly - for (auto ¶m : function.get_function_params ()) + for (auto &p : function.get_function_params ()) { - ResolveType::go (param.get_type ().get ()); - PatternDeclaration::go (param.get_pattern ().get (), Rib::ItemType::Param, - bindings); + if (p->is_variadic ()) + { + auto param = static_cast (p.get ()); + PatternDeclaration::go (param->get_pattern ().get (), + Rib::ItemType::Param, bindings); + } + else if (p->is_self ()) + { + auto param = static_cast (p.get ()); + ResolveType::go (param->get_type ().get ()); + } + else + { + auto param = static_cast (p.get ()); + ResolveType::go (param->get_type ().get ()); + PatternDeclaration::go (param->get_pattern ().get (), + Rib::ItemType::Param, bindings); + } } if (function.has_where_clause ()) @@ -133,43 +150,55 @@ ResolveTraitItems::visit (AST::TraitItemMethod &func) ResolveType::go (function.get_return_type ().get ()); // self turns into (self: Self) as a function param - AST::SelfParam &self_param = function.get_self_param (); - // FIXME: which location should be used for Rust::Identifier `self`? - 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 (nullptr)); - PatternDeclaration::go (&self_pattern, Rib::ItemType::Param); - - if (self_param.has_type ()) - { - // This shouldn't happen the parser should already error for this - rust_assert (!self_param.get_has_ref ()); - ResolveType::go (self_param.get_type ().get ()); - } - else - { - // here we implicitly make self have a type path of Self - std::vector> segments; - segments.push_back (std::unique_ptr ( - 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); - } - std::vector bindings = {PatternBinding (PatternBoundCtx::Product, std::set ())}; // we make a new scope so the names of parameters are resolved and shadowed // correctly - for (auto ¶m : function.get_function_params ()) + for (auto &p : function.get_function_params ()) { - ResolveType::go (param.get_type ().get ()); - PatternDeclaration::go (param.get_pattern ().get (), Rib::ItemType::Param, - bindings); + if (p->is_variadic ()) + { + auto param = static_cast (p.get ()); + PatternDeclaration::go (param->get_pattern ().get (), + Rib::ItemType::Param, bindings); + } + else if (p->is_self ()) + { + auto param = static_cast (p.get ()); + // FIXME: which location should be used for Rust::Identifier `self`? + AST::IdentifierPattern self_pattern ( + param->get_node_id (), {"self"}, param->get_locus (), + param->get_has_ref (), param->get_is_mut (), + std::unique_ptr (nullptr)); + + PatternDeclaration::go (&self_pattern, Rib::ItemType::Param); + + if (param->has_type ()) + { + // This shouldn't happen the parser should already error for this + rust_assert (!param->get_has_ref ()); + ResolveType::go (param->get_type ().get ()); + } + else + { + // here we implicitly make self have a type path of Self + std::vector> segments; + segments.push_back (std::unique_ptr ( + new AST::TypePathSegment ("Self", false, param->get_locus ()))); + + AST::TypePath self_type_path (std::move (segments), + param->get_locus ()); + ResolveType::go (&self_type_path); + } + } + else + { + auto param = static_cast (p.get ()); + ResolveType::go (param->get_type ().get ()); + PatternDeclaration::go (param->get_pattern ().get (), + Rib::ItemType::Param, bindings); + } } if (function.has_where_clause ()) @@ -527,29 +556,32 @@ ResolveItem::visit (AST::Function &function) if (function.has_self_param ()) { // self turns into (self: Self) as a function param - AST::SelfParam &self_param = function.get_self_param (); + std::unique_ptr &s_param = function.get_self_param (); + auto self_param = static_cast (s_param.get ()); + // FIXME: which location should be used for Rust::Identifier `self`? AST::IdentifierPattern self_pattern ( - self_param.get_node_id (), {"self"}, self_param.get_locus (), - self_param.get_has_ref (), self_param.get_is_mut (), + self_param->get_node_id (), {"self"}, self_param->get_locus (), + self_param->get_has_ref (), self_param->get_is_mut (), std::unique_ptr (nullptr)); PatternDeclaration::go (&self_pattern, Rib::ItemType::Param); - if (self_param.has_type ()) + if (self_param->has_type ()) { // This shouldn't happen the parser should already error for this - rust_assert (!self_param.get_has_ref ()); - ResolveType::go (self_param.get_type ().get ()); + rust_assert (!self_param->get_has_ref ()); + ResolveType::go (self_param->get_type ().get ()); } else { // here we implicitly make self have a type path of Self std::vector> segments; segments.push_back (std::unique_ptr ( - new AST::TypePathSegment ("Self", false, self_param.get_locus ()))); + new AST::TypePathSegment ("Self", false, + self_param->get_locus ()))); AST::TypePath self_type_path (std::move (segments), - self_param.get_locus ()); + self_param->get_locus ()); ResolveType::go (&self_type_path); } } @@ -559,11 +591,28 @@ ResolveItem::visit (AST::Function &function) // we make a new scope so the names of parameters are resolved and shadowed // correctly - for (auto ¶m : function.get_function_params ()) + for (auto &p : function.get_function_params ()) { - ResolveType::go (param.get_type ().get ()); - PatternDeclaration::go (param.get_pattern ().get (), Rib::ItemType::Param, - bindings); + if (p->is_variadic ()) + { + auto param = static_cast (p.get ()); + if (param->has_pattern ()) + PatternDeclaration::go (param->get_pattern ().get (), + Rib::ItemType::Param, bindings); + } + else if (p->is_self ()) + { + auto param = static_cast (p.get ()); + if (param->has_type ()) + ResolveType::go (param->get_type ().get ()); + } + else + { + auto param = static_cast (p.get ()); + ResolveType::go (param->get_type ().get ()); + PatternDeclaration::go (param->get_pattern ().get (), + Rib::ItemType::Param, bindings); + } } // resolve the function body diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index 6d5f5324fb0..293c98fd6f2 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -23,6 +23,7 @@ #include "rust-ast-resolve-type.h" #include "rust-ast-resolve-pattern.h" #include "rust-ast-resolve-expr.h" +#include "rust-item.h" namespace Rust { namespace Resolver { @@ -352,11 +353,28 @@ public: // we make a new scope so the names of parameters are resolved and shadowed // correctly - for (auto ¶m : function.get_function_params ()) + for (auto &p : function.get_function_params ()) { - ResolveType::go (param.get_type ().get ()); - PatternDeclaration::go (param.get_pattern ().get (), - Rib::ItemType::Param, bindings); + if (p->is_variadic ()) + { + auto param = static_cast (p.get ()); + PatternDeclaration::go (param->get_pattern ().get (), + Rib::ItemType::Param, bindings); + } + + else if (p->is_self ()) + { + auto param = static_cast (p.get ()); + ResolveType::go (param->get_type ().get ()); + } + else + { + auto param = static_cast (p.get ()); + + ResolveType::go (param->get_type ().get ()); + PatternDeclaration::go (param->get_pattern ().get (), + Rib::ItemType::Param, bindings); + } } // resolve the function body diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index fc81001689b..1ab174b6caa 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -18,6 +18,7 @@ #include "rust-default-resolver.h" #include "rust-ast-full.h" +#include "rust-item.h" namespace Rust { namespace Resolver2_0 { @@ -55,10 +56,25 @@ void DefaultResolver::visit (AST::Function &function) { auto def_fn = [this, &function] () { - for (auto ¶m : function.get_function_params ()) + for (auto &p : function.get_function_params ()) { - param.get_pattern ()->accept_vis (*this); - param.get_type ()->accept_vis (*this); + if (p->is_variadic ()) + { + auto param = static_cast (p.get ()); + param->get_pattern ()->accept_vis (*this); + } + else if (p->is_self ()) + { + auto param = static_cast (p.get ()); + param->get_type ()->accept_vis (*this); + param->get_lifetime ().accept_vis (*this); + } + else + { + auto param = static_cast (p.get ()); + param->get_pattern ()->accept_vis (*this); + param->get_type ()->accept_vis (*this); + } } function.get_definition ()->accept_vis (*this); @@ -801,5 +817,17 @@ void DefaultResolver::visit (AST::BareFunctionType &) {} +void +DefaultResolver::visit (AST::SelfParam &) +{} + +void +DefaultResolver::visit (AST::FunctionParam &) +{} + +void +DefaultResolver::visit (AST::VariadicParam &) +{} + } // namespace Resolver2_0 } // namespace Rust diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index 8af9513b25c..49255d3bc26 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -197,6 +197,9 @@ public: void visit (AST::SliceType &); void visit (AST::InferredType &); void visit (AST::BareFunctionType &); + void visit (AST::FunctionParam &); + void visit (AST::VariadicParam &); + void visit (AST::SelfParam &); protected: DefaultResolver (NameResolutionContext &ctx) : ctx (ctx) {} diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc index 455da3030f8..38a16408436 100644 --- a/gcc/rust/resolve/rust-early-name-resolver.cc +++ b/gcc/rust/resolve/rust-early-name-resolver.cc @@ -662,11 +662,8 @@ EarlyNameResolver::visit (AST::Function &function) for (auto &generic : function.get_generic_params ()) generic->accept_vis (*this); - if (function.has_self_param () && function.get_self_param ().has_type ()) - function.get_self_param ().get_type ()->accept_vis (*this); - - for (auto ¶m : function.get_function_params ()) - param.get_type ()->accept_vis (*this); + for (auto &p : function.get_function_params ()) + p->accept_vis (*this); if (function.has_return_type ()) function.get_return_type ()->accept_vis (*this); @@ -758,8 +755,8 @@ EarlyNameResolver::visit (AST::TraitItemFunc &item) for (auto &generic : decl.get_generic_params ()) generic->accept_vis (*this); - for (auto ¶m : decl.get_function_params ()) - param.get_type ()->accept_vis (*this); + for (auto &p : decl.get_function_params ()) + p->accept_vis (*this); if (item.has_definition ()) item.get_definition ()->accept_vis (*this); @@ -777,8 +774,8 @@ EarlyNameResolver::visit (AST::TraitItemMethod &item) for (auto &generic : decl.get_generic_params ()) generic->accept_vis (*this); - for (auto ¶m : decl.get_function_params ()) - param.get_type ()->accept_vis (*this); + for (auto &p : decl.get_function_params ()) + p->accept_vis (*this); if (item.has_definition ()) item.get_definition ()->accept_vis (*this); @@ -1232,5 +1229,28 @@ EarlyNameResolver::visit (AST::BareFunctionType &type) type.get_return_type ()->accept_vis (*this); } +void +EarlyNameResolver::visit (AST::VariadicParam ¶m) +{ + if (param.has_pattern ()) + param.get_pattern ()->accept_vis (*this); +} + +void +EarlyNameResolver::visit (AST::FunctionParam ¶m) +{ + param.get_pattern ()->accept_vis (*this); + param.get_type ()->accept_vis (*this); +} + +void +EarlyNameResolver::visit (AST::SelfParam ¶m) +{ + if (param.has_type ()) + param.get_type ()->accept_vis (*this); + if (param.has_lifetime ()) + param.get_lifetime ().accept_vis (*this); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h index 41728c6fc1f..cebc6e4b5af 100644 --- a/gcc/rust/resolve/rust-early-name-resolver.h +++ b/gcc/rust/resolve/rust-early-name-resolver.h @@ -277,6 +277,10 @@ private: virtual void visit (AST::SliceType &type); virtual void visit (AST::InferredType &type); virtual void visit (AST::BareFunctionType &type); + + virtual void visit (AST::VariadicParam &type); + virtual void visit (AST::FunctionParam &type); + virtual void visit (AST::SelfParam &type); }; } // namespace Resolver diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc index 3966ccd904e..981bc738d6c 100644 --- a/gcc/rust/util/rust-attributes.cc +++ b/gcc/rust/util/rust-attributes.cc @@ -996,5 +996,17 @@ void AttributeChecker::visit (AST::BareFunctionType &) {} +void +AttributeChecker::visit (AST::SelfParam &) +{} + +void +AttributeChecker::visit (AST::VariadicParam &) +{} + +void +AttributeChecker::visit (AST::FunctionParam &) +{} + } // namespace Analysis } // namespace Rust diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h index 5a93e1c5db9..9db371e81c6 100644 --- a/gcc/rust/util/rust-attributes.h +++ b/gcc/rust/util/rust-attributes.h @@ -264,6 +264,9 @@ private: void visit (AST::SliceType &type); void visit (AST::InferredType &type); void visit (AST::BareFunctionType &type); + void visit (AST::FunctionParam ¶m); + void visit (AST::VariadicParam ¶m); + void visit (AST::SelfParam ¶m); }; } // namespace Analysis