diff options
Diffstat (limited to 'gcc/rust/ast')
38 files changed, 2607 insertions, 852 deletions
diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc deleted file mode 100644 index 13126b4..0000000 --- a/gcc/rust/ast/rust-ast-builder-type.cc +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (C) 2020-2024 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#include "rust-ast-builder-type.h" -#include "rust-ast-builder.h" -#include "rust-ast-full.h" -#include "rust-common.h" - -namespace Rust { -namespace AST { - -ASTTypeBuilder::ASTTypeBuilder () : translated (nullptr) {} - -Type * -ASTTypeBuilder::build (Type &type) -{ - ASTTypeBuilder builder; - type.accept_vis (builder); - rust_assert (builder.translated != nullptr); - return builder.translated; -} - -void -ASTTypeBuilder::visit (BareFunctionType &fntype) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (TupleType &tuple) -{ - std::vector<std::unique_ptr<Type> > elems; - for (auto &elem : tuple.get_elems ()) - { - Type *t = ASTTypeBuilder::build (*elem.get ()); - std::unique_ptr<Type> ty (t); - elems.push_back (std::move (ty)); - } - translated = new TupleType (std::move (elems), tuple.get_locus ()); -} - -void -ASTTypeBuilder::visit (TypePath &path) -{ - std::vector<std::unique_ptr<TypePathSegment> > segments; - for (auto &seg : path.get_segments ()) - { - switch (seg->get_type ()) - { - case TypePathSegment::REG: { - const TypePathSegment &segment - = (const TypePathSegment &) (*seg.get ()); - TypePathSegment *s - = new TypePathSegment (segment.get_ident_segment (), - segment.get_separating_scope_resolution (), - segment.get_locus ()); - std::unique_ptr<TypePathSegment> sg (s); - segments.push_back (std::move (sg)); - } - break; - - case TypePathSegment::GENERIC: { - TypePathSegmentGeneric &generic - = (TypePathSegmentGeneric &) (*seg.get ()); - - GenericArgs args - = Builder::new_generic_args (generic.get_generic_args ()); - TypePathSegmentGeneric *s - = new TypePathSegmentGeneric (generic.get_ident_segment (), false, - std::move (args), - generic.get_locus ()); - std::unique_ptr<TypePathSegment> sg (s); - segments.push_back (std::move (sg)); - } - break; - - case TypePathSegment::FUNCTION: { - rust_unreachable (); - // TODO - // const TypePathSegmentFunction &fn - // = (const TypePathSegmentFunction &) (*seg.get ()); - } - break; - } - } - - translated = new TypePath (std::move (segments), path.get_locus (), - path.has_opening_scope_resolution_op ()); -} - -void -ASTTypeBuilder::visit (QualifiedPathInType &path) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (ArrayType &type) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (ReferenceType &type) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (RawPointerType &type) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (SliceType &type) -{ - Type *t = ASTTypeBuilder::build (type.get_elem_type ()); - std::unique_ptr<Type> ty (t); - translated = new SliceType (std::move (ty), type.get_locus ()); -} - -void -ASTTypeBuilder::visit (InferredType &type) -{ - translated = new InferredType (type.get_locus ()); -} - -void -ASTTypeBuilder::visit (NeverType &type) -{ - translated = new NeverType (type.get_locus ()); -} - -void -ASTTypeBuilder::visit (TraitObjectTypeOneBound &type) -{ - /* TODO */ -} - -void -ASTTypeBuilder::visit (TraitObjectType &type) -{ - /* TODO */ -} - -} // namespace AST -} // namespace Rust diff --git a/gcc/rust/ast/rust-ast-builder-type.h b/gcc/rust/ast/rust-ast-builder-type.h deleted file mode 100644 index b67ae3b..0000000 --- a/gcc/rust/ast/rust-ast-builder-type.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 2020-2024 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#ifndef RUST_AST_BUILDER_TYPE -#define RUST_AST_BUILDER_TYPE - -#include "rust-ast-visitor.h" - -namespace Rust { -namespace AST { - -class ASTTypeBuilder : public DefaultASTVisitor -{ -protected: - using DefaultASTVisitor::visit; - -public: - static Type *build (Type &type); - - void visit (BareFunctionType &fntype) override; - void visit (TupleType &tuple) override; - void visit (TypePath &path) override; - void visit (QualifiedPathInType &path) override; - void visit (ArrayType &type) override; - void visit (ReferenceType &type) override; - void visit (RawPointerType &type) override; - void visit (SliceType &type) override; - void visit (InferredType &type) override; - void visit (NeverType &type) override; - void visit (TraitObjectTypeOneBound &type) override; - void visit (TraitObjectType &type) override; - -private: - ASTTypeBuilder (); - - Type *translated; -}; - -} // namespace AST -} // namespace Rust - -#endif // RUST_AST_BUILDER_TYPE diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 08c52b1..ed10ce7 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -18,7 +18,6 @@ #include "rust-ast-builder.h" #include "optional.h" -#include "rust-ast-builder-type.h" #include "rust-ast.h" #include "rust-common.h" #include "rust-expr.h" @@ -29,7 +28,6 @@ #include "rust-pattern.h" #include "rust-system.h" #include "rust-token.h" -#include <memory> namespace Rust { namespace AST { @@ -332,6 +330,12 @@ Builder::block () const } std::unique_ptr<BlockExpr> +Builder::block (std::unique_ptr<Expr> &&tail_expr) const +{ + return block (tl::nullopt, std::move (tail_expr)); +} + +std::unique_ptr<BlockExpr> Builder::block (std::vector<std::unique_ptr<Stmt>> &&stmts, std::unique_ptr<Expr> &&tail_expr) const { @@ -442,6 +446,14 @@ Builder::field_access (std::unique_ptr<Expr> &&instance, new FieldAccessExpr (std::move (instance), field, {}, loc)); } +std::unique_ptr<StructPatternField> +Builder::struct_pattern_ident_pattern (std::string field_name, + std::unique_ptr<Pattern> &&pattern) +{ + return std::make_unique<StructPatternFieldIdentPat> ( + field_name, std::move (pattern), std::vector<Attribute> (), loc); +} + std::unique_ptr<Pattern> Builder::wildcard () const { @@ -482,9 +494,14 @@ MatchCase Builder::match_case (std::unique_ptr<Pattern> &&pattern, std::unique_ptr<Expr> &&expr) { - return MatchCase (match_arm (std::move (pattern)), std::move (expr)); + return match_case (match_arm (std::move (pattern)), std::move (expr)); } +MatchCase +Builder::match_case (MatchArm &&arm, std::unique_ptr<Expr> &&expr) +{ + return MatchCase (std::move (arm), std::move (expr)); +} std::unique_ptr<Expr> Builder::loop (std::vector<std::unique_ptr<Stmt>> &&stmts) { @@ -523,11 +540,14 @@ Builder::generic_type_param ( std::vector<Attribute> ()); } -std::unique_ptr<Type> -Builder::new_type (Type &type) +std::unique_ptr<Stmt> +Builder::discriminant_value (std::string binding_name, std::string instance) { - Type *t = ASTTypeBuilder::build (type); - return std::unique_ptr<Type> (t); + auto intrinsic = ptrify ( + path_in_expression ({"core", "intrinsics", "discriminant_value"}, true)); + + return let (identifier_pattern (binding_name), nullptr, + call (std::move (intrinsic), identifier (instance))); } std::unique_ptr<GenericParam> @@ -547,6 +567,16 @@ Builder::new_lifetime_param (LifetimeParam ¶m) } std::unique_ptr<GenericParam> +Builder::new_const_param (ConstGenericParam ¶m) const +{ + return std::make_unique<ConstGenericParam> (param.get_name (), + param.get_type ().clone_type (), + param.get_default_value (), + param.get_outer_attrs (), + param.get_locus ()); +} + +std::unique_ptr<GenericParam> Builder::new_type_param ( TypeParam ¶m, std::vector<std::unique_ptr<TypeParamBound>> extra_bounds) { @@ -557,7 +587,7 @@ Builder::new_type_param ( std::unique_ptr<Type> type = nullptr; if (param.has_type ()) - type = new_type (param.get_type ()); + type = param.get_type ().reconstruct (); for (auto &&extra_bound : extra_bounds) type_param_bounds.emplace_back (std::move (extra_bound)); @@ -566,7 +596,8 @@ Builder::new_type_param ( { switch (b->get_bound_type ()) { - case TypeParamBound::TypeParamBoundType::TRAIT: { + case TypeParamBound::TypeParamBoundType::TRAIT: + { const TraitBound &tb = (const TraitBound &) *b.get (); const TypePath &path = tb.get_type_path (); @@ -591,7 +622,8 @@ Builder::new_type_param ( { switch (seg->get_type ()) { - case TypePathSegment::REG: { + case TypePathSegment::REG: + { const TypePathSegment &segment = (const TypePathSegment &) (*seg.get ()); TypePathSegment *s = new TypePathSegment ( @@ -603,7 +635,8 @@ Builder::new_type_param ( } break; - case TypePathSegment::GENERIC: { + case TypePathSegment::GENERIC: + { TypePathSegmentGeneric &generic = (TypePathSegmentGeneric &) (*seg.get ()); @@ -617,7 +650,8 @@ Builder::new_type_param ( } break; - case TypePathSegment::FUNCTION: { + case TypePathSegment::FUNCTION: + { rust_unreachable (); // TODO // const TypePathSegmentFunction &fn @@ -639,7 +673,8 @@ Builder::new_type_param ( } break; - case TypeParamBound::TypeParamBoundType::LIFETIME: { + case TypeParamBound::TypeParamBoundType::LIFETIME: + { const Lifetime &l = (const Lifetime &) *b.get (); auto bl = new Lifetime (l.get_lifetime_type (), @@ -682,7 +717,7 @@ Builder::new_generic_args (GenericArgs &args) for (auto &binding : args.get_binding_args ()) { Type &t = *binding.get_type_ptr ().get (); - std::unique_ptr<Type> ty = new_type (t); + std::unique_ptr<Type> ty = t.reconstruct (); GenericArgsBinding b (binding.get_identifier (), std::move (ty), binding.get_locus ()); binding_args.push_back (std::move (b)); @@ -690,19 +725,25 @@ Builder::new_generic_args (GenericArgs &args) for (auto &arg : args.get_generic_args ()) { + tl::optional<GenericArg> new_arg = tl::nullopt; + switch (arg.get_kind ()) { - case GenericArg::Kind::Type: { - std::unique_ptr<Type> ty = new_type (arg.get_type ()); - GenericArg arg = GenericArg::create_type (std::move (ty)); - } + case GenericArg::Kind::Type: + new_arg = GenericArg::create_type (arg.get_type ().reconstruct ()); break; - - default: - // FIXME - rust_unreachable (); + case GenericArg::Kind::Either: + new_arg + = GenericArg::create_ambiguous (arg.get_path (), arg.get_locus ()); + break; + case GenericArg::Kind::Const: + new_arg + = GenericArg::create_const (arg.get_expression ().clone_expr ()); + // FIXME: Use `reconstruct()` here, not `clone_expr()` break; } + + generic_args.emplace_back (*new_arg); } return GenericArgs (std::move (lifetime_args), std::move (generic_args), diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index 41ce118..843bab8 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -24,6 +24,7 @@ #include "rust-ast.h" #include "rust-item.h" #include "rust-operators.h" +#include <initializer_list> namespace Rust { namespace AST { @@ -51,6 +52,19 @@ vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2) return v; } +template <typename T> +std::vector<std::unique_ptr<T>> +vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2, std::unique_ptr<T> &&t3) +{ + auto v = std::vector<std::unique_ptr<T>> (); + + v.emplace_back (std::move (t1)); + v.emplace_back (std::move (t2)); + v.emplace_back (std::move (t3)); + + return v; +} + /* Pointer-ify something */ template <typename T> static std::unique_ptr<T> @@ -117,6 +131,9 @@ public: /* Create an empty block */ std::unique_ptr<BlockExpr> block () const; + /* Create a block with just a tail expression */ + std::unique_ptr<BlockExpr> block (std::unique_ptr<Expr> &&tail_expr) const; + /* Create an early return expression with an optional expression */ std::unique_ptr<Expr> return_expr (std::unique_ptr<Expr> &&to_return = nullptr); @@ -254,6 +271,10 @@ public: std::unique_ptr<Expr> field_access (std::unique_ptr<Expr> &&instance, std::string field) const; + std::unique_ptr<StructPatternField> + struct_pattern_ident_pattern (std::string field_name, + std::unique_ptr<Pattern> &&pattern); + /* Create a wildcard pattern (`_`) */ std::unique_ptr<Pattern> wildcard () const; /* Create a reference pattern (`&pattern`) */ @@ -268,6 +289,7 @@ public: MatchArm match_arm (std::unique_ptr<Pattern> &&pattern); MatchCase match_case (std::unique_ptr<Pattern> &&pattern, std::unique_ptr<Expr> &&expr); + MatchCase match_case (MatchArm &&arm, std::unique_ptr<Expr> &&expr); /* Create a loop expression */ std::unique_ptr<Expr> loop (std::vector<std::unique_ptr<Stmt>> &&stmts); @@ -285,11 +307,20 @@ public: std::vector<std::unique_ptr<TypeParamBound>> &&bounds, std::unique_ptr<Type> &&type = nullptr); - static std::unique_ptr<Type> new_type (Type &type); + /** + * Create a let statement with the discriminant value of a given enum + * instance. This helper exists since it is a common operation in a lot of the + * derive implementations, and it sucks to repeat all the steps every time. + */ + std::unique_ptr<Stmt> discriminant_value (std::string binding_name, + std::string instance = "self"); static std::unique_ptr<GenericParam> new_lifetime_param (LifetimeParam ¶m); + std::unique_ptr<GenericParam> + new_const_param (ConstGenericParam ¶m) const; + static std::unique_ptr<GenericParam> new_type_param ( TypeParam ¶m, std::vector<std::unique_ptr<TypeParamBound>> extra_trait_bounds = {}); @@ -298,11 +329,13 @@ public: static GenericArgs new_generic_args (GenericArgs &args); -private: - /** - * Location of the generated AST nodes - */ + /* Location of the generated AST nodes */ location_t loc; + +private: + /* Some constexpr helpers for some of the builders */ + static constexpr std::initializer_list<const char *> discriminant_value_path + = {"core", "intrinsics", "discriminant_value"}; }; } // namespace AST diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index c850e96..3d9ea78 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -18,6 +18,7 @@ #include "rust-ast-collector.h" #include "rust-ast.h" +#include "rust-builtin-ast-nodes.h" #include "rust-diagnostics.h" #include "rust-expr.h" #include "rust-item.h" @@ -154,20 +155,24 @@ TokenCollector::visit (Attribute &attrib) { switch (attrib.get_attr_input ().get_attr_input_type ()) { - case AST::AttrInput::AttrInputType::LITERAL: { + case AST::AttrInput::AttrInputType::LITERAL: + { visit (static_cast<AttrInputLiteral &> (attrib.get_attr_input ())); break; } - case AST::AttrInput::AttrInputType::MACRO: { + case AST::AttrInput::AttrInputType::MACRO: + { visit (static_cast<AttrInputMacro &> (attrib.get_attr_input ())); break; } - case AST::AttrInput::AttrInputType::META_ITEM: { + case AST::AttrInput::AttrInputType::META_ITEM: + { visit (static_cast<AttrInputMetaItemContainer &> ( attrib.get_attr_input ())); break; } - case AST::AttrInput::AttrInputType::TOKEN_TREE: { + case AST::AttrInput::AttrInputType::TOKEN_TREE: + { visit (static_cast<DelimTokenTree &> (attrib.get_attr_input ())); break; } @@ -634,7 +639,8 @@ TokenCollector::visit (GenericArg &arg) case GenericArg::Kind::Type: visit (arg.get_type ()); break; - case GenericArg::Kind::Either: { + case GenericArg::Kind::Either: + { auto path = arg.get_path (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path))); } @@ -789,7 +795,8 @@ TokenCollector::visit (Literal &lit, location_t locus) push (Rust::Token::make_float (locus, std::move (value), lit.get_type_hint ())); break; - case Literal::LitType::BOOL: { + case Literal::LitType::BOOL: + { if (value == Values::Keywords::FALSE_LITERAL) push (Rust::Token::make (FALSE_LITERAL, locus)); else if (value == Values::Keywords::TRUE_LITERAL) @@ -833,13 +840,13 @@ TokenCollector::visit (MetaItemLitExpr &item) } void -TokenCollector::visit (MetaItemPathLit &item) +TokenCollector::visit (MetaItemPathExpr &item) { - auto path = item.get_path (); - auto lit = item.get_literal (); + auto &path = item.get_path (); + auto &expr = item.get_expr (); visit (path); - push (Rust::Token::make (COLON, item.get_locus ())); - visit (lit); + push (Rust::Token::make (EQUAL, item.get_locus ())); + visit (expr); } void @@ -864,7 +871,8 @@ TokenCollector::visit (BorrowExpr &expr) push (Rust::Token::make (MUT, UNDEF_LOCATION)); } - visit (expr.get_borrowed_expr ()); + if (expr.has_borrow_expr ()) + visit (expr.get_borrowed_expr ()); } void @@ -1264,12 +1272,34 @@ TokenCollector::visit (BlockExpr &expr) } void +TokenCollector::visit (AnonConst &expr) +{ + if (!expr.is_deferred ()) + { + visit (expr.get_inner_expr ()); + return; + } + + push (Rust::Token::make_string (expr.get_locus (), "_")); +} + +void +TokenCollector::visit (ConstBlock &expr) +{ + push (Rust::Token::make (CONST, expr.get_locus ())); + + // The inner expression is already a block expr, so we don't need to add + // curlies + visit (expr.get_const_expr ()); +} + +void TokenCollector::visit (ClosureExprInnerTyped &expr) { visit_closure_common (expr); push (Rust::Token::make (RETURN_TYPE, expr.get_locus ())); visit (expr.get_return_type ()); - visit (expr.get_definition_block ()); + visit (expr.get_definition_expr ()); } void @@ -1349,6 +1379,13 @@ TokenCollector::visit (ReturnExpr &expr) } void +TokenCollector::visit (TryExpr &expr) +{ + push (Rust::Token::make (TRY, expr.get_locus ())); + visit (expr.get_block_expr ()); +} + +void TokenCollector::visit (UnsafeBlockExpr &expr) { push (Rust::Token::make (UNSAFE, expr.get_locus ())); @@ -1518,7 +1555,95 @@ TokenCollector::visit (AsyncBlockExpr &expr) void TokenCollector::visit (InlineAsm &expr) -{} +{ + push (Rust::Token::make_identifier (expr.get_locus (), "asm")); + push (Rust::Token::make (EXCLAM, expr.get_locus ())); + push (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); + + for (auto &template_str : expr.get_template_strs ()) + push (Rust::Token::make_string (template_str.get_locus (), + std::move (template_str.symbol))); + + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &operand : expr.get_operands ()) + { + using RegisterType = AST::InlineAsmOperand::RegisterType; + switch (operand.get_register_type ()) + { + case RegisterType::In: + { + visit (operand.get_in ().expr); + break; + } + case RegisterType::Out: + { + visit (operand.get_out ().expr); + break; + } + case RegisterType::InOut: + { + visit (operand.get_in_out ().expr); + break; + } + case RegisterType::SplitInOut: + { + auto split = operand.get_split_in_out (); + visit (split.in_expr); + visit (split.out_expr); + break; + } + case RegisterType::Const: + { + visit (operand.get_const ().anon_const.get_inner_expr ()); + break; + } + case RegisterType::Sym: + { + visit (operand.get_sym ().expr); + break; + } + case RegisterType::Label: + { + visit (operand.get_label ().expr); + break; + } + } + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &clobber : expr.get_clobber_abi ()) + { + push (Rust::Token::make_string (expr.get_locus (), + std::move (clobber.symbol))); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto it = expr.named_args.begin (); it != expr.named_args.end (); ++it) + { + auto &arg = *it; + push ( + Rust::Token::make_identifier (expr.get_locus (), arg.first.c_str ())); + push (Rust::Token::make (EQUAL, expr.get_locus ())); + push (Rust::Token::make_identifier (expr.get_locus (), + std::to_string (arg.second))); + + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &option : expr.get_options ()) + { + push (Rust::Token::make_identifier ( + expr.get_locus (), InlineAsm::option_to_string (option).c_str ())); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ())); +} void TokenCollector::visit (LlvmInlineAsm &expr) @@ -1695,7 +1820,8 @@ TokenCollector::visit (UseTreeGlob &use_tree) { switch (use_tree.get_glob_type ()) { - case UseTreeGlob::PathType::PATH_PREFIXED: { + case UseTreeGlob::PathType::PATH_PREFIXED: + { auto path = use_tree.get_path (); visit (path); push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); @@ -1715,7 +1841,8 @@ TokenCollector::visit (UseTreeList &use_tree) { switch (use_tree.get_path_type ()) { - case UseTreeList::PathType::PATH_PREFIXED: { + case UseTreeList::PathType::PATH_PREFIXED: + { auto path = use_tree.get_path (); visit (path); push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); @@ -1743,7 +1870,8 @@ TokenCollector::visit (UseTreeRebind &use_tree) visit (path); switch (use_tree.get_new_bind_type ()) { - case UseTreeRebind::NewBindType::IDENTIFIER: { + case UseTreeRebind::NewBindType::IDENTIFIER: + { push (Rust::Token::make (AS, UNDEF_LOCATION)); auto id = use_tree.get_identifier ().as_string (); push ( @@ -1964,8 +2092,7 @@ TokenCollector::visit (ConstantItem &item) } else { - auto id = item.get_identifier (); - push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); + push (Rust::Token::make_identifier (item.get_identifier ())); } push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (item.get_type ()); @@ -2370,10 +2497,10 @@ TokenCollector::visit (IdentifierPattern &pattern) auto id = pattern.get_ident ().as_string (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); - if (pattern.has_pattern_to_bind ()) + if (pattern.has_subpattern ()) { push (Rust::Token::make (PATTERN_BIND, UNDEF_LOCATION)); - visit (pattern.get_pattern_to_bind ()); + visit (pattern.get_subpattern ()); } } @@ -2591,10 +2718,34 @@ TokenCollector::visit (GroupedPattern &pattern) } void +TokenCollector::visit (SlicePatternItemsNoRest &items) +{ + visit_items_joined_by_separator (items.get_patterns (), COMMA); +} + +void +TokenCollector::visit (SlicePatternItemsHasRest &items) +{ + if (!items.get_lower_patterns ().empty ()) + { + visit_items_joined_by_separator (items.get_lower_patterns (), COMMA); + push (Rust::Token::make (COMMA, UNDEF_LOCATION)); + } + + push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION)); + + if (!items.get_upper_patterns ().empty ()) + { + push (Rust::Token::make (COMMA, UNDEF_LOCATION)); + visit_items_joined_by_separator (items.get_upper_patterns (), COMMA); + } +} + +void TokenCollector::visit (SlicePattern &pattern) { push (Rust::Token::make (LEFT_SQUARE, pattern.get_locus ())); - visit_items_joined_by_separator (pattern.get_items (), COMMA); + visit (pattern.get_items ()); push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION)); } @@ -2862,5 +3013,23 @@ TokenCollector::visit (AST::FormatArgs &fmt) __FILE__, __LINE__); } +void +TokenCollector::visit (AST::OffsetOf &offset_of) +{ + auto loc = offset_of.get_locus (); + + push (Rust::Token::make_identifier (loc, "offset_of")); + push (Rust::Token::make (EXCLAM, loc)); + push (Rust::Token::make (LEFT_PAREN, loc)); + + visit (offset_of.get_type ()); + + push (Rust::Token::make (COMMA, loc)); + + push (Rust::Token::make_identifier (offset_of.get_field ())); + + push (Rust::Token::make (RIGHT_PAREN, loc)); +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index f45e3cc..d3ab18a 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -246,7 +246,7 @@ public: void visit (AttrInputLiteral &attr_input); void visit (AttrInputMacro &attr_input); void visit (MetaItemLitExpr &meta_item); - void visit (MetaItemPathLit &meta_item); + void visit (MetaItemPathExpr &meta_item); void visit (BorrowExpr &expr); void visit (DereferenceExpr &expr); void visit (ErrorPropagationExpr &expr); @@ -277,6 +277,8 @@ public: void visit (ClosureParam ¶m); void visit (ClosureExprInner &expr); void visit (BlockExpr &expr); + void visit (AnonConst &expr); + void visit (ConstBlock &expr); void visit (ClosureExprInnerTyped &expr); void visit (ContinueExpr &expr); void visit (BreakExpr &expr); @@ -287,6 +289,7 @@ public: void visit (RangeFromToInclExpr &expr); void visit (RangeToInclExpr &expr); void visit (ReturnExpr &expr); + void visit (TryExpr &expr); void visit (BoxExpr &expr); void visit (UnsafeBlockExpr &expr); void visit (LoopExpr &expr); @@ -375,6 +378,8 @@ public: void visit (TuplePatternItemsRanged &tuple_items); void visit (TuplePattern &pattern); void visit (GroupedPattern &pattern); + void visit (SlicePatternItemsNoRest &items); + void visit (SlicePatternItemsHasRest &items); void visit (SlicePattern &pattern); void visit (AltPattern &pattern); @@ -400,6 +405,7 @@ public: void visit (BareFunctionType &type); void visit (FormatArgs &fmt); + void visit (OffsetOf &offset_of); }; } // namespace AST diff --git a/gcc/rust/ast/rust-ast-dump.h b/gcc/rust/ast/rust-ast-dump.h index 02c99b7..0c3875e 100644 --- a/gcc/rust/ast/rust-ast-dump.h +++ b/gcc/rust/ast/rust-ast-dump.h @@ -49,7 +49,8 @@ public: { switch (item.get_kind ()) { - case AST::CollectItem::Kind::Token: { + case AST::CollectItem::Kind::Token: + { TokenPtr current = item.get_token (); if (require_spacing (previous, current)) stream << " "; @@ -90,7 +91,6 @@ private: } // namespace Rust // In the global namespace to make it easier to call from debugger -void -debug (Rust::AST::Visitable &v); +void debug (Rust::AST::Visitable &v); #endif // !RUST_AST_DUMP_H diff --git a/gcc/rust/ast/rust-ast-formatting.h b/gcc/rust/ast/rust-ast-formatting.h index 3dfabbc..aace93f 100644 --- a/gcc/rust/ast/rust-ast-formatting.h +++ b/gcc/rust/ast/rust-ast-formatting.h @@ -35,23 +35,18 @@ enum AttrMode INNER }; -std::string -indent_spaces (enum indent_mode mode); +std::string indent_spaces (enum indent_mode mode); // Gets a string in a certain delim type. -std::string -get_string_in_delims (std::string str_input, DelimType delim_type); +std::string get_string_in_delims (std::string str_input, DelimType delim_type); -std::string -get_mode_dump_desc (AttrMode mode); +std::string get_mode_dump_desc (AttrMode mode); // Adds lines below adding attributes -std::string -append_attributes (std::vector<Attribute> attrs, AttrMode mode); +std::string append_attributes (std::vector<Attribute> attrs, AttrMode mode); // Removes the beginning and end quotes of a quoted string. -std::string -unquote_string (std::string input); +std::string unquote_string (std::string input); } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index 9359248..09706ce 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -78,7 +78,7 @@ class LiteralExpr; class AttrInputLiteral; class AttrInputMacro; class MetaItemLitExpr; -class MetaItemPathLit; +class MetaItemPathExpr; class OperatorExpr; class BorrowExpr; class DereferenceExpr; @@ -115,6 +115,8 @@ struct ClosureParam; class ClosureExpr; class ClosureExprInner; class BlockExpr; +class AnonConst; +class ConstBlock; class ClosureExprInnerTyped; class ContinueExpr; class BreakExpr; @@ -126,6 +128,7 @@ class RangeFullExpr; class RangeFromToInclExpr; class RangeToInclExpr; class ReturnExpr; +class TryExpr; class UnsafeBlockExpr; class LoopLabel; class BaseLoopExpr; @@ -146,7 +149,6 @@ class MatchExpr; class AwaitExpr; class AsyncBlockExpr; enum class InlineAsmOption; -struct AnonConst; struct InlineAsmRegOrRegClass; class InlineAsmOperand; struct InlineAsmPlaceHolder; @@ -246,6 +248,8 @@ class TuplePatternItemsMultiple; class TuplePatternItemsRanged; class TuplePattern; class GroupedPattern; +class SlicePatternItemsNoRest; +class SlicePatternItemsHasRest; class SlicePattern; class AltPattern; diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index b6833f6..ab8cdbe 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -19,6 +19,7 @@ #include "rust-ast-visitor.h" #include "rust-ast-full-decls.h" #include "rust-ast.h" +#include "rust-builtin-ast-nodes.h" #include "rust-path.h" #include "rust-token.h" #include "rust-expr.h" @@ -223,10 +224,10 @@ DefaultASTVisitor::visit (AST::SimplePath &path) } void -DefaultASTVisitor::visit (AST::MetaItemPathLit &meta_item) +DefaultASTVisitor::visit (AST::MetaItemPathExpr &meta_item) { visit (meta_item.get_path ()); - visit (meta_item.get_literal ()); + visit (meta_item.get_expr ()); } void @@ -449,20 +450,38 @@ DefaultASTVisitor::visit (AST::BlockExpr &expr) { visit_outer_attrs (expr); visit_inner_attrs (expr); + + if (expr.has_label ()) + visit (expr.get_label ()); + for (auto &stmt : expr.get_statements ()) visit (stmt); + if (expr.has_tail_expr ()) visit (expr.get_tail_expr ()); } void +DefaultASTVisitor::visit (AST::ConstBlock &expr) +{ + visit (expr.get_const_expr ()); +} + +void +DefaultASTVisitor::visit (AST::AnonConst &expr) +{ + if (!expr.is_deferred ()) + visit (expr.get_inner_expr ()); +} + +void DefaultASTVisitor::visit (AST::ClosureExprInnerTyped &expr) { visit_outer_attrs (expr); for (auto ¶m : expr.get_params ()) visit (param); visit (expr.get_return_type ()); - visit (expr.get_definition_block ()); + visit (expr.get_definition_expr ()); } void @@ -538,6 +557,13 @@ DefaultASTVisitor::visit (AST::ReturnExpr &expr) } void +DefaultASTVisitor::visit (AST::TryExpr &expr) +{ + visit_outer_attrs (expr); + visit (expr.get_block_expr ()); +} + +void DefaultASTVisitor::visit (AST::BoxExpr &expr) { visit_outer_attrs (expr); @@ -582,7 +608,10 @@ DefaultASTVisitor::visit (AST::WhileLetLoopExpr &expr) visit_outer_attrs (expr); for (auto &pattern : expr.get_patterns ()) visit (pattern); - visit (expr.get_loop_label ()); + + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + visit (expr.get_scrutinee_expr ()); visit (expr.get_loop_block ()); } @@ -680,33 +709,40 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr) { switch (operand.get_register_type ()) { - case RegisterType::In: { + case RegisterType::In: + { visit (operand.get_in ().expr); break; } - case RegisterType::Out: { + case RegisterType::Out: + { visit (operand.get_out ().expr); break; } - case RegisterType::InOut: { + case RegisterType::InOut: + { visit (operand.get_in_out ().expr); break; } - case RegisterType::SplitInOut: { + case RegisterType::SplitInOut: + { auto split = operand.get_split_in_out (); visit (split.in_expr); visit (split.out_expr); break; } - case RegisterType::Const: { - visit (operand.get_const ().anon_const.expr); + case RegisterType::Const: + { + visit (operand.get_const ().anon_const.get_inner_expr ()); break; } - case RegisterType::Sym: { + case RegisterType::Sym: + { visit (operand.get_sym ().expr); break; } - case RegisterType::Label: { + case RegisterType::Label: + { visit (operand.get_label ().expr); break; } @@ -755,7 +791,8 @@ DefaultASTVisitor::visit (AST::TypeBoundWhereClauseItem &item) void DefaultASTVisitor::visit (AST::Visibility &vis) { - visit (vis.get_path ()); + if (vis.has_path ()) + visit (vis.get_path ()); } void @@ -922,7 +959,7 @@ DefaultASTVisitor::visit (AST::EnumItem &item) void DefaultASTVisitor::visit (AST::EnumItemTuple &item) { - visit (reinterpret_cast<EnumItem &> (item)); + DefaultASTVisitor::visit (static_cast<EnumItem &> (item)); for (auto &field : item.get_tuple_fields ()) visit (field); } @@ -930,7 +967,7 @@ DefaultASTVisitor::visit (AST::EnumItemTuple &item) void DefaultASTVisitor::visit (AST::EnumItemStruct &item) { - visit (reinterpret_cast<EnumItem &> (item)); + DefaultASTVisitor::visit (static_cast<EnumItem &> (item)); for (auto &field : item.get_struct_fields ()) visit (field); } @@ -938,7 +975,7 @@ DefaultASTVisitor::visit (AST::EnumItemStruct &item) void DefaultASTVisitor::visit (AST::EnumItemDiscriminant &item) { - visit (reinterpret_cast<EnumItem &> (item)); + DefaultASTVisitor::visit (static_cast<EnumItem &> (item)); visit (item.get_expr ()); } @@ -1179,8 +1216,8 @@ DefaultASTVisitor::visit (AST::LiteralPattern &pattern) void DefaultASTVisitor::visit (AST::IdentifierPattern &pattern) { - if (pattern.has_pattern_to_bind ()) - visit (pattern.get_pattern_to_bind ()); + if (pattern.has_subpattern ()) + visit (pattern.get_subpattern ()); } void @@ -1310,13 +1347,28 @@ DefaultASTVisitor::visit (AST::GroupedPattern &pattern) } void -DefaultASTVisitor::visit (AST::SlicePattern &pattern) +DefaultASTVisitor::visit (AST::SlicePatternItemsNoRest &items) +{ + for (auto &item : items.get_patterns ()) + visit (item); +} + +void +DefaultASTVisitor::visit (AST::SlicePatternItemsHasRest &items) { - for (auto &item : pattern.get_items ()) + for (auto &item : items.get_lower_patterns ()) + visit (item); + for (auto &item : items.get_upper_patterns ()) visit (item); } void +DefaultASTVisitor::visit (AST::SlicePattern &pattern) +{ + visit (pattern.get_items ()); +} + +void DefaultASTVisitor::visit (AST::AltPattern &pattern) { for (auto &alt : pattern.get_alts ()) @@ -1454,6 +1506,12 @@ DefaultASTVisitor::visit (AST::FormatArgs &) } void +DefaultASTVisitor::visit (AST::OffsetOf &offset_of) +{ + visit (offset_of.get_type ()); +} + +void DefaultASTVisitor::visit (AST::VariadicParam ¶m) { if (param.has_pattern ()) diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index b1fc504..2d81aa1 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -73,7 +73,7 @@ public: virtual void visit (AttrInputLiteral &attr_input) = 0; virtual void visit (AttrInputMacro &attr_input) = 0; virtual void visit (MetaItemLitExpr &meta_item) = 0; - virtual void visit (MetaItemPathLit &meta_item) = 0; + virtual void visit (MetaItemPathExpr &meta_item) = 0; virtual void visit (BorrowExpr &expr) = 0; virtual void visit (DereferenceExpr &expr) = 0; virtual void visit (ErrorPropagationExpr &expr) = 0; @@ -104,6 +104,8 @@ public: virtual void visit (FieldAccessExpr &expr) = 0; virtual void visit (ClosureExprInner &expr) = 0; virtual void visit (BlockExpr &expr) = 0; + virtual void visit (AnonConst &expr) = 0; + virtual void visit (ConstBlock &expr) = 0; virtual void visit (ClosureExprInnerTyped &expr) = 0; virtual void visit (ContinueExpr &expr) = 0; virtual void visit (BreakExpr &expr) = 0; @@ -114,6 +116,7 @@ public: virtual void visit (RangeFromToInclExpr &expr) = 0; virtual void visit (RangeToInclExpr &expr) = 0; virtual void visit (ReturnExpr &expr) = 0; + virtual void visit (TryExpr &expr) = 0; virtual void visit (BoxExpr &expr) = 0; virtual void visit (UnsafeBlockExpr &expr) = 0; virtual void visit (LoopExpr &expr) = 0; @@ -209,6 +212,8 @@ public: virtual void visit (TuplePatternItemsRanged &tuple_items) = 0; virtual void visit (TuplePattern &pattern) = 0; virtual void visit (GroupedPattern &pattern) = 0; + virtual void visit (SlicePatternItemsNoRest &items) = 0; + virtual void visit (SlicePatternItemsHasRest &items) = 0; virtual void visit (SlicePattern &pattern) = 0; virtual void visit (AltPattern &pattern) = 0; @@ -235,6 +240,7 @@ public: // special AST nodes for certain builtin macros such as `asm!()` virtual void visit (FormatArgs &fmt) = 0; + virtual void visit (OffsetOf &fmt) = 0; // TODO: rust-cond-compilation.h visiting? not currently used }; @@ -264,7 +270,7 @@ public: virtual void visit (AST::AttrInputLiteral &attr_input) override; virtual void visit (AST::AttrInputMacro &attr_input) override; virtual void visit (AST::MetaItemLitExpr &meta_item) override; - virtual void visit (AST::MetaItemPathLit &meta_item) override; + virtual void visit (AST::MetaItemPathExpr &meta_item) override; virtual void visit (AST::BorrowExpr &expr) override; virtual void visit (AST::DereferenceExpr &expr) override; virtual void visit (AST::ErrorPropagationExpr &expr) override; @@ -293,6 +299,8 @@ public: virtual void visit (AST::FieldAccessExpr &expr) override; virtual void visit (AST::ClosureExprInner &expr) override; virtual void visit (AST::BlockExpr &expr) override; + virtual void visit (AST::AnonConst &expr) override; + virtual void visit (AST::ConstBlock &expr) override; virtual void visit (AST::ClosureExprInnerTyped &expr) override; virtual void visit (AST::ContinueExpr &expr) override; virtual void visit (AST::BreakExpr &expr) override; @@ -303,6 +311,7 @@ public: virtual void visit (AST::RangeFromToInclExpr &expr) override; virtual void visit (AST::RangeToInclExpr &expr) override; virtual void visit (AST::ReturnExpr &expr) override; + virtual void visit (AST::TryExpr &expr) override; virtual void visit (AST::BoxExpr &expr) override; virtual void visit (AST::UnsafeBlockExpr &expr) override; virtual void visit (AST::LoopExpr &expr) override; @@ -379,6 +388,8 @@ public: virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override; virtual void visit (AST::TuplePattern &pattern) override; virtual void visit (AST::GroupedPattern &pattern) override; + virtual void visit (AST::SlicePatternItemsNoRest &items) override; + virtual void visit (AST::SlicePatternItemsHasRest &items) override; virtual void visit (AST::SlicePattern &pattern) override; virtual void visit (AST::AltPattern &pattern) override; virtual void visit (AST::EmptyStmt &stmt) override; @@ -402,6 +413,7 @@ public: virtual void visit (AST::FunctionParam ¶m) override; virtual void visit (AST::VariadicParam ¶m) override; virtual void visit (AST::FormatArgs &fmt) override; + virtual void visit (AST::OffsetOf &fmt) override; template <typename T> void visit (T &node) { node.accept_vis (*this); } diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 4e82be4..8e856fb 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "rust-operators.h" #include "rust-dir-owner.h" #include "rust-attribute-values.h" +#include "rust-macro-invoc-lexer.h" /* Compilation unit used for various AST-related functions that would make * the headers too long if they were defined inline and don't receive any @@ -249,27 +250,31 @@ Attribute::get_traits_to_derive () auto &input = get_attr_input (); switch (input.get_attr_input_type ()) { - case AST::AttrInput::META_ITEM: { + case AST::AttrInput::META_ITEM: + { auto &meta = static_cast<AST::AttrInputMetaItemContainer &> (input); for (auto ¤t : meta.get_items ()) { // HACK: Find a better way to achieve the downcast. switch (current->get_kind ()) { - case AST::MetaItemInner::Kind::MetaItem: { + case AST::MetaItemInner::Kind::MetaItem: + { // Let raw pointer go out of scope without freeing, it doesn't // own the data anyway auto meta_item = static_cast<AST::MetaItem *> (current.get ()); switch (meta_item->get_item_kind ()) { - case AST::MetaItem::ItemKind::Path: { + case AST::MetaItem::ItemKind::Path: + { auto path = static_cast<AST::MetaItemPath *> (meta_item); result.push_back (path->get_path ()); } break; - case AST::MetaItem::ItemKind::Word: { + case AST::MetaItem::ItemKind::Word: + { auto word = static_cast<AST::MetaWord *> (meta_item); // Convert current word to path current = std::make_unique<AST::MetaItemPath> ( @@ -283,7 +288,7 @@ Attribute::get_traits_to_derive () break; case AST::MetaItem::ItemKind::ListPaths: case AST::MetaItem::ItemKind::NameValueStr: - case AST::MetaItem::ItemKind::PathLit: + case AST::MetaItem::ItemKind::PathExpr: case AST::MetaItem::ItemKind::Seq: case AST::MetaItem::ItemKind::ListNameValueStr: default: @@ -620,7 +625,7 @@ ConstantItem::as_string () const { std::string str = VisItem::as_string (); - str += "const " + identifier; + str += "const " + identifier.as_string (); // DEBUG: null pointer check if (type == nullptr) @@ -782,7 +787,8 @@ UseTreeGlob::as_string () const return "*"; case GLOBAL: return "::*"; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { std::string path_str = path.as_string (); return path_str + "::*"; } @@ -805,7 +811,8 @@ UseTreeList::as_string () const case GLOBAL: path_str = "::{"; break; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { path_str = path.as_string () + "::{"; break; } @@ -1272,6 +1279,25 @@ BlockExpr::as_string () const } std::string +AnonConst::as_string () const +{ + std::string str = "AnonConst: "; + + if (kind == AnonConst::Kind::DeferredInference) + str += "_"; + else + str += expr.value ()->as_string (); + + return str; +} + +std::string +ConstBlock::as_string () const +{ + return "ConstBlock: " + expr.as_string (); +} + +std::string TraitImpl::as_string () const { std::string str = VisItem::as_string (); @@ -1619,6 +1645,19 @@ ReturnExpr::as_string () const } std::string +TryExpr::as_string () const +{ + /* TODO: find way to incorporate outer attrs - may have to represent in + * different style (i.e. something more like BorrowExpr: \n outer attrs) */ + + std::string str ("try "); + + str += block_expr->as_string (); + + return str; +} + +std::string RangeToExpr::as_string () const { return ".." + to->as_string (); @@ -2714,7 +2753,7 @@ ImplTraitTypeOneBound::as_string () const { std::string str ("ImplTraitTypeOneBound: \n TraitBound: "); - return str + trait_bound.as_string (); + return str + trait_bound->as_string (); } std::string @@ -2736,7 +2775,7 @@ std::string ArrayType::as_string () const { // TODO: rewrite to work with non-linearisable types and exprs - return "[" + elem_type->as_string () + "; " + size->as_string () + "]"; + return "[" + elem_type->as_string () + "; " + size.as_string () + "]"; } std::string @@ -3477,13 +3516,24 @@ DelimTokenTree::parse_to_meta_item () const return new AttrInputMetaItemContainer (std::move (meta_items)); } +AttributeParser::AttributeParser ( + std::vector<std::unique_ptr<Token>> token_stream, int stream_start_pos) + : lexer (new MacroInvocLexer (std::move (token_stream))), + parser (new Parser<MacroInvocLexer> (*lexer)) +{ + if (stream_start_pos) + lexer->skip_token (stream_start_pos - 1); +} + +AttributeParser::~AttributeParser () {} + std::unique_ptr<MetaItemInner> AttributeParser::parse_meta_item_inner () { // if first tok not identifier, not a "special" case one - if (peek_token ()->get_id () != IDENTIFIER) + if (lexer->peek_token ()->get_id () != IDENTIFIER) { - switch (peek_token ()->get_id ()) + switch (lexer->peek_token ()->get_id ()) { case CHAR_LITERAL: case STRING_LITERAL: @@ -3504,48 +3554,46 @@ AttributeParser::parse_meta_item_inner () return parse_path_meta_item (); default: - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "unrecognised token '%s' in meta item", - get_token_description (peek_token ()->get_id ())); + get_token_description ( + lexer->peek_token ()->get_id ())); return nullptr; } } // else, check for path - if (peek_token (1)->get_id () == SCOPE_RESOLUTION) + if (lexer->peek_token (1)->get_id () == SCOPE_RESOLUTION) { // path return parse_path_meta_item (); } - auto ident = peek_token ()->as_string (); - auto ident_locus = peek_token ()->get_locus (); + auto ident = lexer->peek_token ()->get_str (); + auto ident_locus = lexer->peek_token ()->get_locus (); - if (is_end_meta_item_tok (peek_token (1)->get_id ())) + if (is_end_meta_item_tok (lexer->peek_token (1)->get_id ())) { // meta word syntax - skip_token (); + lexer->skip_token (); return std::unique_ptr<MetaWord> (new MetaWord (ident, ident_locus)); } - if (peek_token (1)->get_id () == EQUAL) + if (lexer->peek_token (1)->get_id () == EQUAL) { // maybe meta name value str syntax - check next 2 tokens - if (peek_token (2)->get_id () == STRING_LITERAL - && is_end_meta_item_tok (peek_token (3)->get_id ())) + if (lexer->peek_token (2)->get_id () == STRING_LITERAL + && is_end_meta_item_tok (lexer->peek_token (3)->get_id ())) { // meta name value str syntax - auto &value_tok = peek_token (2); - auto value = value_tok->as_string (); + const_TokenPtr value_tok = lexer->peek_token (2); + auto value = value_tok->get_str (); auto locus = value_tok->get_locus (); - skip_token (2); - - // remove the quotes from the string value - std::string raw_value = unquote_string (std::move (value)); + lexer->skip_token (2); return std::unique_ptr<MetaNameValueStr> ( - new MetaNameValueStr (ident, ident_locus, std::move (raw_value), + new MetaNameValueStr (ident, ident_locus, std::move (value), locus)); } else @@ -3555,16 +3603,16 @@ AttributeParser::parse_meta_item_inner () } } - if (peek_token (1)->get_id () != LEFT_PAREN) + if (lexer->peek_token (1)->get_id () != LEFT_PAREN) { - rust_error_at (peek_token (1)->get_locus (), + rust_error_at (lexer->peek_token (1)->get_locus (), "unexpected token '%s' after identifier in attribute", - get_token_description (peek_token (1)->get_id ())); + get_token_description (lexer->peek_token (1)->get_id ())); return nullptr; } // is it one of those special cases like not? - if (peek_token ()->get_id () == IDENTIFIER) + if (lexer->peek_token ()->get_id () == IDENTIFIER) { return parse_path_meta_item (); } @@ -3643,49 +3691,46 @@ AttributeParser::is_end_meta_item_tok (TokenId id) const std::unique_ptr<MetaItem> AttributeParser::parse_path_meta_item () { - SimplePath path = parse_simple_path (); + SimplePath path = parser->parse_simple_path (); if (path.is_empty ()) { - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "failed to parse simple path in attribute"); return nullptr; } - switch (peek_token ()->get_id ()) + switch (lexer->peek_token ()->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { std::vector<std::unique_ptr<MetaItemInner>> meta_items = parse_meta_item_seq (); return std::unique_ptr<MetaItemSeq> ( new MetaItemSeq (std::move (path), std::move (meta_items))); } - case EQUAL: { - skip_token (); + case EQUAL: + { + lexer->skip_token (); - location_t locus = peek_token ()->get_locus (); - Literal lit = parse_literal (); - if (lit.is_error ()) - { - rust_error_at (peek_token ()->get_locus (), - "failed to parse literal in attribute"); - return nullptr; - } - LiteralExpr expr (std::move (lit), {}, locus); - // stream_pos++; - /* shouldn't be required anymore due to parsing literal actually - * skipping the token */ - return std::unique_ptr<MetaItemPathLit> ( - new MetaItemPathLit (std::move (path), std::move (expr))); + std::unique_ptr<Expr> expr = parser->parse_expr (); + + // handle error + // parse_expr should already emit an error and return nullptr + if (!expr) + return nullptr; + + return std::unique_ptr<MetaItemPathExpr> ( + new MetaItemPathExpr (std::move (path), std::move (expr))); } case COMMA: // just simple path return std::unique_ptr<MetaItemPath> ( new MetaItemPath (std::move (path))); default: - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "unrecognised token '%s' in meta item", - get_token_description (peek_token ()->get_id ())); + get_token_description (lexer->peek_token ()->get_id ())); return nullptr; } } @@ -3695,41 +3740,41 @@ AttributeParser::parse_path_meta_item () std::vector<std::unique_ptr<MetaItemInner>> AttributeParser::parse_meta_item_seq () { - int vec_length = token_stream.size (); std::vector<std::unique_ptr<MetaItemInner>> meta_items; - if (peek_token ()->get_id () != LEFT_PAREN) + if (lexer->peek_token ()->get_id () != LEFT_PAREN) { - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "missing left paren in delim token tree"); return {}; } - skip_token (); + lexer->skip_token (); - while (stream_pos < vec_length && peek_token ()->get_id () != RIGHT_PAREN) + while (lexer->peek_token ()->get_id () != END_OF_FILE + && lexer->peek_token ()->get_id () != RIGHT_PAREN) { std::unique_ptr<MetaItemInner> inner = parse_meta_item_inner (); if (inner == nullptr) { - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "failed to parse inner meta item in attribute"); return {}; } meta_items.push_back (std::move (inner)); - if (peek_token ()->get_id () != COMMA) + if (lexer->peek_token ()->get_id () != COMMA) break; - skip_token (); + lexer->skip_token (); } - if (peek_token ()->get_id () != RIGHT_PAREN) + if (lexer->peek_token ()->get_id () != RIGHT_PAREN) { - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "missing right paren in delim token tree"); return {}; } - skip_token (); + lexer->skip_token (); return meta_items; } @@ -3752,130 +3797,19 @@ DelimTokenTree::to_token_stream () const return tokens; } -Literal -AttributeParser::parse_literal () -{ - const std::unique_ptr<Token> &tok = peek_token (); - switch (tok->get_id ()) - { - case CHAR_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::CHAR, tok->get_type_hint ()); - case STRING_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::STRING, - tok->get_type_hint ()); - case BYTE_CHAR_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::BYTE, tok->get_type_hint ()); - case BYTE_STRING_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::BYTE_STRING, - tok->get_type_hint ()); - case RAW_STRING_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::RAW_STRING, - tok->get_type_hint ()); - case INT_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::INT, tok->get_type_hint ()); - case FLOAT_LITERAL: - skip_token (); - return Literal (tok->as_string (), Literal::FLOAT, tok->get_type_hint ()); - case TRUE_LITERAL: - skip_token (); - return Literal ("true", Literal::BOOL, tok->get_type_hint ()); - case FALSE_LITERAL: - skip_token (); - return Literal ("false", Literal::BOOL, tok->get_type_hint ()); - default: - rust_error_at (tok->get_locus (), "expected literal - found '%s'", - get_token_description (tok->get_id ())); - return Literal::create_error (); - } -} - -SimplePath -AttributeParser::parse_simple_path () -{ - bool has_opening_scope_res = false; - if (peek_token ()->get_id () == SCOPE_RESOLUTION) - { - has_opening_scope_res = true; - skip_token (); - } - - std::vector<SimplePathSegment> segments; - - SimplePathSegment segment = parse_simple_path_segment (); - if (segment.is_error ()) - { - rust_error_at ( - peek_token ()->get_locus (), - "failed to parse simple path segment in attribute simple path"); - return SimplePath::create_empty (); - } - segments.push_back (std::move (segment)); - - while (peek_token ()->get_id () == SCOPE_RESOLUTION) - { - skip_token (); - - SimplePathSegment segment = parse_simple_path_segment (); - if (segment.is_error ()) - { - rust_error_at ( - peek_token ()->get_locus (), - "failed to parse simple path segment in attribute simple path"); - return SimplePath::create_empty (); - } - segments.push_back (std::move (segment)); - } - segments.shrink_to_fit (); - - return SimplePath (std::move (segments), has_opening_scope_res); -} - -SimplePathSegment -AttributeParser::parse_simple_path_segment () -{ - const std::unique_ptr<Token> &tok = peek_token (); - switch (tok->get_id ()) - { - case IDENTIFIER: - skip_token (); - return SimplePathSegment (tok->as_string (), tok->get_locus ()); - case SUPER: - skip_token (); - return SimplePathSegment ("super", tok->get_locus ()); - case SELF: - skip_token (); - return SimplePathSegment ("self", tok->get_locus ()); - case CRATE: - skip_token (); - return SimplePathSegment ("crate", tok->get_locus ()); - case DOLLAR_SIGN: - if (peek_token (1)->get_id () == CRATE) - { - skip_token (1); - return SimplePathSegment ("$crate", tok->get_locus ()); - } - gcc_fallthrough (); - default: - rust_error_at (tok->get_locus (), - "unexpected token '%s' in simple path segment", - get_token_description (tok->get_id ())); - return SimplePathSegment::create_error (); - } -} - std::unique_ptr<MetaItemLitExpr> AttributeParser::parse_meta_item_lit () { - location_t locus = peek_token ()->get_locus (); - LiteralExpr lit_expr (parse_literal (), {}, locus); + std::unique_ptr<LiteralExpr> lit_expr = parser->parse_literal_expr ({}); + + // TODO: return nullptr instead? + if (!lit_expr) + lit_expr = std::unique_ptr<LiteralExpr> ( + new LiteralExpr (Literal::create_error (), {}, + lexer->peek_token ()->get_locus ())); + return std::unique_ptr<MetaItemLitExpr> ( - new MetaItemLitExpr (std::move (lit_expr))); + new MetaItemLitExpr (std::move (*lit_expr))); } bool @@ -4084,10 +4018,12 @@ MetaNameValueStr::check_cfg_predicate (const Session &session) const } bool -MetaItemPathLit::check_cfg_predicate (const Session &session) const +MetaItemPathExpr::check_cfg_predicate (const Session &session) const { + // FIXME: Accept path expressions + rust_assert (expr->is_literal ()); return session.options.target_data.has_key_value_pair (path.as_string (), - lit.as_string ()); + expr->as_string ()); } std::vector<std::unique_ptr<Token>> @@ -4175,8 +4111,10 @@ MetaListNameValueStr::to_attribute () const } Attribute -MetaItemPathLit::to_attribute () const +MetaItemPathExpr::to_attribute () const { + rust_assert (expr->is_literal ()); + auto &lit = static_cast<LiteralExpr &> (*expr); return Attribute (path, std::unique_ptr<AttrInputLiteral> ( new AttrInputLiteral (lit))); } @@ -4279,11 +4217,12 @@ AttrInputMacro::AttrInputMacro (const AttrInputMacro &oth) : macro (oth.macro->clone_macro_invocation_impl ()) {} -void +AttrInputMacro & AttrInputMacro::operator= (const AttrInputMacro &oth) { macro = std::unique_ptr<MacroInvocation> ( oth.macro->clone_macro_invocation_impl ()); + return *this; } /* Visitor implementations - these are short but inlining can't happen anyway @@ -4345,7 +4284,7 @@ MetaItemLitExpr::accept_vis (ASTVisitor &vis) } void -MetaItemPathLit::accept_vis (ASTVisitor &vis) +MetaItemPathExpr::accept_vis (ASTVisitor &vis) { vis.visit (*this); } @@ -4513,6 +4452,18 @@ BlockExpr::accept_vis (ASTVisitor &vis) } void +AnonConst::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstBlock::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void ClosureExprInnerTyped::accept_vis (ASTVisitor &vis) { vis.visit (*this); @@ -4573,6 +4524,12 @@ ReturnExpr::accept_vis (ASTVisitor &vis) } void +TryExpr::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void UnsafeBlockExpr::accept_vis (ASTVisitor &vis) { vis.visit (*this); @@ -5010,6 +4967,12 @@ FormatArgs::accept_vis (ASTVisitor &vis) vis.visit (*this); } +void +OffsetOf::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + std::string FormatArgs::as_string () const { @@ -5017,6 +4980,12 @@ FormatArgs::as_string () const return "FormatArgs"; } +std::string +OffsetOf::as_string () const +{ + return "OffsetOf(" + type->as_string () + ", " + field.as_string () + ")"; +} + location_t FormatArgs::get_locus () const { @@ -5047,7 +5016,8 @@ FormatArgs::get_outer_attrs () rust_unreachable (); } -void FormatArgs::set_outer_attrs (std::vector<Attribute>) +void +FormatArgs::set_outer_attrs (std::vector<Attribute>) { rust_unreachable (); } @@ -5060,6 +5030,24 @@ FormatArgs::clone_expr_impl () const return new FormatArgs (*this); } +std::vector<Attribute> & +OffsetOf::get_outer_attrs () +{ + rust_unreachable (); +} + +void +OffsetOf::set_outer_attrs (std::vector<Attribute>) +{ + rust_unreachable (); +} + +Expr * +OffsetOf::clone_expr_impl () const +{ + return new OffsetOf (*this); +} + } // namespace AST std::ostream & diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index aa6ad50..2d2c5d0 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -62,13 +62,14 @@ public: return ident == other.ident; } + operator const std::string & () const { return ident; } + private: std::string ident; location_t loc; }; -std::ostream & -operator<< (std::ostream &os, Identifier const &i); +std::ostream &operator<< (std::ostream &os, Identifier const &i); namespace AST { // foward decl: ast visitor @@ -82,6 +83,38 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; }; +/** + * Base function for reconstructing and asserting that the new NodeId is + * different from the old NodeId. It then wraps the given pointer into a unique + * pointer and returns it. + */ +template <typename T> +std::unique_ptr<T> +reconstruct_base (const T *instance) +{ + auto *reconstructed = instance->reconstruct_impl (); + + rust_assert (reconstructed->get_node_id () != instance->get_node_id ()); + + return std::unique_ptr<T> (reconstructed); +} + +/** + * Reconstruct multiple items in a vector + */ +template <typename T> +std::vector<std::unique_ptr<T>> +reconstruct_vec (const std::vector<std::unique_ptr<T>> &to_reconstruct) +{ + std::vector<std::unique_ptr<T>> reconstructed; + reconstructed.reserve (to_reconstruct.size ()); + + for (const auto &elt : to_reconstruct) + reconstructed.emplace_back (std::unique_ptr<T> (elt->reconstruct_impl ())); + + return reconstructed; +} + // Delimiter types - used in macros and whatever. enum DelimType { @@ -250,6 +283,7 @@ public: std::vector<std::unique_ptr<Token>> to_token_stream () const override; TokenId get_id () const { return tok_ref->get_id (); } + bool has_str () const { return tok_ref->has_str (); } const std::string &get_str () const { return tok_ref->get_str (); } location_t get_locus () const { return tok_ref->get_locus (); } @@ -403,15 +437,15 @@ class SimplePath public: // Constructor - SimplePath (std::vector<SimplePathSegment> path_segments, - bool has_opening_scope_resolution = false, - location_t locus = UNDEF_LOCATION) + explicit SimplePath (std::vector<SimplePathSegment> path_segments, + bool has_opening_scope_resolution = false, + location_t locus = UNDEF_LOCATION) : opening_scope_resolution (has_opening_scope_resolution), segments (std::move (path_segments)), locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} - SimplePath (Identifier ident) + explicit SimplePath (Identifier ident) : opening_scope_resolution (false), segments ({SimplePathSegment (ident.as_string (), ident.get_locus ())}), locus (ident.get_locus ()), @@ -1039,7 +1073,7 @@ public: Path, Word, NameValueStr, - PathLit, + PathExpr, Seq, ListPaths, ListNameValueStr, @@ -1057,7 +1091,7 @@ public: class MetaItemLitExpr; // Forward decl - defined in rust-expr.h -class MetaItemPathLit; +class MetaItemPathExpr; // Forward decl - defined in rust-macro.h class MetaItemPath; @@ -1256,6 +1290,8 @@ public: FieldAccess, Closure, Block, + ConstExpr, + ConstBlock, Continue, Break, Range, @@ -1272,6 +1308,7 @@ public: LlvmInlineAsm, Identifier, FormatArgs, + OffsetOf, MacroInvocation, Borrow, Dereference, @@ -1283,6 +1320,7 @@ public: TypeCast, Assignment, CompoundAssignment, + Try, }; virtual Kind get_expr_kind () const = 0; @@ -1477,6 +1515,10 @@ public: return std::unique_ptr<Type> (clone_type_impl ()); } + // Similar to `clone_type`, but generates a new instance of the node with a + // different NodeId + std::unique_ptr<Type> reconstruct () const { return reconstruct_base (this); } + // virtual destructor virtual ~Type () {} @@ -1495,11 +1537,13 @@ public: virtual location_t get_locus () const = 0; NodeId get_node_id () const { return node_id; } + virtual Type *reconstruct_impl () const = 0; protected: Type () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {} + Type (NodeId node_id) : node_id (node_id) {} - // Clone function implementation as pure virtual method + // Clone and reconstruct function implementations as pure virtual methods virtual Type *clone_type_impl () const = 0; NodeId node_id; @@ -1515,6 +1559,13 @@ public: return std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ()); } + std::unique_ptr<TypeNoBounds> reconstruct () const + { + return reconstruct_base (this); + } + + virtual TypeNoBounds *reconstruct_impl () const override = 0; + protected: // Clone function implementation as pure virtual method virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0; @@ -1549,6 +1600,11 @@ public: return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ()); } + std::unique_ptr<TypeParamBound> reconstruct () const + { + return reconstruct_base (this); + } + virtual std::string as_string () const = 0; NodeId get_node_id () const { return node_id; } @@ -1557,10 +1613,14 @@ public: virtual TypeParamBoundType get_bound_type () const = 0; + virtual TypeParamBound *reconstruct_impl () const = 0; + protected: // Clone function implementation as pure virtual method virtual TypeParamBound *clone_type_param_bound_impl () const = 0; + TypeParamBound () : node_id (Analysis::Mappings::get ().get_next_node_id ()) + {} TypeParamBound (NodeId node_id) : node_id (node_id) {} NodeId node_id; @@ -1622,6 +1682,10 @@ protected: { return new Lifetime (node_id, lifetime_type, lifetime_name, locus); } + Lifetime *reconstruct_impl () const override + { + return new Lifetime (lifetime_type, lifetime_name, locus); + } }; /* Base generic parameter in AST. Abstract - can be represented by a Lifetime diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h index 3684092..2893e7b 100644 --- a/gcc/rust/ast/rust-builtin-ast-nodes.h +++ b/gcc/rust/ast/rust-builtin-ast-nodes.h @@ -225,6 +225,59 @@ protected: virtual Expr *clone_expr_impl () const override; }; +/** + * The node associated with the builtin offset_of!() macro + */ +class OffsetOf : public Expr +{ +public: + OffsetOf (std::unique_ptr<Type> &&type, Identifier field, location_t loc) + : type (std::move (type)), field (field), loc (loc) + {} + + OffsetOf (const OffsetOf &other) + : type (other.type->clone_type ()), field (other.field), loc (other.loc), + marked_for_strip (other.marked_for_strip) + {} + + OffsetOf &operator= (const OffsetOf &other) + { + type = other.type->clone_type (); + field = other.field; + loc = other.loc; + marked_for_strip = other.marked_for_strip; + + return *this; + } + + void accept_vis (AST::ASTVisitor &vis) override; + + virtual location_t get_locus () const override { return loc; } + const Type &get_type () const { return *type; } + Type &get_type () { return *type; } + const Identifier &get_field () const { return field; } + + bool is_expr_without_block () const override { return false; } + + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } + + std::string as_string () const override; + + std::vector<Attribute> &get_outer_attrs () override; + void set_outer_attrs (std::vector<Attribute>) override; + Expr *clone_expr_impl () const override; + + Expr::Kind get_expr_kind () const override { return Expr::Kind::OffsetOf; } + +private: + std::unique_ptr<Type> type; + Identifier field; + + location_t loc; + bool marked_for_strip = false; +}; + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc index cd6be7f..306c6f7 100644 --- a/gcc/rust/ast/rust-collect-lang-items.cc +++ b/gcc/rust/ast/rust-collect-lang-items.cc @@ -109,5 +109,29 @@ CollectLangItems::visit (AST::EnumItem &item) DefaultASTVisitor::visit (item); } +void +CollectLangItems::visit (AST::EnumItemTuple &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::EnumItemStruct &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::EnumItemDiscriminant &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-collect-lang-items.h b/gcc/rust/ast/rust-collect-lang-items.h index ddb34a9..ddc7b51 100644 --- a/gcc/rust/ast/rust-collect-lang-items.h +++ b/gcc/rust/ast/rust-collect-lang-items.h @@ -50,6 +50,9 @@ public: void visit (AST::Function &item) override; void visit (AST::StructStruct &item) override; void visit (AST::EnumItem &item) override; + void visit (AST::EnumItemTuple &item) override; + void visit (AST::EnumItemStruct &item) override; + void visit (AST::EnumItemDiscriminant &item) override; private: template <typename T> void maybe_add_lang_item (const T &item); diff --git a/gcc/rust/ast/rust-cond-compilation.h b/gcc/rust/ast/rust-cond-compilation.h index 610b904..56a5646 100644 --- a/gcc/rust/ast/rust-cond-compilation.h +++ b/gcc/rust/ast/rust-cond-compilation.h @@ -42,8 +42,8 @@ public: protected: // Clone function impl to be overriden in base classes - virtual ConfigurationPredicate * - clone_configuration_predicate_impl () const = 0; + virtual ConfigurationPredicate *clone_configuration_predicate_impl () const + = 0; }; // A configuration option - true if option is set, false if option is not set. diff --git a/gcc/rust/ast/rust-desugar-apit.cc b/gcc/rust/ast/rust-desugar-apit.cc new file mode 100644 index 0000000..bca14ee --- /dev/null +++ b/gcc/rust/ast/rust-desugar-apit.cc @@ -0,0 +1,522 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-desugar-apit.h" +#include "rust-ast.h" +#include "rust-type.h" + +namespace Rust { +namespace AST { + +class DesugarApitType : public DefaultASTVisitor +{ + using DefaultASTVisitor::visit; + +public: + static std::pair<AST::Type *, std::vector<std::unique_ptr<GenericParam>>> + Desugar (AST::Type &type) + { + DesugarApitType visitor (&type); + type.accept_vis (visitor); + rust_assert (visitor.translated != nullptr); + return std::make_pair (visitor.translated, + std::move (visitor.implicit_generic_params)); + } + + // Generate a unique impl trait parameter name + static Identifier get_impl_name () + { + static size_t counter = 0; + return Identifier ("Impl_" + std::to_string (counter++)); + } + + // these can hold other types + void visit (AST::TupleType &tuple) override + { + for (auto &elem : tuple.get_elems ()) + { + auto &type = *elem.get (); + auto desugar = Desugar (type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + continue; + + if (tt != elem.get ()) + elem = std::unique_ptr<Type> (tt); + + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + } + + void visit (AST::ArrayType &type) override + { + auto &element_type = type.get_element_type (); + auto desugar = Desugar (*element_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (tt != element_type.get ()) + element_type = std::unique_ptr<AST::Type> (tt); + + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::ReferenceType &type) override + { + // Get a reference to the current type for in-place modification + auto &referenced_type = type.get_type_referenced (); + auto desugar = Desugar (referenced_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + // Update the reference type's contents rather than creating a new one + if (&referenced_type != tt) + { + std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds ( + static_cast<AST::TypeNoBounds *> (tt)); + type.get_type_ptr () = std::move (new_type_no_bounds); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::RawPointerType &type) override + { + auto &pointed_type = type.get_type_pointed_to (); + auto desugar = Desugar (pointed_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + // Update the pointer's inner type directly using the new accessor + if (&pointed_type != tt) + { + std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds ( + static_cast<AST::TypeNoBounds *> (tt)); + type.get_type_ptr () = std::move (new_type_no_bounds); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::SliceType &type) override + { + auto &element_type = type.get_elem_type (); + auto desugar = Desugar (element_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (&element_type != tt) + { + std::unique_ptr<AST::Type> new_elem_type (tt); + type.get_elem_type_ptr () = std::move (new_elem_type); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::ParenthesisedType &type) override + { + auto &inner_type_ptr = type.get_type_in_parens (); + auto desugar = Desugar (*inner_type_ptr); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (inner_type_ptr.get () != tt) + { + std::unique_ptr<AST::Type> new_inner_type (tt); + inner_type_ptr = std::move (new_inner_type); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + // this is where the desugar happens + void visit (AST::ImplTraitType &type) override + { + // Generate a unique name using the static method + auto ident = get_impl_name (); + + // Create a type path for the new generic parameter + // Create a SimplePathSegment with the identifier string + auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ()); + // Create a vector of SimplePathSegments for SimplePath constructor + std::vector<SimplePathSegment> simple_segs = {simple_seg}; + // Create a SimplePath + auto simple_path = SimplePath (simple_segs, false, type.get_locus ()); + + // Convert to TypePath by creating path segments + std::vector<std::unique_ptr<TypePathSegment>> segments; + segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment ( + PathIdentSegment (ident.as_string (), type.get_locus ()), false, + type.get_locus ()))); + + // Create TypePath from segments + auto type_path + = new TypePath (std::move (segments), type.get_locus (), false); + + // Convert bounds from impl trait to generic parameter bounds + std::vector<std::unique_ptr<TypeParamBound>> bounds; + for (auto &bound : type.get_type_param_bounds ()) + bounds.push_back (bound->clone_type_param_bound ()); + + // Create the new generic parameter + auto generic_param = std::unique_ptr<TypeParam> ( + new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {}, + true /*from impl trait*/)); + + // Store the generic parameter to be added to the function signature + implicit_generic_params.push_back (std::move (generic_param)); + + // Replace impl trait with the new type parameter + translated = type_path; + } + + void visit (AST::ImplTraitTypeOneBound &type) override + { + // Generate a unique name using the static method + auto ident = get_impl_name (); + + // Create a type path for the new generic parameter + // Create a SimplePathSegment with the identifier string + auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ()); + // Create a vector of SimplePathSegments for SimplePath constructor + std::vector<SimplePathSegment> simple_segs = {simple_seg}; + // Create a SimplePath + auto simple_path = SimplePath (simple_segs, false, type.get_locus ()); + + // Convert to TypePath by creating path segments + std::vector<std::unique_ptr<TypePathSegment>> segments; + segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment ( + PathIdentSegment (ident.as_string (), type.get_locus ()), false, + type.get_locus ()))); + + // Create TypePath from segments + auto type_path + = new TypePath (std::move (segments), type.get_locus (), false); + + // Convert the bound to a generic parameter bound + std::vector<std::unique_ptr<TypeParamBound>> bounds; + bounds.push_back (std::move (type.get_trait_bound ())); + + // Create the new generic parameter + auto generic_param = std::unique_ptr<TypeParam> ( + new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {}, + true /*from impl trait*/)); + + // Store the generic parameter to be added to the function signature + implicit_generic_params.push_back (std::move (generic_param)); + + // Replace impl trait with the new type parameter + translated = type_path; + } + +private: + DesugarApitType (AST::Type *base) + : translated (base), implicit_generic_params () + {} + + AST::Type *translated; + std::vector<std::unique_ptr<GenericParam>> implicit_generic_params; +}; + +// --------- + +class ApitBoundProcessor +{ +public: + ApitBoundProcessor ( + WhereClause &where_clause, + std::vector<std::unique_ptr<GenericParam>> &generic_params) + : where_clause (where_clause), generic_params (generic_params) + {} + + void go (std::vector<std::unique_ptr<GenericParam>> &implicit_generics) + { + // some desugars are more complex so imagine this case + // + // pub fn foo(_value: impl Bar<Baz = impl Foo>) -> i32 { + // 15 + // } + // + // this needs to become: + // + // pub fn foo<T, U>(_value: T) -> i32 + // where + // T: Bar<Baz = U>, + // U: Foo, + // { + // 15 + // } + // + // so we need to walk all the implicit generics and the trait bounds paths + // for more generics + + for (auto &implicit_generic : implicit_generics) + { + switch (implicit_generic->get_kind ()) + { + case GenericParam::Kind::Type: + { + TypeParam &p + = *static_cast<TypeParam *> (implicit_generic.get ()); + + process_type_param (p); + generic_params.push_back (std::move (implicit_generic)); + for (auto &synth : synthetic_params) + generic_params.push_back (std::move (synth)); + synthetic_params.clear (); + } + break; + + default: + generic_params.push_back (std::move (implicit_generic)); + break; + } + } + } + +private: + void process_type_param (TypeParam &p) + { + auto &bounds = p.get_type_param_bounds (); + std::vector<size_t> bounds_to_remove; + for (size_t i = 0; i < bounds.size (); i++) + { + auto &tb = bounds[i]; + switch (tb->get_bound_type ()) + { + case TypeParamBound::TypeParamBoundType::TRAIT: + { + TraitBound &ttb = *static_cast<TraitBound *> (tb.get ()); + TypePath &path = ttb.get_type_path (); + bool deusgared = process_type_path (p, ttb, path); + if (deusgared) + bounds_to_remove.push_back (i); + } + + default: + break; + } + } + for (auto it = bounds_to_remove.rbegin (); it != bounds_to_remove.rend (); + ++it) + bounds.erase (bounds.begin () + *it); + } + + bool process_type_path (TypeParam &p, TraitBound &parent, TypePath &path) + { + bool desugared = false; + for (auto &segment : path.get_segments ()) + { + switch (segment->get_type ()) + { + case TypePathSegment::SegmentType::GENERIC: + { + TypePathSegmentGeneric &seg + = *static_cast<TypePathSegmentGeneric *> (segment.get ()); + desugared |= process_generic_segment (p, parent, path, seg); + } + + default: + break; + } + } + return desugared; + } + + bool process_generic_segment (TypeParam &p, TraitBound &parent, + TypePath &path, TypePathSegmentGeneric &seg) + { + // we need to look for any impl types as default arguments in any generics + // and remove this index from the generic arguments by using a where + // constraint instead + + std::vector<std::unique_ptr<WhereClauseItem>> new_clauses; + GenericArgs &generic_args = seg.get_generic_args (); + std::vector<std::reference_wrapper<const GenericArgsBinding>> + bindings_desugared; + std::vector<GenericArgsBinding> &bindings + = generic_args.get_binding_args (); + + for (auto &generic : bindings) + { + auto &t = generic.get_type (); + auto translated = DesugarApitType::Desugar (t); + auto tt = translated.first; + + auto &implicit_generics = translated.second; + if (implicit_generics.empty ()) + continue; + + if (tt != &t) + { + bindings_desugared.push_back (generic); + generic.get_type_ptr () = std::unique_ptr<Type> (tt); + } + + for (auto &implicit_generic : implicit_generics) + { + switch (implicit_generic->get_kind ()) + { + case GenericParam::Kind::Type: + { + TypeParam &tp + = *static_cast<TypeParam *> (implicit_generic.get ()); + + std::vector<std::unique_ptr<TypeParamBound>> + type_param_bounds; + for (auto &b : tp.get_type_param_bounds ()) + type_param_bounds.push_back (std::move (b)); + tp.get_type_param_bounds ().clear (); + + // add synthetic parameter for this + synthetic_params.push_back (std::move (implicit_generic)); + + auto bound_type_path + = get_type_for_identifier (tp.get_type_representation ()); + + auto clause = new TypeBoundWhereClauseItem ( + {}, std::move (bound_type_path), + std::move (type_param_bounds), tp.get_locus ()); + std::unique_ptr<WhereClauseItem> clause_item + = std::unique_ptr<WhereClauseItem> (clause); + new_clauses.push_back (std::move (clause_item)); + } + break; + + default: + synthetic_params.push_back (std::move (implicit_generic)); + break; + } + } + } + + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; + auto bound = std::unique_ptr<TypeParamBound> (new TraitBound (parent)); + type_param_bounds.push_back (std::move (bound)); + auto parent_type_path + = get_type_for_identifier (p.get_type_representation ()); + auto clause + = new TypeBoundWhereClauseItem ({}, std::move (parent_type_path), + std::move (type_param_bounds), + parent.get_locus ()); + std::unique_ptr<WhereClauseItem> clause_item + = std::unique_ptr<WhereClauseItem> (clause); + where_clause.get_items ().push_back (std::move (clause_item)); + + for (auto &where_item : new_clauses) + where_clause.get_items ().push_back (std::move (where_item)); + + return !bindings_desugared.empty (); + } + + static std::unique_ptr<Type> get_type_for_identifier (const Identifier &ident) + { + auto simple_seg + = SimplePathSegment (ident.as_string (), ident.get_locus ()); + std::vector<SimplePathSegment> simple_segs = {simple_seg}; + auto simple_path = SimplePath (simple_segs, false, ident.get_locus ()); + std::vector<std::unique_ptr<TypePathSegment>> segments; + segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment ( + PathIdentSegment (ident.as_string (), ident.get_locus ()), false, + ident.get_locus ()))); + auto type_path = new TypePath (std::move (segments), ident.get_locus ()); + return std::unique_ptr<Type> (type_path); + } + +private: + WhereClause &where_clause; + std::vector<std::unique_ptr<GenericParam>> &generic_params; + + // mutates + std::vector<std::unique_ptr<GenericParam>> synthetic_params; +}; + +// --------- + +DesugarApit::DesugarApit () {} + +void +DesugarApit::go (AST::Crate &crate) +{ + DefaultASTVisitor::visit (crate); +} + +void +DesugarApit::visit (AST::Function &function) +{ + if (!function.has_function_params ()) + return; + + auto &fn_params = function.get_function_params (); + for (auto ¶m : fn_params) + { + if (param->is_variadic () || param->is_self ()) + continue; + + auto *p = param.get (); + auto &fp = *static_cast<AST::FunctionParam *> (p); + auto &type = fp.get_type (); + + auto translated = DesugarApitType::Desugar (type); + auto tt = translated.first; + + auto &implicit_generics = translated.second; + if (implicit_generics.empty ()) + continue; + + if (fp.get_type_ptr ().get () != tt) + { + fp.get_type_ptr () = std::unique_ptr<AST::Type> (tt); + } + + ApitBoundProcessor processor (function.get_where_clause (), + function.get_generic_params ()); + processor.go (implicit_generics); + } +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/ast/rust-desugar-apit.h index 2703438..07c25e2 100644 --- a/gcc/rust/ast/rust-macro.cc +++ b/gcc/rust/ast/rust-desugar-apit.h @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. +// Copyright (C) 2025 Free Software Foundation, Inc. // This file is part of GCC. @@ -16,10 +16,27 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -#include "rust-macro.h" +#ifndef RUST_DESUGAR_APIT_H +#define RUST_DESUGAR_APIT_H + +#include "rust-ast-visitor.h" namespace Rust { namespace AST { +class DesugarApit : public DefaultASTVisitor +{ + using DefaultASTVisitor::visit; + +public: + DesugarApit (); + void go (AST::Crate &); + +private: + void visit (AST::Function &) override; +}; + } // namespace AST } // namespace Rust + +#endif // ! RUST_DESUGAR_APIT_H diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc index ffc3470..5cc1c19 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.cc +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -17,7 +17,6 @@ // <http://www.gnu.org/licenses/>. #include "rust-desugar-for-loops.h" -#include "rust-ast-visitor.h" #include "rust-ast.h" #include "rust-hir-map.h" #include "rust-path.h" @@ -31,32 +30,10 @@ namespace AST { DesugarForLoops::DesugarForLoops () {} -void -DesugarForLoops::go (AST::Crate &crate) -{ - DefaultASTVisitor::visit (crate); -} - -static void -replace_for_loop (std::unique_ptr<Expr> &for_loop, - std::unique_ptr<Expr> &&expanded) -{ - for_loop = std::move (expanded); -} - -MatchArm -DesugarForLoops::DesugarCtx::make_match_arm (std::unique_ptr<Pattern> &&path) -{ - auto patterns = std::vector<std::unique_ptr<Pattern>> (); - patterns.emplace_back (std::move (path)); - - return MatchArm (std::move (patterns), loc); -} - MatchCase DesugarForLoops::DesugarCtx::make_break_arm () { - auto arm = make_match_arm (std::unique_ptr<Pattern> (new PathInExpression ( + auto arm = builder.match_arm (std::unique_ptr<Pattern> (new PathInExpression ( builder.path_in_expression (LangItem::Kind::OPTION_NONE)))); auto break_expr @@ -79,7 +56,7 @@ DesugarForLoops::DesugarCtx::make_continue_arm () builder.path_in_expression (LangItem::Kind::OPTION_SOME), std::move (pattern_item))); - auto val_arm = make_match_arm (std::move (pattern)); + auto val_arm = builder.match_arm (std::move (pattern)); auto next = builder.identifier (DesugarCtx::next_value_id); @@ -91,14 +68,8 @@ DesugarForLoops::DesugarCtx::make_continue_arm () return MatchCase (std::move (val_arm), std::move (assignment)); } -std::unique_ptr<Stmt> -DesugarForLoops::DesugarCtx::statementify (std::unique_ptr<Expr> &&expr) -{ - return std::unique_ptr<Stmt> (new ExprStmt (std::move (expr), loc, true)); -} - std::unique_ptr<Expr> -DesugarForLoops::desugar (AST::ForLoopExpr &expr) +DesugarForLoops::desugar (ForLoopExpr &expr) { auto ctx = DesugarCtx (expr.get_locus ()); @@ -140,10 +111,10 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr) auto loop_stmts = std::vector<std::unique_ptr<Stmt>> (); loop_stmts.emplace_back (std::move (let_next)); - loop_stmts.emplace_back (ctx.statementify (std::move (match_next))); + loop_stmts.emplace_back (ctx.builder.statementify (std::move (match_next))); loop_stmts.emplace_back (std::move (let_pat)); loop_stmts.emplace_back ( - ctx.statementify (expr.get_loop_block ().clone_expr ())); + ctx.builder.statementify (expr.get_loop_block ().clone_expr ())); // loop { // <let_next>; @@ -170,34 +141,18 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr) } void -DesugarForLoops::maybe_desugar_expr (std::unique_ptr<Expr> &expr) +DesugarForLoops::go (std::unique_ptr<Expr> &ptr) { - if (expr->get_expr_kind () == AST::Expr::Kind::Loop) - { - auto &loop = static_cast<AST::BaseLoopExpr &> (*expr); + rust_assert (ptr->get_expr_kind () == Expr::Kind::Loop); - if (loop.get_loop_kind () == AST::BaseLoopExpr::Kind::For) - { - auto &for_loop = static_cast<AST::ForLoopExpr &> (loop); + auto &loop = static_cast<BaseLoopExpr &> (*ptr); - auto desugared = desugar (for_loop); - - replace_for_loop (expr, std::move (desugared)); - } - } -} - -void -DesugarForLoops::visit (AST::BlockExpr &block) -{ - for (auto &stmt : block.get_statements ()) - if (stmt->get_stmt_kind () == AST::Stmt::Kind::Expr) - maybe_desugar_expr (static_cast<AST::ExprStmt &> (*stmt).get_expr_ptr ()); + rust_assert (loop.get_loop_kind () == BaseLoopExpr::Kind::For); - if (block.has_tail_expr ()) - maybe_desugar_expr (block.get_tail_expr_ptr ()); + auto &for_loop = static_cast<ForLoopExpr &> (loop); + auto desugared = DesugarForLoops ().desugar (for_loop); - DefaultASTVisitor::visit (block); + ptr = std::move (desugared); } } // namespace AST diff --git a/gcc/rust/ast/rust-desugar-for-loops.h b/gcc/rust/ast/rust-desugar-for-loops.h index 7beb692..96b63ff 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.h +++ b/gcc/rust/ast/rust-desugar-for-loops.h @@ -20,7 +20,6 @@ #define RUST_DESUGAR_FOR_LOOPS_H #include "rust-ast-builder.h" -#include "rust-ast-visitor.h" #include "rust-expr.h" namespace Rust { @@ -69,15 +68,14 @@ namespace AST { // of the way the typechecker is currently structured, where it will fetch name // resolution information in order to typecheck paths - which technically isn't // necessary. -class DesugarForLoops : public DefaultASTVisitor +class DesugarForLoops { - using DefaultASTVisitor::visit; - public: - DesugarForLoops (); - void go (AST::Crate &); + static void go (std::unique_ptr<Expr> &ptr); private: + DesugarForLoops (); + struct DesugarCtx { DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {} @@ -85,10 +83,8 @@ private: Builder builder; location_t loc; - MatchArm make_match_arm (std::unique_ptr<Pattern> &&pattern); MatchCase make_break_arm (); MatchCase make_continue_arm (); - std::unique_ptr<Stmt> statementify (std::unique_ptr<Expr> &&expr); constexpr static const char *continue_pattern_id = "#val"; constexpr static const char *next_value_id = "#__next"; @@ -96,10 +92,7 @@ private: constexpr static const char *result_id = "#result"; }; - std::unique_ptr<Expr> desugar (AST::ForLoopExpr &expr); - void maybe_desugar_expr (std::unique_ptr<Expr> &expr); - - void visit (AST::BlockExpr &) override; + std::unique_ptr<Expr> desugar (ForLoopExpr &expr); }; } // namespace AST diff --git a/gcc/rust/ast/rust-desugar-question-mark.cc b/gcc/rust/ast/rust-desugar-question-mark.cc index 4d2933b..01400d8 100644 --- a/gcc/rust/ast/rust-desugar-question-mark.cc +++ b/gcc/rust/ast/rust-desugar-question-mark.cc @@ -18,7 +18,6 @@ #include "rust-desugar-question-mark.h" #include "rust-ast-builder.h" -#include "rust-ast-visitor.h" namespace Rust { namespace AST { @@ -26,42 +25,14 @@ namespace AST { DesugarQuestionMark::DesugarQuestionMark () {} void -DesugarQuestionMark::go (AST::Crate &crate) +DesugarQuestionMark::go (std::unique_ptr<Expr> &ptr) { - DesugarQuestionMark::visit (crate); -} - -void -DesugarQuestionMark::visit (ExprStmt &stmt) -{ - if (stmt.get_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation) - desugar_and_replace (stmt.get_expr_ptr ()); - - DefaultASTVisitor::visit (stmt); -} - -void -DesugarQuestionMark::visit (CallExpr &call) -{ - if (call.get_function_expr ().get_expr_kind () - == Expr::Kind::ErrorPropagation) - desugar_and_replace (call.get_function_expr_ptr ()); - - for (auto &arg : call.get_params ()) - if (arg->get_expr_kind () == Expr::Kind::ErrorPropagation) - desugar_and_replace (arg); - - DefaultASTVisitor::visit (call); -} + rust_assert (ptr->get_expr_kind () == Expr::Kind::ErrorPropagation); -void -DesugarQuestionMark::visit (LetStmt &stmt) -{ - if (stmt.has_init_expr () - && stmt.get_init_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation) - desugar_and_replace (stmt.get_init_expr_ptr ()); + auto original = static_cast<ErrorPropagationExpr &> (*ptr); + auto desugared = DesugarQuestionMark ().desugar (original); - DefaultASTVisitor::visit (stmt); + ptr = std::move (desugared); } MatchArm @@ -99,6 +70,12 @@ ok_case (Builder &builder) MatchCase err_case (Builder &builder) { + // TODO: We need to handle the case where there is an enclosing `try {}` + // block, as that will create an additional block label that we can break to. + // This allows try blocks to use the question mark operator without having the + // offending statement early return from the enclosing function + // FIXME: How to mark that there is an enclosing block label? + auto val = builder.identifier_pattern ("err"); auto patterns = std::vector<std::unique_ptr<Pattern>> (); @@ -154,14 +131,5 @@ DesugarQuestionMark::desugar (ErrorPropagationExpr &expr) expr.get_locus ())); } -void -DesugarQuestionMark::desugar_and_replace (std::unique_ptr<Expr> &ptr) -{ - auto original = static_cast<ErrorPropagationExpr &> (*ptr); - auto desugared = desugar (original); - - ptr = std::move (desugared); -} - } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-desugar-question-mark.h b/gcc/rust/ast/rust-desugar-question-mark.h index e4c513f..542c52b 100644 --- a/gcc/rust/ast/rust-desugar-question-mark.h +++ b/gcc/rust/ast/rust-desugar-question-mark.h @@ -19,9 +19,7 @@ #ifndef RUST_DESUGAR_QUESTION_MARK #define RUST_DESUGAR_QUESTION_MARK -#include "rust-ast-visitor.h" #include "rust-expr.h" -#include "rust-stmt.h" namespace Rust { namespace AST { @@ -56,21 +54,15 @@ namespace AST { // } // } // ``` -class DesugarQuestionMark : public DefaultASTVisitor +class DesugarQuestionMark { - using DefaultASTVisitor::visit; - public: - DesugarQuestionMark (); - void go (AST::Crate &); + static void go (std::unique_ptr<Expr> &ptr); private: - void desugar_and_replace (std::unique_ptr<Expr> &ptr); - std::unique_ptr<Expr> desugar (ErrorPropagationExpr &); + DesugarQuestionMark (); - void visit (AST::ExprStmt &) override; - void visit (AST::CallExpr &) override; - void visit (AST::LetStmt &) override; + std::unique_ptr<Expr> desugar (ErrorPropagationExpr &); }; } // namespace AST diff --git a/gcc/rust/ast/rust-desugar-try-block.cc b/gcc/rust/ast/rust-desugar-try-block.cc new file mode 100644 index 0000000..07f06aa --- /dev/null +++ b/gcc/rust/ast/rust-desugar-try-block.cc @@ -0,0 +1,62 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-desugar-try-block.h" +#include "rust-ast-builder.h" +#include "rust-expr.h" + +namespace Rust { +namespace AST { + +DesugarTryBlock::DesugarTryBlock () {} + +void +DesugarTryBlock::go (std::unique_ptr<Expr> &ptr) +{ + rust_assert (ptr->get_expr_kind () == Expr::Kind::Try); + + auto original = static_cast<TryExpr &> (*ptr); + auto desugared = DesugarTryBlock ().desugar (original); + + ptr = std::move (desugared); +} + +std::unique_ptr<Expr> +DesugarTryBlock::desugar (TryExpr &expr) +{ + auto builder = Builder (expr.get_locus ()); + auto &block = expr.get_block_expr (); + + if (block.has_statements ()) + rust_sorry_at (expr.get_locus (), + "cannot desugar try-blocks with statements"); + + auto tail_expr = builder.tuple (); + + if (block.has_tail_expr ()) + tail_expr = block.get_tail_expr ().clone_expr (); + + // Wrap in Try::from_ok call + auto from_ok = builder.path_in_expression (LangItem::Kind::TRY_FROM_OK); + auto call = builder.call (ptrify (from_ok), std::move (tail_expr)); + + return builder.block (std::move (call)); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-desugar-try-block.h b/gcc/rust/ast/rust-desugar-try-block.h new file mode 100644 index 0000000..bfd0463 --- /dev/null +++ b/gcc/rust/ast/rust-desugar-try-block.h @@ -0,0 +1,42 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_DESUGAR_TRY_BLOCK +#define RUST_DESUGAR_TRY_BLOCK + +#include "rust-expr.h" + +namespace Rust { +namespace AST { + +// FIXME: Add documentation +class DesugarTryBlock +{ +public: + static void go (std::unique_ptr<Expr> &ptr); + +private: + DesugarTryBlock (); + + std::unique_ptr<Expr> desugar (TryExpr &); +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DESUGAR_TRY_BLOCK diff --git a/gcc/rust/ast/rust-desugar-while-let.cc b/gcc/rust/ast/rust-desugar-while-let.cc new file mode 100644 index 0000000..5eadc59 --- /dev/null +++ b/gcc/rust/ast/rust-desugar-while-let.cc @@ -0,0 +1,104 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-desugar-while-let.h" +#include "rust-ast.h" +#include "rust-hir-map.h" +#include "rust-path.h" +#include "rust-pattern.h" +#include "rust-stmt.h" +#include "rust-expr.h" +#include "rust-ast-builder.h" + +namespace Rust { +namespace AST { + +DesugarWhileLet::DesugarWhileLet () {} + +MatchCase +DesugarWhileLet::DesugarCtx::make_break_arm () +{ + auto arm = builder.match_arm (builder.wildcard ()); + + auto break_expr + = std::unique_ptr<Expr> (new BreakExpr (tl::nullopt, nullptr, {}, loc)); + + return MatchCase (std::move (arm), std::move (break_expr)); +} + +MatchCase +DesugarWhileLet::DesugarCtx::make_continue_arm ( + std::unique_ptr<Pattern> &&pattern, std::unique_ptr<BlockExpr> &&body) +{ + auto arm = builder.match_arm (std::move (pattern)); + + return MatchCase (std::move (arm), std::move (body)); +} + +std::unique_ptr<Expr> +DesugarWhileLet::desugar (WhileLetLoopExpr &expr) +{ + rust_assert (expr.get_patterns ().size () == 1); + + auto pattern = expr.get_patterns ()[0]->clone_pattern (); + auto body = expr.get_loop_block ().clone_block_expr (); + auto scrutinee = expr.get_scrutinee_expr ().clone_expr (); + + auto ctx = DesugarCtx (expr.get_locus ()); + + // _ => break, + auto break_arm = ctx.make_break_arm (); + + // <pattern> => <body>, + auto continue_arm + = ctx.make_continue_arm (std::move (pattern), std::move (body)); + + // match <scrutinee> { + // <continue_arm> + // <break_arm> + // } + auto match_expr + = ctx.builder.match (std::move (scrutinee), + {std::move (continue_arm), std::move (break_arm)}); + + auto loop_stmts = std::vector<std::unique_ptr<Stmt>> (); + loop_stmts.emplace_back (ctx.builder.statementify (std::move (match_expr))); + + // loop { + // <match_expr> + // } + return ctx.builder.loop (std::move (loop_stmts)); +} + +void +DesugarWhileLet::go (std::unique_ptr<Expr> &ptr) +{ + rust_assert (ptr->get_expr_kind () == Expr::Kind::Loop); + + auto &loop = static_cast<BaseLoopExpr &> (*ptr); + + rust_assert (loop.get_loop_kind () == BaseLoopExpr::Kind::WhileLet); + + auto &while_let = static_cast<WhileLetLoopExpr &> (loop); + auto desugared = DesugarWhileLet ().desugar (while_let); + + ptr = std::move (desugared); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-desugar-while-let.h b/gcc/rust/ast/rust-desugar-while-let.h new file mode 100644 index 0000000..60e0693 --- /dev/null +++ b/gcc/rust/ast/rust-desugar-while-let.h @@ -0,0 +1,71 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_DESUGAR_WHILE_LET_H +#define RUST_DESUGAR_WHILE_LET_H + +#include "rust-ast-builder.h" +#include "rust-expr.h" + +namespace Rust { +namespace AST { + +// Desugar while-let into a set of other AST nodes. The desugar is of the +// following form: +// +// ``` +// whilet let <pat> = <expr> <body> +// ``` +// +// becomes: +// +// ``` +// loop { +// match <expr> { +// <pat> => <body>, +// _ => break +// } +// } +// ``` +class DesugarWhileLet +{ +public: + static void go (std::unique_ptr<Expr> &ptr); + +private: + DesugarWhileLet (); + + struct DesugarCtx + { + DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {} + + Builder builder; + location_t loc; + + MatchCase make_break_arm (); + MatchCase make_continue_arm (std::unique_ptr<Pattern> &&pattern, + std::unique_ptr<BlockExpr> &&body); + }; + + std::unique_ptr<Expr> desugar (WhileLetLoopExpr &expr); +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DESUGAR_WHILE_LET_H diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index fdb6360..7b0df25 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1,6 +1,7 @@ #ifndef RUST_AST_EXPR_H #define RUST_AST_EXPR_H +#include "optional.h" #include "rust-ast.h" #include "rust-common.h" #include "rust-path.h" @@ -182,9 +183,13 @@ public: AttrInputMacro (AttrInputMacro &&oth) : macro (std::move (oth.macro)) {} - void operator= (const AttrInputMacro &oth); + AttrInputMacro &operator= (const AttrInputMacro &oth); - void operator= (AttrInputMacro &&oth) { macro = std::move (oth.macro); } + AttrInputMacro &operator= (AttrInputMacro &&oth) + { + macro = std::move (oth.macro); + return *this; + } std::string as_string () const override; @@ -244,36 +249,50 @@ protected: } }; -// more generic meta item "path = lit" form -class MetaItemPathLit : public MetaItem +// more generic meta item "path = expr" form +class MetaItemPathExpr : public MetaItem { SimplePath path; - LiteralExpr lit; + std::unique_ptr<Expr> expr; public: - MetaItemPathLit (SimplePath path, LiteralExpr lit_expr) - : path (std::move (path)), lit (std::move (lit_expr)) + MetaItemPathExpr (SimplePath path, std::unique_ptr<Expr> expr) + : path (std::move (path)), expr (std::move (expr)) {} + MetaItemPathExpr (const MetaItemPathExpr &other) + : MetaItem (other), path (other.path), expr (other.expr->clone_expr ()) + {} + + MetaItemPathExpr (MetaItemPathExpr &&) = default; + + MetaItemPathExpr &operator= (MetaItemPathExpr &&) = default; + + MetaItemPathExpr operator= (const MetaItemPathExpr &other) + { + MetaItem::operator= (other); + path = other.path; + expr = other.expr->clone_expr (); + return *this; + } + SimplePath get_path () const { return path; } SimplePath &get_path () { return path; } - LiteralExpr get_literal () const { return lit; } - - LiteralExpr &get_literal () { return lit; } + Expr &get_expr () { return *expr; } std::string as_string () const override { - return path.as_string () + " = " + lit.as_string (); + return path.as_string () + " = " + expr->as_string (); } MetaItem::ItemKind get_item_kind () const override { - return MetaItem::ItemKind::PathLit; + return MetaItem::ItemKind::PathExpr; } - // There are two Locations in MetaItemPathLit (path and lit_expr), + // There are two Locations in MetaItemPathExpr (path and expr), // we have no idea use which of them, just simply return UNKNOWN_LOCATION // now. // Maybe we will figure out when we really need the location in the future. @@ -289,9 +308,9 @@ public: protected: // Use covariance to implement clone function as returning this type - MetaItemPathLit *clone_meta_item_inner_impl () const override + MetaItemPathExpr *clone_meta_item_inner_impl () const override { - return new MetaItemPathLit (*this); + return new MetaItemPathExpr (*this); } }; @@ -395,6 +414,8 @@ public: return *main_or_left_expr; } + bool has_borrow_expr () const { return main_or_left_expr != nullptr; } + bool get_is_mut () const { return mutability == Mutability::Mut; } Mutability get_mutability () const { return mutability; } @@ -1160,11 +1181,11 @@ protected: // Value array elements class ArrayElemsValues : public ArrayElems { - std::vector<std::unique_ptr<Expr> > values; + std::vector<std::unique_ptr<Expr>> values; location_t locus; public: - ArrayElemsValues (std::vector<std::unique_ptr<Expr> > elems, location_t locus) + ArrayElemsValues (std::vector<std::unique_ptr<Expr>> elems, location_t locus) : ArrayElems (), values (std::move (elems)), locus (locus) {} @@ -1192,14 +1213,16 @@ public: std::string as_string () const override; + location_t get_locus () const { return locus; } + void accept_vis (ASTVisitor &vis) override; // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Expr> > &get_values () const + const std::vector<std::unique_ptr<Expr>> &get_values () const { return values; } - std::vector<std::unique_ptr<Expr> > &get_values () { return values; } + std::vector<std::unique_ptr<Expr>> &get_values () { return values; } size_t get_num_values () const { return values.size (); } @@ -1214,6 +1237,8 @@ protected: class ArrayElemsCopied : public ArrayElems { std::unique_ptr<Expr> elem_to_copy; + + // TODO: This should be replaced by a ConstExpr std::unique_ptr<Expr> num_copies; location_t locus; @@ -1246,6 +1271,8 @@ public: std::string as_string () const override; + location_t get_locus () const { return locus; } + void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? @@ -1472,7 +1499,7 @@ class TupleExpr : public ExprWithoutBlock { std::vector<Attribute> outer_attrs; std::vector<Attribute> inner_attrs; - std::vector<std::unique_ptr<Expr> > tuple_elems; + std::vector<std::unique_ptr<Expr>> tuple_elems; location_t locus; // TODO: find another way to store this to save memory? @@ -1492,7 +1519,7 @@ public: outer_attrs = std::move (new_attrs); } - TupleExpr (std::vector<std::unique_ptr<Expr> > tuple_elements, + TupleExpr (std::vector<std::unique_ptr<Expr>> tuple_elements, std::vector<Attribute> inner_attribs, std::vector<Attribute> outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), @@ -1543,14 +1570,11 @@ public: bool is_marked_for_strip () const override { return marked_for_strip; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Expr> > &get_tuple_elems () const - { - return tuple_elems; - } - std::vector<std::unique_ptr<Expr> > &get_tuple_elems () + const std::vector<std::unique_ptr<Expr>> &get_tuple_elems () const { return tuple_elems; } + std::vector<std::unique_ptr<Expr>> &get_tuple_elems () { return tuple_elems; } bool is_unit () const { return tuple_elems.size () == 0; } @@ -1775,6 +1799,8 @@ public: std::string as_string () const; + location_t get_locus () const { return locus; } + // TODO: is this better? Or is a "vis_block" better? Expr &get_base_struct () { @@ -1972,7 +1998,7 @@ protected: class StructExprStructFields : public StructExprStruct { // std::vector<StructExprField> fields; - std::vector<std::unique_ptr<StructExprField> > fields; + std::vector<std::unique_ptr<StructExprField>> fields; // bool has_struct_base; StructBase struct_base; @@ -1985,8 +2011,8 @@ public: // Constructor for StructExprStructFields when no struct base is used StructExprStructFields ( PathInExpression struct_path, - std::vector<std::unique_ptr<StructExprField> > expr_fields, - location_t locus, StructBase base_struct = StructBase::error (), + std::vector<std::unique_ptr<StructExprField>> expr_fields, location_t locus, + StructBase base_struct = StructBase::error (), std::vector<Attribute> inner_attribs = std::vector<Attribute> (), std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : StructExprStruct (std::move (struct_path), std::move (inner_attribs), @@ -2023,11 +2049,11 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: this mutable getter seems really dodgy. Think up better way. - std::vector<std::unique_ptr<StructExprField> > &get_fields () + std::vector<std::unique_ptr<StructExprField>> &get_fields () { return fields; } - const std::vector<std::unique_ptr<StructExprField> > &get_fields () const + const std::vector<std::unique_ptr<StructExprField>> &get_fields () const { return fields; } @@ -2084,7 +2110,7 @@ class CallExpr : public ExprWithoutBlock { std::vector<Attribute> outer_attrs; std::unique_ptr<Expr> function; - std::vector<std::unique_ptr<Expr> > params; + std::vector<std::unique_ptr<Expr>> params; location_t locus; public: @@ -2093,7 +2119,7 @@ public: std::string as_string () const override; CallExpr (std::unique_ptr<Expr> function_expr, - std::vector<std::unique_ptr<Expr> > function_params, + std::vector<std::unique_ptr<Expr>> function_params, std::vector<Attribute> outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), function (std::move (function_expr)), @@ -2150,11 +2176,11 @@ public: bool is_marked_for_strip () const override { return function == nullptr; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Expr> > &get_params () const + const std::vector<std::unique_ptr<Expr>> &get_params () const { return params; } - std::vector<std::unique_ptr<Expr> > &get_params () { return params; } + std::vector<std::unique_ptr<Expr>> &get_params () { return params; } // TODO: is this better? Or is a "vis_block" better? Expr &get_function_expr () @@ -2190,7 +2216,7 @@ class MethodCallExpr : public ExprWithoutBlock std::vector<Attribute> outer_attrs; std::unique_ptr<Expr> receiver; PathExprSegment method_name; - std::vector<std::unique_ptr<Expr> > params; + std::vector<std::unique_ptr<Expr>> params; location_t locus; public: @@ -2198,7 +2224,7 @@ public: MethodCallExpr (std::unique_ptr<Expr> call_receiver, PathExprSegment method_path, - std::vector<std::unique_ptr<Expr> > method_params, + std::vector<std::unique_ptr<Expr>> method_params, std::vector<Attribute> outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), receiver (std::move (call_receiver)), @@ -2254,11 +2280,11 @@ public: bool is_marked_for_strip () const override { return receiver == nullptr; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Expr> > &get_params () const + const std::vector<std::unique_ptr<Expr>> &get_params () const { return params; } - std::vector<std::unique_ptr<Expr> > &get_params () { return params; } + std::vector<std::unique_ptr<Expr>> &get_params () { return params; } // TODO: is this better? Or is a "vis_block" better? Expr &get_receiver_expr () @@ -2504,6 +2530,8 @@ public: bool get_has_move () const { return has_move; } Expr::Kind get_expr_kind () const override { return Expr::Kind::Closure; } + + virtual Expr &get_definition_expr () = 0; }; // Represents a non-type-specified closure expression AST node @@ -2563,7 +2591,7 @@ public: return closure_inner == nullptr; } - Expr &get_definition_expr () + Expr &get_definition_expr () override { rust_assert (closure_inner != nullptr); return *closure_inner; @@ -2583,7 +2611,7 @@ class BlockExpr : public ExprWithBlock { std::vector<Attribute> outer_attrs; std::vector<Attribute> inner_attrs; - std::vector<std::unique_ptr<Stmt> > statements; + std::vector<std::unique_ptr<Stmt>> statements; std::unique_ptr<Expr> expr; tl::optional<LoopLabel> label; location_t start_locus; @@ -2599,7 +2627,7 @@ public: // Returns whether the block contains a final expression. bool has_tail_expr () const { return expr != nullptr; } - BlockExpr (std::vector<std::unique_ptr<Stmt> > block_statements, + BlockExpr (std::vector<std::unique_ptr<Stmt>> block_statements, std::unique_ptr<Expr> block_expr, std::vector<Attribute> inner_attribs, std::vector<Attribute> outer_attribs, @@ -2678,11 +2706,11 @@ public: const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; } std::vector<Attribute> &get_inner_attrs () { return inner_attrs; } - const std::vector<std::unique_ptr<Stmt> > &get_statements () const + const std::vector<std::unique_ptr<Stmt>> &get_statements () const { return statements; } - std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; } + std::vector<std::unique_ptr<Stmt>> &get_statements () { return statements; } // TODO: is this better? Or is a "vis_block" better? Expr &get_tail_expr () @@ -2744,6 +2772,151 @@ protected: } }; +class AnonConst : public ExprWithBlock +{ +public: + enum class Kind + { + Explicit, + DeferredInference, + }; + + AnonConst (std::unique_ptr<Expr> &&expr, location_t locus = UNKNOWN_LOCATION) + : ExprWithBlock (), locus (locus), kind (Kind::Explicit), + expr (std::move (expr)) + { + rust_assert (this->expr.value ()); + } + + AnonConst (location_t locus = UNKNOWN_LOCATION) + : ExprWithBlock (), locus (locus), kind (Kind::DeferredInference), + expr (tl::nullopt) + {} + + AnonConst (const AnonConst &other) + { + node_id = other.node_id; + locus = other.locus; + kind = other.kind; + + if (other.expr) + expr = other.expr.value ()->clone_expr (); + } + + AnonConst operator= (const AnonConst &other) + { + node_id = other.node_id; + locus = other.locus; + kind = other.kind; + + if (other.expr) + expr = other.expr.value ()->clone_expr (); + + return *this; + } + + std::string as_string () const override; + + Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstExpr; } + + location_t get_locus () const override { return locus; } + + Expr &get_inner_expr () + { + rust_assert (expr.has_value ()); + return *expr.value (); + } + + NodeId get_node_id () const override { return node_id; } + + /* FIXME: AnonConst are always "internal" and should not have outer attributes + * - is that true? Or should we instead call + * expr->get_outer_attrs()/expr->set_outer_attrs() */ + + std::vector<Attribute> &get_outer_attrs () override + { + static auto attrs = std::vector<Attribute> (); + return attrs; + } + + void set_outer_attrs (std::vector<Attribute>) override {} + + /* FIXME: Likewise for mark_for_strip() ? */ + void mark_for_strip () override {} + bool is_marked_for_strip () const override { return false; } + + void accept_vis (ASTVisitor &vis) override; + + bool is_deferred () const { return kind == Kind::DeferredInference; } + +private: + location_t locus; + Kind kind; + tl::optional<std::unique_ptr<Expr>> expr; + + AnonConst *clone_expr_with_block_impl () const override + { + return new AnonConst (*this); + } +}; + +class ConstBlock : public ExprWithBlock +{ +public: + ConstBlock (AnonConst &&expr, location_t locus = UNKNOWN_LOCATION, + std::vector<Attribute> &&outer_attrs = {}) + : ExprWithBlock (), expr (std::move (expr)), + outer_attrs (std::move (outer_attrs)), locus (locus) + {} + + ConstBlock (const ConstBlock &other) + : ExprWithBlock (other), expr (other.expr), outer_attrs (other.outer_attrs), + locus (other.locus) + {} + + ConstBlock operator= (const ConstBlock &other) + { + expr = other.expr; + node_id = other.node_id; + outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + std::string as_string () const override; + + Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstBlock; } + + AnonConst &get_const_expr () { return expr; } + + void accept_vis (ASTVisitor &vis) override; + + std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } + + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } + + location_t get_locus () const override { return locus; } + + bool is_marked_for_strip () const override { return marked_for_strip; } + void mark_for_strip () override { marked_for_strip = true; } + +private: + AnonConst expr; + + std::vector<Attribute> outer_attrs; + location_t locus; + bool marked_for_strip = false; + + ConstBlock *clone_expr_with_block_impl () const override + { + return new ConstBlock (*this); + } +}; + // Represents a type-specified closure expression AST node class ClosureExprInnerTyped : public ClosureExpr { @@ -2812,7 +2985,7 @@ public: bool is_marked_for_strip () const override { return expr == nullptr; } // TODO: is this better? Or is a "vis_block" better? - BlockExpr &get_definition_block () + BlockExpr &get_definition_expr () override { rust_assert (expr != nullptr); return *expr; @@ -3572,6 +3745,82 @@ protected: } }; +// Try expression AST node representation +class TryExpr : public ExprWithBlock +{ + std::vector<Attribute> outer_attrs; + std::unique_ptr<BlockExpr> block_expr; + location_t locus; + + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + +public: + std::string as_string () const override; + + // Constructor for ReturnExpr. + TryExpr (std::unique_ptr<BlockExpr> block_expr, + std::vector<Attribute> outer_attribs, location_t locus) + : outer_attrs (std::move (outer_attribs)), + block_expr (std::move (block_expr)), locus (locus) + { + rust_assert (this->block_expr); + } + + // Copy constructor with clone + TryExpr (TryExpr const &other) + : ExprWithBlock (other), outer_attrs (other.outer_attrs), + block_expr (other.block_expr->clone_block_expr ()), locus (other.locus), + marked_for_strip (other.marked_for_strip) + {} + + // Overloaded assignment operator to clone return_expr pointer + TryExpr &operator= (TryExpr const &other) + { + ExprWithBlock::operator= (other); + locus = other.locus; + marked_for_strip = other.marked_for_strip; + outer_attrs = other.outer_attrs; + + block_expr = other.block_expr->clone_block_expr (); + + return *this; + } + + // move constructors + TryExpr (TryExpr &&other) = default; + TryExpr &operator= (TryExpr &&other) = default; + + location_t get_locus () const override final { return locus; } + + void accept_vis (ASTVisitor &vis) override; + + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } + + // TODO: is this better? Or is a "vis_block" better? + BlockExpr &get_block_expr () { return *block_expr; } + + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } + + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::Try; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TryExpr *clone_expr_with_block_impl () const override + { + return new TryExpr (*this); + } +}; + // Forward decl - defined in rust-macro.h class MacroInvocation; @@ -3847,14 +4096,14 @@ protected: class WhileLetLoopExpr : public BaseLoopExpr { // MatchArmPatterns patterns; - std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined + std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined std::unique_ptr<Expr> scrutinee; public: std::string as_string () const override; // Constructor with a loop label - WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns, + WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern>> match_arm_patterns, std::unique_ptr<Expr> scrutinee, std::unique_ptr<BlockExpr> loop_block, location_t locus, tl::optional<LoopLabel> loop_label = tl::nullopt, @@ -3908,11 +4157,11 @@ public: } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Pattern> > &get_patterns () const + const std::vector<std::unique_ptr<Pattern>> &get_patterns () const { return match_arm_patterns; } - std::vector<std::unique_ptr<Pattern> > &get_patterns () + std::vector<std::unique_ptr<Pattern>> &get_patterns () { return match_arm_patterns; } @@ -4195,7 +4444,7 @@ protected: class IfLetExpr : public ExprWithBlock { std::vector<Attribute> outer_attrs; - std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined + std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined std::unique_ptr<Expr> value; std::unique_ptr<BlockExpr> if_block; location_t locus; @@ -4203,7 +4452,7 @@ class IfLetExpr : public ExprWithBlock public: std::string as_string () const override; - IfLetExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns, + IfLetExpr (std::vector<std::unique_ptr<Pattern>> match_arm_patterns, std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block, std::vector<Attribute> outer_attrs, location_t locus) : outer_attrs (std::move (outer_attrs)), @@ -4297,11 +4546,11 @@ public: } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Pattern> > &get_patterns () const + const std::vector<std::unique_ptr<Pattern>> &get_patterns () const { return match_arm_patterns; } - std::vector<std::unique_ptr<Pattern> > &get_patterns () + std::vector<std::unique_ptr<Pattern>> &get_patterns () { return match_arm_patterns; } @@ -4341,11 +4590,11 @@ class IfLetExprConseqElse : public IfLetExpr public: std::string as_string () const override; - IfLetExprConseqElse ( - std::vector<std::unique_ptr<Pattern> > match_arm_patterns, - std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block, - std::unique_ptr<ExprWithBlock> else_block, - std::vector<Attribute> outer_attrs, location_t locus) + IfLetExprConseqElse (std::vector<std::unique_ptr<Pattern>> match_arm_patterns, + std::unique_ptr<Expr> value, + std::unique_ptr<BlockExpr> if_block, + std::unique_ptr<ExprWithBlock> else_block, + std::vector<Attribute> outer_attrs, location_t locus) : IfLetExpr (std::move (match_arm_patterns), std::move (value), std::move (if_block), std::move (outer_attrs), locus), else_block (std::move (else_block)) @@ -4398,7 +4647,7 @@ struct MatchArm private: std::vector<Attribute> outer_attrs; // MatchArmPatterns patterns; - std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined + std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined // bool has_match_arm_guard; // inlined from MatchArmGuard @@ -4411,7 +4660,7 @@ public: bool has_match_arm_guard () const { return guard_expr != nullptr; } // Constructor for match arm with a guard expression - MatchArm (std::vector<std::unique_ptr<Pattern> > match_arm_patterns, + MatchArm (std::vector<std::unique_ptr<Pattern>> match_arm_patterns, location_t locus, std::unique_ptr<Expr> guard_expr = nullptr, std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) : outer_attrs (std::move (outer_attrs)), @@ -4463,7 +4712,7 @@ public: static MatchArm create_error () { location_t locus = UNDEF_LOCATION; - return MatchArm (std::vector<std::unique_ptr<Pattern> > (), locus); + return MatchArm (std::vector<std::unique_ptr<Pattern>> (), locus); } std::string as_string () const; @@ -4485,11 +4734,11 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - const std::vector<std::unique_ptr<Pattern> > &get_patterns () const + const std::vector<std::unique_ptr<Pattern>> &get_patterns () const { return match_arm_patterns; } - std::vector<std::unique_ptr<Pattern> > &get_patterns () + std::vector<std::unique_ptr<Pattern>> &get_patterns () { return match_arm_patterns; } @@ -4836,29 +5085,6 @@ enum class InlineAsmOption MAY_UNWIND = 1 << 8, }; -struct AnonConst -{ - NodeId id; - std::unique_ptr<Expr> expr; - AnonConst (NodeId id, std::unique_ptr<Expr> expr) - : id (id), expr (std::move (expr)) - { - rust_assert (this->expr != nullptr); - } - AnonConst (const AnonConst &other) - { - id = other.id; - expr = other.expr->clone_expr (); - } - - AnonConst operator= (const AnonConst &other) - { - id = other.id; - expr = other.expr->clone_expr (); - return *this; - } -}; - struct InlineAsmRegOrRegClass { enum Type @@ -5288,6 +5514,20 @@ struct TupleTemplateStr // Inline Assembly Node class InlineAsm : public ExprWithoutBlock { +public: + enum class Option + { + PURE = 1 << 0, + NOMEM = 1 << 1, + READONLY = 1 << 2, + PRESERVES_FLAGS = 1 << 3, + NORETURN = 1 << 4, + NOSTACK = 1 << 5, + ATT_SYNTAX = 1 << 6, + RAW = 1 << 7, + MAY_UNWIND = 1 << 8, + }; + private: location_t locus; // TODO: Not sure how outer_attrs plays with InlineAsm, I put it here in order @@ -5311,7 +5551,7 @@ public: std::map<std::string, int> named_args; std::set<int> reg_args; std::vector<TupleClobber> clobber_abi; - std::set<InlineAsmOption> options; + std::set<InlineAsm::Option> options; std::vector<location_t> line_spans; @@ -5342,7 +5582,7 @@ public: std::vector<TupleClobber> get_clobber_abi () { return clobber_abi; } - std::set<InlineAsmOption> get_options () { return options; } + std::set<InlineAsm::Option> get_options () { return options; } InlineAsm *clone_expr_without_block_impl () const override { @@ -5350,6 +5590,33 @@ public: } Expr::Kind get_expr_kind () const override { return Expr::Kind::InlineAsm; } + + static std::string option_to_string (Option option) + { + switch (option) + { + case Option::PURE: + return "pure"; + case Option::NOMEM: + return "nomem"; + case Option::READONLY: + return "readonly"; + case Option::PRESERVES_FLAGS: + return "preserves_flags"; + case Option::NORETURN: + return "noreturn"; + case Option::NOSTACK: + return "nostack"; + case Option::ATT_SYNTAX: + return "att_syntax"; + case Option::RAW: + return "raw"; + case Option::MAY_UNWIND: + return "may_unwind"; + default: + rust_unreachable (); + } + } }; class LlvmInlineAsm : public ExprWithoutBlock diff --git a/gcc/rust/ast/rust-expression-yeast.cc b/gcc/rust/ast/rust-expression-yeast.cc new file mode 100644 index 0000000..9f6a62f --- /dev/null +++ b/gcc/rust/ast/rust-expression-yeast.cc @@ -0,0 +1,118 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-expression-yeast.h" +#include "rust-ast-visitor.h" +#include "rust-desugar-question-mark.h" +#include "rust-desugar-try-block.h" +#include "rust-desugar-for-loops.h" +#include "rust-ast-full.h" +#include "rust-desugar-while-let.h" +#include "rust-expr.h" +#include "rust-stmt.h" + +namespace Rust { +namespace AST { + +void +ExpressionYeast::go (AST::Crate &crate) +{ + DefaultASTVisitor::visit (crate); +} + +void +ExpressionYeast::dispatch_loops (std::unique_ptr<Expr> &loop_expr) +{ + auto &loop = static_cast<BaseLoopExpr &> (*loop_expr.get ()); + + switch (loop.get_loop_kind ()) + { + case BaseLoopExpr::Kind::For: + DesugarForLoops::go (loop_expr); + break; + case BaseLoopExpr::Kind::WhileLet: + DesugarWhileLet::go (loop_expr); + break; + default: + break; + } +} + +void +ExpressionYeast::dispatch (std::unique_ptr<Expr> &expr) +{ + switch (expr->get_expr_kind ()) + { + case Expr::Kind::ErrorPropagation: + DesugarQuestionMark::go (expr); + break; + case Expr::Kind::Try: + DesugarTryBlock::go (expr); + break; + case Expr::Kind::Loop: + dispatch_loops (expr); + break; + + default: + break; + } +} + +void +ExpressionYeast::visit (ExprStmt &stmt) +{ + dispatch (stmt.get_expr_ptr ()); + + DefaultASTVisitor::visit (stmt); +} + +void +ExpressionYeast::visit (CallExpr &call) +{ + dispatch (call.get_function_expr_ptr ()); + + for (auto &arg : call.get_params ()) + dispatch (arg); + + DefaultASTVisitor::visit (call); +} + +void +ExpressionYeast::visit (BlockExpr &block) +{ + for (auto &stmt : block.get_statements ()) + if (stmt->get_stmt_kind () == Stmt::Kind::Expr) + dispatch (static_cast<ExprStmt &> (*stmt).get_expr_ptr ()); + + if (block.has_tail_expr ()) + dispatch (block.get_tail_expr_ptr ()); + + DefaultASTVisitor::visit (block); +} + +void +ExpressionYeast::visit (LetStmt &stmt) +{ + if (stmt.has_init_expr ()) + dispatch (stmt.get_init_expr_ptr ()); + + DefaultASTVisitor::visit (stmt); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-expression-yeast.h b/gcc/rust/ast/rust-expression-yeast.h new file mode 100644 index 0000000..855918f --- /dev/null +++ b/gcc/rust/ast/rust-expression-yeast.h @@ -0,0 +1,52 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_EXPRESSION_YEAST +#define RUST_EXPRESSION_YEAST + +#include "rust-ast-visitor.h" +#include "rust-ast.h" +#include "rust-desugar-question-mark.h" + +namespace Rust { +namespace AST { + +// This visitor takes care of all the expression desugars: try-blocks, +// error-propagation, etc. +class ExpressionYeast : public AST::DefaultASTVisitor +{ + using AST::DefaultASTVisitor::visit; + +public: + void go (AST::Crate &); + +private: + // Dispatch to the proper desugar + void dispatch (std::unique_ptr<Expr> &expr); + void dispatch_loops (std::unique_ptr<Expr> &loop_expr); + + void visit (AST::ExprStmt &) override; + void visit (AST::CallExpr &) override; + void visit (AST::LetStmt &) override; + void visit (AST::BlockExpr &) override; +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_EXPRESSION_YEAST diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h index a54faec..3722db2 100644 --- a/gcc/rust/ast/rust-fmt.h +++ b/gcc/rust/ast/rust-fmt.h @@ -266,11 +266,10 @@ enum ParseMode extern "C" { -FormatArgsHandle -collect_pieces (const char *input, bool append_newline, ParseMode parse_mode); +FormatArgsHandle collect_pieces (const char *input, bool append_newline, + ParseMode parse_mode); -FormatArgsHandle -clone_pieces (const FormatArgsHandle &); +FormatArgsHandle clone_pieces (const FormatArgsHandle &); void destroy_pieces (FormatArgsHandle); diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 062f85d..d11eed7 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -51,21 +51,12 @@ class TypePath; // A type generic parameter (as opposed to a lifetime generic parameter) class TypeParam : public GenericParam { - // bool has_outer_attribute; - // std::unique_ptr<Attribute> outer_attr; AST::AttrVec outer_attrs; - Identifier type_representation; - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - std::vector<std::unique_ptr<TypeParamBound>> - type_param_bounds; // inlined form - - // bool has_type; + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; std::unique_ptr<Type> type; - location_t locus; + bool was_impl_trait; public: Identifier get_type_representation () const { return type_representation; } @@ -85,18 +76,19 @@ public: std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds = std::vector<std::unique_ptr<TypeParamBound>> (), std::unique_ptr<Type> type = nullptr, - AST::AttrVec outer_attrs = {}) + AST::AttrVec outer_attrs = {}, bool was_impl_trait = false) : GenericParam (Analysis::Mappings::get ().get_next_node_id ()), outer_attrs (std::move (outer_attrs)), type_representation (std::move (type_representation)), type_param_bounds (std::move (type_param_bounds)), - type (std::move (type)), locus (locus) + type (std::move (type)), locus (locus), was_impl_trait (was_impl_trait) {} // Copy constructor uses clone TypeParam (TypeParam const &other) : GenericParam (other.node_id), outer_attrs (other.outer_attrs), - type_representation (other.type_representation), locus (other.locus) + type_representation (other.type_representation), locus (other.locus), + was_impl_trait (other.was_impl_trait) { // guard to prevent null pointer dereference if (other.type != nullptr) @@ -114,6 +106,7 @@ public: outer_attrs = other.outer_attrs; locus = other.locus; node_id = other.node_id; + was_impl_trait = other.was_impl_trait; // guard to prevent null pointer dereference if (other.type != nullptr) @@ -153,17 +146,19 @@ public: return type; } - // TODO: mutable getter seems kinda dodgy std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds () { return type_param_bounds; } + const std::vector<std::unique_ptr<TypeParamBound>> & get_type_param_bounds () const { return type_param_bounds; } + bool from_impl_trait () const { return was_impl_trait; } + protected: // Clone function implementation as virtual method TypeParam *clone_generic_param_impl () const override @@ -2455,7 +2450,7 @@ class ConstantItem : public VisItem, public AssociatedItem // either has an identifier or "_" - maybe handle in identifier? // bool identifier_is_underscore; // if no identifier declared, identifier will be "_" - std::string identifier; + Identifier identifier; std::unique_ptr<Type> type; std::unique_ptr<Expr> const_expr; @@ -2465,7 +2460,7 @@ class ConstantItem : public VisItem, public AssociatedItem public: std::string as_string () const override; - ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type, + ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type, std::unique_ptr<Expr> const_expr, std::vector<Attribute> outer_attrs, location_t locus) : VisItem (std::move (vis), std::move (outer_attrs)), @@ -2473,7 +2468,7 @@ public: const_expr (std::move (const_expr)), locus (locus) {} - ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type, + ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type, std::vector<Attribute> outer_attrs, location_t locus) : VisItem (std::move (vis), std::move (outer_attrs)), identifier (std::move (ident)), type (std::move (type)), @@ -2516,7 +2511,7 @@ public: /* Returns whether constant item is an "unnamed" (wildcard underscore used * as identifier) constant. */ - bool is_unnamed () const { return identifier == "_"; } + bool is_unnamed () const { return identifier.as_string () == "_"; } location_t get_locus () const override final { return locus; } @@ -2561,7 +2556,7 @@ public: return type; } - std::string get_identifier () const { return identifier; } + const Identifier &get_identifier () const { return identifier; } Item::Kind get_item_kind () const override { diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index fc01e57..4165075 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -27,6 +27,11 @@ #include "rust-macro-builtins.h" namespace Rust { + +// forward declarations for AttributeParser +class MacroInvocLexer; +template <typename ManagedTokenSource> class Parser; + namespace AST { class MacroFragSpec @@ -756,22 +761,16 @@ private: std::vector<std::unique_ptr<MacroInvocation>> pending_eager_invocs; protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ MacroInvocation *clone_pattern_impl () const final override { return clone_macro_invocation_impl (); } - /* Use covariance to implement clone function as returning this object rather - * than base */ MacroInvocation *clone_expr_without_block_impl () const final override { return clone_macro_invocation_impl (); } - /* Use covariance to implement clone function as returning this object rather - * than base */ MacroInvocation *clone_type_no_bounds_impl () const final override { return clone_macro_invocation_impl (); @@ -788,6 +787,20 @@ public: return new MacroInvocation (*this); } + std::unique_ptr<MacroInvocation> reconstruct_macro_invocation () const + { + return nullptr; + // return reconstruct (this, + // &MacroInvocation::reconstruct_macro_invocation_impl); + } + + MacroInvocation *reconstruct_impl () const override + { + return new MacroInvocation (kind, builtin_kind, invoc_data, outer_attrs, + locus, is_semi_coloned, + reconstruct_vec (pending_eager_invocs)); + } + void add_semicolon () override { is_semi_coloned = true; } Pattern::Kind get_pattern_kind () override @@ -1108,16 +1121,14 @@ struct AttributeParser { private: // TODO: might as well rewrite to use lexer tokens - std::vector<std::unique_ptr<Token>> token_stream; - int stream_pos; + std::unique_ptr<MacroInvocLexer> lexer; + std::unique_ptr<Parser<MacroInvocLexer>> parser; public: AttributeParser (std::vector<std::unique_ptr<Token>> token_stream, - int stream_start_pos = 0) - : token_stream (std::move (token_stream)), stream_pos (stream_start_pos) - {} + int stream_start_pos = 0); - ~AttributeParser () = default; + ~AttributeParser (); std::vector<std::unique_ptr<MetaItemInner>> parse_meta_item_seq (); @@ -1126,24 +1137,10 @@ private: std::unique_ptr<MetaItemInner> parse_meta_item_inner (); // Returns whether token can end a meta item. bool is_end_meta_item_tok (TokenId id) const; - // Parses a simple path. - SimplePath parse_simple_path (); - // Parses a segment of a simple path (but not scope resolution operator). - SimplePathSegment parse_simple_path_segment (); // Parses a MetaItemLitExpr. std::unique_ptr<MetaItemLitExpr> parse_meta_item_lit (); - // Parses a literal. - Literal parse_literal (); // Parses a meta item that begins with a simple path. std::unique_ptr<MetaItem> parse_path_meta_item (); - - // TODO: should this be const? - std::unique_ptr<Token> &peek_token (int i = 0) - { - return token_stream[stream_pos + i]; - } - - void skip_token (int i = 0) { stream_pos += 1 + i; } }; } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc index 8e43ddf..793423a 100644 --- a/gcc/rust/ast/rust-path.cc +++ b/gcc/rust/ast/rust-path.cc @@ -266,6 +266,27 @@ TypePath::as_simple_path () const locus); } +std::string +TypePath::make_debug_string () const +{ + rust_assert (!segments.empty ()); + + std::string output; + + for (const auto &segment : segments) + { + if (segment != nullptr && !segment->is_lang_item () + && !segment->is_error ()) + { + if (!output.empty () || has_opening_scope_resolution_op ()) + output.append ("::"); + output.append (segment->get_ident_segment ().as_string ()); + } + } + + return output; +} + // hopefully definition here will prevent circular dependency issue TraitBound * TypePath::to_trait_bound (bool in_parens) const diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index a4ba93b..a1b19d5 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -391,6 +391,13 @@ public: return default_value.value (); } + tl::optional<GenericArg> &get_default_value () { return default_value; } + + const tl::optional<GenericArg> &get_default_value () const + { + return default_value; + } + std::string as_string () const override; void accept_vis (ASTVisitor &vis) override; @@ -779,6 +786,11 @@ public: { return new TypePathSegment (*this); } + virtual TypePathSegment *reconstruct_impl () const + { + return new TypePathSegment (lang_item, ident_segment, + has_separating_scope_resolution, locus); + } public: virtual ~TypePathSegment () {} @@ -790,6 +802,11 @@ public: { return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ()); } + // Unique pointer custom reconstruct function + std::unique_ptr<TypePathSegment> reconstruct () const + { + return reconstruct_base (this); + } TypePathSegment (PathIdentSegment ident_segment, bool has_separating_scope_resolution, location_t locus) @@ -814,6 +831,15 @@ public: node_id (Analysis::Mappings::get ().get_next_node_id ()) {} + // General constructor + TypePathSegment (tl::optional<LangItem::Kind> lang_item, + tl::optional<PathIdentSegment> ident_segment, + bool has_separating_scope_resolution, location_t locus) + : lang_item (lang_item), ident_segment (ident_segment), locus (locus), + has_separating_scope_resolution (has_separating_scope_resolution), + node_id (Analysis::Mappings::get ().get_next_node_id ()) + {} + TypePathSegment (TypePathSegment const &other) : lang_item (other.lang_item), ident_segment (other.ident_segment), locus (other.locus), @@ -968,11 +994,7 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_pattern" better? - GenericArgs &get_generic_args () - { - rust_assert (has_generic_args ()); - return generic_args; - } + GenericArgs &get_generic_args () { return generic_args; } // Use covariance to override base class method TypePathSegmentGeneric *clone_type_path_segment_impl () const override @@ -1149,6 +1171,11 @@ protected: { return new TypePath (*this); } + TypePath *reconstruct_impl () const override + { + return new TypePath (reconstruct_vec (segments), locus, + has_opening_scope_resolution); + } public: /* Returns whether the TypePath has an opening scope resolution operator @@ -1215,6 +1242,8 @@ public: std::string as_string () const override; + std::string make_debug_string () const; + /* Converts TypePath to SimplePath if possible (i.e. no generic or function * arguments). Otherwise returns an empty SimplePath. */ SimplePath as_simple_path () const; @@ -1438,6 +1467,12 @@ protected: { return new QualifiedPathInType (*this); } + QualifiedPathInType *reconstruct_impl () const override + { + return new QualifiedPathInType (path_type, + associated_segment->reconstruct (), + reconstruct_vec (segments), locus); + } public: QualifiedPathInType ( diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc index fc7b610..15ab0b7 100644 --- a/gcc/rust/ast/rust-pattern.cc +++ b/gcc/rust/ast/rust-pattern.cc @@ -65,8 +65,8 @@ IdentifierPattern::as_string () const str += variable_ident.as_string (); - if (has_pattern_to_bind ()) - str += " @ " + to_bind->as_string (); + if (has_subpattern ()) + str += " @ " + subpattern->as_string (); return str; } @@ -327,17 +327,53 @@ GroupedExpr::as_string () const } std::string -SlicePattern::as_string () const +SlicePatternItemsNoRest::as_string () const { - std::string str ("SlicePattern: "); + std::string str; - for (const auto &pattern : items) + for (const auto &pattern : patterns) str += "\n " + pattern->as_string (); return str; } std::string +SlicePatternItemsHasRest::as_string () const +{ + std::string str; + + str += "\n Lower patterns: "; + if (lower_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &lower : lower_patterns) + str += "\n " + lower->as_string (); + } + + str += "\n Upper patterns: "; + if (upper_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &upper : upper_patterns) + str += "\n " + upper->as_string (); + } + + return str; +} + +std::string +SlicePattern::as_string () const +{ + return "SlicePattern: " + items->as_string (); +} + +std::string AltPattern::as_string () const { std::string str ("AltPattern: "); @@ -367,6 +403,18 @@ GroupedExpr::accept_vis (ASTVisitor &vis) } void +SlicePatternItemsNoRest::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void +SlicePatternItemsHasRest::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void SlicePattern::accept_vis (ASTVisitor &vis) { vis.visit (*this); diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 69dbd98..4945ec4 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -74,7 +74,7 @@ class IdentifierPattern : public Pattern bool is_mut; // bool has_pattern; - std::unique_ptr<Pattern> to_bind; + std::unique_ptr<Pattern> subpattern; location_t locus; NodeId node_id; @@ -82,22 +82,22 @@ public: std::string as_string () const override; // Returns whether the IdentifierPattern has a pattern to bind. - bool has_pattern_to_bind () const { return to_bind != nullptr; } + bool has_subpattern () const { return subpattern != nullptr; } // Constructor IdentifierPattern (Identifier ident, location_t locus, bool is_ref = false, bool is_mut = false, - std::unique_ptr<Pattern> to_bind = nullptr) + std::unique_ptr<Pattern> subpattern = nullptr) : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), - is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus), + is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} IdentifierPattern (NodeId node_id, Identifier ident, location_t locus, bool is_ref = false, bool is_mut = false, - std::unique_ptr<Pattern> to_bind = nullptr) + std::unique_ptr<Pattern> subpattern = nullptr) : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), - is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus), + is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus), node_id (node_id) {} @@ -107,8 +107,8 @@ public: is_mut (other.is_mut), locus (other.locus), node_id (other.node_id) { // fix to get prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); } // Overload assignment operator to use clone @@ -121,10 +121,10 @@ public: node_id = other.node_id; // fix to prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); else - to_bind = nullptr; + subpattern = nullptr; return *this; } @@ -137,11 +137,10 @@ public: void accept_vis (ASTVisitor &vis) override; - // TODO: is this better? Or is a "vis_pattern" better? - Pattern &get_pattern_to_bind () + Pattern &get_subpattern () { - rust_assert (has_pattern_to_bind ()); - return *to_bind; + rust_assert (has_subpattern ()); + return *subpattern; } Identifier get_ident () const { return variable_ident; } @@ -375,8 +374,7 @@ enum class RangeKind EXCLUDED, }; -RangeKind -tokenid_to_rangekind (TokenId id); +RangeKind tokenid_to_rangekind (TokenId id); // AST node for matching within a certain range (range pattern) class RangePattern : public Pattern { @@ -950,7 +948,7 @@ public: * is empty). */ bool has_struct_pattern_elems () const { return !elems.is_empty (); } - location_t get_locus () const override { return path.get_locus (); } + location_t get_locus () const override { return locus; } void accept_vis (ASTVisitor &vis) override; @@ -1523,41 +1521,217 @@ protected: } }; +// Base abstract class representing patterns in a SlicePattern +class SlicePatternItems +{ +public: + enum SlicePatternItemType + { + NO_REST, + HAS_REST, + }; + + virtual ~SlicePatternItems () {} + + // TODO: should this store location data? + + // Unique pointer custom clone function + std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const + { + return std::unique_ptr<SlicePatternItems> ( + clone_slice_pattern_items_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + + virtual SlicePatternItemType get_pattern_type () const = 0; + +protected: + // pure virtual clone implementation + virtual SlicePatternItems *clone_slice_pattern_items_impl () const = 0; +}; + +// Class representing the patterns in a SlicePattern without `..` +class SlicePatternItemsNoRest : public SlicePatternItems +{ + std::vector<std::unique_ptr<Pattern>> patterns; + +public: + SlicePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns) + : patterns (std::move (patterns)) + {} + + // Copy constructor with vector clone + SlicePatternItemsNoRest (SlicePatternItemsNoRest const &other) + { + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to vector clone + SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest const &other) + { + patterns.clear (); + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + SlicePatternItemsNoRest (SlicePatternItemsNoRest &&other) = default; + SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest &&other) + = default; + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; } + const std::vector<std::unique_ptr<Pattern>> &get_patterns () const + { + return patterns; + } + + SlicePatternItemType get_pattern_type () const override + { + return SlicePatternItemType::NO_REST; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SlicePatternItemsNoRest *clone_slice_pattern_items_impl () const override + { + return new SlicePatternItemsNoRest (*this); + } +}; + +// Class representing the patterns in a SlicePattern that contains a `..` +class SlicePatternItemsHasRest : public SlicePatternItems +{ + std::vector<std::unique_ptr<Pattern>> lower_patterns; + std::vector<std::unique_ptr<Pattern>> upper_patterns; + +public: + SlicePatternItemsHasRest ( + std::vector<std::unique_ptr<Pattern>> lower_patterns, + std::vector<std::unique_ptr<Pattern>> upper_patterns) + : lower_patterns (std::move (lower_patterns)), + upper_patterns (std::move (upper_patterns)) + {} + + // Copy constructor with vector clone + SlicePatternItemsHasRest (SlicePatternItemsHasRest const &other) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to clone + SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest const &other) + { + lower_patterns.clear (); + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.clear (); + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + SlicePatternItemsHasRest (SlicePatternItemsHasRest &&other) = default; + SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest &&other) + = default; + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () + { + return lower_patterns; + } + const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const + { + return lower_patterns; + } + + // TODO: seems kinda dodgy. Think of better way. + std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () + { + return upper_patterns; + } + const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const + { + return upper_patterns; + } + + SlicePatternItemType get_pattern_type () const override + { + return SlicePatternItemType::HAS_REST; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SlicePatternItemsHasRest *clone_slice_pattern_items_impl () const override + { + return new SlicePatternItemsHasRest (*this); + } +}; + // AST node representing patterns that can match slices and arrays class SlicePattern : public Pattern { - std::vector<std::unique_ptr<Pattern>> items; + std::unique_ptr<SlicePatternItems> items; location_t locus; NodeId node_id; public: std::string as_string () const override; - SlicePattern (std::vector<std::unique_ptr<Pattern>> items, location_t locus) + SlicePattern (std::unique_ptr<SlicePatternItems> items, location_t locus) : items (std::move (items)), locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} - // Copy constructor with vector clone + // Copy constructor requires clone SlicePattern (SlicePattern const &other) : locus (other.locus) { + // guard to prevent null dereference + rust_assert (other.items != nullptr); + node_id = other.node_id; - items.reserve (other.items.size ()); - for (const auto &e : other.items) - items.push_back (e->clone_pattern ()); + items = other.items->clone_slice_pattern_items (); } - // Overloaded assignment operator to vector clone + // Overloaded assignment operator to clone SlicePattern &operator= (SlicePattern const &other) { locus = other.locus; node_id = other.node_id; - items.clear (); - items.reserve (other.items.size ()); - for (const auto &e : other.items) - items.push_back (e->clone_pattern ()); + // guard to prevent null dereference + rust_assert (other.items != nullptr); + items = other.items->clone_slice_pattern_items (); return *this; } @@ -1570,10 +1744,10 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: seems kinda dodgy. Think of better way. - std::vector<std::unique_ptr<Pattern>> &get_items () { return items; } - const std::vector<std::unique_ptr<Pattern>> &get_items () const + SlicePatternItems &get_items () { - return items; + rust_assert (items != nullptr); + return *items; } NodeId get_node_id () const override { return node_id; } diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 1bb521d..2a3496b 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -19,7 +19,9 @@ #ifndef RUST_AST_TYPE_H #define RUST_AST_TYPE_H +#include "optional.h" #include "rust-ast.h" +#include "rust-expr.h" #include "rust-path.h" namespace Rust { @@ -73,6 +75,13 @@ public: type_path (std::move (type_path)), locus (locus) {} + TraitBound (TraitBound const &other) + : TypeParamBound (other.get_node_id ()), in_parens (other.in_parens), + opening_question_mark (other.opening_question_mark), + for_lifetimes (other.for_lifetimes), type_path (other.type_path), + locus (other.locus) + {} + std::string as_string () const override; location_t get_locus () const override final { return locus; } @@ -99,6 +108,11 @@ protected: return new TraitBound (node_id, type_path, locus, in_parens, opening_question_mark, for_lifetimes); } + TraitBound *reconstruct_impl () const override + { + return new TraitBound (type_path, locus, in_parens, opening_question_mark, + for_lifetimes); + } }; // definition moved to rust-ast.h @@ -120,6 +134,10 @@ protected: { return new ImplTraitType (*this); } + ImplTraitType *reconstruct_impl () const override + { + return new ImplTraitType (reconstruct_vec (type_param_bounds), locus); + } public: ImplTraitType ( @@ -129,7 +147,8 @@ public: {} // copy constructor with vector clone - ImplTraitType (ImplTraitType const &other) : locus (other.locus) + ImplTraitType (ImplTraitType const &other) + : Type (other.node_id), locus (other.locus) { type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) @@ -184,6 +203,11 @@ protected: { return new TraitObjectType (*this); } + TraitObjectType *reconstruct_impl () const override + { + return new TraitObjectType (reconstruct_vec (type_param_bounds), locus, + has_dyn); + } public: TraitObjectType ( @@ -195,7 +219,7 @@ public: // copy constructor with vector clone TraitObjectType (TraitObjectType const &other) - : has_dyn (other.has_dyn), locus (other.locus) + : Type (other.node_id), has_dyn (other.has_dyn), locus (other.locus) { type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) @@ -251,6 +275,10 @@ protected: { return new ParenthesisedType (*this); } + ParenthesisedType *reconstruct_impl () const override + { + return new ParenthesisedType (type_in_parens->reconstruct (), locus); + } public: // Constructor uses Type pointer for polymorphism @@ -305,33 +333,35 @@ public: // Impl trait with a single bound? Poor reference material here. class ImplTraitTypeOneBound : public TypeNoBounds { - TraitBound trait_bound; + std::unique_ptr<TypeParamBound> trait_bound; location_t locus; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override - { - return new ImplTraitTypeOneBound (*this); - } - public: - ImplTraitTypeOneBound (TraitBound trait_bound, location_t locus) + ImplTraitTypeOneBound (std::unique_ptr<TypeParamBound> trait_bound, + location_t locus) : trait_bound (std::move (trait_bound)), locus (locus) {} + ImplTraitTypeOneBound (ImplTraitTypeOneBound const &other) + : trait_bound (other.trait_bound->clone_type_param_bound ()), + locus (other.locus) + {} + std::string as_string () const override; location_t get_locus () const override final { return locus; } void accept_vis (ASTVisitor &vis) override; - // TODO: would a "vis_type" be better? - TraitBound &get_trait_bound () + std::unique_ptr<TypeParamBound> &get_trait_bound () { return trait_bound; } + + TypeNoBounds *clone_type_no_bounds_impl () const override { - // TODO: check to ensure invariants are met? - return trait_bound; + return new ImplTraitTypeOneBound (*this); + } + TypeNoBounds *reconstruct_impl () const override + { + return new ImplTraitTypeOneBound (trait_bound->reconstruct (), locus); } }; @@ -350,6 +380,10 @@ protected: { return new TraitObjectTypeOneBound (*this); } + TraitObjectTypeOneBound *reconstruct_impl () const override + { + return new TraitObjectTypeOneBound (trait_bound, locus, has_dyn); + } public: TraitObjectTypeOneBound (TraitBound trait_bound, location_t locus, @@ -443,6 +477,10 @@ protected: { return new TupleType (*this); } + TupleType *reconstruct_impl () const override + { + return new TupleType (reconstruct_vec (elems), locus); + } }; /* A type with no values, representing the result of computations that never @@ -459,6 +497,10 @@ protected: { return new NeverType (*this); } + NeverType *reconstruct_impl () const override + { + return new NeverType (locus); + } public: NeverType (location_t locus) : locus (locus) {} @@ -529,6 +571,9 @@ public: return *type; } + // Getter for direct access to the type unique_ptr + std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -536,6 +581,10 @@ protected: { return new RawPointerType (*this); } + RawPointerType *reconstruct_impl () const override + { + return new RawPointerType (pointer_type, type->reconstruct (), locus); + } }; // A type pointing to memory owned by another value @@ -604,6 +653,9 @@ public: TypeNoBounds &get_base_type () { return *type; } + // Getter for direct access to the type unique_ptr + std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -611,33 +663,42 @@ protected: { return new ReferenceType (*this); } + ReferenceType *reconstruct_impl () const override + { + return new ReferenceType (has_mut, type->reconstruct (), locus, + // TODO: Improve this - it's ugly! + has_lifetime () ? tl::make_optional<Lifetime> ( + lifetime->get_lifetime_type (), + lifetime->get_lifetime_name (), + lifetime->get_locus ()) + : tl::nullopt); + } }; // A fixed-size sequence of elements of a specified type class ArrayType : public TypeNoBounds { std::unique_ptr<Type> elem_type; - std::unique_ptr<Expr> size; + AnonConst size; location_t locus; public: // Constructor requires pointers for polymorphism - ArrayType (std::unique_ptr<Type> type, std::unique_ptr<Expr> array_size, - location_t locus) + ArrayType (std::unique_ptr<Type> type, AnonConst array_size, location_t locus) : elem_type (std::move (type)), size (std::move (array_size)), locus (locus) {} // Copy constructor requires deep copies of both unique pointers ArrayType (ArrayType const &other) - : elem_type (other.elem_type->clone_type ()), - size (other.size->clone_expr ()), locus (other.locus) + : elem_type (other.elem_type->clone_type ()), size (other.size), + locus (other.locus) {} // Overload assignment operator to deep copy pointers ArrayType &operator= (ArrayType const &other) { elem_type = other.elem_type->clone_type (); - size = other.size->clone_expr (); + size = other.size; locus = other.locus; return *this; } @@ -660,12 +721,15 @@ public: } // TODO: would a "vis_expr" be better? - Expr &get_size_expr () + AnonConst &get_size_expr () { - rust_assert (size != nullptr); - return *size; + // rust_assert (size != nullptr); + + return size; } + std::unique_ptr<Type> &get_element_type () { return elem_type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -673,6 +737,12 @@ protected: { return new ArrayType (*this); } + ArrayType *reconstruct_impl () const override + { + return new ArrayType (elem_type->reconstruct (), + size /* FIXME: This should be `reconstruct_expr()` */, + locus); + } }; /* A dynamically-sized type representing a "view" into a sequence of elements of @@ -719,13 +789,20 @@ public: return *elem_type; } + // Getter for direct access to the elem_type unique_ptr + std::unique_ptr<Type> &get_elem_type_ptr () { return elem_type; } + protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ + /* Use covariance to implement clone function as returning this object + * rather than base */ SliceType *clone_type_no_bounds_impl () const override { return new SliceType (*this); } + SliceType *reconstruct_impl () const override + { + return new SliceType (elem_type->reconstruct (), locus); + } }; /* Type used in generic arguments to explicitly request type inference (wildcard @@ -736,13 +813,21 @@ class InferredType : public TypeNoBounds // e.g. Vec<_> = whatever protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ + /* Use covariance to implement clone function as returning this object + * rather than base */ InferredType *clone_type_no_bounds_impl () const override { + // This goes through the copy constructor return new InferredType (*this); } + InferredType *reconstruct_impl () const override + { + // This goes through the base constructor which calls the base + // TypeNoBounds constructor, which allocates a new NodeId + return new InferredType (locus); + } + public: InferredType (location_t locus) : locus (locus) {} @@ -961,9 +1046,17 @@ public: FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; } + BareFunctionType *reconstruct_impl () const override + { + return new BareFunctionType ( + for_lifetimes, function_qualifiers, params, + /* FIXME: Should params be reconstruct() as well? */ + _is_variadic, variadic_attrs, return_type->reconstruct (), locus); + } + protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ + /* Use covariance to implement clone function as returning this object + * rather than base */ BareFunctionType *clone_type_no_bounds_impl () const override { return new BareFunctionType (*this); @@ -980,13 +1073,13 @@ class MacroInvocation; * function item type? * closure expression types? * primitive types (bool, int, float, char, str (the slice)) - * Although supposedly TypePaths are used to reference these types (including - * primitives) */ + * Although supposedly TypePaths are used to reference these types + * (including primitives) */ /* FIXME: Incomplete spec references: - * anonymous type parameters, aka "impl Trait in argument position" - impl then - * trait bounds abstract return types, aka "impl Trait in return position" - - * impl then trait bounds */ + * anonymous type parameters, aka "impl Trait in argument position" - impl + * then trait bounds abstract return types, aka "impl Trait in return + * position" - impl then trait bounds */ } // namespace AST } // namespace Rust |