aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/ast
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/ast')
-rw-r--r--gcc/rust/ast/rust-ast-builder-type.cc163
-rw-r--r--gcc/rust/ast/rust-ast-builder-type.h57
-rw-r--r--gcc/rust/ast/rust-ast-builder.cc578
-rw-r--r--gcc/rust/ast/rust-ast-builder.h204
-rw-r--r--gcc/rust/ast/rust-ast-collector.cc280
-rw-r--r--gcc/rust/ast/rust-ast-collector.h7
-rw-r--r--gcc/rust/ast/rust-ast-fragment.h15
-rw-r--r--gcc/rust/ast/rust-ast-full-decls.h10
-rw-r--r--gcc/rust/ast/rust-ast-visitor.cc158
-rw-r--r--gcc/rust/ast/rust-ast-visitor.h26
-rw-r--r--gcc/rust/ast/rust-ast.cc135
-rw-r--r--gcc/rust/ast/rust-ast.h231
-rw-r--r--gcc/rust/ast/rust-builtin-ast-nodes.h2
-rw-r--r--gcc/rust/ast/rust-collect-lang-items.cc137
-rw-r--r--gcc/rust/ast/rust-collect-lang-items.h64
-rw-r--r--gcc/rust/ast/rust-desugar-apit.cc518
-rw-r--r--gcc/rust/ast/rust-desugar-apit.h (renamed from gcc/rust/ast/rust-macro.cc)21
-rw-r--r--gcc/rust/ast/rust-desugar-for-loops.cc204
-rw-r--r--gcc/rust/ast/rust-desugar-for-loops.h108
-rw-r--r--gcc/rust/ast/rust-desugar-question-mark.cc167
-rw-r--r--gcc/rust/ast/rust-desugar-question-mark.h79
-rw-r--r--gcc/rust/ast/rust-expr.h989
-rw-r--r--gcc/rust/ast/rust-fmt.cc6
-rw-r--r--gcc/rust/ast/rust-fmt.h12
-rw-r--r--gcc/rust/ast/rust-item.h494
-rw-r--r--gcc/rust/ast/rust-macro.h43
-rw-r--r--gcc/rust/ast/rust-path.cc37
-rw-r--r--gcc/rust/ast/rust-path.h320
-rw-r--r--gcc/rust/ast/rust-pattern.cc32
-rw-r--r--gcc/rust/ast/rust-pattern.h66
-rw-r--r--gcc/rust/ast/rust-stmt.h31
-rw-r--r--gcc/rust/ast/rust-type.h69
32 files changed, 4364 insertions, 899 deletions
diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc
new file mode 100644
index 0000000..13126b4
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-builder-type.cc
@@ -0,0 +1,163 @@
+// 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
new file mode 100644
index 0000000..b67ae3b
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-builder-type.h
@@ -0,0 +1,57 @@
+// 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 1138d3d..e4c03e5 100644
--- a/gcc/rust/ast/rust-ast-builder.cc
+++ b/gcc/rust/ast/rust-ast-builder.cc
@@ -17,15 +17,31 @@
// <http://www.gnu.org/licenses/>.
#include "rust-ast-builder.h"
-#include "rust-ast-full-decls.h"
-#include "rust-ast-full.h"
+#include "optional.h"
+#include "rust-ast-builder-type.h"
+#include "rust-ast.h"
+#include "rust-common.h"
#include "rust-expr.h"
+#include "rust-keyword-values.h"
+#include "rust-path.h"
+#include "rust-item.h"
+#include "rust-path.h"
+#include "rust-pattern.h"
+#include "rust-system.h"
#include "rust-token.h"
-#include "rust-make-unique.h"
+#include <memory>
namespace Rust {
namespace AST {
+std::unique_ptr<Stmt>
+Builder::statementify (std::unique_ptr<Expr> &&value,
+ bool semicolon_followed) const
+{
+ return std::make_unique<ExprStmt> (std::move (value), loc,
+ semicolon_followed);
+}
+
std::unique_ptr<Expr>
Builder::literal_string (std::string &&content) const
{
@@ -35,6 +51,17 @@ Builder::literal_string (std::string &&content) const
}
std::unique_ptr<Expr>
+Builder::literal_bool (bool b) const
+{
+ auto str
+ = b ? Values::Keywords::TRUE_LITERAL : Values::Keywords::FALSE_LITERAL;
+
+ return std::unique_ptr<Expr> (
+ new AST::LiteralExpr (std::move (str), Literal::LitType::BOOL,
+ PrimitiveCoreType::CORETYPE_BOOL, {}, loc));
+}
+
+std::unique_ptr<Expr>
Builder::call (std::unique_ptr<Expr> &&path,
std::vector<std::unique_ptr<Expr>> &&args) const
{
@@ -43,19 +70,56 @@ Builder::call (std::unique_ptr<Expr> &&path,
}
std::unique_ptr<Expr>
+Builder::call (std::unique_ptr<Expr> &&path, std::unique_ptr<Expr> &&arg) const
+{
+ auto args = std::vector<std::unique_ptr<Expr>> ();
+ args.emplace_back (std::move (arg));
+
+ return call (std::move (path), std::move (args));
+}
+
+std::unique_ptr<Expr>
Builder::array (std::vector<std::unique_ptr<Expr>> &&members) const
{
- auto elts = Rust::make_unique<ArrayElemsValues> (std::move (members), loc);
+ auto elts = std::make_unique<ArrayElemsValues> (std::move (members), loc);
return std::unique_ptr<Expr> (new ArrayExpr (std::move (elts), {}, {}, loc));
}
std::unique_ptr<Expr>
+Builder::qualified_path_in_expression (std::unique_ptr<Type> &&type,
+ TypePath trait,
+ PathExprSegment segment) const
+{
+ auto segments = {segment};
+
+ return qualified_path_in_expression (std::move (type), trait, segments);
+}
+
+std::unique_ptr<Expr>
+Builder::qualified_path_in_expression (
+ std::unique_ptr<Type> &&type, TypePath trait,
+ std::vector<PathExprSegment> &&segments) const
+{
+ auto qual_type = QualifiedPathType (std::move (type), loc, trait);
+
+ return std::unique_ptr<QualifiedPathInExpression> (
+ new QualifiedPathInExpression (qual_type, std::move (segments), {}, loc));
+}
+
+std::unique_ptr<Expr>
Builder::identifier (std::string name) const
{
return std::unique_ptr<Expr> (new IdentifierExpr (name, {}, loc));
}
+std::unique_ptr<Pattern>
+Builder::identifier_pattern (std::string name, bool mut) const
+{
+ return std::unique_ptr<Pattern> (
+ new IdentifierPattern (name, loc, false, mut));
+}
+
std::unique_ptr<Expr>
Builder::tuple_idx (std::string receiver, int idx) const
{
@@ -63,12 +127,48 @@ Builder::tuple_idx (std::string receiver, int idx) const
new TupleIndexExpr (identifier (receiver), idx, {}, loc));
}
+std::unique_ptr<Expr>
+Builder::tuple (std::vector<std::unique_ptr<Expr>> &&values) const
+{
+ return std::unique_ptr<TupleExpr> (
+ new TupleExpr (std::move (values), {}, {}, loc));
+}
+
+std::unique_ptr<Param>
+Builder::self_ref_param (bool mutability) const
+{
+ return std::make_unique<SelfParam> (tl::nullopt, mutability, loc);
+}
+
+std::unique_ptr<Param>
+Builder::function_param (std::unique_ptr<Pattern> &&pattern,
+ std::unique_ptr<Type> &&type) const
+{
+ return std::unique_ptr<FunctionParam> (
+ new FunctionParam (std::move (pattern), std::move (type), {}, loc));
+}
+
FunctionQualifiers
Builder::fn_qualifiers () const
{
return FunctionQualifiers (loc, Async::No, Const::No, Unsafety::Normal);
}
+std::unique_ptr<Function>
+Builder::function (std::string function_name,
+ std::vector<std::unique_ptr<Param>> params,
+ std::unique_ptr<Type> return_type,
+ std::unique_ptr<BlockExpr> block,
+ std::vector<std::unique_ptr<GenericParam>> generic_params,
+ FunctionQualifiers qualifiers, WhereClause where_clause,
+ Visibility visibility) const
+{
+ return std::unique_ptr<Function> (
+ new Function (function_name, qualifiers, std::move (generic_params),
+ std::move (params), std::move (return_type), where_clause,
+ std::move (block), visibility, {}, loc));
+}
+
PathExprSegment
Builder::path_segment (std::string seg) const
{
@@ -82,6 +182,28 @@ Builder::type_path_segment (std::string seg) const
new TypePathSegment (seg, false, loc));
}
+std::unique_ptr<TypePathSegment>
+Builder::type_path_segment (LangItem::Kind lang_item) const
+{
+ return std::unique_ptr<TypePathSegment> (
+ new TypePathSegment (lang_item, loc));
+}
+
+std::unique_ptr<TypePathSegment>
+Builder::type_path_segment_generic (std::string seg, GenericArgs args) const
+{
+ return std::unique_ptr<TypePathSegment> (
+ new TypePathSegmentGeneric (PathIdentSegment (seg, loc), false, args, loc));
+}
+
+std::unique_ptr<TypePathSegment>
+Builder::type_path_segment_generic (LangItem::Kind lang_item,
+ GenericArgs args) const
+{
+ return std::unique_ptr<TypePathSegment> (
+ new TypePathSegmentGeneric (lang_item, args, loc));
+}
+
std::unique_ptr<Type>
Builder::single_type_path (std::string type) const
{
@@ -91,39 +213,156 @@ Builder::single_type_path (std::string type) const
return std::unique_ptr<Type> (new TypePath (std::move (segments), loc));
}
+std::unique_ptr<Type>
+Builder::single_type_path (LangItem::Kind lang_item) const
+{
+ return std::unique_ptr<Type> (new TypePath (lang_item, {}, loc));
+}
+
+std::unique_ptr<Type>
+Builder::single_generic_type_path (std::string type, GenericArgs args) const
+{
+ auto segments = std::vector<std::unique_ptr<TypePathSegment>> ();
+ segments.emplace_back (type_path_segment_generic (type, args));
+
+ return std::unique_ptr<Type> (new TypePath (std::move (segments), loc));
+}
+
+std::unique_ptr<Type>
+Builder::single_generic_type_path (LangItem::Kind lang_item,
+ GenericArgs args) const
+{
+ auto segments = std::vector<std::unique_ptr<TypePathSegment>> ();
+ segments.emplace_back (type_path_segment_generic (lang_item, args));
+
+ return std::unique_ptr<Type> (new TypePath (std::move (segments), loc));
+}
+
+TypePath
+Builder::type_path (std::vector<std::unique_ptr<TypePathSegment>> &&segments,
+ bool opening_scope) const
+{
+ return TypePath (std::move (segments), loc, opening_scope);
+}
+
+TypePath
+Builder::type_path (std::vector<std::string> &&segments,
+ bool opening_scope) const
+{
+ auto type_segments = std::vector<std::unique_ptr<TypePathSegment>> ();
+
+ for (auto &&segment : segments)
+ type_segments.emplace_back (type_path_segment (segment));
+
+ return TypePath (std::move (type_segments), loc, opening_scope);
+}
+
+TypePath
+Builder::type_path (std::unique_ptr<TypePathSegment> &&segment) const
+{
+ auto segments = std::vector<std::unique_ptr<TypePathSegment>> ();
+ segments.emplace_back (std::move (segment));
+
+ return type_path (std::move (segments));
+}
+
+TypePath
+Builder::type_path (std::string type) const
+{
+ return type_path (type_path_segment (type));
+}
+
+TypePath
+Builder::type_path (LangItem::Kind lang_item) const
+{
+ return type_path (type_path_segment (lang_item));
+}
+
+std::unique_ptr<Type>
+Builder::reference_type (std::unique_ptr<TypeNoBounds> &&inner_type,
+ bool mutability) const
+{
+ return std::make_unique<ReferenceType> (mutability, std::move (inner_type),
+ loc);
+}
+
PathInExpression
-Builder::path_in_expression (std::vector<std::string> &&segments) const
+Builder::path_in_expression (std::vector<std::string> &&segments,
+ bool opening_scope) const
{
auto path_segments = std::vector<PathExprSegment> ();
for (auto &seg : segments)
path_segments.emplace_back (path_segment (seg));
- return PathInExpression (std::move (path_segments), {}, loc);
+ return PathInExpression (std::move (path_segments), {}, loc, opening_scope);
}
-std::unique_ptr<Expr>
+PathInExpression
+Builder::path_in_expression (LangItem::Kind lang_item) const
+{
+ return PathInExpression (lang_item, {}, loc);
+}
+
+PathInExpression
+Builder::variant_path (const std::string &enum_path,
+ const std::string &variant) const
+{
+ return PathInExpression ({path_segment (enum_path), path_segment (variant)},
+ {}, loc, false);
+}
+
+std::unique_ptr<BlockExpr>
+Builder::block (tl::optional<std::unique_ptr<Stmt>> &&stmt,
+ std::unique_ptr<Expr> &&tail_expr) const
+{
+ auto stmts = std::vector<std::unique_ptr<Stmt>> ();
+
+ if (stmt)
+ stmts.emplace_back (std::move (*stmt));
+
+ return block (std::move (stmts), std::move (tail_expr));
+}
+
+std::unique_ptr<BlockExpr>
+Builder::block () const
+{
+ auto stmts = std::vector<std::unique_ptr<Stmt>> ();
+
+ return block (std::move (stmts));
+}
+
+std::unique_ptr<BlockExpr>
Builder::block (std::vector<std::unique_ptr<Stmt>> &&stmts,
std::unique_ptr<Expr> &&tail_expr) const
{
- return std::unique_ptr<Expr> (new BlockExpr (std::move (stmts),
- std::move (tail_expr), {}, {},
- LoopLabel::error (), loc, loc));
+ return std::unique_ptr<BlockExpr> (new BlockExpr (std::move (stmts),
+ std::move (tail_expr), {},
+ {}, tl::nullopt, loc, loc));
+}
+
+std::unique_ptr<Expr>
+Builder::return_expr (std::unique_ptr<Expr> &&to_return)
+{
+ return std::unique_ptr<Expr> (
+ new ReturnExpr (std::move (to_return), {}, loc));
}
std::unique_ptr<Stmt>
-Builder::let (std::unique_ptr<Pattern> pattern, std::unique_ptr<Type> type,
- std::unique_ptr<Expr> init) const
+Builder::let (std::unique_ptr<Pattern> &&pattern, std::unique_ptr<Type> &&type,
+ std::unique_ptr<Expr> &&init) const
{
return std::unique_ptr<Stmt> (new LetStmt (std::move (pattern),
std::move (init), std::move (type),
- {}, loc));
+ tl::nullopt, {}, loc));
}
std::unique_ptr<Expr>
Builder::ref (std::unique_ptr<Expr> &&of, bool mut) const
{
+ auto mutability = mut ? Mutability::Mut : Mutability::Imm;
return std::unique_ptr<Expr> (
- new BorrowExpr (std::move (of), mut, /* is double */ false, {}, loc));
+ new BorrowExpr (std::move (of), mutability,
+ /* raw */ false, /* is double */ false, {}, loc));
}
std::unique_ptr<Expr>
@@ -133,6 +372,37 @@ Builder::deref (std::unique_ptr<Expr> &&of) const
}
std::unique_ptr<Expr>
+Builder::comparison_expr (std::unique_ptr<Expr> &&lhs,
+ std::unique_ptr<Expr> &&rhs,
+ ComparisonOperator op) const
+{
+ return std::make_unique<ComparisonExpr> (std::move (lhs), std::move (rhs), op,
+ loc);
+}
+
+std::unique_ptr<Expr>
+Builder::boolean_operation (std::unique_ptr<Expr> &&lhs,
+ std::unique_ptr<Expr> &&rhs,
+ LazyBooleanOperator op) const
+{
+ return std::make_unique<LazyBooleanExpr> (std::move (lhs), std::move (rhs),
+ op, loc);
+}
+
+std::unique_ptr<Stmt>
+Builder::struct_struct (std::string struct_name,
+ std::vector<std::unique_ptr<GenericParam>> &&generics,
+ std::vector<StructField> &&fields)
+{
+ auto is_unit = fields.empty ();
+
+ return std::unique_ptr<Stmt> (
+ new StructStruct (std::move (fields), struct_name, std::move (generics),
+ WhereClause::create_empty (), is_unit,
+ Visibility::create_private (), {}, loc));
+}
+
+std::unique_ptr<Expr>
Builder::struct_expr_struct (std::string struct_name) const
{
return std::unique_ptr<Expr> (
@@ -144,9 +414,16 @@ Builder::struct_expr (
std::string struct_name,
std::vector<std::unique_ptr<StructExprField>> &&fields) const
{
+ return struct_expr (path_in_expression ({struct_name}), std::move (fields));
+}
+
+std::unique_ptr<Expr>
+Builder::struct_expr (
+ PathInExpression struct_name,
+ std::vector<std::unique_ptr<StructExprField>> &&fields) const
+{
return std::unique_ptr<Expr> (
- new StructExprStructFields (path_in_expression ({struct_name}),
- std::move (fields), loc));
+ new StructExprStructFields (struct_name, std::move (fields), loc));
}
std::unique_ptr<StructExprField>
@@ -165,11 +442,280 @@ 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
{
return std::unique_ptr<Pattern> (new WildcardPattern (loc));
}
+std::unique_ptr<Pattern>
+Builder::ref_pattern (std::unique_ptr<Pattern> &&inner) const
+{
+ return std::make_unique<ReferencePattern> (std::move (inner), false, false,
+ loc);
+}
+
+std::unique_ptr<Path>
+Builder::lang_item_path (LangItem::Kind kind) const
+{
+ return std::unique_ptr<Path> (new PathInExpression (kind, {}, loc));
+}
+
+std::unique_ptr<Expr>
+Builder::match (std::unique_ptr<Expr> &&scrutinee,
+ std::vector<MatchCase> &&cases)
+{
+ return std::unique_ptr<Expr> (
+ new MatchExpr (std::move (scrutinee), std::move (cases), {}, {}, loc));
+}
+
+MatchArm
+Builder::match_arm (std::unique_ptr<Pattern> &&pattern)
+{
+ auto patterns = std::vector<std::unique_ptr<Pattern>> ();
+ patterns.emplace_back (std::move (pattern));
+
+ return MatchArm (std::move (patterns), loc);
+}
+
+MatchCase
+Builder::match_case (std::unique_ptr<Pattern> &&pattern,
+ std::unique_ptr<Expr> &&expr)
+{
+ return MatchCase (match_arm (std::move (pattern)), std::move (expr));
+}
+
+std::unique_ptr<Expr>
+Builder::loop (std::vector<std::unique_ptr<Stmt>> &&stmts)
+{
+ auto block_expr = block (std::move (stmts), nullptr);
+
+ return std::unique_ptr<Expr> (new LoopExpr (std::move (block_expr), loc));
+}
+
+std::unique_ptr<TypeParamBound>
+Builder::trait_bound (TypePath bound)
+{
+ return std::make_unique<TraitBound> (bound, loc);
+}
+
+std::unique_ptr<Item>
+Builder::trait_impl (TypePath trait_path, std::unique_ptr<Type> target,
+ std::vector<std::unique_ptr<AssociatedItem>> trait_items,
+ std::vector<std::unique_ptr<GenericParam>> generics,
+ WhereClause where_clause, Visibility visibility) const
+{
+ return std::unique_ptr<Item> (
+ new TraitImpl (trait_path, /* unsafe */ false,
+ /* exclam */ false, std::move (trait_items),
+ std::move (generics), std::move (target), where_clause,
+ visibility, {}, {}, loc));
+}
+
+std::unique_ptr<GenericParam>
+Builder::generic_type_param (
+ std::string type_representation,
+ std::vector<std::unique_ptr<TypeParamBound>> &&bounds,
+ std::unique_ptr<Type> &&type)
+{
+ return std::make_unique<TypeParam> (type_representation, loc,
+ std::move (bounds), std::move (type),
+ std::vector<Attribute> ());
+}
+
+std::unique_ptr<Type>
+Builder::new_type (Type &type)
+{
+ Type *t = ASTTypeBuilder::build (type);
+ return std::unique_ptr<Type> (t);
+}
+
+std::unique_ptr<GenericParam>
+Builder::new_lifetime_param (LifetimeParam &param)
+{
+ Lifetime l = new_lifetime (param.get_lifetime ());
+ std::vector<Lifetime> lifetime_bounds;
+ for (auto b : param.get_lifetime_bounds ())
+ {
+ Lifetime bl = new_lifetime (b);
+ lifetime_bounds.push_back (bl);
+ }
+
+ auto p = new LifetimeParam (l, std::move (lifetime_bounds),
+ param.get_outer_attrs (), param.get_locus ());
+ return std::unique_ptr<GenericParam> (p);
+}
+
+std::unique_ptr<GenericParam>
+Builder::new_type_param (
+ TypeParam &param, std::vector<std::unique_ptr<TypeParamBound>> extra_bounds)
+{
+ location_t locus = param.get_locus ();
+ AST::AttrVec outer_attrs = param.get_outer_attrs ();
+ Identifier type_representation = param.get_type_representation ();
+ std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
+ std::unique_ptr<Type> type = nullptr;
+
+ if (param.has_type ())
+ type = new_type (param.get_type ());
+
+ for (auto &&extra_bound : extra_bounds)
+ type_param_bounds.emplace_back (std::move (extra_bound));
+
+ for (const auto &b : param.get_type_param_bounds ())
+ {
+ switch (b->get_bound_type ())
+ {
+ case TypeParamBound::TypeParamBoundType::TRAIT: {
+ const TraitBound &tb = (const TraitBound &) *b.get ();
+ const TypePath &path = tb.get_type_path ();
+
+ std::vector<LifetimeParam> for_lifetimes;
+ for (const auto &lifetime : tb.get_for_lifetimes ())
+ {
+ std::vector<Lifetime> lifetime_bounds;
+ for (const auto &b : lifetime.get_lifetime_bounds ())
+ {
+ Lifetime bl = new_lifetime (b);
+ lifetime_bounds.push_back (std::move (bl));
+ }
+
+ Lifetime nl = new_lifetime (lifetime.get_lifetime ());
+ LifetimeParam p (std::move (nl), std::move (lifetime_bounds),
+ {}, lifetime.get_locus ());
+ for_lifetimes.push_back (std::move (p));
+ }
+
+ 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
+ = 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;
+ }
+ }
+
+ TypePath p (std::move (segments), path.get_locus (),
+ path.has_opening_scope_resolution_op ());
+
+ TraitBound *b = new TraitBound (std::move (p), tb.get_locus (),
+ tb.is_in_parens (),
+ tb.has_opening_question_mark (),
+ std::move (for_lifetimes));
+ std::unique_ptr<TypeParamBound> bound (b);
+ type_param_bounds.push_back (std::move (bound));
+ }
+ break;
+
+ case TypeParamBound::TypeParamBoundType::LIFETIME: {
+ const Lifetime &l = (const Lifetime &) *b.get ();
+
+ auto bl = new Lifetime (l.get_lifetime_type (),
+ l.get_lifetime_name (), l.get_locus ());
+ std::unique_ptr<TypeParamBound> bound (bl);
+ type_param_bounds.push_back (std::move (bound));
+ }
+ break;
+ }
+ }
+
+ auto type_param
+ = new TypeParam (type_representation, locus, std::move (type_param_bounds),
+ std::move (type), std::move (outer_attrs));
+
+ return std::unique_ptr<GenericParam> (type_param);
+}
+
+Lifetime
+Builder::new_lifetime (const Lifetime &lifetime)
+{
+ return Lifetime (lifetime.get_lifetime_type (), lifetime.get_lifetime_name (),
+ lifetime.get_locus ());
+}
+
+GenericArgs
+Builder::new_generic_args (GenericArgs &args)
+{
+ std::vector<Lifetime> lifetime_args;
+ std::vector<GenericArg> generic_args;
+ std::vector<GenericArgsBinding> binding_args;
+ location_t locus = args.get_locus ();
+
+ for (const auto &lifetime : args.get_lifetime_args ())
+ {
+ Lifetime l = new_lifetime (lifetime);
+ lifetime_args.push_back (std::move (l));
+ }
+
+ for (auto &binding : args.get_binding_args ())
+ {
+ Type &t = *binding.get_type_ptr ().get ();
+ std::unique_ptr<Type> ty = new_type (t);
+ GenericArgsBinding b (binding.get_identifier (), std::move (ty),
+ binding.get_locus ());
+ binding_args.push_back (std::move (b));
+ }
+
+ for (auto &arg : args.get_generic_args ())
+ {
+ 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));
+ }
+ break;
+
+ default:
+ // FIXME
+ rust_unreachable ();
+ break;
+ }
+ }
+
+ return GenericArgs (std::move (lifetime_args), std::move (generic_args),
+ std::move (binding_args), locus);
+}
+
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h
index 5c33954..682af79 100644
--- a/gcc/rust/ast/rust-ast-builder.h
+++ b/gcc/rust/ast/rust-ast-builder.h
@@ -20,10 +20,45 @@
#define AST_BUILDER_H
#include "rust-ast-full.h"
+#include "rust-expr.h"
+#include "rust-ast.h"
+#include "rust-item.h"
+#include "rust-operators.h"
namespace Rust {
namespace AST {
+template <typename T>
+std::vector<std::unique_ptr<T>>
+vec (std::unique_ptr<T> &&t)
+{
+ auto v = std::vector<std::unique_ptr<T>> ();
+
+ v.emplace_back (std::move (t));
+
+ return v;
+}
+
+template <typename T>
+std::vector<std::unique_ptr<T>>
+vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2)
+{
+ auto v = std::vector<std::unique_ptr<T>> ();
+
+ v.emplace_back (std::move (t1));
+ v.emplace_back (std::move (t2));
+
+ return v;
+}
+
+/* Pointer-ify something */
+template <typename T>
+static std::unique_ptr<T>
+ptrify (T value)
+{
+ return std::unique_ptr<T> (new T (value));
+}
+
// TODO: Use this builder when expanding regular macros
/* Builder class with helper methods to create AST nodes. This builder is
* tailored towards generating multiple AST nodes from a single location, and
@@ -33,15 +68,28 @@ class Builder
public:
Builder (location_t loc) : loc (loc) {}
+ /* Create an expression statement from an expression */
+ std::unique_ptr<Stmt> statementify (std::unique_ptr<Expr> &&value,
+ bool semicolon_followed = true) const;
+
/* Create a string literal expression ("content") */
std::unique_ptr<Expr> literal_string (std::string &&content) const;
+ /* Create a boolean literal expression (true) */
+ std::unique_ptr<Expr> literal_bool (bool b) const;
+
/* Create an identifier expression (`variable`) */
std::unique_ptr<Expr> identifier (std::string name) const;
+ std::unique_ptr<Pattern> identifier_pattern (std::string name,
+ bool mut = false) const;
/* Create a tuple index expression (`receiver.0`) */
std::unique_ptr<Expr> tuple_idx (std::string receiver, int idx) const;
+ /* Create a tuple expression (`(a1, a2, a3)`) */
+ std::unique_ptr<Expr> tuple (std::vector<std::unique_ptr<Expr>> &&values
+ = {}) const;
+
/* Create a reference to an expression (`&of`) */
std::unique_ptr<Expr> ref (std::unique_ptr<Expr> &&of,
bool mut = false) const;
@@ -49,23 +97,45 @@ public:
/* Create a dereference of an expression (`*of`) */
std::unique_ptr<Expr> deref (std::unique_ptr<Expr> &&of) const;
+ /* Build a comparison expression (`lhs == rhs`) */
+ std::unique_ptr<Expr> comparison_expr (std::unique_ptr<Expr> &&lhs,
+ std::unique_ptr<Expr> &&rhs,
+ ComparisonOperator op) const;
+
+ /* Build a lazy boolean operator expression (`lhs && rhs`) */
+ std::unique_ptr<Expr> boolean_operation (std::unique_ptr<Expr> &&lhs,
+ std::unique_ptr<Expr> &&rhs,
+ LazyBooleanOperator op) const;
+
/* Create a block with an optional tail expression */
- std::unique_ptr<Expr> block (std::vector<std::unique_ptr<Stmt>> &&stmts,
- std::unique_ptr<Expr> &&tail_expr
- = nullptr) const;
+ std::unique_ptr<BlockExpr> block (std::vector<std::unique_ptr<Stmt>> &&stmts,
+ std::unique_ptr<Expr> &&tail_expr
+ = nullptr) const;
+ std::unique_ptr<BlockExpr> block (tl::optional<std::unique_ptr<Stmt>> &&stmt,
+ std::unique_ptr<Expr> &&tail_expr
+ = nullptr) const;
+ /* Create an empty block */
+ std::unique_ptr<BlockExpr> block () const;
+
+ /* Create an early return expression with an optional expression */
+ std::unique_ptr<Expr> return_expr (std::unique_ptr<Expr> &&to_return
+ = nullptr);
/* Create a let binding with an optional type and initializer (`let <name> :
* <type> = <init>`) */
- std::unique_ptr<Stmt> let (std::unique_ptr<Pattern> pattern,
- std::unique_ptr<Type> type = nullptr,
- std::unique_ptr<Expr> init = nullptr) const;
+ std::unique_ptr<Stmt> let (std::unique_ptr<Pattern> &&pattern,
+ std::unique_ptr<Type> &&type = nullptr,
+ std::unique_ptr<Expr> &&init = nullptr) const;
/**
* Create a call expression to a function, struct or enum variant, given its
* arguments (`path(arg0, arg1, arg2)`)
*/
std::unique_ptr<Expr> call (std::unique_ptr<Expr> &&path,
- std::vector<std::unique_ptr<Expr>> &&args) const;
+ std::vector<std::unique_ptr<Expr>> &&args
+ = {}) const;
+ std::unique_ptr<Expr> call (std::unique_ptr<Expr> &&path,
+ std::unique_ptr<Expr> &&arg) const;
/**
* Create an array expression (`[member0, member1, member2]`)
@@ -73,36 +143,107 @@ public:
std::unique_ptr<Expr>
array (std::vector<std::unique_ptr<Expr>> &&members) const;
+ /* Create a qualified path in expression (`<type as Trait>::seg::expr`) */
+ std::unique_ptr<Expr>
+ qualified_path_in_expression (std::unique_ptr<Type> &&type, TypePath trait,
+ PathExprSegment segment) const;
+ std::unique_ptr<Expr>
+ qualified_path_in_expression (std::unique_ptr<Type> &&type, TypePath trait,
+ std::vector<PathExprSegment> &&segments
+ = {}) const;
+
+ /* Self parameter for a function definition (`&self`) */
+ std::unique_ptr<Param> self_ref_param (bool mutability = false) const;
+ /* A regular named function parameter for a definition (`a: type`) */
+ std::unique_ptr<Param> function_param (std::unique_ptr<Pattern> &&pattern,
+ std::unique_ptr<Type> &&type) const;
+
/* Empty function qualifiers, with no specific qualifiers */
FunctionQualifiers fn_qualifiers () const;
+ std::unique_ptr<Function>
+ function (std::string function_name,
+ std::vector<std::unique_ptr<Param>> params,
+ std::unique_ptr<Type> return_type, std::unique_ptr<BlockExpr> block,
+ std::vector<std::unique_ptr<GenericParam>> generic_params = {},
+ FunctionQualifiers qualifiers
+ = FunctionQualifiers (UNKNOWN_LOCATION, Async::No, Const::No,
+ Unsafety::Normal),
+ WhereClause where_clause = WhereClause::create_empty (),
+ Visibility visibility = Visibility::create_private ()) const;
+
/* Create a single path segment from one string */
PathExprSegment path_segment (std::string seg) const;
/* And similarly for type path segments */
std::unique_ptr<TypePathSegment> type_path_segment (std::string seg) const;
+ std::unique_ptr<TypePathSegment>
+ type_path_segment (LangItem::Kind lang_item) const;
+
+ std::unique_ptr<TypePathSegment>
+ type_path_segment_generic (std::string seg, GenericArgs args) const;
+ std::unique_ptr<TypePathSegment>
+ type_path_segment_generic (LangItem::Kind lang_item, GenericArgs args) const;
/* Create a Type from a single string - the most basic kind of type in our AST
*/
std::unique_ptr<Type> single_type_path (std::string type) const;
+ std::unique_ptr<Type> single_type_path (LangItem::Kind lang_item) const;
+
+ std::unique_ptr<Type> single_generic_type_path (std::string type,
+ GenericArgs args) const;
+ std::unique_ptr<Type> single_generic_type_path (LangItem::Kind lang_item,
+ GenericArgs args) const;
+
+ TypePath type_path (std::vector<std::unique_ptr<TypePathSegment>> &&segment,
+ bool opening_scope = false) const;
+ TypePath type_path (std::vector<std::string> &&segments,
+ bool opening_scope = false) const;
+ TypePath type_path (std::unique_ptr<TypePathSegment> &&segment) const;
+ TypePath type_path (std::string type) const;
+ TypePath type_path (LangItem::Kind lang_item) const;
+
+ std::unique_ptr<Type>
+ reference_type (std::unique_ptr<TypeNoBounds> &&inner_type,
+ bool mutability = false) const;
/**
* Create a path in expression from multiple segments (`Clone::clone`). You
* do not need to separate the segments using `::`, you can simply provide a
* vector of strings to the functions which will get turned into path segments
*/
- PathInExpression
- path_in_expression (std::vector<std::string> &&segments) const;
+ PathInExpression path_in_expression (std::vector<std::string> &&segments,
+ bool opening_scope = false) const;
+
+ /**
+ * Create a path in expression from a lang item.
+ */
+ PathInExpression path_in_expression (LangItem::Kind lang_item) const;
+
+ /* Create the path to an enum's variant (`Result::Ok`) */
+ PathInExpression variant_path (const std::string &enum_path,
+ const std::string &variant) const;
+
+ /* Create a new struct */
+ std::unique_ptr<Stmt>
+ struct_struct (std::string struct_name,
+ std::vector<std::unique_ptr<GenericParam>> &&generics,
+ std::vector<StructField> &&fields);
/* Create a struct expression for unit structs (`S`) */
std::unique_ptr<Expr> struct_expr_struct (std::string struct_name) const;
/**
* Create an expression for struct instantiation with fields (`S { a, b: c }`)
+ * Named tuple expressions (`S(a, b, c)`) are call expressions and can thus be
+ * constructed with `call`
*/
std::unique_ptr<Expr>
struct_expr (std::string struct_name,
std::vector<std::unique_ptr<StructExprField>> &&fields) const;
+ std::unique_ptr<Expr>
+ struct_expr (PathInExpression struct_name,
+ std::vector<std::unique_ptr<StructExprField>> &&fields) const;
/* Create a field expression for struct instantiation (`field_name: value`) */
std::unique_ptr<StructExprField>
@@ -113,8 +254,53 @@ 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`) */
+ std::unique_ptr<Pattern> ref_pattern (std::unique_ptr<Pattern> &&inner) const;
+
+ /* Create a lang item path usable as a general path */
+ std::unique_ptr<Path> lang_item_path (LangItem::Kind) const;
+
+ /* Create match expressions and their components */
+ std::unique_ptr<Expr> match (std::unique_ptr<Expr> &&scrutinee,
+ std::vector<MatchCase> &&cases);
+ MatchArm match_arm (std::unique_ptr<Pattern> &&pattern);
+ MatchCase match_case (std::unique_ptr<Pattern> &&pattern,
+ std::unique_ptr<Expr> &&expr);
+
+ /* Create a loop expression */
+ std::unique_ptr<Expr> loop (std::vector<std::unique_ptr<Stmt>> &&stmts);
+
+ std::unique_ptr<TypeParamBound> trait_bound (TypePath bound);
+ std::unique_ptr<Item>
+ trait_impl (TypePath trait_path, std::unique_ptr<Type> target,
+ std::vector<std::unique_ptr<AssociatedItem>> trait_items = {},
+ std::vector<std::unique_ptr<GenericParam>> generics = {},
+ WhereClause where_clause = WhereClause::create_empty (),
+ Visibility visibility = Visibility::create_private ()) const;
+
+ std::unique_ptr<GenericParam>
+ generic_type_param (std::string type_representation,
+ std::vector<std::unique_ptr<TypeParamBound>> &&bounds,
+ std::unique_ptr<Type> &&type = nullptr);
+
+ static std::unique_ptr<Type> new_type (Type &type);
+
+ static std::unique_ptr<GenericParam>
+ new_lifetime_param (LifetimeParam &param);
+
+ static std::unique_ptr<GenericParam> new_type_param (
+ TypeParam &param,
+ std::vector<std::unique_ptr<TypeParamBound>> extra_trait_bounds = {});
+
+ static Lifetime new_lifetime (const Lifetime &lifetime);
+
+ static GenericArgs new_generic_args (GenericArgs &args);
private:
/**
diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index a2cb506..709908b 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -15,11 +15,17 @@
// 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-collector.h"
#include "rust-ast.h"
#include "rust-diagnostics.h"
+#include "rust-expr.h"
#include "rust-item.h"
#include "rust-keyword-values.h"
+#include "rust-location.h"
+#include "rust-path.h"
+#include "rust-system.h"
+#include "rust-token.h"
namespace Rust {
namespace AST {
@@ -248,29 +254,6 @@ TokenCollector::visit (Visibility &vis)
}
void
-TokenCollector::visit (NamedFunctionParam &param)
-{
- auto name = param.get_name ();
- if (!param.is_variadic ())
- {
- push (
- Rust::Token::make_identifier (param.get_locus (), std::move (name)));
- push (Rust::Token::make (COLON, UNDEF_LOCATION));
- visit (param.get_type ());
- }
- else
- {
- if (name != "")
- {
- push (Rust::Token::make_identifier (param.get_locus (),
- std::move (name)));
- push (Rust::Token::make (COLON, UNDEF_LOCATION));
- }
- push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION));
- }
-}
-
-void
TokenCollector::visit (std::vector<std::unique_ptr<GenericParam>> &params)
{
push (Rust::Token::make (LEFT_ANGLE, UNDEF_LOCATION));
@@ -396,6 +379,9 @@ TokenCollector::visit (Token &tok)
case BYTE_STRING_LITERAL:
push (Rust::Token::make_byte_string (tok.get_locus (), std::move (data)));
break;
+ case RAW_STRING_LITERAL:
+ push (Rust::Token::make_raw_string (tok.get_locus (), std::move (data)));
+ break;
case INNER_DOC_COMMENT:
push (Rust::Token::make_inner_doc_comment (tok.get_locus (),
std::move (data)));
@@ -475,6 +461,7 @@ TokenCollector::visit (LifetimeParam &lifetime_param)
// TODO what to do with outer attr? They are not mentioned in the reference.
+ visit_items_as_lines (lifetime_param.get_outer_attrs ());
auto lifetime = lifetime_param.get_lifetime ();
visit (lifetime);
@@ -494,6 +481,7 @@ TokenCollector::visit (ConstGenericParam &param)
// Syntax:
// const IDENTIFIER : Type ( = Block | IDENTIFIER | -?LITERAL )?
+ visit_items_as_lines (param.get_outer_attrs ());
push (Rust::Token::make (CONST, param.get_locus ()));
auto id = param.get_name ().as_string ();
push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
@@ -503,7 +491,7 @@ TokenCollector::visit (ConstGenericParam &param)
if (param.has_default_value ())
{
push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
- visit (param.get_default_value ());
+ visit (param.get_default_value_unchecked ());
}
}
@@ -545,11 +533,23 @@ TokenCollector::visit (PathExprSegment &segment)
void
TokenCollector::visit (PathInExpression &path)
{
- if (path.opening_scope_resolution ())
+ if (path.is_lang_item ())
{
- push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ()));
+ push (Rust::Token::make (TokenId::HASH, path.get_locus ()));
+ push (Rust::Token::make (TokenId::LEFT_SQUARE, path.get_locus ()));
+ push (Rust::Token::make_identifier (path.get_locus (), "lang"));
+ push (Rust::Token::make (TokenId::EQUAL, path.get_locus ()));
+ push (
+ Rust::Token::make_string (path.get_locus (),
+ LangItem::ToString (path.get_lang_item ())));
+ push (Rust::Token::make (TokenId::RIGHT_SQUARE, path.get_locus ()));
+
+ return;
}
+ if (path.opening_scope_resolution ())
+ push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ()));
+
visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION);
}
@@ -558,10 +558,14 @@ TokenCollector::visit (TypePathSegment &segment)
{
// Syntax:
// PathIdentSegment
- auto ident_segment = segment.get_ident_segment ();
- auto id = ident_segment.as_string ();
- push (
- Rust::Token::make_identifier (ident_segment.get_locus (), std::move (id)));
+
+ auto locus = segment.is_lang_item ()
+ ? segment.get_locus ()
+ : segment.get_ident_segment ().get_locus ();
+ auto segment_string = segment.is_lang_item ()
+ ? LangItem::PrettyString (segment.get_lang_item ())
+ : segment.get_ident_segment ().as_string ();
+ push (Rust::Token::make_identifier (locus, std::move (segment_string)));
}
void
@@ -573,10 +577,13 @@ TokenCollector::visit (TypePathSegmentGeneric &segment)
// `<` `>`
// | `<` ( GenericArg `,` )* GenericArg `,`? `>`
- auto ident_segment = segment.get_ident_segment ();
- auto id = ident_segment.as_string ();
- push (
- Rust::Token::make_identifier (ident_segment.get_locus (), std::move (id)));
+ auto locus = segment.is_lang_item ()
+ ? segment.get_locus ()
+ : segment.get_ident_segment ().get_locus ();
+ auto segment_string = segment.is_lang_item ()
+ ? LangItem::PrettyString (segment.get_lang_item ())
+ : segment.get_ident_segment ().as_string ();
+ push (Rust::Token::make_identifier (locus, std::move (segment_string)));
if (segment.get_separating_scope_resolution ())
push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
@@ -632,8 +639,6 @@ TokenCollector::visit (GenericArg &arg)
push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path)));
}
break;
- case GenericArg::Kind::Error:
- rust_unreachable ();
}
}
@@ -690,19 +695,19 @@ TokenCollector::visit (TypePath &path)
void
TokenCollector::visit (PathIdentSegment &segment)
{
- if (segment.is_super_segment ())
+ if (segment.is_super_path_seg ())
{
push (Rust::Token::make (SUPER, segment.get_locus ()));
}
- else if (segment.is_crate_segment ())
+ else if (segment.is_crate_path_seg ())
{
push (Rust::Token::make (CRATE, segment.get_locus ()));
}
- else if (segment.is_lower_self ())
+ else if (segment.is_lower_self_seg ())
{
push (Rust::Token::make (SELF, segment.get_locus ()));
}
- else if (segment.is_big_self ())
+ else if (segment.is_big_self_seg ())
{
push (Rust::Token::make (SELF_ALIAS, segment.get_locus ()));
}
@@ -773,6 +778,9 @@ TokenCollector::visit (Literal &lit, location_t locus)
case Literal::LitType::BYTE_STRING:
push (Rust::Token::make_byte_string (locus, std::move (value)));
break;
+ case Literal::LitType::RAW_STRING:
+ push (Rust::Token::make_raw_string (locus, std::move (value)));
+ break;
case Literal::LitType::INT:
push (
Rust::Token::make_int (locus, std::move (value), lit.get_type_hint ()));
@@ -840,8 +848,21 @@ TokenCollector::visit (BorrowExpr &expr)
push (Rust::Token::make (AMP, expr.get_locus ()));
if (expr.get_is_double_borrow ())
push (Rust::Token::make (AMP, UNDEF_LOCATION));
- if (expr.get_is_mut ())
- push (Rust::Token::make (MUT, UNDEF_LOCATION));
+
+ if (expr.is_raw_borrow ())
+ {
+ push (Rust::Token::make_identifier (expr.get_locus (),
+ Values::WeakKeywords::RAW));
+ if (expr.get_is_mut ())
+ push (Rust::Token::make (MUT, UNDEF_LOCATION));
+ else
+ push (Rust::Token::make (CONST, UNDEF_LOCATION));
+ }
+ else
+ {
+ if (expr.get_is_mut ())
+ push (Rust::Token::make (MUT, UNDEF_LOCATION));
+ }
visit (expr.get_borrowed_expr ());
}
@@ -1096,8 +1117,7 @@ TokenCollector::visit (StructExprStruct &expr)
void
TokenCollector::visit (StructExprFieldIdentifier &expr)
{
- // TODO: Add attributes
- // visit_items_as_lines (expr.get_attrs ());
+ visit_items_as_lines (expr.get_outer_attrs ());
auto id = expr.get_field_name ().as_string ();
push (Rust::Token::make_identifier (expr.get_locus (), std::move (id)));
}
@@ -1105,8 +1125,7 @@ TokenCollector::visit (StructExprFieldIdentifier &expr)
void
TokenCollector::visit (StructExprFieldIdentifierValue &expr)
{
- // TODO: Add attributes
- // visit_items_as_lines (expr.get_attrs ());
+ visit_items_as_lines (expr.get_outer_attrs ());
auto id = expr.get_field_name ();
push (Rust::Token::make_identifier (expr.get_locus (), std::move (id)));
push (Rust::Token::make (COLON, UNDEF_LOCATION));
@@ -1116,8 +1135,7 @@ TokenCollector::visit (StructExprFieldIdentifierValue &expr)
void
TokenCollector::visit (StructExprFieldIndexValue &expr)
{
- // TODO: Add attributes
- // visit_items_as_lines (expr.get_attrs ());
+ visit_items_as_lines (expr.get_outer_attrs ());
push (Rust::Token::make_int (expr.get_locus (),
std::to_string (expr.get_index ())));
push (Rust::Token::make (COLON, UNDEF_LOCATION));
@@ -1246,6 +1264,22 @@ TokenCollector::visit (BlockExpr &expr)
}
void
+TokenCollector::visit (AnonConst &expr)
+{
+ visit (expr.get_inner_expr ());
+}
+
+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);
@@ -1259,7 +1293,7 @@ TokenCollector::visit (ContinueExpr &expr)
{
push (Rust::Token::make (CONTINUE, expr.get_locus ()));
if (expr.has_label ())
- visit (expr.get_label ());
+ visit (expr.get_label_unchecked ());
}
void
@@ -1267,7 +1301,7 @@ TokenCollector::visit (BreakExpr &expr)
{
push (Rust::Token::make (BREAK, expr.get_locus ()));
if (expr.has_label ())
- visit (expr.get_label ());
+ visit (expr.get_label_unchecked ());
if (expr.has_break_expr ())
visit (expr.get_break_expr ());
}
@@ -1316,6 +1350,13 @@ TokenCollector::visit (RangeToInclExpr &expr)
}
void
+TokenCollector::visit (BoxExpr &expr)
+{
+ push (Rust::Token::make (BOX, expr.get_locus ()));
+ visit (expr.get_boxed_expr ());
+}
+
+void
TokenCollector::visit (ReturnExpr &expr)
{
push (Rust::Token::make (RETURN_KW, expr.get_locus ()));
@@ -1491,6 +1532,132 @@ TokenCollector::visit (AsyncBlockExpr &expr)
visit (expr.get_block_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)
+{
+ push (Rust::Token::make_identifier (expr.get_locus (), "llvm_asm"));
+ push (Rust::Token::make (EXCLAM, expr.get_locus ()));
+ push (Rust::Token::make (LEFT_PAREN, expr.get_locus ()));
+ for (auto &template_str : expr.get_templates ())
+ push (Rust::Token::make_string (template_str.get_locus (),
+ std::move (template_str.symbol)));
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+ for (auto output : expr.get_outputs ())
+ {
+ push (Rust::Token::make_string (expr.get_locus (),
+ std::move (output.constraint)));
+ visit (output.expr);
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+ for (auto input : expr.get_inputs ())
+ {
+ push (Rust::Token::make_string (expr.get_locus (),
+ std::move (input.constraint)));
+ visit (input.expr);
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+ for (auto &clobber : expr.get_clobbers ())
+ {
+ 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 ()));
+ // Dump options
+
+ push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ()));
+}
+
// rust-item.h
void
@@ -1501,6 +1668,7 @@ TokenCollector::visit (TypeParam &param)
// TypeParamBounds :
// TypeParamBound ( + TypeParamBound )* +?
+ visit_items_as_lines (param.get_outer_attrs ());
auto id = param.get_type_representation ().as_string ();
push (Rust::Token::make_identifier (param.get_locus (), std::move (id)));
if (param.has_type_param_bounds ())
@@ -2453,10 +2621,7 @@ TokenCollector::visit (StructPattern &pattern)
void
TokenCollector::visit (TupleStructItemsNoRange &pattern)
{
- for (auto &pat : pattern.get_patterns ())
- {
- visit (pat);
- }
+ visit_items_joined_by_separator (pattern.get_patterns ());
}
void
@@ -2559,6 +2724,13 @@ TokenCollector::visit (LetStmt &stmt)
push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
visit (stmt.get_init_expr ());
}
+
+ if (stmt.has_else_expr ())
+ {
+ push (Rust::Token::make (ELSE, UNDEF_LOCATION));
+ visit (stmt.get_else_expr ());
+ }
+
push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
}
diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h
index fdc99bb..fa835ce 100644
--- a/gcc/rust/ast/rust-ast-collector.h
+++ b/gcc/rust/ast/rust-ast-collector.h
@@ -210,7 +210,6 @@ public:
void visit (TupleField &field);
void visit (StructField &field);
void visit (SimplePathSegment &segment);
- void visit (NamedFunctionParam &param);
void visit (MacroRule &rule);
void visit (WhereClause &rule);
void visit (std::vector<LifetimeParam> &for_lifetimes);
@@ -278,6 +277,8 @@ public:
void visit (ClosureParam &param);
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);
@@ -288,6 +289,7 @@ public:
void visit (RangeFromToInclExpr &expr);
void visit (RangeToInclExpr &expr);
void visit (ReturnExpr &expr);
+ void visit (BoxExpr &expr);
void visit (UnsafeBlockExpr &expr);
void visit (LoopExpr &expr);
void visit (WhileLoopExpr &expr);
@@ -302,7 +304,8 @@ public:
void visit (MatchExpr &expr);
void visit (AwaitExpr &expr);
void visit (AsyncBlockExpr &expr);
-
+ void visit (InlineAsm &expr);
+ void visit (LlvmInlineAsm &expr);
// rust-item.h
void visit (TypeParam &param);
void visit (LifetimeWhereClauseItem &item);
diff --git a/gcc/rust/ast/rust-ast-fragment.h b/gcc/rust/ast/rust-ast-fragment.h
index 33603ac..8dde9ed 100644
--- a/gcc/rust/ast/rust-ast-fragment.h
+++ b/gcc/rust/ast/rust-ast-fragment.h
@@ -123,12 +123,25 @@ private:
void assert_single_fragment (SingleASTNode::NodeType expected) const;
};
+enum class InvocKind
+{
+ Expr,
+ Semicoloned,
+};
+
+enum class AsmKind
+{
+ Global,
+ Inline
+};
+
/**
* This is the type for transcriber functions found in
* rust-macro-builtins.{h,cc}.
*/
using MacroTranscriberFunc
- = std::function<tl::optional<Fragment> (location_t, MacroInvocData &)>;
+ = std::function<tl::optional<Fragment> (location_t, MacroInvocData &,
+ InvocKind semicolon)>;
} // 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 dd982c4..aabb1e4 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -61,7 +61,7 @@ class PathIdentSegment;
struct GenericArgsBinding;
struct GenericArgs;
class PathExprSegment;
-class PathPattern;
+class Path;
class PathInExpression;
class TypePathSegment;
class TypePathSegmentGeneric;
@@ -115,6 +115,8 @@ struct ClosureParam;
class ClosureExpr;
class ClosureExprInner;
class BlockExpr;
+class AnonConst;
+class ConstBlock;
class ClosureExprInnerTyped;
class ContinueExpr;
class BreakExpr;
@@ -145,10 +147,9 @@ struct MatchCase;
class MatchExpr;
class AwaitExpr;
class AsyncBlockExpr;
-enum class InlineAsmOptions;
-struct AnonConst;
+enum class InlineAsmOption;
struct InlineAsmRegOrRegClass;
-struct InlineAsmOperand;
+class InlineAsmOperand;
struct InlineAsmPlaceHolder;
struct InlineAsmTemplatePiece;
struct TupleClobber;
@@ -202,7 +203,6 @@ class TraitImpl;
class ExternalItem;
class ExternalTypeItem;
class ExternalStaticItem;
-class NamedFunctionParam;
class ExternBlock;
// rust-macro.h
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index de4242a..7caa54b 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -69,7 +69,7 @@ DefaultASTVisitor::visit (AST::Lifetime &lifetime)
void
DefaultASTVisitor::visit (AST::LifetimeParam &lifetime_param)
{
- visit (lifetime_param.get_outer_attribute ());
+ visit_outer_attrs (lifetime_param);
visit (lifetime_param.get_lifetime ());
for (auto &lifetime_bound : lifetime_param.get_lifetime_bounds ())
visit (lifetime_bound);
@@ -78,19 +78,21 @@ DefaultASTVisitor::visit (AST::LifetimeParam &lifetime_param)
void
DefaultASTVisitor::visit (AST::ConstGenericParam &const_param)
{
- visit (const_param.get_outer_attribute ());
+ visit_outer_attrs (const_param);
if (const_param.has_type ())
visit (const_param.get_type ());
if (const_param.has_default_value ())
- visit (const_param.get_default_value ());
+ visit (const_param.get_default_value_unchecked ());
}
void
DefaultASTVisitor::visit (AST::PathInExpression &path)
{
visit_outer_attrs (path);
- for (auto &segment : path.get_segments ())
- visit (segment);
+
+ if (!path.is_lang_item ())
+ for (auto &segment : path.get_segments ())
+ visit (segment);
}
void
@@ -106,7 +108,8 @@ DefaultASTVisitor::visit (GenericArgsBinding &binding)
void
DefaultASTVisitor::visit (AST::TypePathSegmentGeneric &segment)
{
- visit (segment.get_generic_args ());
+ if (segment.has_generic_args ())
+ visit (segment.get_generic_args ());
}
void
@@ -390,6 +393,7 @@ DefaultASTVisitor::visit (AST::StructExprStructFields &expr)
{
visit_outer_attrs (expr);
visit_inner_attrs (expr);
+ visit (expr.get_struct_name ());
if (expr.has_struct_base ())
visit (expr.get_struct_base ());
for (auto &field : expr.get_fields ())
@@ -401,6 +405,7 @@ DefaultASTVisitor::visit (AST::StructExprStructBase &expr)
{
visit_outer_attrs (expr);
visit_inner_attrs (expr);
+ visit (expr.get_struct_name ());
visit (expr.get_struct_base ());
}
@@ -451,6 +456,18 @@ DefaultASTVisitor::visit (AST::BlockExpr &expr)
}
void
+DefaultASTVisitor::visit (AST::ConstBlock &expr)
+{
+ visit (expr.get_const_expr ());
+}
+
+void
+DefaultASTVisitor::visit (AST::AnonConst &expr)
+{
+ visit (expr.get_inner_expr ());
+}
+
+void
DefaultASTVisitor::visit (AST::ClosureExprInnerTyped &expr)
{
visit_outer_attrs (expr);
@@ -473,7 +490,8 @@ void
DefaultASTVisitor::visit (AST::ContinueExpr &expr)
{
visit_outer_attrs (expr);
- visit (expr.get_label ());
+ if (expr.has_label ())
+ visit (expr.get_label_unchecked ());
}
void
@@ -481,7 +499,7 @@ DefaultASTVisitor::visit (AST::BreakExpr &expr)
{
visit_outer_attrs (expr);
if (expr.has_label ())
- visit (expr.get_label ());
+ visit (expr.get_label_unchecked ());
if (expr.has_break_expr ())
visit (expr.get_break_expr ());
@@ -532,6 +550,13 @@ DefaultASTVisitor::visit (AST::ReturnExpr &expr)
}
void
+DefaultASTVisitor::visit (AST::BoxExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit (expr.get_boxed_expr ());
+}
+
+void
DefaultASTVisitor::visit (AST::UnsafeBlockExpr &expr)
{
visit_outer_attrs (expr);
@@ -548,7 +573,8 @@ void
DefaultASTVisitor::visit (AST::LoopExpr &expr)
{
visit_outer_attrs (expr);
- visit (expr.get_loop_label ());
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
visit (expr.get_loop_block ());
}
@@ -556,8 +582,9 @@ void
DefaultASTVisitor::visit (AST::WhileLoopExpr &expr)
{
visit_outer_attrs (expr);
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
visit (expr.get_predicate_expr ());
- visit (expr.get_loop_label ());
visit (expr.get_loop_block ());
}
@@ -567,8 +594,8 @@ DefaultASTVisitor::visit (AST::WhileLetLoopExpr &expr)
visit_outer_attrs (expr);
for (auto &pattern : expr.get_patterns ())
visit (pattern);
- visit (expr.get_scrutinee_expr ());
visit (expr.get_loop_label ());
+ visit (expr.get_scrutinee_expr ());
visit (expr.get_loop_block ());
}
@@ -578,7 +605,8 @@ DefaultASTVisitor::visit (AST::ForLoopExpr &expr)
visit_outer_attrs (expr);
visit (expr.get_pattern ());
visit (expr.get_iterator_expr ());
- visit (expr.get_loop_label ());
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
visit (expr.get_loop_block ());
}
@@ -656,9 +684,62 @@ DefaultASTVisitor::visit (AST::AsyncBlockExpr &expr)
}
void
+DefaultASTVisitor::visit (AST::InlineAsm &expr)
+{
+ visit_outer_attrs (expr);
+ using RegisterType = AST::InlineAsmOperand::RegisterType;
+ for (auto &operand : expr.get_operands ())
+ {
+ 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;
+ }
+ }
+ }
+}
+
+void
+DefaultASTVisitor::visit (AST::LlvmInlineAsm &expr)
+{
+ for (auto &output : expr.get_outputs ())
+ visit (output.expr);
+
+ for (auto &input : expr.get_inputs ())
+ visit (input.expr);
+}
+
+void
DefaultASTVisitor::visit (AST::TypeParam &param)
{
- visit (param.get_outer_attribute ());
+ visit_outer_attrs (param);
for (auto &bound : param.get_type_param_bounds ())
visit (bound);
if (param.has_type ())
@@ -686,7 +767,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
@@ -759,10 +841,18 @@ DefaultASTVisitor::visit (AST::UseTreeRebind &use_tree)
void
DefaultASTVisitor::visit (AST::UseDeclaration &use_decl)
{
+ visit (use_decl.get_visibility ());
visit (use_decl.get_tree ());
}
void
+DefaultASTVisitor::visit_function_params (AST::Function &function)
+{
+ for (auto &param : function.get_function_params ())
+ visit (param);
+}
+
+void
DefaultASTVisitor::visit (AST::Function &function)
{
visit_outer_attrs (function);
@@ -770,10 +860,9 @@ DefaultASTVisitor::visit (AST::Function &function)
visit (function.get_qualifiers ());
for (auto &generic : function.get_generic_params ())
visit (generic);
- if (function.has_self_param ())
- visit (function.get_self_param ());
- for (auto &param : function.get_function_params ())
- visit (param);
+
+ visit_function_params (function);
+
if (function.has_return_type ())
visit (function.get_return_type ());
if (function.has_where_clause ())
@@ -846,7 +935,7 @@ DefaultASTVisitor::visit (AST::EnumItem &item)
void
DefaultASTVisitor::visit (AST::EnumItemTuple &item)
{
- visit (reinterpret_cast<EnumItem &> (item));
+ DefaultASTVisitor::visit (reinterpret_cast<EnumItem &> (item));
for (auto &field : item.get_tuple_fields ())
visit (field);
}
@@ -854,7 +943,7 @@ DefaultASTVisitor::visit (AST::EnumItemTuple &item)
void
DefaultASTVisitor::visit (AST::EnumItemStruct &item)
{
- visit (reinterpret_cast<EnumItem &> (item));
+ DefaultASTVisitor::visit (reinterpret_cast<EnumItem &> (item));
for (auto &field : item.get_struct_fields ())
visit (field);
}
@@ -862,7 +951,7 @@ DefaultASTVisitor::visit (AST::EnumItemStruct &item)
void
DefaultASTVisitor::visit (AST::EnumItemDiscriminant &item)
{
- visit (reinterpret_cast<EnumItem &> (item));
+ DefaultASTVisitor::visit (reinterpret_cast<EnumItem &> (item));
visit (item.get_expr ());
}
@@ -936,6 +1025,8 @@ DefaultASTVisitor::visit (AST::Trait &trait)
visit_inner_attrs (trait);
+ visit (trait.get_implicit_self ());
+
for (auto &generic : trait.get_generic_params ())
visit (generic);
@@ -976,6 +1067,7 @@ DefaultASTVisitor::visit (AST::TraitImpl &impl)
if (impl.has_where_clause ())
visit (impl.get_where_clause ());
visit (impl.get_type ());
+ visit (impl.get_trait_path ());
visit_inner_attrs (impl);
for (auto &item : impl.get_impl_items ())
visit (item);
@@ -997,14 +1089,6 @@ DefaultASTVisitor::visit (AST::ExternalStaticItem &item)
}
void
-DefaultASTVisitor::visit (AST::NamedFunctionParam &param)
-{
- visit_outer_attrs (param);
- if (!param.is_variadic ())
- visit (param.get_type ());
-}
-
-void
DefaultASTVisitor::visit (AST::ExternBlock &block)
{
visit_outer_attrs (block);
@@ -1392,33 +1476,33 @@ DefaultASTVisitor::visit (AST::VariadicParam &param)
void
ContextualASTVisitor::visit (AST::Crate &crate)
{
- push_context (Context::CRATE);
+ ctx.enter (Kind::CRATE);
DefaultASTVisitor::visit (crate);
- pop_context ();
+ ctx.exit ();
}
void
ContextualASTVisitor::visit (AST::InherentImpl &impl)
{
- push_context (Context::INHERENT_IMPL);
+ ctx.enter (Kind::INHERENT_IMPL);
DefaultASTVisitor::visit (impl);
- pop_context ();
+ ctx.exit ();
}
void
ContextualASTVisitor::visit (AST::TraitImpl &impl)
{
- push_context (Context::TRAIT_IMPL);
+ ctx.enter (Kind::TRAIT_IMPL);
DefaultASTVisitor::visit (impl);
- pop_context ();
+ ctx.exit ();
}
void
ContextualASTVisitor::visit (AST::Trait &trait)
{
- push_context (Context::TRAIT);
+ ctx.enter (Kind::TRAIT);
DefaultASTVisitor::visit (trait);
- pop_context ();
+ ctx.exit ();
}
} // namespace AST
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index 622e7f7..2a3c744 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -24,7 +24,9 @@
#include "rust-ast-full-decls.h"
#include "rust-ast.h"
#include "rust-item.h"
+#include "rust-path.h"
#include "rust-system.h"
+#include "rust-stacked-contexts.h"
namespace Rust {
namespace AST {
@@ -102,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;
@@ -112,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 (BoxExpr &expr) = 0;
virtual void visit (UnsafeBlockExpr &expr) = 0;
virtual void visit (LoopExpr &expr) = 0;
virtual void visit (WhileLoopExpr &expr) = 0;
@@ -127,6 +132,8 @@ public:
virtual void visit (MatchExpr &expr) = 0;
virtual void visit (AwaitExpr &expr) = 0;
virtual void visit (AsyncBlockExpr &expr) = 0;
+ virtual void visit (InlineAsm &expr) = 0;
+ virtual void visit (LlvmInlineAsm &expr) = 0;
// rust-item.h
virtual void visit (TypeParam &param) = 0;
@@ -237,9 +244,10 @@ public:
class DefaultASTVisitor : public ASTVisitor
{
public:
+ virtual void visit_function_params (AST::Function &function);
+
virtual void visit (AST::Crate &crate);
-protected:
virtual void visit (AST::Token &tok) override;
virtual void visit (AST::DelimTokenTree &delim_tok_tree) override;
virtual void visit (AST::AttrInputMetaItemContainer &input) override;
@@ -287,6 +295,8 @@ protected:
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;
@@ -297,6 +307,7 @@ protected:
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::BoxExpr &expr) override;
virtual void visit (AST::UnsafeBlockExpr &expr) override;
virtual void visit (AST::LoopExpr &expr) override;
virtual void visit (AST::WhileLoopExpr &expr) override;
@@ -309,6 +320,9 @@ protected:
virtual void visit (AST::MatchExpr &expr) override;
virtual void visit (AST::AwaitExpr &expr) override;
virtual void visit (AST::AsyncBlockExpr &expr) override;
+ virtual void visit (InlineAsm &expr) override;
+ virtual void visit (LlvmInlineAsm &expr) override;
+
virtual void visit (AST::TypeParam &param) override;
virtual void visit (AST::LifetimeWhereClauseItem &item) override;
virtual void visit (AST::TypeBoundWhereClauseItem &item) override;
@@ -418,7 +432,6 @@ protected:
virtual void visit (AST::WhereClause &where);
virtual void visit (AST::StructField &field);
virtual void visit (AST::TupleField &field);
- virtual void visit (AST::NamedFunctionParam &param);
virtual void visit (AST::MacroRule &rule);
virtual void visit (AST::MacroInvocData &data);
virtual void visit (AST::MacroTranscriber &transcriber);
@@ -443,7 +456,7 @@ protected:
class ContextualASTVisitor : public DefaultASTVisitor
{
protected:
- enum class Context
+ enum class Kind
{
FUNCTION,
INHERENT_IMPL,
@@ -452,6 +465,7 @@ protected:
MODULE,
CRATE,
};
+
using DefaultASTVisitor::visit;
virtual void visit (AST::Crate &crate) override;
@@ -467,11 +481,7 @@ protected:
DefaultASTVisitor::visit (item);
}
- std::vector<Context> context;
-
- void push_context (Context ctx) { context.push_back (ctx); }
-
- void pop_context () { context.pop_back (); }
+ StackedContexts<Kind> ctx;
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 326379c..5b797e8 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -20,6 +20,8 @@ along with GCC; see the file COPYING3. If not see
#include "rust-ast.h"
#include "optional.h"
#include "rust-builtin-ast-nodes.h"
+#include "rust-common.h"
+#include "rust-expr.h"
#include "rust-system.h"
#include "rust-ast-full.h"
#include "rust-diagnostics.h"
@@ -270,8 +272,8 @@ Attribute::get_traits_to_derive ()
case AST::MetaItem::ItemKind::Word: {
auto word = static_cast<AST::MetaWord *> (meta_item);
// Convert current word to path
- current
- = make_unique<AST::MetaItemPath> (AST::MetaItemPath (
+ current = std::make_unique<AST::MetaItemPath> (
+ AST::MetaItemPath (
AST::SimplePath (word->get_ident ())));
auto path
= static_cast<AST::MetaItemPath *> (current.get ());
@@ -309,7 +311,8 @@ Attribute::get_traits_to_derive ()
// Copy constructor must deep copy attr_input as unique pointer
Attribute::Attribute (Attribute const &other)
- : path (other.path), locus (other.locus)
+ : path (other.path), locus (other.locus),
+ inner_attribute (other.inner_attribute)
{
// guard to protect from null pointer dereference
if (other.attr_input != nullptr)
@@ -322,6 +325,7 @@ Attribute::operator= (Attribute const &other)
{
path = other.path;
locus = other.locus;
+ inner_attribute = other.inner_attribute;
// guard to protect from null pointer dereference
if (other.attr_input != nullptr)
attr_input = other.attr_input->clone_attr_input ();
@@ -1064,7 +1068,7 @@ Function::Function (Function const &other)
: VisItem (other), ExternalItem (other.get_node_id ()),
qualifiers (other.qualifiers), function_name (other.function_name),
where_clause (other.where_clause), locus (other.locus),
- is_default (other.is_default),
+ has_default (other.has_default),
is_external_function (other.is_external_function)
{
// guard to prevent null dereference (always required)
@@ -1096,7 +1100,7 @@ Function::operator= (Function const &other)
// visibility = other.visibility->clone_visibility();
// outer_attrs = other.outer_attrs;
locus = other.locus;
- is_default = other.is_default;
+ has_default = other.has_default;
is_external_function = other.is_external_function;
// guard to prevent null dereference (always required)
@@ -1268,6 +1272,18 @@ BlockExpr::as_string () const
}
std::string
+AnonConst::as_string () const
+{
+ return "AnonConst: " + expr->as_string ();
+}
+
+std::string
+ConstBlock::as_string () const
+{
+ return "ConstBlock: " + expr.as_string ();
+}
+
+std::string
TraitImpl::as_string () const
{
std::string str = VisItem::as_string ();
@@ -1570,18 +1586,37 @@ BorrowExpr::as_string () const
std::string str ("&");
- if (double_borrow)
- str += "&";
-
- if (is_mut)
- str += "mut ";
+ if (raw_borrow)
+ {
+ str += "raw ";
+ str += get_is_mut () ? "const " : "mut ";
+ }
+ else
+ {
+ if (double_borrow)
+ str += "&";
+ if (get_is_mut ())
+ str += "mut ";
+ }
str += main_or_left_expr->as_string ();
return str;
}
std::string
+BoxExpr::as_string () const
+{
+ return "box " + expr->as_string ();
+}
+
+void
+BoxExpr::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+std::string
ReturnExpr::as_string () const
{
/* TODO: find way to incorporate outer attrs - may have to represent in
@@ -1608,7 +1643,7 @@ ContinueExpr::as_string () const
std::string str ("continue ");
if (has_label ())
- str += label.as_string ();
+ str += get_label_unchecked ().as_string ();
return str;
}
@@ -2072,7 +2107,7 @@ WhileLoopExpr::as_string () const
if (!has_loop_label ())
str += "none";
else
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
str += "\n Conditional expr: " + condition->as_string ();
@@ -2092,7 +2127,7 @@ WhileLetLoopExpr::as_string () const
if (!has_loop_label ())
str += "none";
else
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
str += "\n Match arm patterns: ";
if (match_arm_patterns.empty ())
@@ -2123,7 +2158,7 @@ LoopExpr::as_string () const
if (!has_loop_label ())
str += "none";
else
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
str += "\n Loop block: " + loop_block->as_string ();
@@ -2160,7 +2195,7 @@ BreakExpr::as_string () const
std::string str ("break ");
if (has_label ())
- str += label.as_string () + " ";
+ str += get_label_unchecked ().as_string () + " ";
if (has_break_expr ())
str += break_expr->as_string ();
@@ -2387,11 +2422,11 @@ LifetimeParam::as_string () const
{
std::string str ("LifetimeParam: ");
- str += "\n Outer attribute: ";
+ str += "\n Outer attribute:";
if (!has_outer_attribute ())
str += "none";
- else
- str += outer_attr.as_string ();
+ for (auto &attr : outer_attrs)
+ str += " " + attr.as_string ();
str += "\n Lifetime: " + lifetime.as_string ();
@@ -2462,9 +2497,6 @@ MacroMatchRepetition::as_string () const
std::string
Lifetime::as_string () const
{
- if (is_error ())
- return "error lifetime";
-
switch (lifetime_type)
{
case NAMED:
@@ -2483,11 +2515,11 @@ TypeParam::as_string () const
{
std::string str ("TypeParam: ");
- str += "\n Outer attribute: ";
+ str += "\n Outer attribute:";
if (!has_outer_attribute ())
str += "none";
- else
- str += outer_attr.as_string ();
+ for (auto &attr : outer_attrs)
+ str += " " + attr.as_string ();
str += "\n Identifier: " + type_representation.as_string ();
@@ -2522,7 +2554,7 @@ ForLoopExpr::as_string () const
if (!has_loop_label ())
str += "none";
else
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
str += "\n Pattern: " + pattern->as_string ();
@@ -2589,7 +2621,7 @@ ReferenceType::as_string () const
std::string str ("&");
if (has_lifetime ())
- str += lifetime.as_string () + " ";
+ str += get_lifetime ().as_string () + " ";
if (has_mut)
str += "mut ";
@@ -2694,7 +2726,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
@@ -2975,22 +3007,6 @@ ExternalStaticItem::as_string () const
}
std::string
-NamedFunctionParam::as_string () const
-{
- std::string str = append_attributes (outer_attrs, OUTER);
-
- if (has_name ())
- str += "\n" + name;
-
- if (is_variadic ())
- str += "...";
- else
- str += "\n Type: " + param_type->as_string ();
-
- return str;
-}
-
-std::string
TraitItemConst::as_string () const
{
// TODO: rewrite to work with non-linearisable exprs
@@ -3063,7 +3079,7 @@ SelfParam::as_string () const
else if (has_lifetime ())
{
// ref and lifetime
- std::string str = "&" + lifetime.as_string () + " ";
+ std::string str = "&" + get_lifetime ().as_string () + " ";
if (is_mut)
str += "mut ";
@@ -3485,6 +3501,7 @@ AttributeParser::parse_meta_item_inner ()
case STRING_LITERAL:
case BYTE_CHAR_LITERAL:
case BYTE_STRING_LITERAL:
+ case RAW_STRING_LITERAL:
case INT_LITERAL:
case FLOAT_LITERAL:
case TRUE_LITERAL:
@@ -3767,6 +3784,10 @@ AttributeParser::parse_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 ());
@@ -4258,7 +4279,7 @@ BlockExpr::normalize_tail_expr ()
if (!stmt.is_semicolon_followed ())
{
- expr = std::move (stmt.take_expr ());
+ expr = stmt.take_expr ();
statements.pop_back ();
}
}
@@ -4504,6 +4525,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);
@@ -4636,6 +4669,18 @@ AsyncBlockExpr::accept_vis (ASTVisitor &vis)
}
void
+InlineAsm::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+LlvmInlineAsm::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
TypeParam::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index edf726b..49dfcde 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -57,6 +57,11 @@ public:
bool empty () const { return ident.empty (); }
+ bool operator== (const Identifier &other) const
+ {
+ return ident == other.ident;
+ }
+
private:
std::string ident;
location_t loc;
@@ -70,16 +75,6 @@ namespace AST {
class ASTVisitor;
using AttrVec = std::vector<Attribute>;
-// The available kinds of AST Nodes
-enum class Kind
-{
- UNKNOWN,
- MODULE,
- MACRO_RULES_DEFINITION,
- MACRO_INVOCATION,
- IDENTIFIER,
-};
-
class Visitable
{
public:
@@ -87,20 +82,6 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
};
-// Abstract base class for all AST elements
-class Node : public Visitable
-{
-public:
- /**
- * Get the kind of Node this is. This is used to differentiate various AST
- * elements with very little overhead when extracting the derived type
- * through static casting is not necessary.
- */
- // FIXME: Mark this as `= 0` in the future to make sure every node
- // implements it
- virtual Kind get_ast_kind () const { return Kind::UNKNOWN; }
-};
-
// Delimiter types - used in macros and whatever.
enum DelimType
{
@@ -250,6 +231,7 @@ public:
{
case STRING_LITERAL:
case BYTE_STRING_LITERAL:
+ case RAW_STRING_LITERAL:
return true;
default:
return false;
@@ -311,6 +293,7 @@ public:
STRING,
BYTE,
BYTE_STRING,
+ RAW_STRING,
INT,
FLOAT,
BOOL,
@@ -374,7 +357,7 @@ public:
// TODO: put checks in constructor to enforce this rule?
SimplePathSegment (std::string segment_name, location_t locus)
: segment_name (std::move (segment_name)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
/* Returns whether simple path segment is in an invalid state (currently, if
@@ -420,19 +403,19 @@ 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 ())
+ 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 ()),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
// Creates an empty SimplePath.
@@ -679,6 +662,9 @@ public:
// Returns whether the attribute is considered an "empty" attribute.
bool is_empty () const { return attr_input == nullptr && path.is_empty (); }
+ // Returns whether the attribute has no input
+ bool empty_input () const { return !attr_input; }
+
location_t get_locus () const { return locus; }
AttrInput &get_attr_input () const { return *attr_input; }
@@ -1037,6 +1023,7 @@ public:
}
DelimType get_delim_type () const { return delim_type; }
+ location_t get_locus () const { return locus; }
};
/* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr
@@ -1090,7 +1077,7 @@ class MetaListNameValueStr;
/* Base statement abstract class. Note that most "statements" are not allowed
* in top-level module scope - only a subclass of statements called "items"
* are. */
-class Stmt : public Node
+class Stmt : public Visitable
{
public:
enum class Kind
@@ -1127,7 +1114,7 @@ public:
virtual void add_semicolon () {}
protected:
- Stmt () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
+ Stmt () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
// Clone function implementation as pure virtual method
virtual Stmt *clone_stmt_impl () const = 0;
@@ -1139,6 +1126,28 @@ protected:
class Item : public Stmt
{
public:
+ enum class Kind
+ {
+ MacroRulesDefinition,
+ MacroInvocation,
+ Module,
+ ExternCrate,
+ UseDeclaration,
+ Function,
+ TypeAlias,
+ Struct,
+ EnumItem,
+ Enum,
+ Union,
+ ConstantItem,
+ StaticItem,
+ Trait,
+ Impl,
+ ExternBlock,
+ };
+
+ virtual Kind get_item_kind () const = 0;
+
// Unique pointer custom clone function
std::unique_ptr<Item> clone_item () const
{
@@ -1219,14 +1228,67 @@ public:
{
return outer_attrs;
}
+
+ virtual Item::Kind get_item_kind () const override = 0;
};
+
// forward decl of ExprWithoutBlock
class ExprWithoutBlock;
// Base expression AST node - abstract
-class Expr : public Node
+class Expr : public Visitable
{
public:
+ enum class Kind
+ {
+ PathInExpression,
+ QualifiedPathInExpression,
+ Literal,
+ Operator,
+ Grouped,
+ Array,
+ ArrayIndex,
+ Tuple,
+ TupleIndex,
+ Struct,
+ Call,
+ MethodCall,
+ FieldAccess,
+ Closure,
+ Block,
+ ConstExpr,
+ ConstBlock,
+ Continue,
+ Break,
+ Range,
+ Box,
+ Return,
+ UnsafeBlock,
+ Loop,
+ If,
+ IfLet,
+ Match,
+ Await,
+ AsyncBlock,
+ InlineAsm,
+ LlvmInlineAsm,
+ Identifier,
+ FormatArgs,
+ MacroInvocation,
+ Borrow,
+ Dereference,
+ ErrorPropagation,
+ Negation,
+ ArithmeticOrLogical,
+ Comparison,
+ LazyBoolean,
+ TypeCast,
+ Assignment,
+ CompoundAssignment,
+ };
+
+ virtual Kind get_expr_kind () const = 0;
+
// Unique pointer custom clone function
std::unique_ptr<Expr> clone_expr () const
{
@@ -1264,7 +1326,7 @@ public:
protected:
// Constructor
- Expr () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
+ Expr () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
// Clone function implementation as pure virtual method
virtual Expr *clone_expr_impl () const = 0;
@@ -1341,7 +1403,7 @@ public:
outer_attrs = std::move (new_attrs);
}
- Kind get_ast_kind () const override { return Kind::IDENTIFIER; }
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Identifier; }
protected:
// Clone method implementation
@@ -1408,7 +1470,7 @@ protected:
class TraitBound;
// Base class for types as represented in AST - abstract
-class Type : public Node
+class Type : public Visitable
{
public:
// Unique pointer custom clone function
@@ -1437,7 +1499,7 @@ public:
NodeId get_node_id () const { return node_id; }
protected:
- Type () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
+ Type () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
// Clone function implementation as pure virtual method
virtual Type *clone_type_impl () const = 0;
@@ -1475,6 +1537,12 @@ protected:
class TypeParamBound : public Visitable
{
public:
+ enum TypeParamBoundType
+ {
+ TRAIT,
+ LIFETIME
+ };
+
virtual ~TypeParamBound () {}
// Unique pointer custom clone function
@@ -1489,6 +1557,8 @@ public:
virtual location_t get_locus () const = 0;
+ virtual TypeParamBoundType get_bound_type () const = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual TypeParamBound *clone_type_param_bound_impl () const = 0;
@@ -1519,7 +1589,7 @@ public:
// Constructor
Lifetime (LifetimeType type, std::string name = std::string (),
location_t locus = UNDEF_LOCATION)
- : TypeParamBound (Analysis::Mappings::get ()->get_next_node_id ()),
+ : TypeParamBound (Analysis::Mappings::get ().get_next_node_id ()),
lifetime_type (type), lifetime_name (std::move (name)), locus (locus)
{}
@@ -1529,27 +1599,24 @@ public:
lifetime_name (std::move (name)), locus (locus)
{}
- // Creates an "error" lifetime.
- static Lifetime error () { return Lifetime (NAMED, ""); }
-
static Lifetime elided () { return Lifetime (WILDCARD, ""); }
// Returns true if the lifetime is in an error state.
- bool is_error () const
- {
- return lifetime_type == NAMED && lifetime_name.empty ();
- }
-
std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
- LifetimeType get_lifetime_type () { return lifetime_type; }
+ LifetimeType get_lifetime_type () const { return lifetime_type; }
location_t get_locus () const override final { return locus; }
std::string get_lifetime_name () const { return lifetime_name; }
+ TypeParamBoundType get_bound_type () const override
+ {
+ return TypeParamBound::TypeParamBoundType::LIFETIME;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1585,10 +1652,10 @@ public:
virtual Kind get_kind () const = 0;
- NodeId get_node_id () { return node_id; }
+ NodeId get_node_id () const { return node_id; }
protected:
- GenericParam () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
+ GenericParam () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
GenericParam (NodeId node_id) : node_id (node_id) {}
// Clone function implementation as pure virtual method
@@ -1602,7 +1669,7 @@ class LifetimeParam : public GenericParam
{
Lifetime lifetime;
std::vector<Lifetime> lifetime_bounds;
- Attribute outer_attr;
+ AST::AttrVec outer_attrs;
location_t locus;
public:
@@ -1610,32 +1677,27 @@ public:
Lifetime &get_lifetime () { return lifetime; }
- Attribute &get_outer_attribute () { return outer_attr; }
+ AST::AttrVec &get_outer_attrs () { return outer_attrs; }
// Returns whether the lifetime param has any lifetime bounds.
bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); }
std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
- // Returns whether the lifetime param has an outer attribute.
- bool has_outer_attribute () const { return !outer_attr.is_empty (); }
-
- // Creates an error state lifetime param.
- static LifetimeParam create_error ()
+ const std::vector<Lifetime> &get_lifetime_bounds () const
{
- return LifetimeParam (Lifetime::error (), {}, Attribute::create_empty (),
- UNDEF_LOCATION);
+ return lifetime_bounds;
}
- // Returns whether the lifetime param is in an error state.
- bool is_error () const { return lifetime.is_error (); }
+ // Returns whether the lifetime param has an outer attribute.
+ bool has_outer_attribute () const { return !outer_attrs.empty (); }
// Constructor
LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds,
- Attribute outer_attr, location_t locus)
+ AST::AttrVec outer_attrs, location_t locus)
: lifetime (std::move (lifetime)),
lifetime_bounds (std::move (lifetime_bounds)),
- outer_attr (std::move (outer_attr)), locus (locus)
+ outer_attrs (std::move (outer_attrs)), locus (locus)
{}
std::string as_string () const override;
@@ -1682,12 +1744,12 @@ class TraitItem : public AssociatedItem
{
protected:
TraitItem (location_t locus)
- : node_id (Analysis::Mappings::get ()->get_next_node_id ()),
+ : node_id (Analysis::Mappings::get ().get_next_node_id ()),
vis (Visibility::create_private ()), locus (locus)
{}
TraitItem (Visibility vis, location_t locus)
- : node_id (Analysis::Mappings::get ()->get_next_node_id ()), vis (vis),
+ : node_id (Analysis::Mappings::get ().get_next_node_id ()), vis (vis),
locus (locus)
{}
@@ -1713,7 +1775,7 @@ public:
class ExternalItem : public Visitable
{
public:
- ExternalItem () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
+ ExternalItem () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
ExternalItem (NodeId node_id) : node_id (node_id) {}
@@ -1929,13 +1991,6 @@ public:
return std::move (item);
}
- std::unique_ptr<AssociatedItem> take_trait_item ()
- {
- rust_assert (!is_error ());
- return std::unique_ptr<AssociatedItem> (
- static_cast<AssociatedItem *> (assoc_item.release ()));
- }
-
std::unique_ptr<ExternalItem> take_external_item ()
{
rust_assert (!is_error ());
@@ -1948,16 +2003,6 @@ public:
return std::move (assoc_item);
}
- std::unique_ptr<AssociatedItem> take_impl_item ()
- {
- return take_assoc_item ();
- }
-
- std::unique_ptr<AssociatedItem> take_trait_impl_item ()
- {
- return take_assoc_item ();
- }
-
std::unique_ptr<Type> take_type ()
{
rust_assert (!is_error ());
@@ -1987,7 +2032,7 @@ public:
Crate (std::vector<std::unique_ptr<Item>> items,
std::vector<Attribute> inner_attrs)
: inner_attrs (std::move (inner_attrs)), items (std::move (items)),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
// Copy constructor with vector clone
@@ -2047,11 +2092,6 @@ public:
}
};
-// Base path expression AST node - abstract
-class PathExpr : public ExprWithoutBlock
-{
-};
-
} // namespace AST
} // namespace Rust
@@ -2064,6 +2104,19 @@ template <> struct less<Rust::Identifier>
return lhs.as_string () < rhs.as_string ();
}
};
+
+template <> struct hash<Rust::Identifier>
+{
+ std::size_t operator() (const Rust::Identifier &k) const
+ {
+ using std::hash;
+ using std::size_t;
+ using std::string;
+
+ return hash<string> () (k.as_string ()) ^ (hash<int> () (k.get_locus ()));
+ }
+};
+
} // namespace std
#endif
diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h
index 3e21d7e..df3db85 100644
--- a/gcc/rust/ast/rust-builtin-ast-nodes.h
+++ b/gcc/rust/ast/rust-builtin-ast-nodes.h
@@ -202,6 +202,8 @@ public:
const FormatArguments &get_arguments () const { return arguments; }
virtual location_t get_locus () const override;
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::FormatArgs; }
+
private:
location_t loc;
// FIXME: This probably needs to be a separate type - it is one in rustc's
diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc
new file mode 100644
index 0000000..306c6f7
--- /dev/null
+++ b/gcc/rust/ast/rust-collect-lang-items.cc
@@ -0,0 +1,137 @@
+// Copyright (C) 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-collect-lang-items.h"
+#include "optional.h"
+#include "rust-ast-collector.h"
+#include "rust-ast-visitor.h"
+#include "rust-ast.h"
+#include "rust-attribute-values.h"
+#include "rust-attributes.h"
+#include "rust-hir-map.h"
+#include "rust-item.h"
+
+namespace Rust {
+namespace AST {
+
+template <typename T>
+tl::optional<LangItem::Kind>
+get_lang_item_attr (const T &maybe_lang_item)
+{
+ for (const auto &attr : maybe_lang_item.get_outer_attrs ())
+ {
+ const auto &str_path = attr.get_path ().as_string ();
+ if (!Analysis::Attributes::is_known (str_path))
+ {
+ rust_error_at (attr.get_locus (), "unknown attribute %qs",
+ str_path.c_str ());
+ continue;
+ }
+
+ bool is_lang_item = str_path == Values::Attributes::LANG
+ && attr.has_attr_input ()
+ && attr.get_attr_input ().get_attr_input_type ()
+ == AST::AttrInput::AttrInputType::LITERAL;
+
+ if (is_lang_item)
+ {
+ auto &literal
+ = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
+ const auto &lang_item_type_str = literal.get_literal ().as_string ();
+
+ return LangItem::Parse (lang_item_type_str);
+ }
+ }
+
+ return tl::nullopt;
+}
+
+template <typename T>
+void
+CollectLangItems::maybe_add_lang_item (const T &item)
+{
+ if (auto lang_item = get_lang_item_attr (item))
+ mappings.insert_lang_item_node (lang_item.value (), item.get_node_id ());
+}
+
+void
+CollectLangItems::visit (AST::Trait &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit (item);
+}
+
+void
+CollectLangItems::visit (AST::TraitItemType &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit (item);
+}
+
+void
+CollectLangItems::visit (AST::Function &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit (item);
+}
+
+void
+CollectLangItems::visit (AST::StructStruct &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit (item);
+}
+
+void
+CollectLangItems::visit (AST::EnumItem &item)
+{
+ maybe_add_lang_item (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
new file mode 100644
index 0000000..ddc7b51
--- /dev/null
+++ b/gcc/rust/ast/rust-collect-lang-items.h
@@ -0,0 +1,64 @@
+// Copyright (C) 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_COLLECT_LANG_ITEMS_H
+#define RUST_COLLECT_LANG_ITEMS_H
+
+#include "rust-ast-visitor.h"
+#include "rust-ast.h"
+#include "rust-hir-map.h"
+#include "rust-item.h"
+
+namespace Rust {
+namespace AST {
+
+// This class collects lang items ahead of lowering, as they are now needed for
+// some parts of name resolution
+class CollectLangItems : public DefaultASTVisitor
+{
+public:
+ CollectLangItems () : mappings (Analysis::Mappings::get ()){};
+
+ void go (AST::Crate &crate) { DefaultASTVisitor::visit (crate); }
+
+ Analysis::Mappings &mappings;
+
+ // We must implement visitors for all constructs that could be lang items.
+ // Lang items can be traits, but also enums, and even enum variants.
+ //
+ // https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs
+
+ using DefaultASTVisitor::visit;
+
+ void visit (AST::Trait &item) override;
+ void visit (AST::TraitItemType &item) override;
+ 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);
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_COLLECT_LANG_ITEMS_H
diff --git a/gcc/rust/ast/rust-desugar-apit.cc b/gcc/rust/ast/rust-desugar-apit.cc
new file mode 100644
index 0000000..5b9486e
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-apit.cc
@@ -0,0 +1,518 @@
+// 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 &param : 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 f36feda..07c25e2 100644
--- a/gcc/rust/ast/rust-macro.cc
+++ b/gcc/rust/ast/rust-desugar-apit.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2024 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
new file mode 100644
index 0000000..ffc3470
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-for-loops.cc
@@ -0,0 +1,204 @@
+// 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-for-loops.h"
+#include "rust-ast-visitor.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 {
+
+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 (
+ builder.path_in_expression (LangItem::Kind::OPTION_NONE))));
+
+ auto break_expr
+ = std::unique_ptr<Expr> (new BreakExpr (tl::nullopt, nullptr, {}, loc));
+
+ return MatchCase (std::move (arm), std::move (break_expr));
+}
+
+MatchCase
+DesugarForLoops::DesugarCtx::make_continue_arm ()
+{
+ auto val = builder.identifier_pattern (DesugarCtx::continue_pattern_id);
+
+ auto patterns = std::vector<std::unique_ptr<Pattern>> ();
+ patterns.emplace_back (std::move (val));
+
+ auto pattern_item = std::unique_ptr<TupleStructItems> (
+ new TupleStructItemsNoRange (std::move (patterns)));
+ auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern (
+ builder.path_in_expression (LangItem::Kind::OPTION_SOME),
+ std::move (pattern_item)));
+
+ auto val_arm = make_match_arm (std::move (pattern));
+
+ auto next = builder.identifier (DesugarCtx::next_value_id);
+
+ auto assignment = std::unique_ptr<Expr> (
+ new AssignmentExpr (std::move (next),
+ builder.identifier (DesugarCtx::continue_pattern_id),
+ {}, loc));
+
+ 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)
+{
+ auto ctx = DesugarCtx (expr.get_locus ());
+
+ auto into_iter = std::make_unique<PathInExpression> (
+ ctx.builder.path_in_expression (LangItem::Kind::INTOITER_INTOITER));
+ auto next = std::make_unique<PathInExpression> (
+ ctx.builder.path_in_expression (LangItem::Kind::ITERATOR_NEXT));
+
+ // IntoIterator::into_iter(<head>)
+ auto into_iter_call
+ = ctx.builder.call (std::move (into_iter),
+ expr.get_iterator_expr ().clone_expr ());
+
+ // Iterator::next(iter)
+ auto next_call = ctx.builder.call (
+ std::move (next),
+ ctx.builder.ref (ctx.builder.identifier (DesugarCtx::iter_id), true));
+
+ // None => break,
+ auto break_arm = ctx.make_break_arm ();
+ // Some(val) => __next = val; },
+ auto continue_arm = ctx.make_continue_arm ();
+
+ // match <next_call> {
+ // <continue_arm>
+ // <break_arm>
+ // }
+ auto match_next
+ = ctx.builder.match (std::move (next_call),
+ {std::move (continue_arm), std::move (break_arm)});
+
+ // let mut __next;
+ auto let_next = ctx.builder.let (
+ ctx.builder.identifier_pattern (DesugarCtx::next_value_id, true));
+ // let <pattern> = __next;
+ auto let_pat
+ = ctx.builder.let (expr.get_pattern ().clone_pattern (), nullptr,
+ ctx.builder.identifier (DesugarCtx::next_value_id));
+
+ 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 (std::move (let_pat));
+ loop_stmts.emplace_back (
+ ctx.statementify (expr.get_loop_block ().clone_expr ()));
+
+ // loop {
+ // <let_next>;
+ // <match_next>;
+ // <let_pat>;
+ //
+ // <body>;
+ // }
+ auto loop = ctx.builder.loop (std::move (loop_stmts));
+
+ auto mut_iter_pattern
+ = ctx.builder.identifier_pattern (DesugarCtx::iter_id, true);
+ auto match_iter
+ = ctx.builder.match (std::move (into_iter_call),
+ {ctx.builder.match_case (std::move (mut_iter_pattern),
+ std::move (loop))});
+
+ auto let_result
+ = ctx.builder.let (ctx.builder.identifier_pattern (DesugarCtx::result_id),
+ nullptr, std::move (match_iter));
+ auto result_return = ctx.builder.identifier (DesugarCtx::result_id);
+
+ return ctx.builder.block (std::move (let_result), std::move (result_return));
+}
+
+void
+DesugarForLoops::maybe_desugar_expr (std::unique_ptr<Expr> &expr)
+{
+ if (expr->get_expr_kind () == AST::Expr::Kind::Loop)
+ {
+ auto &loop = static_cast<AST::BaseLoopExpr &> (*expr);
+
+ if (loop.get_loop_kind () == AST::BaseLoopExpr::Kind::For)
+ {
+ auto &for_loop = static_cast<AST::ForLoopExpr &> (loop);
+
+ 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 ());
+
+ if (block.has_tail_expr ())
+ maybe_desugar_expr (block.get_tail_expr_ptr ());
+
+ DefaultASTVisitor::visit (block);
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-for-loops.h b/gcc/rust/ast/rust-desugar-for-loops.h
new file mode 100644
index 0000000..7beb692
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-for-loops.h
@@ -0,0 +1,108 @@
+// 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_FOR_LOOPS_H
+#define RUST_DESUGAR_FOR_LOOPS_H
+
+#include "rust-ast-builder.h"
+#include "rust-ast-visitor.h"
+#include "rust-expr.h"
+
+namespace Rust {
+namespace AST {
+
+// Desugar for-loops into a set of other AST nodes. The desugar is of the
+// following form:
+//
+// ```
+// for <pat> in <head> <body>
+// ```
+//
+// becomes:
+//
+// ```
+// {
+// let result = match ::std::iter::IntoIterator::into_iter(<head>) {
+// mut iter => {
+// loop {
+// let mut __next;
+// match ::std::iter::Iterator::next(&mut iter) {
+// ::std::option::Option::Some(val) => __next = val,
+// ::std::option::Option::None => break
+// };
+// let <pat> = __next;
+//
+// <body>;
+// }
+// }
+// };
+// result
+// }
+// ```
+//
+// NOTE: In a perfect world, this would be an immutable visitor which would take
+// ownership of the AST node and return a new one, instead of mutating this one
+// in place. Nevertheless, this isn't Rust, and doing immutable visitors in C++
+// sucks, and the world isn't perfect, so we are impure and sad.
+//
+// NOTE: This class could eventually be removed in favor of
+// an HIR desugar. This would avoid mutating the AST and would be cleaner.
+// However, it requires multiple changes in the way we do typechecking and name
+// resolution, as this desugar creates new bindings. Because of this, these new
+// bindings need to be inserted into the name-resolution context outside of the
+// name resolution pass, which is difficult. Those bindings are needed because
+// 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
+{
+ using DefaultASTVisitor::visit;
+
+public:
+ DesugarForLoops ();
+ void go (AST::Crate &);
+
+private:
+ struct DesugarCtx
+ {
+ DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {}
+
+ 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";
+ constexpr static const char *iter_id = "#iter";
+ 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;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DESUGAR_FOR_LOOPS_H
diff --git a/gcc/rust/ast/rust-desugar-question-mark.cc b/gcc/rust/ast/rust-desugar-question-mark.cc
new file mode 100644
index 0000000..4d2933b
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-question-mark.cc
@@ -0,0 +1,167 @@
+// 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-question-mark.h"
+#include "rust-ast-builder.h"
+#include "rust-ast-visitor.h"
+
+namespace Rust {
+namespace AST {
+
+DesugarQuestionMark::DesugarQuestionMark () {}
+
+void
+DesugarQuestionMark::go (AST::Crate &crate)
+{
+ 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);
+}
+
+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 ());
+
+ DefaultASTVisitor::visit (stmt);
+}
+
+MatchArm
+make_match_arm (std::unique_ptr<Pattern> &&pattern)
+{
+ auto loc = pattern->get_locus ();
+
+ auto patterns = std::vector<std::unique_ptr<Pattern>> ();
+ patterns.emplace_back (std::move (pattern));
+
+ return MatchArm (std::move (patterns), loc);
+}
+
+MatchCase
+ok_case (Builder &builder)
+{
+ auto val = builder.identifier_pattern ("val");
+
+ auto patterns = std::vector<std::unique_ptr<Pattern>> ();
+ patterns.emplace_back (std::move (val));
+
+ auto pattern_item = std::unique_ptr<TupleStructItems> (
+ new TupleStructItemsNoRange (std::move (patterns)));
+ auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern (
+ builder.path_in_expression (LangItem::Kind::RESULT_OK),
+ std::move (pattern_item)));
+
+ auto arm = make_match_arm (std::move (pattern));
+
+ auto ret_val = builder.identifier ("val");
+
+ return MatchCase (std::move (arm), std::move (ret_val));
+}
+
+MatchCase
+err_case (Builder &builder)
+{
+ auto val = builder.identifier_pattern ("err");
+
+ auto patterns = std::vector<std::unique_ptr<Pattern>> ();
+ patterns.emplace_back (std::move (val));
+
+ auto pattern_item = std::unique_ptr<TupleStructItems> (
+ new TupleStructItemsNoRange (std::move (patterns)));
+ auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern (
+ builder.path_in_expression (LangItem::Kind::RESULT_ERR),
+ std::move (pattern_item)));
+
+ auto arm = make_match_arm (std::move (pattern));
+
+ auto try_from_err = std::make_unique<PathInExpression> (
+ builder.path_in_expression (LangItem::Kind::TRY_FROM_ERROR));
+ auto from_from = std::make_unique<PathInExpression> (
+ builder.path_in_expression (LangItem::Kind::FROM_FROM));
+
+ auto early_return = builder.return_expr (
+ builder.call (std::move (try_from_err),
+ builder.call (std::move (from_from),
+ builder.identifier ("err"))));
+
+ return MatchCase (std::move (arm), std::move (early_return));
+}
+
+std::unique_ptr<Expr>
+DesugarQuestionMark::desugar (ErrorPropagationExpr &expr)
+{
+ auto builder = Builder (expr.get_locus ());
+
+ // Try::into_result(<expr>)
+ auto try_into = std::make_unique<PathInExpression> (
+ builder.path_in_expression (LangItem::Kind::TRY_INTO_RESULT));
+ auto call = builder.call (std::move (try_into),
+ expr.get_propagating_expr ().clone_expr ());
+
+ // Ok(val) => val,
+ auto ok_match_case = ok_case (builder);
+ // Err(err) => return Try::from_error(From::from(err)),
+ auto err_match_case = err_case (builder);
+
+ auto cases = std::vector<MatchCase> ();
+ cases.emplace_back (ok_match_case);
+ cases.emplace_back (err_match_case);
+
+ // match <call> {
+ // <ok_arm>
+ // <err_arm>
+ // }
+ return std::unique_ptr<MatchExpr> (new MatchExpr (std::move (call),
+ std::move (cases), {}, {},
+ 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
new file mode 100644
index 0000000..e4c513f
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-question-mark.h
@@ -0,0 +1,79 @@
+// 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_QUESTION_MARK
+#define RUST_DESUGAR_QUESTION_MARK
+
+#include "rust-ast-visitor.h"
+#include "rust-expr.h"
+#include "rust-stmt.h"
+
+namespace Rust {
+namespace AST {
+
+// NOTE: One more complexity compare to desugaring for-loops is that we need to
+// desugar every possible expression... should we do that during lowering
+// instead? but would it get resolved and expanded etc? Not sure...
+
+// The goal of this desugar is to go from this:
+//
+// ```
+// <expr>?
+// ```
+//
+// to this:
+//
+// ```
+// match Try::into_result(<expr>) {
+// Ok(val) => val,
+// Err(err) => return Try::from_err(From::from(err))
+// }
+// ```
+//
+// We use lang items for almost everything, so the actual desugared code looks
+// more like this:
+//
+// ```
+// match #[lang = "into_result"](<expr>) {
+// #[lang = "Ok"](val) => val,
+// #[lang = "Err"](err) => {
+// return #[lang = "from_error"](#[lang ="from"](err))
+// }
+// }
+// ```
+class DesugarQuestionMark : public DefaultASTVisitor
+{
+ using DefaultASTVisitor::visit;
+
+public:
+ DesugarQuestionMark ();
+ void go (AST::Crate &);
+
+private:
+ void desugar_and_replace (std::unique_ptr<Expr> &ptr);
+ std::unique_ptr<Expr> desugar (ErrorPropagationExpr &);
+
+ void visit (AST::ExprStmt &) override;
+ void visit (AST::CallExpr &) override;
+ void visit (AST::LetStmt &) override;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DESUGAR_QUESTION_MARK
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index d3dc197..ba20bfa 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -2,6 +2,7 @@
#define RUST_AST_EXPR_H
#include "rust-ast.h"
+#include "rust-common.h"
#include "rust-path.h"
#include "rust-macro.h"
#include "rust-operators.h"
@@ -14,7 +15,7 @@ namespace AST {
// Loop label expression AST node used with break and continue expressions
// TODO: inline?
-class LoopLabel /*: public Node*/
+class LoopLabel /*: public Visitable*/
{
Lifetime label; // or type LIFETIME_OR_LABEL
location_t locus;
@@ -26,15 +27,10 @@ public:
LoopLabel (Lifetime loop_label, location_t locus = UNDEF_LOCATION)
: label (std::move (loop_label)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
// Returns whether the LoopLabel is in an error state.
- bool is_error () const { return label.is_error (); }
-
- // Creates an error state LoopLabel.
- static LoopLabel error () { return LoopLabel (Lifetime::error ()); }
-
location_t get_locus () const { return locus; }
Lifetime &get_lifetime () { return label; }
@@ -116,6 +112,8 @@ public:
outer_attrs = std::move (new_attrs);
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Literal; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -302,7 +300,7 @@ protected:
class OperatorExpr : public ExprWithoutBlock
{
// TODO: create binary and unary operator subclasses?
-public:
+private:
location_t locus;
protected:
@@ -364,24 +362,28 @@ public:
{
outer_attrs = std::move (new_attrs);
}
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Operator; }
};
/* Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be
* overloaded. */
class BorrowExpr : public OperatorExpr
{
- bool is_mut;
+ Mutability mutability;
+ bool raw_borrow;
bool double_borrow;
public:
std::string as_string () const override;
- BorrowExpr (std::unique_ptr<Expr> borrow_lvalue, bool is_mut_borrow,
- bool is_double_borrow, std::vector<Attribute> outer_attribs,
- location_t locus)
+ BorrowExpr (std::unique_ptr<Expr> borrow_lvalue, Mutability mutability,
+ bool raw_borrow, bool is_double_borrow,
+ std::vector<Attribute> outer_attribs, location_t locus)
: OperatorExpr (std::move (borrow_lvalue), std::move (outer_attribs),
locus),
- is_mut (is_mut_borrow), double_borrow (is_double_borrow)
+ mutability (mutability), raw_borrow (raw_borrow),
+ double_borrow (is_double_borrow)
{}
void accept_vis (ASTVisitor &vis) override;
@@ -393,9 +395,14 @@ public:
return *main_or_left_expr;
}
- bool get_is_mut () const { return is_mut; }
+ bool get_is_mut () const { return mutability == Mutability::Mut; }
+
+ Mutability get_mutability () const { return mutability; }
bool get_is_double_borrow () const { return double_borrow; }
+ bool is_raw_borrow () const { return raw_borrow; }
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Borrow; }
protected:
/* Use covariance to implement clone function as returning this object rather
@@ -427,6 +434,8 @@ public:
return *main_or_left_expr;
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Dereference; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -458,6 +467,11 @@ public:
return *main_or_left_expr;
}
+ Expr::Kind get_expr_kind () const override
+ {
+ return Expr::Kind::ErrorPropagation;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -501,6 +515,8 @@ public:
return *main_or_left_expr;
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Negation; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -589,6 +605,11 @@ public:
void visit_lhs (ASTVisitor &vis) { main_or_left_expr->accept_vis (vis); }
void visit_rhs (ASTVisitor &vis) { right_expr->accept_vis (vis); }
+ Expr::Kind get_expr_kind () const override
+ {
+ return Expr::Kind::ArithmeticOrLogical;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -676,6 +697,8 @@ public:
ExprType get_kind () { return expr_type; }
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Comparison; }
+
/* TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2)
* maybe? */
protected:
@@ -764,6 +787,8 @@ public:
ExprType get_kind () { return expr_type; }
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::LazyBoolean; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -826,6 +851,8 @@ public:
return *type_to_convert_to;
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::TypeCast; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -904,6 +931,8 @@ public:
return *right_expr;
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Assignment; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -990,6 +1019,11 @@ public:
return right_expr;
}
+ Expr::Kind get_expr_kind () const override
+ {
+ return Expr::Kind::CompoundAssignment;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1084,6 +1118,8 @@ public:
return expr_in_parens;
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Grouped; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1113,7 +1149,7 @@ public:
NodeId get_node_id () const { return node_id; }
protected:
- ArrayElems () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
+ ArrayElems () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
// pure virtual clone implementation
virtual ArrayElems *clone_array_elems_impl () const = 0;
@@ -1178,6 +1214,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;
@@ -1313,6 +1351,8 @@ public:
return internal_elements;
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Array; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1418,6 +1458,8 @@ public:
outer_attrs = std::move (new_attrs);
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::ArrayIndex; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1514,6 +1556,8 @@ public:
bool is_unit () const { return tuple_elems.size () == 0; }
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Tuple; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1601,6 +1645,8 @@ public:
outer_attrs = std::move (new_attrs);
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::TupleIndex; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1644,6 +1690,8 @@ public:
{
outer_attrs = std::move (new_attrs);
}
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Struct; }
};
// Actual AST node of the struct creator (with no fields). Not abstract!
@@ -1758,13 +1806,26 @@ public:
NodeId get_node_id () const { return node_id; }
+ const std::vector<AST::Attribute> &get_outer_attrs () const
+ {
+ return outer_attrs;
+ }
+
+ std::vector<AST::Attribute> &get_outer_attrs () { return outer_attrs; }
+
protected:
// pure virtual clone implementation
virtual StructExprField *clone_struct_expr_field_impl () const = 0;
- StructExprField () : node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ StructExprField () : node_id (Analysis::Mappings::get ().get_next_node_id ())
+ {}
+
+ StructExprField (AST::AttrVec outer_attrs)
+ : outer_attrs (std::move (outer_attrs)),
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
+ AST::AttrVec outer_attrs;
NodeId node_id;
};
@@ -1775,9 +1836,10 @@ class StructExprFieldIdentifier : public StructExprField
location_t locus;
public:
- StructExprFieldIdentifier (Identifier field_identifier, location_t locus)
- : StructExprField (), field_name (std::move (field_identifier)),
- locus (locus)
+ StructExprFieldIdentifier (Identifier field_identifier,
+ AST::AttrVec outer_attrs, location_t locus)
+ : StructExprField (std::move (outer_attrs)),
+ field_name (std::move (field_identifier)), locus (locus)
{}
std::string as_string () const override { return field_name.as_string (); }
@@ -1804,19 +1866,22 @@ class StructExprFieldWithVal : public StructExprField
std::unique_ptr<Expr> value;
protected:
- StructExprFieldWithVal (std::unique_ptr<Expr> field_value)
- : StructExprField (), value (std::move (field_value))
+ StructExprFieldWithVal (std::unique_ptr<Expr> field_value,
+ AST::AttrVec outer_attrs)
+ : StructExprField (std::move (outer_attrs)), value (std::move (field_value))
{}
// Copy constructor requires clone
StructExprFieldWithVal (StructExprFieldWithVal const &other)
- : value (other.value->clone_expr ())
+ : StructExprField (other.get_outer_attrs ()),
+ value (other.value->clone_expr ())
{}
// Overload assignment operator to clone unique_ptr
StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other)
{
value = other.value->clone_expr ();
+ outer_attrs = other.get_outer_attrs ();
return *this;
}
@@ -1845,8 +1910,15 @@ class StructExprFieldIdentifierValue : public StructExprFieldWithVal
public:
StructExprFieldIdentifierValue (Identifier field_identifier,
std::unique_ptr<Expr> field_value,
+ AST::AttrVec outer_attrs, location_t locus)
+ : StructExprFieldWithVal (std::move (field_value), std::move (outer_attrs)),
+ field_name (std::move (field_identifier)), locus (locus)
+ {}
+
+ StructExprFieldIdentifierValue (Identifier field_identifier,
+ std::unique_ptr<Expr> field_value,
location_t locus)
- : StructExprFieldWithVal (std::move (field_value)),
+ : StructExprFieldWithVal (std::move (field_value), {}),
field_name (std::move (field_identifier)), locus (locus)
{}
@@ -1876,9 +1948,9 @@ class StructExprFieldIndexValue : public StructExprFieldWithVal
public:
StructExprFieldIndexValue (TupleIndex tuple_index,
std::unique_ptr<Expr> field_value,
- location_t locus)
- : StructExprFieldWithVal (std::move (field_value)), index (tuple_index),
- locus (locus)
+ AST::AttrVec outer_attrs, location_t locus)
+ : StructExprFieldWithVal (std::move (field_value), std::move (outer_attrs)),
+ index (tuple_index), locus (locus)
{}
std::string as_string () const override;
@@ -2093,6 +2165,8 @@ public:
return *function;
}
+ std::unique_ptr<Expr> &get_function_expr_ptr () { return function; }
+
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
@@ -2101,6 +2175,8 @@ public:
outer_attrs = std::move (new_attrs);
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Call; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2204,6 +2280,8 @@ public:
outer_attrs = std::move (new_attrs);
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::MethodCall; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2289,6 +2367,8 @@ public:
outer_attrs = std::move (new_attrs);
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::FieldAccess; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -2424,6 +2504,8 @@ public:
}
bool get_has_move () const { return has_move; }
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Closure; }
};
// Represents a non-type-specified closure expression AST node
@@ -2505,7 +2587,7 @@ class BlockExpr : public ExprWithBlock
std::vector<Attribute> inner_attrs;
std::vector<std::unique_ptr<Stmt> > statements;
std::unique_ptr<Expr> expr;
- LoopLabel label;
+ tl::optional<LoopLabel> label;
location_t start_locus;
location_t end_locus;
bool marked_for_strip = false;
@@ -2522,8 +2604,9 @@ public:
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, LoopLabel label,
- location_t start_locus, location_t end_locus)
+ std::vector<Attribute> outer_attribs,
+ tl::optional<LoopLabel> label, location_t start_locus,
+ location_t end_locus)
: outer_attrs (std::move (outer_attribs)),
inner_attrs (std::move (inner_attribs)),
statements (std::move (block_statements)), expr (std::move (block_expr)),
@@ -2642,8 +2725,10 @@ public:
outer_attrs = std::move (new_attrs);
}
- bool has_label () { return !label.is_error (); }
- LoopLabel &get_label () { return label; }
+ bool has_label () { return label.has_value (); }
+ LoopLabel &get_label () { return label.value (); }
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Block; }
protected:
/* Use covariance to implement clone function as returning this object rather
@@ -2661,6 +2746,124 @@ protected:
}
};
+class AnonConst : public ExprWithBlock
+{
+public:
+ AnonConst (std::unique_ptr<Expr> &&expr, location_t locus = UNKNOWN_LOCATION)
+ : ExprWithBlock (), locus (locus), expr (std::move (expr))
+ {
+ rust_assert (this->expr);
+ }
+
+ AnonConst (const AnonConst &other)
+ {
+ node_id = other.node_id;
+ locus = other.locus;
+ expr = other.expr->clone_expr ();
+ }
+
+ AnonConst operator= (const AnonConst &other)
+ {
+ node_id = other.node_id;
+ locus = other.locus;
+ expr = other.expr->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 () { return *expr; }
+ 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;
+
+private:
+ location_t locus;
+ 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
{
@@ -2761,7 +2964,7 @@ protected:
class ContinueExpr : public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
- Lifetime label;
+ tl::optional<Lifetime> label;
location_t locus;
// TODO: find another way to store this to save memory?
@@ -2771,11 +2974,11 @@ public:
std::string as_string () const override;
// Returns true if the continue expr has a label.
- bool has_label () const { return !label.is_error (); }
+ bool has_label () const { return label.has_value (); }
// Constructor for a ContinueExpr with a label.
- ContinueExpr (Lifetime label, std::vector<Attribute> outer_attribs,
- location_t locus)
+ ContinueExpr (tl::optional<Lifetime> label,
+ std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)), label (std::move (label)),
locus (locus)
{}
@@ -2796,7 +2999,13 @@ public:
outer_attrs = std::move (new_attrs);
}
- Lifetime &get_label () { return label; }
+ Lifetime &get_label_unchecked () { return label.value (); }
+ const Lifetime &get_label_unchecked () const { return label.value (); }
+
+ tl::optional<Lifetime> &get_label () { return label; }
+ const tl::optional<Lifetime> &get_label () const { return label; }
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Continue; }
protected:
/* Use covariance to implement clone function as returning this object rather
@@ -2812,7 +3021,7 @@ protected:
class BreakExpr : public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
- LoopLabel label;
+ tl::optional<LoopLabel> label;
std::unique_ptr<Expr> break_expr;
location_t locus;
@@ -2823,14 +3032,15 @@ public:
std::string as_string () const override;
// Returns whether the break expression has a label or not.
- bool has_label () const { return !label.is_error (); }
+ bool has_label () const { return label.has_value (); }
/* Returns whether the break expression has an expression used in the break or
* not. */
bool has_break_expr () const { return break_expr != nullptr; }
// Constructor for a break expression
- BreakExpr (LoopLabel break_label, std::unique_ptr<Expr> expr_in_break,
+ BreakExpr (tl::optional<LoopLabel> break_label,
+ std::unique_ptr<Expr> expr_in_break,
std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)), label (std::move (break_label)),
break_expr (std::move (expr_in_break)), locus (locus)
@@ -2892,7 +3102,13 @@ public:
outer_attrs = std::move (new_attrs);
}
- LoopLabel &get_label () { return label; }
+ LoopLabel &get_label_unchecked () { return label.value (); }
+ const LoopLabel &get_label_unchecked () const { return label.value (); }
+
+ tl::optional<LoopLabel> &get_label () { return label; }
+ const tl::optional<LoopLabel> &get_label () const { return label; }
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Break; }
protected:
/* Use covariance to implement clone function as returning this object rather
@@ -2908,6 +3124,10 @@ class RangeExpr : public ExprWithoutBlock
{
location_t locus;
+ // Some visitors still check for attributes on RangeExprs, and they will need
+ // to be supported in the future - so keep that for now
+ std::vector<Attribute> empty_attributes = {};
+
protected:
// outer attributes not allowed before range expressions
RangeExpr (location_t locus) : locus (locus) {}
@@ -2917,15 +3137,13 @@ public:
std::vector<Attribute> &get_outer_attrs () override final
{
- // RangeExpr cannot have any outer attributes
- rust_assert (false);
+ return empty_attributes;
}
// should never be called - error if called
- void set_outer_attrs (std::vector<Attribute> /* new_attrs */) override
- {
- rust_assert (false);
- }
+ void set_outer_attrs (std::vector<Attribute> /* new_attrs */) override {}
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Range; }
};
// Range from (inclusive) and to (exclusive) expression AST node object
@@ -3310,6 +3528,81 @@ protected:
}
};
+class BoxExpr : public ExprWithoutBlock
+{
+ std::unique_ptr<Expr> expr;
+ std::vector<Attribute> outer_attrs;
+ location_t locus;
+
+public:
+ BoxExpr (std::unique_ptr<Expr> expr, std::vector<Attribute> outer_attrs,
+ location_t locus)
+ : expr (std::move (expr)), outer_attrs (outer_attrs), locus (locus)
+ {}
+
+ // Copy constructor with clone
+ BoxExpr (BoxExpr const &other)
+ : ExprWithoutBlock (other), outer_attrs (other.outer_attrs),
+ locus (other.locus)
+ {
+ // guard to protect from null pointer dereference
+ if (other.expr != nullptr)
+ expr = other.expr->clone_expr ();
+ }
+
+ BoxExpr &operator= (BoxExpr const &other)
+ {
+ ExprWithoutBlock::operator= (other);
+ locus = other.locus;
+ outer_attrs = other.outer_attrs;
+
+ // guard to protect from null pointer dereference
+ if (other.expr != nullptr)
+ expr = other.expr->clone_expr ();
+ else
+ expr = nullptr;
+
+ return *this;
+ }
+
+ // move constructors
+ BoxExpr (BoxExpr &&other) = default;
+ BoxExpr &operator= (BoxExpr &&other) = default;
+
+ location_t get_locus () const override final { return locus; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ void mark_for_strip () override { expr = nullptr; }
+ bool is_marked_for_strip () const override { return expr == nullptr; }
+
+ 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);
+ }
+
+ std::string as_string () const override;
+
+ Expr &get_boxed_expr ()
+ {
+ rust_assert (expr != nullptr);
+ return *expr;
+ }
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Box; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ BoxExpr *clone_expr_without_block_impl () const override
+ {
+ return new BoxExpr (*this);
+ }
+};
+
// Return expression AST node representation
class ReturnExpr : public ExprWithoutBlock
{
@@ -3388,6 +3681,8 @@ public:
outer_attrs = std::move (new_attrs);
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Return; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3470,6 +3765,8 @@ public:
outer_attrs = std::move (new_attrs);
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::UnsafeBlock; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3485,7 +3782,7 @@ class BaseLoopExpr : public ExprWithBlock
protected:
// protected to allow subclasses better use of them
std::vector<Attribute> outer_attrs;
- LoopLabel loop_label;
+ tl::optional<LoopLabel> loop_label;
std::unique_ptr<BlockExpr> loop_block;
private:
@@ -3494,7 +3791,7 @@ private:
protected:
// Constructor for BaseLoopExpr
BaseLoopExpr (std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs
= std::vector<Attribute> ())
: outer_attrs (std::move (outer_attribs)),
@@ -3534,9 +3831,10 @@ protected:
BaseLoopExpr &operator= (BaseLoopExpr &&other) = default;
public:
- bool has_loop_label () const { return !loop_label.is_error (); }
+ bool has_loop_label () const { return loop_label.has_value (); }
- LoopLabel &get_loop_label () { return loop_label; }
+ LoopLabel &get_loop_label () { return loop_label.value (); }
+ const LoopLabel &get_loop_label () const { return loop_label.value (); }
location_t get_locus () const override final { return locus; }
@@ -3558,6 +3856,18 @@ public:
{
outer_attrs = std::move (new_attrs);
}
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Loop; }
+
+ enum class Kind
+ {
+ Loop,
+ While,
+ WhileLet,
+ For
+ };
+
+ virtual Kind get_loop_kind () const = 0;
};
// 'Loop' expression (i.e. the infinite loop) AST node
@@ -3568,7 +3878,7 @@ public:
// Constructor for LoopExpr
LoopExpr (std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
: BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
std::move (outer_attribs))
@@ -3576,6 +3886,11 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ BaseLoopExpr::Kind get_loop_kind () const override
+ {
+ return BaseLoopExpr::Kind::Loop;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3596,7 +3911,7 @@ public:
// Constructor for while loop with loop label
WhileLoopExpr (std::unique_ptr<Expr> loop_condition,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs
= std::vector<Attribute> ())
: BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
@@ -3634,6 +3949,11 @@ public:
return *condition;
}
+ BaseLoopExpr::Kind get_loop_kind () const override
+ {
+ return BaseLoopExpr::Kind::While;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3657,7 +3977,7 @@ public:
WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
std::unique_ptr<Expr> scrutinee,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs
= std::vector<Attribute> ())
: BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
@@ -3717,6 +4037,11 @@ public:
return match_arm_patterns;
}
+ BaseLoopExpr::Kind get_loop_kind () const override
+ {
+ return BaseLoopExpr::Kind::WhileLet;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3739,7 +4064,7 @@ public:
ForLoopExpr (std::unique_ptr<Pattern> loop_pattern,
std::unique_ptr<Expr> iterator_expr,
std::unique_ptr<BlockExpr> loop_body, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
: BaseLoopExpr (std::move (loop_body), locus, std::move (loop_label),
std::move (outer_attribs)),
@@ -3786,6 +4111,11 @@ public:
return *pattern;
}
+ BaseLoopExpr::Kind get_loop_kind () const override
+ {
+ return BaseLoopExpr::Kind::For;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3909,6 +4239,8 @@ public:
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::If; }
+
protected:
// Base clone function but still concrete as concrete base class
virtual IfExpr *clone_if_expr_impl () const { return new IfExpr (*this); }
@@ -4103,6 +4435,8 @@ public:
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::IfLet; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base (or rather this or any derived object) */
@@ -4298,7 +4632,7 @@ private:
public:
MatchCase (MatchArm arm, std::unique_ptr<Expr> expr)
: arm (std::move (arm)), expr (std::move (expr)),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
MatchCase (const MatchCase &other)
@@ -4432,6 +4766,8 @@ public:
const std::vector<MatchCase> &get_match_cases () const { return match_arms; }
std::vector<MatchCase> &get_match_cases () { return match_arms; }
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Match; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -4511,6 +4847,8 @@ public:
outer_attrs = std::move (new_attrs);
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Await; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -4593,6 +4931,8 @@ public:
outer_attrs = std::move (new_attrs);
}
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::AsyncBlock; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -4603,7 +4943,7 @@ protected:
};
// Inline-assembly specific options
-enum class InlineAsmOptions
+enum class InlineAsmOption
{
PURE = 1 << 0,
NOMEM = 1 << 1,
@@ -4616,12 +4956,6 @@ enum class InlineAsmOptions
MAY_UNWIND = 1 << 8,
};
-struct AnonConst
-{
- NodeId id;
- std::unique_ptr<Expr> value;
-};
-
struct InlineAsmRegOrRegClass
{
enum Type
@@ -4640,13 +4974,39 @@ struct InlineAsmRegOrRegClass
std::string Symbol;
};
+ Type type;
+ struct Reg reg;
+ struct RegClass reg_class;
+
Identifier name;
location_t locus;
};
-struct InlineAsmOperand
+struct LlvmOperand
{
- enum RegisterType
+ std::string constraint;
+ std::unique_ptr<Expr> expr;
+
+ LlvmOperand (std::string constraint, std::unique_ptr<Expr> &&expr)
+ : constraint (constraint), expr (std::move (expr))
+ {}
+
+ LlvmOperand (const LlvmOperand &other)
+ : constraint (other.constraint), expr (other.expr->clone_expr ())
+ {}
+ LlvmOperand &operator= (const LlvmOperand &other)
+ {
+ constraint = other.constraint;
+ expr = other.expr->clone_expr ();
+
+ return *this;
+ }
+};
+
+class InlineAsmOperand
+{
+public:
+ enum class RegisterType
{
In,
Out,
@@ -4654,46 +5014,339 @@ struct InlineAsmOperand
SplitInOut,
Const,
Sym,
+ Label,
+ };
+
+ class Register
+ {
+ public:
+ Register () {}
+ virtual ~Register () = default;
+
+ std::unique_ptr<Register> clone () const
+ {
+ return std::unique_ptr<Register> (clone_impl ());
+ }
+
+ protected:
+ virtual Register *clone_impl () const = 0;
};
- struct In
+ class In : public Register
{
- InlineAsmRegOrRegClass reg;
+ public:
+ tl::optional<InlineAsmRegOrRegClass> reg;
std::unique_ptr<Expr> expr;
+
+ In (tl::optional<struct InlineAsmRegOrRegClass> &reg,
+ std::unique_ptr<Expr> expr)
+ : reg (reg), expr (std::move (expr))
+ {
+ rust_assert (this->expr != nullptr);
+ }
+
+ In (const In &other)
+ {
+ reg = other.reg;
+
+ expr = other.expr->clone_expr ();
+ }
+
+ In operator= (const In &other)
+ {
+ reg = other.reg;
+ expr = other.expr->clone_expr ();
+
+ return *this;
+ }
+
+ private:
+ In *clone_impl () const { return new In (*this); }
};
- struct Out
+ class Out : public Register
{
- InlineAsmRegOrRegClass reg;
+ public:
+ tl::optional<InlineAsmRegOrRegClass> reg;
bool late;
std::unique_ptr<Expr> expr; // can be null
+
+ Out (tl::optional<struct InlineAsmRegOrRegClass> &reg, bool late,
+ std::unique_ptr<Expr> expr)
+ : reg (reg), late (late), expr (std::move (expr))
+ {
+ rust_assert (this->expr != nullptr);
+ }
+
+ Out (const Out &other)
+ {
+ reg = other.reg;
+ late = other.late;
+ expr = other.expr->clone_expr ();
+ }
+
+ Out operator= (const Out &other)
+ {
+ reg = other.reg;
+ late = other.late;
+ expr = other.expr->clone_expr ();
+ return *this;
+ }
+
+ private:
+ Out *clone_impl () const { return new Out (*this); }
};
- struct InOut
+ class InOut : public Register
{
- InlineAsmRegOrRegClass reg;
+ public:
+ tl::optional<InlineAsmRegOrRegClass> reg;
bool late;
std::unique_ptr<Expr> expr; // this can't be null
+
+ InOut (tl::optional<struct InlineAsmRegOrRegClass> &reg, bool late,
+ std::unique_ptr<Expr> expr)
+ : reg (reg), late (late), expr (std::move (expr))
+ {
+ rust_assert (this->expr != nullptr);
+ }
+
+ InOut (const InOut &other)
+ {
+ reg = other.reg;
+ late = other.late;
+ expr = other.expr->clone_expr ();
+ }
+
+ InOut operator= (const InOut &other)
+ {
+ reg = other.reg;
+ late = other.late;
+ expr = other.expr->clone_expr ();
+
+ return *this;
+ }
+
+ private:
+ InOut *clone_impl () const { return new InOut (*this); }
};
- struct SplitInOut
+ class SplitInOut : public Register
{
- InlineAsmRegOrRegClass reg;
+ public:
+ tl::optional<InlineAsmRegOrRegClass> reg;
bool late;
std::unique_ptr<Expr> in_expr;
std::unique_ptr<Expr> out_expr; // could be null
+
+ SplitInOut (tl::optional<struct InlineAsmRegOrRegClass> &reg, bool late,
+ std::unique_ptr<Expr> in_expr, std::unique_ptr<Expr> out_expr)
+ : reg (reg), late (late), in_expr (std::move (in_expr)),
+ out_expr (std::move (out_expr))
+ {
+ rust_assert (this->in_expr != nullptr);
+ rust_assert (this->out_expr != nullptr);
+ }
+
+ SplitInOut (const SplitInOut &other)
+ {
+ reg = other.reg;
+ late = other.late;
+ in_expr = other.in_expr->clone_expr ();
+ out_expr = other.out_expr->clone_expr ();
+ }
+
+ SplitInOut operator= (const SplitInOut &other)
+ {
+ reg = other.reg;
+ late = other.late;
+ in_expr = other.in_expr->clone_expr ();
+ out_expr = other.out_expr->clone_expr ();
+
+ return *this;
+ }
+
+ private:
+ SplitInOut *clone_impl () const { return new SplitInOut (*this); }
};
- struct Const
+ class Const : public Register
{
+ public:
AnonConst anon_const;
+
+ private:
+ Const *clone_impl () const { return new Const (*this); }
+ };
+
+ class Sym : public Register
+ {
+ public:
+ std::unique_ptr<Expr> expr;
+
+ Sym (std::unique_ptr<Expr> expr) : expr (std::move (expr))
+ {
+ rust_assert (this->expr != nullptr);
+ }
+ Sym (const Sym &other)
+ {
+ expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
+ }
+
+ Sym operator= (const Sym &other)
+ {
+ expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
+ return *this;
+ }
+
+ private:
+ Sym *clone_impl () const { return new Sym (*this); }
};
- struct Sym
+ class Label : public Register
{
- std::unique_ptr<Expr> sym;
+ public:
+ std::string label_name;
+ std::unique_ptr<Expr> expr;
+
+ Label (tl::optional<std::string> label_name, std::unique_ptr<Expr> expr)
+ : expr (std::move (expr))
+ {
+ rust_assert (this->expr != nullptr);
+ if (label_name.has_value ())
+ this->label_name = label_name.value ();
+ }
+ Label (const Label &other)
+ {
+ expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
+ }
+
+ Label operator= (const Label &other)
+ {
+ expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
+ return *this;
+ }
+
+ private:
+ Label *clone_impl () const { return new Label (*this); }
};
+
+ InlineAsmOperand (const InlineAsmOperand &other)
+ : register_type (other.register_type), locus (other.locus),
+ reg (other.reg->clone ())
+ {}
+
+ InlineAsmOperand (const In &reg, location_t locus)
+ : register_type (RegisterType::In), locus (locus), reg (new In (reg))
+ {}
+ InlineAsmOperand (const Out &reg, location_t locus)
+ : register_type (RegisterType::Out), locus (locus), reg (new Out (reg))
+ {}
+ InlineAsmOperand (const InOut &reg, location_t locus)
+ : register_type (RegisterType::InOut), locus (locus), reg (new InOut (reg))
+ {}
+ InlineAsmOperand (const SplitInOut &reg, location_t locus)
+ : register_type (RegisterType::SplitInOut), locus (locus),
+ reg (new SplitInOut (reg))
+ {}
+ InlineAsmOperand (const Const &reg, location_t locus)
+ : register_type (RegisterType::Const), locus (locus), reg (new Const (reg))
+ {}
+ InlineAsmOperand (const Sym &reg, location_t locus)
+ : register_type (RegisterType::Sym), locus (locus), reg (new Sym (reg))
+ {}
+ InlineAsmOperand (const Label &reg, location_t locus)
+ : register_type (RegisterType::Label), locus (locus), reg (new Label (reg))
+ {}
+
+ location_t get_locus () const { return locus; }
+ RegisterType get_register_type () const { return register_type; }
+
+ // Potentially fail immediately if you don't use get_register_type() to
+ // inspect the RegisterType first before calling the following functions Check
+ // first
+ In &get_in ()
+ {
+ rust_assert (register_type == RegisterType::In);
+ return static_cast<In &> (*reg);
+ }
+ const In &get_in () const
+ {
+ rust_assert (register_type == RegisterType::In);
+ return static_cast<const In &> (*reg);
+ }
+
+ Out &get_out ()
+ {
+ rust_assert (register_type == RegisterType::Out);
+ return static_cast<Out &> (*reg);
+ }
+ const Out &get_out () const
+ {
+ rust_assert (register_type == RegisterType::Out);
+ return static_cast<const Out &> (*reg);
+ }
+
+ InOut &get_in_out ()
+ {
+ rust_assert (register_type == RegisterType::InOut);
+ return static_cast<InOut &> (*reg);
+ }
+ const InOut &get_in_out () const
+ {
+ rust_assert (register_type == RegisterType::InOut);
+ return static_cast<const InOut &> (*reg);
+ }
+
+ SplitInOut &get_split_in_out ()
+ {
+ rust_assert (register_type == RegisterType::SplitInOut);
+ return static_cast<SplitInOut &> (*reg);
+ }
+ const SplitInOut &get_split_in_out () const
+ {
+ rust_assert (register_type == RegisterType::SplitInOut);
+ return static_cast<const SplitInOut &> (*reg);
+ }
+
+ Const &get_const ()
+ {
+ rust_assert (register_type == RegisterType::Const);
+ return static_cast<Const &> (*reg);
+ }
+ const Const &get_const () const
+ {
+ rust_assert (register_type == RegisterType::Const);
+ return static_cast<Const &> (*reg);
+ }
+
+ Sym &get_sym ()
+ {
+ rust_assert (register_type == RegisterType::Sym);
+ return static_cast<Sym &> (*reg);
+ }
+ const Sym &get_sym () const
+ {
+ rust_assert (register_type == RegisterType::Sym);
+ return static_cast<const Sym &> (*reg);
+ }
+
+ Label &get_label ()
+ {
+ rust_assert (register_type == RegisterType::Label);
+ return static_cast<Label &> (*reg);
+ }
+ const Label &get_label () const
+ {
+ rust_assert (register_type == RegisterType::Label);
+ return static_cast<const Label &> (*reg);
+ }
+
+private:
+ RegisterType register_type;
+
location_t locus;
+ std::unique_ptr<Register> reg;
};
struct InlineAsmPlaceHolder
@@ -4706,11 +5359,8 @@ struct InlineAsmPlaceHolder
struct InlineAsmTemplatePiece
{
bool is_placeholder;
- union
- {
- std::string string;
- InlineAsmPlaceHolder placeholder;
- };
+ std::string string;
+ InlineAsmPlaceHolder placeholder;
};
struct TupleClobber
@@ -4723,21 +5373,192 @@ struct TupleClobber
struct TupleTemplateStr
{
// as gccrs still doesn't contain a symbol class I have put them as strings
- std::string symbol;
- std::string optional_symbol;
location_t loc;
+ std::string symbol;
+
+ location_t get_locus () { return loc; }
+ TupleTemplateStr (location_t loc, const std::string &symbol)
+ : loc (loc), symbol (symbol)
+ {}
};
// 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
+ // to override, very hacky.
+ std::vector<Attribute> outer_attrs;
+
+public:
+ // https://github.com/rust-lang/rust/blob/55cac26a9ef17da1c9c77c0816e88e178b7cc5dd/compiler/rustc_builtin_macros/src/asm.rs#L56C1-L64C7
+ // let mut args = AsmArgs {
+ // templates: vec![first_template],
+ // operands: vec![],
+ // named_args: Default::default(),
+ // reg_args: Default::default(),
+ // clobber_abis: Vec::new(),
+ // options: ast::InlineAsmOptions::empty(),
+ // options_spans: vec![],
+ // };
std::vector<InlineAsmTemplatePiece> template_;
std::vector<TupleTemplateStr> template_strs;
std::vector<InlineAsmOperand> operands;
- TupleClobber clobber_abi;
- InlineAsmOptions options;
+ std::map<std::string, int> named_args;
+ std::set<int> reg_args;
+ std::vector<TupleClobber> clobber_abi;
+ std::set<InlineAsm::Option> options;
+
std::vector<location_t> line_spans;
+
+ bool is_global_asm;
+
+ InlineAsm (location_t locus, bool is_global_asm)
+ : locus (locus), is_global_asm (is_global_asm)
+ {}
+
+ void accept_vis (ASTVisitor &vis) override;
+ std::string as_string () const override { return "InlineAsm AST Node"; }
+
+ location_t get_locus () const override { return locus; }
+
+ void mark_for_strip () override {}
+
+ bool is_marked_for_strip () const override { return false; }
+
+ std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
+
+ void set_outer_attrs (std::vector<Attribute> v) override { outer_attrs = v; }
+
+ std::vector<InlineAsmTemplatePiece> get_template_ () { return template_; }
+
+ std::vector<TupleTemplateStr> get_template_strs () { return template_strs; }
+
+ std::vector<InlineAsmOperand> get_operands () { return operands; }
+
+ std::vector<TupleClobber> get_clobber_abi () { return clobber_abi; }
+
+ std::set<InlineAsm::Option> get_options () { return options; }
+
+ InlineAsm *clone_expr_without_block_impl () const override
+ {
+ return new InlineAsm (*this);
+ }
+
+ 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
+{
+ // llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
+ // Asm, Outputs, Inputs, Clobbers, Options,
+
+public:
+ enum class Dialect
+ {
+ Att,
+ Intel,
+ };
+
+private:
+ location_t locus;
+ std::vector<Attribute> outer_attrs;
+ std::vector<LlvmOperand> inputs;
+ std::vector<LlvmOperand> outputs;
+ std::vector<TupleTemplateStr> templates;
+ std::vector<TupleClobber> clobbers;
+ bool volatility;
+ bool align_stack;
+ Dialect dialect;
+
+public:
+ LlvmInlineAsm (location_t locus) : locus (locus) {}
+
+ Dialect get_dialect () { return dialect; }
+
+ location_t get_locus () const override { return locus; }
+
+ void mark_for_strip () override {}
+
+ bool is_marked_for_strip () const override { return false; }
+
+ std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ std::string as_string () const override { return "InlineAsm AST Node"; }
+
+ void set_outer_attrs (std::vector<Attribute> v) override { outer_attrs = v; }
+
+ LlvmInlineAsm *clone_expr_without_block_impl () const override
+ {
+ return new LlvmInlineAsm (*this);
+ }
+
+ std::vector<TupleTemplateStr> &get_templates () { return templates; }
+
+ Expr::Kind get_expr_kind () const override
+ {
+ return Expr::Kind::LlvmInlineAsm;
+ }
+
+ void set_align_stack (bool align_stack) { this->align_stack = align_stack; }
+ bool is_stack_aligned () { return align_stack; }
+
+ void set_volatile (bool volatility) { this->volatility = volatility; }
+ bool is_volatile () { return volatility; }
+
+ void set_dialect (Dialect dialect) { this->dialect = dialect; }
+
+ void set_inputs (std::vector<LlvmOperand> operands) { inputs = operands; }
+ void set_outputs (std::vector<LlvmOperand> operands) { outputs = operands; }
+
+ std::vector<LlvmOperand> &get_inputs () { return inputs; }
+ std::vector<LlvmOperand> &get_outputs () { return outputs; }
+
+ std::vector<TupleClobber> &get_clobbers () { return clobbers; }
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-fmt.cc b/gcc/rust/ast/rust-fmt.cc
index a48e8f5..c739943 100644
--- a/gcc/rust/ast/rust-fmt.cc
+++ b/gcc/rust/ast/rust-fmt.cc
@@ -29,9 +29,11 @@ ffi::RustHamster::to_string () const
}
Pieces
-Pieces::collect (const std::string &to_parse, bool append_newline)
+Pieces::collect (const std::string &to_parse, bool append_newline,
+ ffi::ParseMode parse_mode)
{
- auto handle = ffi::collect_pieces (to_parse.c_str (), append_newline);
+ auto handle
+ = ffi::collect_pieces (to_parse.c_str (), append_newline, parse_mode);
// this performs multiple copies, can we avoid them maybe?
// TODO: Instead of just creating a vec of, basically, `ffi::Piece`s, we
diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h
index 6a0c116..fa0f5ec 100644
--- a/gcc/rust/ast/rust-fmt.h
+++ b/gcc/rust/ast/rust-fmt.h
@@ -20,7 +20,6 @@
#define RUST_FMT_H
#include "rust-system.h"
-#include <cstddef>
// FIXME: How to encode Option?
@@ -259,10 +258,16 @@ struct FormatArgsHandle
RustString rust_string;
};
+enum ParseMode
+{
+ Format = 0,
+ InlineAsm,
+};
+
extern "C" {
FormatArgsHandle
-collect_pieces (const char *input, bool append_newline);
+collect_pieces (const char *input, bool append_newline, ParseMode parse_mode);
FormatArgsHandle
clone_pieces (const FormatArgsHandle &);
@@ -275,7 +280,8 @@ void destroy_pieces (FormatArgsHandle);
struct Pieces
{
- static Pieces collect (const std::string &to_parse, bool append_newline);
+ static Pieces collect (const std::string &to_parse, bool append_newline,
+ ffi::ParseMode parse_mode);
~Pieces ();
Pieces (const Pieces &other);
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index c03de9b..2f53f8d 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;
- 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; }
@@ -77,26 +68,27 @@ public:
bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
// Returns whether the type param has an outer attribute.
- bool has_outer_attribute () const { return !outer_attr.is_empty (); }
+ bool has_outer_attribute () const { return !outer_attrs.empty (); }
- Attribute &get_outer_attribute () { return outer_attr; }
+ AST::AttrVec &get_outer_attrs () { return outer_attrs; }
TypeParam (Identifier type_representation, location_t locus = UNDEF_LOCATION,
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds
= std::vector<std::unique_ptr<TypeParamBound>> (),
std::unique_ptr<Type> type = nullptr,
- Attribute outer_attr = Attribute::create_empty ())
- : GenericParam (Analysis::Mappings::get ()->get_next_node_id ()),
- outer_attr (std::move (outer_attr)),
+ 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_attr (other.outer_attr),
- type_representation (other.type_representation), locus (other.locus)
+ : GenericParam (other.node_id), outer_attrs (other.outer_attrs),
+ 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)
@@ -111,9 +103,10 @@ public:
TypeParam &operator= (TypeParam const &other)
{
type_representation = other.type_representation;
- outer_attr = other.outer_attr;
+ 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
@@ -210,7 +205,7 @@ public:
location_t locus)
: lifetime (std::move (lifetime)),
lifetime_bounds (std::move (lifetime_bounds)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
std::string as_string () const override;
@@ -258,7 +253,7 @@ public:
: for_lifetimes (std::move (for_lifetimes)),
bound_type (std::move (bound_type)),
type_param_bounds (std::move (type_param_bounds)),
- node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
+ node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
{}
// Copy constructor requires clone
@@ -339,7 +334,7 @@ class WhereClause
public:
WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items)
: where_clause_items (std::move (where_clause_items)),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
// copy constructor with vector clone
@@ -396,7 +391,7 @@ class Param : public Visitable
public:
Param (std::vector<Attribute> outer_attrs, location_t locus)
: outer_attrs (std::move (outer_attrs)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
virtual ~Param () = default;
@@ -434,13 +429,14 @@ class SelfParam : public Param
bool has_ref;
bool is_mut;
// bool has_lifetime; // only possible if also ref
- Lifetime lifetime;
+ tl::optional<Lifetime> lifetime;
// bool has_type; // only possible if not ref
std::unique_ptr<Type> type;
// Unrestricted constructor used for error state
- SelfParam (Lifetime lifetime, bool has_ref, bool is_mut, Type *type)
+ SelfParam (tl::optional<Lifetime> lifetime, bool has_ref, bool is_mut,
+ Type *type)
: Param ({}, UNDEF_LOCATION), has_ref (has_ref), is_mut (is_mut),
lifetime (std::move (lifetime)), type (type)
{}
@@ -453,7 +449,7 @@ public:
bool has_type () const { return type != nullptr; }
// Returns whether the self-param has a valid lifetime.
- bool has_lifetime () const { return !lifetime.is_error (); }
+ bool has_lifetime () const { return lifetime.has_value (); }
// Returns whether the self-param is in an error state.
bool is_error () const
@@ -472,11 +468,11 @@ public:
// Type-based self parameter (not ref, no lifetime)
SelfParam (std::unique_ptr<Type> type, bool is_mut, location_t locus)
: Param ({}, locus), has_ref (false), is_mut (is_mut),
- lifetime (Lifetime::error ()), type (std::move (type))
+ lifetime (tl::nullopt), type (std::move (type))
{}
// Lifetime-based self parameter (is ref, no type)
- SelfParam (Lifetime lifetime, bool is_mut, location_t locus)
+ SelfParam (tl::optional<Lifetime> lifetime, bool is_mut, location_t locus)
: Param ({}, locus), has_ref (true), is_mut (is_mut),
lifetime (std::move (lifetime))
{}
@@ -522,8 +518,8 @@ public:
bool get_has_ref () const { return has_ref; };
bool get_is_mut () const { return is_mut; }
- Lifetime get_lifetime () const { return lifetime; }
- Lifetime &get_lifetime () { return lifetime; }
+ Lifetime get_lifetime () const { return lifetime.value (); }
+ Lifetime &get_lifetime () { return lifetime.value (); }
NodeId get_node_id () const { return node_id; }
@@ -758,8 +754,6 @@ public:
Identifier get_name () const { return module_name; }
- AST::Kind get_ast_kind () const override { return AST::Kind::MODULE; }
-
private:
Identifier module_name;
location_t locus;
@@ -899,6 +893,8 @@ public:
void mark_for_strip () override { module_name = {""}; }
bool is_marked_for_strip () const override { return module_name.empty (); }
+ Item::Kind get_item_kind () const override { return Item::Kind::Module; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -960,6 +956,8 @@ public:
return referenced_crate.empty ();
}
+ Item::Kind get_item_kind () const override { return Item::Kind::ExternCrate; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1018,7 +1016,7 @@ protected:
virtual UseTree *clone_use_tree_impl () const = 0;
UseTree (location_t locus)
- : locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
};
@@ -1213,7 +1211,7 @@ public:
std::string as_string () const override;
- NewBindType get_new_bind_type () { return bind_type; }
+ NewBindType get_new_bind_type () const { return bind_type; }
void accept_vis (ASTVisitor &vis) override;
@@ -1301,6 +1299,11 @@ public:
void mark_for_strip () override { use_tree = nullptr; }
bool is_marked_for_strip () const override { return use_tree == nullptr; }
+ Item::Kind get_item_kind () const override
+ {
+ return Item::Kind::UseDeclaration;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1323,7 +1326,7 @@ class Function : public VisItem, public AssociatedItem, public ExternalItem
WhereClause where_clause;
tl::optional<std::unique_ptr<BlockExpr>> function_body;
location_t locus;
- bool is_default;
+ bool has_default;
bool is_external_function;
public:
@@ -1348,6 +1351,8 @@ public:
bool has_body () const { return function_body.has_value (); }
+ bool is_default () const { return has_default; }
+
// Mega-constructor with all possible fields
Function (Identifier function_name, FunctionQualifiers qualifiers,
std::vector<std::unique_ptr<GenericParam>> generic_params,
@@ -1355,7 +1360,7 @@ public:
std::unique_ptr<Type> return_type, WhereClause where_clause,
tl::optional<std::unique_ptr<BlockExpr>> function_body,
Visibility vis, std::vector<Attribute> outer_attrs,
- location_t locus, bool is_default = false,
+ location_t locus, bool has_default = false,
bool is_external_function = false)
: VisItem (std::move (vis), std::move (outer_attrs)),
ExternalItem (Stmt::node_id), qualifiers (std::move (qualifiers)),
@@ -1365,7 +1370,7 @@ public:
return_type (std::move (return_type)),
where_clause (std::move (where_clause)),
function_body (std::move (function_body)), locus (locus),
- is_default (is_default), is_external_function (is_external_function)
+ has_default (has_default), is_external_function (is_external_function)
{}
// TODO: add constructor with less fields
@@ -1459,6 +1464,8 @@ public:
// ExternalItem::node_id is same as Stmt::node_id
NodeId get_node_id () const override { return Stmt::node_id; }
+ Item::Kind get_item_kind () const override { return Item::Kind::Function; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1590,6 +1597,8 @@ public:
Identifier get_new_type_name () const { return new_type_name; }
+ Item::Kind get_item_kind () const override { return Item::Kind::TypeAlias; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1649,6 +1658,8 @@ public:
Identifier get_identifier () const { return struct_name; }
+ Item::Kind get_item_kind () const override { return Item::Kind::Struct; }
+
protected:
Struct (Identifier struct_name,
std::vector<std::unique_ptr<GenericParam>> generic_params,
@@ -1718,7 +1729,7 @@ public:
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
: outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
field_name (std::move (field_name)), field_type (std::move (field_type)),
- node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
+ node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
{}
// Copy constructor
@@ -1878,7 +1889,7 @@ public:
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
: outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
field_type (std::move (field_type)),
- node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
+ node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
{}
// Copy constructor with clone
@@ -1994,6 +2005,41 @@ class EnumItem : public VisItem
location_t locus;
public:
+ enum class Kind
+ {
+ Identifier,
+ Tuple,
+ Struct,
+
+ // FIXME: In the future, we'll need to remove this possibility as well as
+ // remove the EnumItemDiscriminant class. The feature for arbitrary
+ // discriminants on all kinds of variants has been stabilized, and a
+ // "discriminant" is no longer an enum item variant - it's simply an
+ // optional part of all variants.
+ //
+ // Per the reference:
+ //
+ // EnumItem :
+ // OuterAttribute* Visibility?
+ // IDENTIFIER ( EnumItemTuple | EnumItemStruct )? EnumItemDiscriminant?
+ //
+ // EnumItemTuple :
+ // ( TupleFields? )
+ //
+ // EnumItemStruct :
+ // { StructFields? }
+ //
+ // EnumItemDiscriminant :
+ // = Expression
+ //
+ // So we instead need to remove the class, and add an optional expression to
+ // the base EnumItem class
+ //
+ // gccrs#3340
+
+ Discriminant,
+ };
+
virtual ~EnumItem () {}
EnumItem (Identifier variant_name, Visibility vis,
@@ -2002,6 +2048,8 @@ public:
variant_name (std::move (variant_name)), locus (locus)
{}
+ virtual Kind get_enum_item_kind () const { return Kind::Identifier; }
+
// Unique pointer custom clone function
std::unique_ptr<EnumItem> clone_enum_item () const
{
@@ -2021,6 +2069,8 @@ public:
void mark_for_strip () override { variant_name = {""}; }
bool is_marked_for_strip () const override { return variant_name.empty (); }
+ Item::Kind get_item_kind () const override { return Item::Kind::EnumItem; }
+
protected:
EnumItem *clone_item_impl () const override { return new EnumItem (*this); }
};
@@ -2043,6 +2093,11 @@ public:
tuple_fields (std::move (tuple_fields))
{}
+ EnumItem::Kind get_enum_item_kind () const override
+ {
+ return EnumItem::Kind::Tuple;
+ }
+
std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
@@ -2080,6 +2135,11 @@ public:
struct_fields (std::move (struct_fields))
{}
+ EnumItem::Kind get_enum_item_kind () const override
+ {
+ return EnumItem::Kind::Struct;
+ }
+
std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
@@ -2133,6 +2193,11 @@ public:
EnumItemDiscriminant (EnumItemDiscriminant &&other) = default;
EnumItemDiscriminant &operator= (EnumItemDiscriminant &&other) = default;
+ EnumItem::Kind get_enum_item_kind () const override
+ {
+ return EnumItem::Kind::Discriminant;
+ }
+
std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
@@ -2269,6 +2334,8 @@ public:
// TODO: is this better? Or is a "vis_block" better?
WhereClause &get_where_clause () { return where_clause; }
+ Item::Kind get_item_kind () const override { return Item::Kind::Enum; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2368,6 +2435,8 @@ public:
Identifier get_identifier () const { return union_name; }
+ Item::Kind get_item_kind () const override { return Item::Kind::Union; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2489,6 +2558,11 @@ public:
std::string get_identifier () const { return identifier; }
+ Item::Kind get_item_kind () const override
+ {
+ return Item::Kind::ConstantItem;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2610,6 +2684,8 @@ public:
Identifier get_identifier () const { return name; }
+ Item::Kind get_item_kind () const override { return Item::Kind::StaticItem; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2831,6 +2907,7 @@ class Trait : public VisItem
bool has_auto;
Identifier name;
std::vector<std::unique_ptr<GenericParam>> generic_params;
+ TypeParam self_param;
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
WhereClause where_clause;
std::vector<Attribute> inner_attrs;
@@ -2870,7 +2947,7 @@ public:
std::vector<Attribute> inner_attrs, location_t locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
has_unsafe (is_unsafe), has_auto (is_auto), name (std::move (name)),
- generic_params (std::move (generic_params)),
+ generic_params (std::move (generic_params)), self_param ({"Self"}, locus),
type_param_bounds (std::move (type_param_bounds)),
where_clause (std::move (where_clause)),
inner_attrs (std::move (inner_attrs)),
@@ -2880,8 +2957,9 @@ public:
// Copy constructor with vector clone
Trait (Trait const &other)
: VisItem (other), has_unsafe (other.has_unsafe), has_auto (other.has_auto),
- name (other.name), where_clause (other.where_clause),
- inner_attrs (other.inner_attrs), locus (other.locus)
+ name (other.name), self_param (other.self_param),
+ where_clause (other.where_clause), inner_attrs (other.inner_attrs),
+ locus (other.locus)
{
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
@@ -2901,6 +2979,7 @@ public:
{
VisItem::operator= (other);
name = other.name;
+ self_param = other.self_param;
has_unsafe = other.has_unsafe;
has_auto = other.has_auto;
where_clause = other.where_clause;
@@ -2968,19 +3047,9 @@ public:
WhereClause &get_where_clause () { return where_clause; }
- void insert_implict_self (std::unique_ptr<AST::GenericParam> &&param)
- {
- std::vector<std::unique_ptr<GenericParam>> new_list;
- new_list.reserve (generic_params.size () + 1);
-
- new_list.push_back (std::move (param));
- for (auto &p : generic_params)
- {
- new_list.push_back (std::move (p));
- }
+ AST::TypeParam &get_implicit_self () { return self_param; }
- generic_params = std::move (new_list);
- }
+ Item::Kind get_item_kind () const override { return Item::Kind::Trait; }
protected:
/* Use covariance to implement clone function as returning this object
@@ -3054,6 +3123,8 @@ public:
return trait_type;
}
+ Item::Kind get_item_kind () const override { return Item::Kind::Impl; }
+
protected:
// Mega-constructor
Impl (std::vector<std::unique_ptr<GenericParam>> generic_params,
@@ -3202,8 +3273,8 @@ public:
: Impl (std::move (generic_params), std::move (trait_type),
std::move (where_clause), std::move (vis), std::move (inner_attrs),
std::move (outer_attrs), locus),
- has_unsafe (is_unsafe), has_exclam (has_exclam),
- trait_path (std::move (trait_path)), impl_items (std::move (impl_items))
+ has_unsafe (is_unsafe), has_exclam (has_exclam), trait_path (trait_path),
+ impl_items (std::move (impl_items))
{}
// Copy constructor with vector clone
@@ -3251,11 +3322,7 @@ public:
}
// TODO: is this better? Or is a "vis_block" better?
- TypePath &get_trait_path ()
- {
- // TODO: assert that trait path is not empty?
- return trait_path;
- }
+ TypePath &get_trait_path () { return trait_path; }
protected:
/* Use covariance to implement clone function as returning this object
@@ -3528,303 +3595,6 @@ protected:
}
};
-// A named function parameter used in external functions
-class NamedFunctionParam
-{
- // bool has_name; // otherwise is _
- std::string name;
-
- std::unique_ptr<Type> param_type;
-
- // seemingly new since writing this node
- std::vector<Attribute> outer_attrs;
-
- NodeId node_id;
- location_t locus;
- bool variadic;
-
-public:
- /* Returns whether the named function parameter has a name (i.e. name is not
- * '_'). */
- bool has_name () const { return name != "_" && name != ""; }
-
- bool has_outer_attrs () const { return !outer_attrs.empty (); }
-
- // Returns whether the named function parameter is in an error state.
- bool is_error () const
- {
- // also if identifier is "" but that is probably more costly to compute
- return param_type == nullptr && !variadic;
- }
-
- bool is_variadic () const { return variadic; }
-
- std::string get_name () const { return name; }
-
- location_t get_locus () { return locus; }
-
- // Creates an error state named function parameter.
- static NamedFunctionParam create_error ()
- {
- return NamedFunctionParam ("", nullptr, {}, UNDEF_LOCATION);
- }
-
- NamedFunctionParam (std::string name, std::unique_ptr<Type> param_type,
- std::vector<Attribute> outer_attrs, location_t locus)
- : name (std::move (name)), param_type (std::move (param_type)),
- outer_attrs (std::move (outer_attrs)),
- node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus),
- variadic (false)
- {}
-
- NamedFunctionParam (std::string name, std::vector<Attribute> outer_attrs,
- location_t locus)
- : name (std::move (name)), param_type (nullptr),
- outer_attrs (std::move (outer_attrs)),
- node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus),
- variadic (true)
- {}
-
- NamedFunctionParam (std::vector<Attribute> outer_attrs, location_t locus)
- : name (""), param_type (nullptr), outer_attrs (std::move (outer_attrs)),
- node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus),
- variadic (true)
- {}
-
- // Copy constructor
- NamedFunctionParam (NamedFunctionParam const &other)
- : name (other.name), outer_attrs (other.outer_attrs),
- variadic (other.variadic)
- {
- node_id = other.node_id;
- // guard to prevent null dereference (only required if error state)
- if (other.param_type != nullptr)
- param_type = other.param_type->clone_type ();
- else
- param_type = nullptr;
- }
-
- ~NamedFunctionParam () = default;
-
- // Overloaded assignment operator to clone
- NamedFunctionParam &operator= (NamedFunctionParam const &other)
- {
- node_id = other.node_id;
- name = other.name;
- // has_name = other.has_name;
- outer_attrs = other.outer_attrs;
-
- // guard to prevent null dereference (only required if error state)
- if (other.param_type != nullptr)
- param_type = other.param_type->clone_type ();
- else
- param_type = nullptr;
-
- return *this;
- }
-
- // move constructors
- NamedFunctionParam (NamedFunctionParam &&other) = default;
- NamedFunctionParam &operator= (NamedFunctionParam &&other) = default;
-
- std::string as_string () const;
-
- // Based on idea that nane should never be empty.
- void mark_for_strip () { param_type = nullptr; };
- bool is_marked_for_strip () const { return is_error (); };
-
- // TODO: this mutable getter seems really dodgy. Think up better way.
- std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
- const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
-
- // TODO: is this better? Or is a "vis_block" better?
- Type &get_type ()
- {
- rust_assert (param_type != nullptr);
- return *param_type;
- }
-
- std::unique_ptr<Type> &get_type_ptr ()
- {
- rust_assert (param_type != nullptr);
- return param_type;
- }
-
- NodeId get_node_id () const { return node_id; }
-};
-
-// A function item used in an extern block
-class ExternalFunctionItem : public ExternalItem
-{
- // bool has_outer_attrs;
- std::vector<Attribute> outer_attrs;
-
- // bool has_visibility;
- Visibility visibility;
-
- Identifier item_name;
- location_t locus;
-
- // bool has_generics;
- // Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
-
- // bool has_return_type;
- // FunctionReturnType return_type;
- std::unique_ptr<Type> return_type; // inlined
-
- // bool has_where_clause;
- WhereClause where_clause;
-
- std::vector<NamedFunctionParam> function_params;
-
-public:
- // Returns whether item has generic parameters.
- bool has_generics () const { return !generic_params.empty (); }
-
- // Returns whether item has a return type (otherwise void).
- bool has_return_type () const { return return_type != nullptr; }
-
- // Returns whether item has a where clause.
- bool has_where_clause () const { return !where_clause.is_empty (); }
-
- // Returns whether item has outer attributes.
- bool has_outer_attrs () const { return !outer_attrs.empty (); }
-
- // Returns whether item has non-default visibility.
- bool has_visibility () const { return !visibility.is_error (); }
-
- // Returns whether item has variadic parameters.
- bool is_variadic () const
- {
- return function_params.size () != 0
- && function_params.back ().is_variadic ();
- }
-
- location_t get_locus () const { return locus; }
-
- Visibility &get_visibility () { return visibility; }
- const Visibility &get_visibility () const { return visibility; }
-
- ExternalFunctionItem (
- Identifier item_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
- std::unique_ptr<Type> return_type, WhereClause where_clause,
- std::vector<NamedFunctionParam> function_params, Visibility vis,
- std::vector<Attribute> outer_attrs, location_t locus)
- : ExternalItem (), outer_attrs (std::move (outer_attrs)),
- visibility (std::move (vis)), item_name (std::move (item_name)),
- locus (locus), generic_params (std::move (generic_params)),
- return_type (std::move (return_type)),
- where_clause (std::move (where_clause)),
- function_params (std::move (function_params))
- {
- // TODO: assert that if has variadic outer attrs, then has_variadics is
- // true?
- }
-
- // Copy constructor with clone
- ExternalFunctionItem (ExternalFunctionItem const &other)
- : ExternalItem (other.get_node_id ()), outer_attrs (other.outer_attrs),
- visibility (other.visibility), item_name (other.item_name),
- locus (other.locus), where_clause (other.where_clause),
- function_params (other.function_params)
- {
- node_id = other.node_id;
- // guard to prevent null pointer dereference
- if (other.return_type != nullptr)
- return_type = other.return_type->clone_type ();
-
- generic_params.reserve (other.generic_params.size ());
- for (const auto &e : other.generic_params)
- generic_params.push_back (e->clone_generic_param ());
- }
-
- // Overloaded assignment operator with clone
- ExternalFunctionItem &operator= (ExternalFunctionItem const &other)
- {
- outer_attrs = other.outer_attrs;
- visibility = other.visibility;
- item_name = other.item_name;
- locus = other.locus;
- where_clause = other.where_clause;
- function_params = other.function_params;
- node_id = other.node_id;
-
- // guard to prevent null pointer dereference
- if (other.return_type != nullptr)
- return_type = other.return_type->clone_type ();
- else
- return_type = nullptr;
-
- generic_params.reserve (other.generic_params.size ());
- for (const auto &e : other.generic_params)
- generic_params.push_back (e->clone_generic_param ());
-
- return *this;
- }
-
- // move constructors
- ExternalFunctionItem (ExternalFunctionItem &&other) = default;
- ExternalFunctionItem &operator= (ExternalFunctionItem &&other) = default;
-
- std::string as_string () const override;
-
- void accept_vis (ASTVisitor &vis) override;
-
- // Based on idea that nane should never be empty.
- void mark_for_strip () override { item_name = {""}; };
- bool is_marked_for_strip () const override { return item_name.empty (); };
-
- // TODO: this mutable getter seems really dodgy. Think up better way.
- std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
- const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
-
- std::vector<NamedFunctionParam> &get_function_params ()
- {
- return function_params;
- }
- const std::vector<NamedFunctionParam> &get_function_params () const
- {
- return function_params;
- }
-
- std::vector<std::unique_ptr<GenericParam>> &get_generic_params ()
- {
- return generic_params;
- }
- const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const
- {
- return generic_params;
- }
-
- // TODO: is this better? Or is a "vis_block" better?
- WhereClause &get_where_clause () { return where_clause; }
-
- // TODO: is this better? Or is a "vis_block" better?
- Type &get_return_type ()
- {
- rust_assert (has_return_type ());
- return *return_type;
- }
-
- std::unique_ptr<Type> &get_return_type_ptr ()
- {
- rust_assert (has_return_type ());
- return return_type;
- }
-
- Identifier get_identifier () const { return item_name; };
-
-protected:
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- ExternalFunctionItem *clone_external_item_impl () const override
- {
- return new ExternalFunctionItem (*this);
- }
-};
-
// An extern block AST node
class ExternBlock : public VisItem
{
@@ -3917,6 +3687,8 @@ public:
const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
+ Item::Kind get_item_kind () const override { return Item::Kind::ExternBlock; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 507e595..575cd23 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -24,11 +24,11 @@
#include "rust-ast-fragment.h"
#include "rust-location.h"
#include "rust-item.h"
-#include "rust-make-unique.h"
#include "rust-macro-builtins.h"
namespace Rust {
namespace AST {
+
class MacroFragSpec
{
public:
@@ -482,7 +482,7 @@ private:
* should make use of the actual rules. If the macro is builtin, then another
* associated transcriber should be used
*/
- static Fragment dummy_builtin (location_t, MacroInvocData &)
+ static Fragment dummy_builtin (location_t, MacroInvocData &, AST::InvocKind)
{
rust_unreachable ();
return Fragment::create_error ();
@@ -521,7 +521,7 @@ public:
mbe (Identifier rule_name, DelimType delim_type, std::vector<MacroRule> rules,
std::vector<Attribute> outer_attrs, location_t locus)
{
- return Rust::make_unique<MacroRulesDefinition> (
+ return std::make_unique<MacroRulesDefinition> (
MacroRulesDefinition (rule_name, delim_type, rules, outer_attrs, locus,
AST::MacroRulesDefinition::MacroKind::MBE,
AST::Visibility::create_error ()));
@@ -532,7 +532,7 @@ public:
std::vector<Attribute> outer_attrs, location_t locus,
Visibility vis)
{
- return Rust::make_unique<MacroRulesDefinition> (MacroRulesDefinition (
+ return std::make_unique<MacroRulesDefinition> (MacroRulesDefinition (
rule_name, AST::DelimType::CURLY, rules, outer_attrs, locus,
AST::MacroRulesDefinition::MacroKind::DeclMacro, vis));
}
@@ -572,13 +572,13 @@ public:
is_builtin_rule = true;
}
- AST::Kind get_ast_kind () const override
+ MacroKind get_kind () const { return kind; }
+
+ Item::Kind get_item_kind () const override
{
- return AST::Kind::MACRO_RULES_DEFINITION;
+ return Item::Kind::MacroRulesDefinition;
}
- MacroKind get_kind () const { return kind; }
-
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -610,11 +610,6 @@ public:
std::string as_string () const override;
- Pattern::Kind get_pattern_kind () override
- {
- return Pattern::Kind::MacroInvocation;
- }
-
/**
* The default constructor you should use. Whenever we parse a macro call, we
* cannot possibly know whether or not this call refers to a builtin macro or
@@ -677,11 +672,6 @@ public:
return ExprWithoutBlock::get_node_id ();
}
- AST::Kind get_ast_kind () const override
- {
- return AST::Kind::MACRO_INVOCATION;
- }
-
NodeId get_macro_node_id () const { return node_id; }
MacroInvocData &get_invoc_data () { return invoc_data; }
@@ -720,7 +710,7 @@ private:
location_t locus, bool is_semi_coloned,
std::vector<std::unique_ptr<MacroInvocation>> &&pending_eager_invocs)
: TraitItem (locus), outer_attrs (std::move (outer_attrs)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ()),
+ node_id (Analysis::Mappings::get ().get_next_node_id ()),
invoc_data (std::move (invoc_data)), is_semi_coloned (is_semi_coloned),
kind (kind), builtin_kind (builtin_kind),
pending_eager_invocs (std::move (pending_eager_invocs))
@@ -800,6 +790,21 @@ public:
void add_semicolon () override { is_semi_coloned = true; }
+ Pattern::Kind get_pattern_kind () override
+ {
+ return Pattern::Kind::MacroInvocation;
+ }
+
+ Expr::Kind get_expr_kind () const override
+ {
+ return Expr::Kind::MacroInvocation;
+ }
+
+ Item::Kind get_item_kind () const override
+ {
+ return Item::Kind::MacroInvocation;
+ }
+
protected:
Item *clone_item_impl () const override
{
diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc
index 9131962..ef61d57 100644
--- a/gcc/rust/ast/rust-path.cc
+++ b/gcc/rust/ast/rust-path.cc
@@ -17,6 +17,7 @@ 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-path.h"
#include "rust-system.h"
#include "rust-ast-full.h"
#include "rust-diagnostics.h"
@@ -118,7 +119,7 @@ ConstGenericParam::as_string () const
str += "const " + name.as_string () + ": " + type->as_string ();
if (has_default_value ())
- str += " = " + get_default_value ().as_string ();
+ str += " = " + get_default_value_unchecked ().as_string ();
return str;
}
@@ -135,8 +136,11 @@ PathExprSegment::as_string () const
}
std::string
-PathPattern::as_string () const
+Path::as_string () const
{
+ // FIXME: Impl for lang items
+ rust_assert (kind == Kind::Regular);
+
std::string str;
for (const auto &segment : segments)
@@ -149,8 +153,10 @@ PathPattern::as_string () const
}
SimplePath
-PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const
+Path::convert_to_simple_path (bool with_opening_scope_resolution) const
{
+ rust_assert (kind == Kind::Regular);
+
if (!has_segments ())
return SimplePath::create_empty ();
@@ -197,7 +203,7 @@ PathInExpression::as_string () const
if (has_opening_scope_resolution)
str = "::";
- return str + PathPattern::as_string ();
+ return str + Path::as_string ();
}
std::string
@@ -260,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
@@ -297,7 +324,7 @@ TypePathFunction::as_string () const
std::string
QualifiedPathInExpression::as_string () const
{
- return path_type.as_string () + "::" + PathPattern::as_string ();
+ return path_type.as_string () + "::" + Path::as_string ();
}
std::string
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 83412eb..6f53188 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -21,7 +21,11 @@
/* "Path" (identifier within namespaces, essentially) handling. Required include
* for virtually all AST-related functionality. */
+#include "optional.h"
#include "rust-ast.h"
+#include "rust-hir-map.h"
+#include "rust-mapping-common.h"
+#include "rust-system.h"
#include "system.h"
namespace Rust {
@@ -52,10 +56,16 @@ public:
location_t get_locus () const { return locus; }
- bool is_super_segment () const { return as_string ().compare ("super") == 0; }
- bool is_crate_segment () const { return as_string ().compare ("crate") == 0; }
- bool is_lower_self () const { return as_string ().compare ("self") == 0; }
- bool is_big_self () const { return as_string ().compare ("Self") == 0; }
+ bool is_super_path_seg () const
+ {
+ return as_string ().compare ("super") == 0;
+ }
+ bool is_crate_path_seg () const
+ {
+ return as_string ().compare ("crate") == 0;
+ }
+ bool is_lower_self_seg () const { return as_string ().compare ("self") == 0; }
+ bool is_big_self_seg () const { return as_string ().compare ("Self") == 0; }
};
// A binding of an identifier to a type used in generic arguments in paths
@@ -157,17 +167,11 @@ public:
*/
enum class Kind
{
- Error,
Const, // A const value
Type, // A type argument (not discernable during parsing)
Either, // Either a type or a const value, cleared up during resolving
};
- static GenericArg create_error ()
- {
- return GenericArg (nullptr, nullptr, {""}, Kind::Error, UNDEF_LOCATION);
- }
-
static GenericArg create_const (std::unique_ptr<Expr> expression)
{
auto locus = expression->get_locus ();
@@ -212,8 +216,6 @@ public:
GenericArg (GenericArg &&other) = default;
GenericArg &operator= (GenericArg &&other) = default;
- bool is_error () const { return kind == Kind::Error; }
-
Kind get_kind () const { return kind; }
location_t get_locus () const { return locus; }
@@ -229,8 +231,6 @@ public:
break;
case Kind::Either:
break;
- case Kind::Error:
- rust_unreachable ();
}
}
@@ -273,8 +273,6 @@ public:
{
switch (get_kind ())
{
- case Kind::Error:
- rust_unreachable ();
case Kind::Either:
return "Ambiguous: " + path.as_string ();
case Kind::Const:
@@ -345,32 +343,32 @@ class ConstGenericParam : public GenericParam
/**
* Default value for the const generic parameter
*/
- GenericArg default_value;
+ tl::optional<GenericArg> default_value;
- Attribute outer_attr;
+ AST::AttrVec outer_attrs;
location_t locus;
public:
ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type,
- GenericArg default_value, Attribute outer_attr,
- location_t locus)
+ tl::optional<GenericArg> default_value,
+ AST::AttrVec outer_attrs, location_t locus)
: name (name), type (std::move (type)),
- default_value (std::move (default_value)), outer_attr (outer_attr),
+ default_value (std::move (default_value)), outer_attrs (outer_attrs),
locus (locus)
{}
ConstGenericParam (const ConstGenericParam &other)
: GenericParam (), name (other.name), type (other.type->clone_type ()),
- default_value (other.default_value), outer_attr (other.outer_attr),
+ default_value (other.default_value), outer_attrs (other.outer_attrs),
locus (other.locus)
{}
bool has_type () const { return type != nullptr; }
- bool has_default_value () const { return !default_value.is_error (); }
+ bool has_default_value () const { return default_value.has_value (); }
const Identifier &get_name () const { return name; }
- Attribute &get_outer_attribute () { return outer_attr; }
+ AST::AttrVec &get_outer_attrs () { return outer_attrs; }
AST::Type &get_type ()
{
@@ -379,18 +377,18 @@ public:
return *type;
}
- GenericArg &get_default_value ()
+ GenericArg &get_default_value_unchecked ()
{
rust_assert (has_default_value ());
- return default_value;
+ return default_value.value ();
}
- const GenericArg &get_default_value () const
+ const GenericArg &get_default_value_unchecked () const
{
rust_assert (has_default_value ());
- return default_value;
+ return default_value.value ();
}
std::string as_string () const override;
@@ -476,15 +474,23 @@ public:
std::string as_string () const;
- // TODO: is this better? Or is a "vis_pattern" better?
std::vector<GenericArg> &get_generic_args () { return generic_args; }
- // TODO: is this better? Or is a "vis_pattern" better?
std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; }
+ const std::vector<GenericArgsBinding> &get_binding_args () const
+ {
+ return binding_args;
+ }
+
std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; };
- location_t get_locus () { return locus; }
+ const std::vector<Lifetime> &get_lifetime_args () const
+ {
+ return lifetime_args;
+ };
+
+ location_t get_locus () const { return locus; }
};
/* A segment of a path in expression, including an identifier aspect and maybe
@@ -506,7 +512,7 @@ public:
GenericArgs generic_args = GenericArgs::create_empty ())
: segment_name (std::move (segment_name)),
generic_args (std::move (generic_args)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
/* Constructor for segment with generic arguments (from segment name and all
@@ -519,7 +525,7 @@ public:
generic_args (GenericArgs (std::move (lifetime_args),
std::move (generic_args),
std::move (binding_args))),
- locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
// Returns whether path expression segment is in an error state.
@@ -549,68 +555,102 @@ public:
bool is_super_path_seg () const
{
- return !has_generic_args () && get_ident_segment ().is_super_segment ();
+ return !has_generic_args () && get_ident_segment ().is_super_path_seg ();
}
bool is_crate_path_seg () const
{
- return !has_generic_args () && get_ident_segment ().is_crate_segment ();
+ return !has_generic_args () && get_ident_segment ().is_crate_path_seg ();
}
bool is_lower_self_seg () const
{
- return !has_generic_args () && get_ident_segment ().is_lower_self ();
+ return !has_generic_args () && get_ident_segment ().is_lower_self_seg ();
}
};
// AST node representing a pattern that involves a "path" - abstract base
// class
-class PathPattern : public Pattern
+class Path : public Pattern
{
- std::vector<PathExprSegment> segments;
+public:
+ enum class Kind
+ {
+ LangItem,
+ Regular,
+ };
-protected:
- PathPattern (std::vector<PathExprSegment> segments)
- : segments (std::move (segments))
+ Path (std::vector<PathExprSegment> segments)
+ : segments (std::move (segments)), lang_item (tl::nullopt),
+ kind (Kind::Regular)
+ {}
+
+ Path (LangItem::Kind lang_item)
+ : segments ({}), lang_item (lang_item), kind (Kind::LangItem)
{}
// Returns whether path has segments.
- bool has_segments () const { return !segments.empty (); }
+ bool has_segments () const
+ {
+ rust_assert (kind == Kind::Regular);
+ return !segments.empty ();
+ }
/* Converts path segments to their equivalent SimplePath segments if
* possible, and creates a SimplePath from them. */
SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const;
- // Removes all segments of the path.
- void remove_all_segments ()
- {
- segments.clear ();
- segments.shrink_to_fit ();
- }
-
-public:
/* Returns whether the path is a single segment (excluding qualified path
* initial as segment). */
- bool is_single_segment () const { return segments.size () == 1; }
+ bool is_single_segment () const
+ {
+ rust_assert (kind == Kind::Regular);
+ return segments.size () == 1;
+ }
std::string as_string () const override;
+ bool is_lang_item () const { return kind == Kind::LangItem; }
+
// TODO: this seems kinda dodgy
- std::vector<PathExprSegment> &get_segments () { return segments; }
- const std::vector<PathExprSegment> &get_segments () const { return segments; }
+ std::vector<PathExprSegment> &get_segments ()
+ {
+ rust_assert (kind == Kind::Regular);
+ return segments;
+ }
+ const std::vector<PathExprSegment> &get_segments () const
+ {
+ rust_assert (kind == Kind::Regular);
+ return segments;
+ }
+
+ LangItem::Kind get_lang_item () const
+ {
+ rust_assert (kind == Kind::LangItem);
+ return *lang_item;
+ }
Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
+ Path::Kind get_path_kind () { return kind; }
+
+protected:
+ std::vector<PathExprSegment> segments;
+ tl::optional<LangItem::Kind> lang_item;
+
+ Path::Kind kind;
};
/* AST node representing a path-in-expression pattern (path that allows
* generic arguments) */
-class PathInExpression : public PathPattern, public PathExpr
+class PathInExpression : public Path, public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
bool has_opening_scope_resolution;
location_t locus;
NodeId _node_id;
+ bool marked_for_strip;
+
public:
std::string as_string () const override;
@@ -618,16 +658,25 @@ public:
PathInExpression (std::vector<PathExprSegment> path_segments,
std::vector<Attribute> outer_attrs, location_t locus,
bool has_opening_scope_resolution = false)
- : PathPattern (std::move (path_segments)),
- outer_attrs (std::move (outer_attrs)),
+ : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)),
has_opening_scope_resolution (has_opening_scope_resolution),
- locus (locus), _node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()),
+ marked_for_strip (false)
+ {}
+
+ PathInExpression (LangItem::Kind lang_item,
+ std::vector<Attribute> outer_attrs, location_t locus)
+ : Path (lang_item), outer_attrs (std::move (outer_attrs)),
+ has_opening_scope_resolution (false), locus (locus),
+ _node_id (Analysis::Mappings::get ().get_next_node_id ()),
+ marked_for_strip (false)
{}
// Creates an error state path in expression.
static PathInExpression create_error ()
{
- return PathInExpression ({}, {}, UNDEF_LOCATION);
+ return PathInExpression (std::vector<PathExprSegment> (), {},
+ UNDEF_LOCATION);
}
// Returns whether path in expression is in an error state.
@@ -650,9 +699,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
- // Invalid if path is empty (error state), so base stripping on that.
- void mark_for_strip () override { remove_all_segments (); }
- bool is_marked_for_strip () const override { return is_error (); }
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
bool opening_scope_resolution () const
{
@@ -669,14 +717,17 @@ public:
outer_attrs = std::move (new_attrs);
}
- NodeId get_pattern_node_id () const { return get_node_id (); }
-
PathExprSegment &get_final_segment () { return get_segments ().back (); }
const PathExprSegment &get_final_segment () const
{
return get_segments ().back ();
}
+ Expr::Kind get_expr_kind () const override
+ {
+ return Expr::Kind::PathInExpression;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -711,7 +762,8 @@ public:
};
private:
- PathIdentSegment ident_segment;
+ tl::optional<LangItem::Kind> lang_item;
+ tl::optional<PathIdentSegment> ident_segment;
location_t locus;
protected:
@@ -741,21 +793,30 @@ public:
TypePathSegment (PathIdentSegment ident_segment,
bool has_separating_scope_resolution, location_t locus)
- : ident_segment (std::move (ident_segment)), locus (locus),
+ : lang_item (tl::nullopt), ident_segment (std::move (ident_segment)),
+ locus (locus),
has_separating_scope_resolution (has_separating_scope_resolution),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
+ {}
+
+ TypePathSegment (LangItem::Kind lang_item, location_t locus)
+ : lang_item (lang_item), ident_segment (tl::nullopt), locus (locus),
+ has_separating_scope_resolution (false),
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
TypePathSegment (std::string segment_name,
bool has_separating_scope_resolution, location_t locus)
- : ident_segment (PathIdentSegment (std::move (segment_name), locus)),
+ : lang_item (tl::nullopt),
+ ident_segment (PathIdentSegment (std::move (segment_name), locus)),
locus (locus),
has_separating_scope_resolution (has_separating_scope_resolution),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
TypePathSegment (TypePathSegment const &other)
- : ident_segment (other.ident_segment), locus (other.locus),
+ : lang_item (other.lang_item), ident_segment (other.ident_segment),
+ locus (other.locus),
has_separating_scope_resolution (other.has_separating_scope_resolution),
node_id (other.node_id)
{}
@@ -763,6 +824,7 @@ public:
TypePathSegment &operator= (TypePathSegment const &other)
{
ident_segment = other.ident_segment;
+ lang_item = other.lang_item;
locus = other.locus;
has_separating_scope_resolution = other.has_separating_scope_resolution;
node_id = other.node_id;
@@ -773,16 +835,28 @@ public:
TypePathSegment (TypePathSegment &&other) = default;
TypePathSegment &operator= (TypePathSegment &&other) = default;
- virtual std::string as_string () const { return ident_segment.as_string (); }
+ virtual std::string as_string () const
+ {
+ if (lang_item.has_value ())
+ return LangItem::PrettyString (*lang_item);
+
+ return ident_segment->as_string ();
+ }
/* Returns whether the type path segment is in an error state. May be
* virtual in future. */
- bool is_error () const { return ident_segment.is_error (); }
+ bool is_error () const
+ {
+ rust_assert (ident_segment);
+ return ident_segment->is_error ();
+ }
/* Returns whether segment is identifier only (as opposed to generic args or
* function). Overridden in derived classes with other segments. */
virtual bool is_ident_only () const { return true; }
+ bool is_lang_item () const { return lang_item.has_value (); }
+
location_t get_locus () const { return locus; }
// not pure virtual as class not abstract
@@ -793,23 +867,41 @@ public:
return has_separating_scope_resolution;
}
- PathIdentSegment &get_ident_segment () { return ident_segment; };
- const PathIdentSegment &get_ident_segment () const { return ident_segment; };
+ PathIdentSegment &get_ident_segment ()
+ {
+ rust_assert (!is_lang_item ());
+ return *ident_segment;
+ };
+
+ const PathIdentSegment &get_ident_segment () const
+ {
+ rust_assert (!is_lang_item ());
+ return *ident_segment;
+ };
+
+ LangItem::Kind get_lang_item () const
+ {
+ rust_assert (is_lang_item ());
+ return *lang_item;
+ }
NodeId get_node_id () const { return node_id; }
bool is_crate_path_seg () const
{
- return get_ident_segment ().is_crate_segment ();
+ return get_ident_segment ().is_crate_path_seg ();
}
bool is_super_path_seg () const
{
- return get_ident_segment ().is_super_segment ();
+ return get_ident_segment ().is_super_path_seg ();
+ }
+ bool is_big_self_seg () const
+ {
+ return get_ident_segment ().is_big_self_seg ();
}
- bool is_big_self_seg () const { return get_ident_segment ().is_big_self (); }
bool is_lower_self_seg () const
{
- return get_ident_segment ().is_lower_self ();
+ return get_ident_segment ().is_lower_self_seg ();
}
};
@@ -834,6 +926,12 @@ public:
generic_args (std::move (generic_args))
{}
+ TypePathSegmentGeneric (LangItem::Kind lang_item, GenericArgs generic_args,
+ location_t locus)
+ : TypePathSegment (lang_item, locus),
+ generic_args (std::move (generic_args))
+ {}
+
// Constructor from segment name and all args
TypePathSegmentGeneric (std::string segment_name,
bool has_separating_scope_resolution,
@@ -870,11 +968,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
@@ -891,7 +985,7 @@ private:
/*bool has_inputs;
TypePathFnInputs inputs;*/
// inlined from TypePathFnInputs
- std::vector<std::unique_ptr<Type> > inputs;
+ std::vector<std::unique_ptr<Type>> inputs;
// bool has_type;
std::unique_ptr<Type> return_type;
@@ -924,8 +1018,8 @@ public:
}
// Constructor
- TypePathFunction (std::vector<std::unique_ptr<Type> > inputs,
- location_t locus, std::unique_ptr<Type> type = nullptr)
+ TypePathFunction (std::vector<std::unique_ptr<Type>> inputs, location_t locus,
+ std::unique_ptr<Type> type = nullptr)
: inputs (std::move (inputs)), return_type (std::move (type)),
is_invalid (false), locus (locus)
{}
@@ -970,11 +1064,11 @@ public:
std::string as_string () const;
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Type> > &get_params () const
+ const std::vector<std::unique_ptr<Type>> &get_params () const
{
return inputs;
}
- std::vector<std::unique_ptr<Type> > &get_params () { return inputs; }
+ std::vector<std::unique_ptr<Type>> &get_params () { return inputs; }
// TODO: is this better? Or is a "vis_pattern" better?
Type &get_return_type ()
@@ -1038,11 +1132,10 @@ public:
}
};
-// Path used inside types
class TypePath : public TypeNoBounds
{
bool has_opening_scope_resolution;
- std::vector<std::unique_ptr<TypePathSegment> > segments;
+ std::vector<std::unique_ptr<TypePathSegment>> segments;
location_t locus;
protected:
@@ -1067,12 +1160,20 @@ public:
// Creates an error state TypePath.
static TypePath create_error ()
{
- return TypePath (std::vector<std::unique_ptr<TypePathSegment> > (),
+ return TypePath (std::vector<std::unique_ptr<TypePathSegment>> (),
UNDEF_LOCATION);
}
// Constructor
- TypePath (std::vector<std::unique_ptr<TypePathSegment> > segments,
+ TypePath (std::vector<std::unique_ptr<TypePathSegment>> segments,
+ location_t locus, bool has_opening_scope_resolution = false)
+ : TypeNoBounds (),
+ has_opening_scope_resolution (has_opening_scope_resolution),
+ segments (std::move (segments)), locus (locus)
+ {}
+
+ TypePath (LangItem::Kind lang_item,
+ std::vector<std::unique_ptr<TypePathSegment>> segments,
location_t locus, bool has_opening_scope_resolution = false)
: TypeNoBounds (),
has_opening_scope_resolution (has_opening_scope_resolution),
@@ -1110,6 +1211,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;
@@ -1118,15 +1221,19 @@ public:
TraitBound *to_trait_bound (bool in_parens) const override;
location_t get_locus () const override final { return locus; }
+ NodeId get_node_id () const { return node_id; }
+
+ void mark_for_strip () override {}
+ bool is_marked_for_strip () const override { return false; }
void accept_vis (ASTVisitor &vis) override;
// TODO: this seems kinda dodgy
- std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
+ std::vector<std::unique_ptr<TypePathSegment>> &get_segments ()
{
return segments;
}
- const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const
+ const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const
{
return segments;
}
@@ -1147,9 +1254,8 @@ public:
QualifiedPathType (std::unique_ptr<Type> invoke_on_type,
location_t locus = UNDEF_LOCATION,
TypePath trait_path = TypePath::create_error ())
- : type_to_invoke_on (std::move (invoke_on_type)),
- trait_path (std::move (trait_path)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ : type_to_invoke_on (std::move (invoke_on_type)), trait_path (trait_path),
+ locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
// Copy constructor uses custom deep copy for Type to preserve polymorphism
@@ -1226,7 +1332,7 @@ public:
/* AST node representing a qualified path-in-expression pattern (path that
* allows specifying trait functions) */
-class QualifiedPathInExpression : public PathPattern, public PathExpr
+class QualifiedPathInExpression : public Path, public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
QualifiedPathType path_type;
@@ -1240,10 +1346,9 @@ public:
std::vector<PathExprSegment> path_segments,
std::vector<Attribute> outer_attrs,
location_t locus)
- : PathPattern (std::move (path_segments)),
- outer_attrs (std::move (outer_attrs)),
+ : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)),
path_type (std::move (qual_path_type)), locus (locus),
- _node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ _node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
/* TODO: maybe make a shortcut constructor that has QualifiedPathType
@@ -1287,6 +1392,11 @@ public:
NodeId get_node_id () const override { return _node_id; }
+ Expr::Kind get_expr_kind () const override
+ {
+ return Expr::Kind::QualifiedPathInExpression;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1316,7 +1426,7 @@ class QualifiedPathInType : public TypeNoBounds
{
QualifiedPathType path_type;
std::unique_ptr<TypePathSegment> associated_segment;
- std::vector<std::unique_ptr<TypePathSegment> > segments;
+ std::vector<std::unique_ptr<TypePathSegment>> segments;
location_t locus;
protected:
@@ -1331,7 +1441,7 @@ public:
QualifiedPathInType (
QualifiedPathType qual_path_type,
std::unique_ptr<TypePathSegment> associated_segment,
- std::vector<std::unique_ptr<TypePathSegment> > path_segments,
+ std::vector<std::unique_ptr<TypePathSegment>> path_segments,
location_t locus)
: path_type (std::move (qual_path_type)),
associated_segment (std::move (associated_segment)),
@@ -1378,7 +1488,7 @@ public:
{
return QualifiedPathInType (
QualifiedPathType::create_error (), nullptr,
- std::vector<std::unique_ptr<TypePathSegment> > (), UNDEF_LOCATION);
+ std::vector<std::unique_ptr<TypePathSegment>> (), UNDEF_LOCATION);
}
std::string as_string () const override;
@@ -1398,11 +1508,11 @@ public:
}
// TODO: this seems kinda dodgy
- std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
+ std::vector<std::unique_ptr<TypePathSegment>> &get_segments ()
{
return segments;
}
- const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const
+ const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const
{
return segments;
}
diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc
index 9091637..c62a4c3 100644
--- a/gcc/rust/ast/rust-pattern.cc
+++ b/gcc/rust/ast/rust-pattern.cc
@@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see
#include "rust-diagnostics.h"
#include "rust-ast-visitor.h"
#include "rust-macro.h"
-#include "rust-session-manager.h"
#include "rust-lex.h"
#include "rust-parse.h"
#include "rust-operators.h"
@@ -30,6 +29,22 @@ along with GCC; see the file COPYING3. If not see
namespace Rust {
namespace AST {
+RangeKind
+tokenid_to_rangekind (TokenId id)
+{
+ switch (id)
+ {
+ case DOT_DOT_EQ:
+ return RangeKind::INCLUDED;
+ case ELLIPSIS:
+ return RangeKind::ELLIPSIS;
+ case DOT_DOT:
+ return RangeKind::EXCLUDED;
+ default:
+ rust_unreachable ();
+ }
+}
+
std::string
LiteralPattern::as_string () const
{
@@ -73,10 +88,17 @@ std::string
RangePattern::as_string () const
{
// TODO: maybe rewrite to work with non-linearisable bounds
- if (has_ellipsis_syntax)
- return lower->as_string () + "..." + upper->as_string ();
- else
- return lower->as_string () + "..=" + upper->as_string ();
+ switch (range_kind)
+ {
+ case RangeKind::EXCLUDED:
+ return lower->as_string () + ".." + upper->as_string ();
+ case RangeKind::INCLUDED:
+ return lower->as_string () + "..=" + upper->as_string ();
+ case RangeKind::ELLIPSIS:
+ return lower->as_string () + "..." + upper->as_string ();
+ default:
+ rust_unreachable ();
+ }
}
std::string
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index abf6de6..6810732 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -36,13 +36,13 @@ public:
// Constructor for a literal pattern
LiteralPattern (Literal lit, location_t locus)
: lit (std::move (lit)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
LiteralPattern (std::string val, Literal::LitType type, location_t locus,
PrimitiveCoreType type_hint)
: lit (Literal (std::move (val), type, type_hint)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
location_t get_locus () const override final { return locus; }
@@ -90,7 +90,7 @@ public:
std::unique_ptr<Pattern> to_bind = nullptr)
: Pattern (), variable_ident (std::move (ident)), is_ref (is_ref),
is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
IdentifierPattern (NodeId node_id, Identifier ident, location_t locus,
@@ -175,7 +175,7 @@ public:
std::string as_string () const override { return std::string (1, '_'); }
WildcardPattern (location_t locus)
- : locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
location_t get_locus () const override final { return locus; }
@@ -204,7 +204,7 @@ public:
std::string as_string () const override { return ".."; }
RestPattern (location_t locus)
- : locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
location_t get_locus () const override final { return locus; }
@@ -368,13 +368,22 @@ protected:
}
};
+enum class RangeKind
+{
+ INCLUDED,
+ ELLIPSIS,
+ EXCLUDED,
+};
+
+RangeKind
+tokenid_to_rangekind (TokenId id);
// AST node for matching within a certain range (range pattern)
class RangePattern : public Pattern
{
std::unique_ptr<RangePatternBound> lower;
std::unique_ptr<RangePatternBound> upper;
- bool has_ellipsis_syntax;
+ RangeKind range_kind;
/* location only stored to avoid a dereference - lower pattern should give
* correct location so maybe change in future */
@@ -386,18 +395,18 @@ public:
// Constructor
RangePattern (std::unique_ptr<RangePatternBound> lower,
- std::unique_ptr<RangePatternBound> upper, location_t locus,
- bool has_ellipsis_syntax = false)
+ std::unique_ptr<RangePatternBound> upper, RangeKind range_kind,
+ location_t locus)
: lower (std::move (lower)), upper (std::move (upper)),
- has_ellipsis_syntax (has_ellipsis_syntax), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ range_kind (range_kind), locus (locus),
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
// Copy constructor with clone
RangePattern (RangePattern const &other)
: lower (other.lower->clone_range_pattern_bound ()),
upper (other.upper->clone_range_pattern_bound ()),
- has_ellipsis_syntax (other.has_ellipsis_syntax), locus (other.locus),
+ range_kind (other.range_kind), locus (other.locus),
node_id (other.node_id)
{}
@@ -406,7 +415,7 @@ public:
{
lower = other.lower->clone_range_pattern_bound ();
upper = other.upper->clone_range_pattern_bound ();
- has_ellipsis_syntax = other.has_ellipsis_syntax;
+ range_kind = other.range_kind;
locus = other.locus;
node_id = other.node_id;
@@ -419,11 +428,16 @@ public:
location_t get_locus () const override final { return locus; }
- bool get_has_ellipsis_syntax () { return has_ellipsis_syntax; }
+ bool get_has_ellipsis_syntax () const
+ {
+ return range_kind == RangeKind::ELLIPSIS;
+ }
+
+ RangeKind get_range_kind () const { return range_kind; }
- bool get_has_lower_bound () { return lower != nullptr; }
+ bool get_has_lower_bound () const { return lower != nullptr; }
- bool get_has_upper_bound () { return upper != nullptr; }
+ bool get_has_upper_bound () const { return upper != nullptr; }
void accept_vis (ASTVisitor &vis) override;
@@ -469,7 +483,7 @@ public:
bool ref_has_two_amps, location_t locus)
: has_two_amps (ref_has_two_amps), is_mut (is_mut_reference),
pattern (std::move (pattern)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
// Copy constructor requires clone
@@ -612,7 +626,7 @@ public:
std::vector<Attribute> outer_attribs,
location_t locus)
: StructPatternField (std::move (outer_attribs), locus,
- Analysis::Mappings::get ()->get_next_node_id ()),
+ Analysis::Mappings::get ().get_next_node_id ()),
index (index), tuple_pattern (std::move (tuple_pattern))
{}
@@ -692,7 +706,7 @@ public:
std::vector<Attribute> outer_attrs,
location_t locus)
: StructPatternField (std::move (outer_attrs), locus,
- Analysis::Mappings::get ()->get_next_node_id ()),
+ Analysis::Mappings::get ().get_next_node_id ()),
ident (std::move (ident)), ident_pattern (std::move (ident_pattern))
{}
@@ -771,7 +785,7 @@ public:
StructPatternFieldIdent (Identifier ident, bool is_ref, bool is_mut,
std::vector<Attribute> outer_attrs, location_t locus)
: StructPatternField (std::move (outer_attrs), locus,
- Analysis::Mappings::get ()->get_next_node_id ()),
+ Analysis::Mappings::get ().get_next_node_id ()),
has_ref (is_ref), has_mut (is_mut), ident (std::move (ident))
{}
@@ -926,7 +940,7 @@ public:
StructPatternElements elems
= StructPatternElements::create_empty ())
: path (std::move (struct_path)), elems (std::move (elems)),
- node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
+ node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus)
{}
/* TODO: constructor to construct via elements included in
@@ -1146,7 +1160,7 @@ public:
TupleStructPattern (PathInExpression tuple_struct_path,
std::unique_ptr<TupleStructItems> items)
: path (std::move (tuple_struct_path)), items (std::move (items)),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{
rust_assert (this->items != nullptr);
}
@@ -1395,7 +1409,7 @@ public:
TuplePattern (std::unique_ptr<TuplePatternItems> items, location_t locus)
: items (std::move (items)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{
rust_assert (this->items != nullptr);
}
@@ -1462,7 +1476,7 @@ public:
GroupedPattern (std::unique_ptr<Pattern> pattern_in_parens, location_t locus)
: pattern_in_parens (std::move (pattern_in_parens)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
// Copy constructor uses clone
@@ -1521,7 +1535,7 @@ public:
SlicePattern (std::vector<std::unique_ptr<Pattern>> items, location_t locus)
: items (std::move (items)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
// Copy constructor with vector clone
@@ -1588,7 +1602,7 @@ public:
AltPattern (std::vector<std::unique_ptr<Pattern>> alts, location_t locus)
: alts (std::move (alts)), locus (locus),
- node_id (Analysis::Mappings::get ()->get_next_node_id ())
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
// Copy constructor with vector clone
@@ -1643,7 +1657,7 @@ protected:
};
// Moved definition to rust-path.h
-class PathPattern;
+class Path;
// Forward decls for paths (defined in rust-path.h)
class PathInExpression;
diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h
index 51c5918..e64fbe4 100644
--- a/gcc/rust/ast/rust-stmt.h
+++ b/gcc/rust/ast/rust-stmt.h
@@ -19,10 +19,11 @@
#ifndef RUST_AST_STATEMENT_H
#define RUST_AST_STATEMENT_H
+#include "optional.h"
#include "rust-ast.h"
#include "rust-path.h"
#include "rust-expr.h"
-#include <memory>
+#include "rust-system.h"
namespace Rust {
namespace AST {
@@ -72,6 +73,8 @@ class LetStmt : public Stmt
// bool has_init_expr;
std::unique_ptr<Expr> init_expr;
+ tl::optional<std::unique_ptr<Expr>> else_expr;
+
location_t locus;
public:
@@ -85,15 +88,18 @@ public:
// Returns whether let statement has an initialisation expression.
bool has_init_expr () const { return init_expr != nullptr; }
+ bool has_else_expr () const { return else_expr.has_value (); }
std::string as_string () const override;
LetStmt (std::unique_ptr<Pattern> variables_pattern,
std::unique_ptr<Expr> init_expr, std::unique_ptr<Type> type,
+ tl::optional<std::unique_ptr<Expr>> else_expr,
std::vector<Attribute> outer_attrs, location_t locus)
: outer_attrs (std::move (outer_attrs)),
variables_pattern (std::move (variables_pattern)),
- type (std::move (type)), init_expr (std::move (init_expr)), locus (locus)
+ type (std::move (type)), init_expr (std::move (init_expr)),
+ else_expr (std::move (else_expr)), locus (locus)
{}
// Copy constructor with clone
@@ -107,6 +113,9 @@ public:
// guard to prevent null dereference (always required)
if (other.init_expr != nullptr)
init_expr = other.init_expr->clone_expr ();
+ if (other.else_expr.has_value ())
+ else_expr = other.else_expr.value ()->clone_expr ();
+
if (other.type != nullptr)
type = other.type->clone_type ();
}
@@ -128,6 +137,12 @@ public:
init_expr = other.init_expr->clone_expr ();
else
init_expr = nullptr;
+
+ if (other.else_expr != nullptr)
+ else_expr = other.else_expr.value ()->clone_expr ();
+ else
+ else_expr = tl::nullopt;
+
if (other.type != nullptr)
type = other.type->clone_type ();
else
@@ -162,12 +177,24 @@ public:
return *init_expr;
}
+ Expr &get_else_expr ()
+ {
+ rust_assert (has_else_expr ());
+ return *else_expr.value ();
+ }
+
std::unique_ptr<Expr> &get_init_expr_ptr ()
{
rust_assert (has_init_expr ());
return init_expr;
}
+ std::unique_ptr<Expr> &get_else_expr_ptr ()
+ {
+ rust_assert (has_else_expr ());
+ return else_expr.value ();
+ }
+
Pattern &get_pattern ()
{
rust_assert (variables_pattern != nullptr);
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 23572a2..c785b6e 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -48,11 +48,16 @@ public:
std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; }
+ const std::vector<LifetimeParam> &get_for_lifetimes () const
+ {
+ return for_lifetimes;
+ }
+
TraitBound (TypePath type_path, location_t locus, bool in_parens = false,
bool opening_question_mark = false,
std::vector<LifetimeParam> for_lifetimes
= std::vector<LifetimeParam> ())
- : TypeParamBound (Analysis::Mappings::get ()->get_next_node_id ()),
+ : TypeParamBound (Analysis::Mappings::get ().get_next_node_id ()),
in_parens (in_parens), opening_question_mark (opening_question_mark),
for_lifetimes (std::move (for_lifetimes)),
type_path (std::move (type_path)), locus (locus)
@@ -68,6 +73,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; }
@@ -81,6 +93,11 @@ public:
bool is_in_parens () const { return in_parens; }
bool has_opening_question_mark () const { return opening_question_mark; }
+ TypeParamBoundType get_bound_type () const override
+ {
+ return TypeParamBound::TypeParamBoundType::TRAIT;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -295,33 +312,31 @@ 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);
}
};
@@ -519,6 +534,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 */
@@ -532,7 +550,7 @@ protected:
class ReferenceType : public TypeNoBounds
{
// bool has_lifetime; // TODO: handle in lifetime or something?
- Lifetime lifetime;
+ tl::optional<Lifetime> lifetime;
bool has_mut;
std::unique_ptr<TypeNoBounds> type;
@@ -543,11 +561,12 @@ public:
bool is_mut () const { return has_mut; }
// Returns whether the reference has a lifetime.
- bool has_lifetime () const { return !lifetime.is_error (); }
+ bool has_lifetime () const { return lifetime.has_value (); }
// Constructor
ReferenceType (bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds,
- location_t locus, Lifetime lifetime = Lifetime::elided ())
+ location_t locus,
+ tl::optional<Lifetime> lifetime = Lifetime::elided ())
: lifetime (std::move (lifetime)), has_mut (is_mut),
type (std::move (type_no_bounds)), locus (locus)
{}
@@ -588,10 +607,14 @@ public:
bool get_has_mut () const { return has_mut; }
- Lifetime &get_lifetime () { return lifetime; }
+ Lifetime &get_lifetime () { return lifetime.value (); }
+ const Lifetime &get_lifetime () const { return lifetime.value (); }
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 */
@@ -654,6 +677,11 @@ public:
return *size;
}
+ std::unique_ptr<Type> &get_element_type () { return elem_type; }
+
+ // Additional getter for direct access to the size expr unique_ptr
+ std::unique_ptr<Expr> &get_size_ptr () { return size; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -707,6 +735,9 @@ 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 */