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.cc1
-rw-r--r--gcc/rust/ast/rust-ast-builder.cc370
-rw-r--r--gcc/rust/ast/rust-ast-builder.h187
-rw-r--r--gcc/rust/ast/rust-ast-collector.cc147
-rw-r--r--gcc/rust/ast/rust-ast-collector.h4
-rw-r--r--gcc/rust/ast/rust-ast-full-decls.h1
-rw-r--r--gcc/rust/ast/rust-ast-visitor.cc92
-rw-r--r--gcc/rust/ast/rust-ast-visitor.h19
-rw-r--r--gcc/rust/ast/rust-ast.cc51
-rw-r--r--gcc/rust/ast/rust-ast.h161
-rw-r--r--gcc/rust/ast/rust-builtin-ast-nodes.h2
-rw-r--r--gcc/rust/ast/rust-collect-lang-items.cc113
-rw-r--r--gcc/rust/ast/rust-collect-lang-items.h61
-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.h304
-rw-r--r--gcc/rust/ast/rust-item.h439
-rw-r--r--gcc/rust/ast/rust-macro.h39
-rw-r--r--gcc/rust/ast/rust-path.cc34
-rw-r--r--gcc/rust/ast/rust-path.h436
-rw-r--r--gcc/rust/ast/rust-pattern.cc1
-rw-r--r--gcc/rust/ast/rust-stmt.h31
-rw-r--r--gcc/rust/ast/rust-type.h10
25 files changed, 2146 insertions, 915 deletions
diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc
index e76d0de..13126b4 100644
--- a/gcc/rust/ast/rust-ast-builder-type.cc
+++ b/gcc/rust/ast/rust-ast-builder-type.cc
@@ -20,7 +20,6 @@
#include "rust-ast-builder.h"
#include "rust-ast-full.h"
#include "rust-common.h"
-#include "rust-make-unique.h"
namespace Rust {
namespace AST {
diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc
index 529c686..08c52b1 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 "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
{
@@ -83,12 +183,27 @@ Builder::type_path_segment (std::string seg) const
}
std::unique_ptr<TypePathSegment>
-Builder::generic_type_path_segment (std::string seg, GenericArgs args) const
+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
{
@@ -99,40 +214,146 @@ Builder::single_type_path (std::string type) const
}
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 (generic_type_path_segment (type, args));
+ 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>
@@ -151,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> (
@@ -162,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>
@@ -189,6 +448,81 @@ 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)
{
@@ -213,7 +547,8 @@ Builder::new_lifetime_param (LifetimeParam &param)
}
std::unique_ptr<GenericParam>
-Builder::new_type_param (TypeParam &param)
+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 ();
@@ -224,6 +559,9 @@ Builder::new_type_param (TypeParam &param)
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 ())
diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h
index bad79d0..41ce118 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,42 +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>
- generic_type_path_segment (std::string seg, GenericArgs args) const;
+ 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>
@@ -121,13 +256,43 @@ public:
/* 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);
+ 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);
diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index 2022668..c850e96 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -15,12 +15,15 @@
// 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"
@@ -251,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));
@@ -511,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 ());
}
}
@@ -553,25 +533,24 @@ 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 ()));
- visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION);
-}
+ return;
+ }
-void
-TokenCollector::visit (RegularPath &path)
-{
- // FIXME: We probably want to have a proper implementation here, and call this
- // function from things like the PathInExpression visitor
-}
+ if (path.opening_scope_resolution ())
+ push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ()));
-void
-TokenCollector::visit (LangItemPath &path)
-{
- // TODO: Implement proper token collection for lang item paths
+ visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION);
}
void
@@ -579,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
@@ -594,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));
@@ -653,8 +639,6 @@ TokenCollector::visit (GenericArg &arg)
push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path)));
}
break;
- case GenericArg::Kind::Error:
- rust_unreachable ();
}
}
@@ -711,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 ()));
}
@@ -1293,7 +1277,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
@@ -1301,7 +1285,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 ());
}
@@ -1536,6 +1520,47 @@ void
TokenCollector::visit (InlineAsm &expr)
{}
+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
@@ -2499,10 +2524,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
@@ -2605,6 +2627,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 32a5bd3..f45e3cc 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);
@@ -234,8 +233,6 @@ public:
void visit (PathExprSegment &segment);
void visit (PathIdentSegment &segment);
void visit (PathInExpression &path);
- void visit (RegularPath &path);
- void visit (LangItemPath &path);
void visit (TypePathSegment &segment);
void visit (TypePathSegmentGeneric &segment);
void visit (TypePathSegmentFunction &segment);
@@ -306,6 +303,7 @@ public:
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-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h
index 80d217e..9359248 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -202,7 +202,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 8f53e52..b6833f6 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -82,26 +82,17 @@ DefaultASTVisitor::visit (AST::ConstGenericParam &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::RegularPath &path)
-{
- for (auto &segment : path.get_segments ())
- visit (segment);
-}
-
-void
-DefaultASTVisitor::visit (AST::LangItemPath &path)
-{}
-
-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
@@ -117,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
@@ -401,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 ())
@@ -412,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 ());
}
@@ -484,7 +478,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
@@ -492,7 +487,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 ());
@@ -566,7 +561,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 ());
}
@@ -574,8 +570,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 ());
}
@@ -585,8 +582,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 ());
}
@@ -596,7 +593,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 ());
}
@@ -717,6 +715,16 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr)
}
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_outer_attrs (param);
@@ -820,10 +828,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);
@@ -831,10 +847,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 ())
@@ -997,6 +1012,8 @@ DefaultASTVisitor::visit (AST::Trait &trait)
visit_inner_attrs (trait);
+ visit (trait.get_implicit_self ());
+
for (auto &generic : trait.get_generic_params ())
visit (generic);
@@ -1037,6 +1054,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);
@@ -1058,14 +1076,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);
@@ -1453,33 +1463,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 50b9301..b1fc504 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -26,6 +26,7 @@
#include "rust-item.h"
#include "rust-path.h"
#include "rust-system.h"
+#include "rust-stacked-contexts.h"
namespace Rust {
namespace AST {
@@ -59,8 +60,6 @@ public:
// virtual void visit(TraitImplItem& trait_impl_item) = 0;
// rust-path.h
- virtual void visit (RegularPath &path) = 0;
- virtual void visit (LangItemPath &path) = 0;
virtual void visit (PathInExpression &path) = 0;
virtual void visit (TypePathSegment &segment) = 0;
virtual void visit (TypePathSegmentGeneric &segment) = 0;
@@ -132,6 +131,7 @@ public:
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;
@@ -242,6 +242,8 @@ public:
class DefaultASTVisitor : public ASTVisitor
{
public:
+ virtual void visit_function_params (AST::Function &function);
+
virtual void visit (AST::Crate &crate);
virtual void visit (AST::Token &tok) override;
@@ -251,8 +253,6 @@ public:
virtual void visit (AST::Lifetime &lifetime) override;
virtual void visit (AST::LifetimeParam &lifetime_param) override;
virtual void visit (AST::ConstGenericParam &const_param) override;
- virtual void visit (AST::RegularPath &path) override;
- virtual void visit (AST::LangItemPath &path) override;
virtual void visit (AST::PathInExpression &path) override;
virtual void visit (AST::TypePathSegment &segment) override;
virtual void visit (AST::TypePathSegmentGeneric &segment) override;
@@ -317,6 +317,7 @@ public:
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;
@@ -427,7 +428,6 @@ public:
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);
@@ -452,7 +452,7 @@ public:
class ContextualASTVisitor : public DefaultASTVisitor
{
protected:
- enum class Context
+ enum class Kind
{
FUNCTION,
INHERENT_IMPL,
@@ -461,6 +461,7 @@ protected:
MODULE,
CRATE,
};
+
using DefaultASTVisitor::visit;
virtual void visit (AST::Crate &crate) override;
@@ -476,11 +477,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 1d52352..4e82be4 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -272,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 ());
@@ -1068,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)
@@ -1100,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)
@@ -1631,7 +1631,7 @@ ContinueExpr::as_string () const
std::string str ("continue ");
if (has_label ())
- str += label.as_string ();
+ str += get_label_unchecked ().as_string ();
return str;
}
@@ -2095,7 +2095,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 ();
@@ -2115,7 +2115,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 ())
@@ -2146,7 +2146,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 ();
@@ -2183,7 +2183,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 ();
@@ -2485,9 +2485,6 @@ MacroMatchRepetition::as_string () const
std::string
Lifetime::as_string () const
{
- if (is_error ())
- return "error lifetime";
-
switch (lifetime_type)
{
case NAMED:
@@ -2545,7 +2542,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 ();
@@ -2612,7 +2609,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 ";
@@ -2998,22 +2995,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
@@ -3086,7 +3067,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 ";
@@ -4286,7 +4267,7 @@ BlockExpr::normalize_tail_expr ()
if (!stmt.is_semicolon_followed ())
{
- expr = std::move (stmt.take_expr ());
+ expr = stmt.take_expr ();
statements.pop_back ();
}
}
@@ -4670,6 +4651,12 @@ InlineAsm::accept_vis (ASTVisitor &vis)
}
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 42ad011..aa6ad50 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
{
@@ -681,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; }
@@ -1039,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
@@ -1092,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
@@ -1141,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
{
@@ -1221,14 +1228,65 @@ 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,
+ 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
{
@@ -1343,7 +1401,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
@@ -1410,7 +1468,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
@@ -1539,17 +1597,9 @@ 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;
@@ -1640,15 +1690,6 @@ public:
// Returns whether the lifetime param has an outer attribute.
bool has_outer_attribute () const { return !outer_attrs.empty (); }
- // Creates an error state lifetime param.
- static LifetimeParam create_error ()
- {
- return LifetimeParam (Lifetime::error (), {}, {}, UNDEF_LOCATION);
- }
-
- // Returns whether the lifetime param is in an error state.
- bool is_error () const { return lifetime.is_error (); }
-
// Constructor
LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds,
AST::AttrVec outer_attrs, location_t locus)
@@ -1948,13 +1989,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 ());
@@ -1967,16 +2001,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 ());
@@ -2078,6 +2102,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 7ebd656..3684092 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..cd6be7f
--- /dev/null
+++ b/gcc/rust/ast/rust-collect-lang-items.cc
@@ -0,0 +1,113 @@
+// 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);
+}
+
+} // 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..ddb34a9
--- /dev/null
+++ b/gcc/rust/ast/rust-collect-lang-items.h
@@ -0,0 +1,61 @@
+// 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;
+
+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-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 438d3d3..fdb6360 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -15,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;
@@ -31,11 +31,6 @@ public:
{}
// 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; }
@@ -117,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 */
@@ -365,6 +362,8 @@ 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
@@ -403,6 +402,8 @@ public:
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
* than base */
@@ -433,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 */
@@ -464,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 */
@@ -507,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 */
@@ -595,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 */
@@ -682,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:
@@ -770,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 */
@@ -832,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 */
@@ -910,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 */
@@ -996,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 */
@@ -1090,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 */
@@ -1319,6 +1349,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 */
@@ -1424,6 +1456,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 */
@@ -1520,6 +1554,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 */
@@ -1607,6 +1643,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 */
@@ -1650,6 +1688,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!
@@ -2123,6 +2163,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; }
@@ -2131,6 +2173,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 */
@@ -2234,6 +2278,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 */
@@ -2319,6 +2365,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 */
@@ -2454,6 +2502,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
@@ -2535,7 +2585,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;
@@ -2552,8 +2602,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)),
@@ -2672,8 +2723,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
@@ -2791,7 +2844,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?
@@ -2801,11 +2854,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)
{}
@@ -2826,7 +2879,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
@@ -2842,7 +2901,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;
@@ -2853,14 +2912,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)
@@ -2922,7 +2982,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
@@ -2938,6 +3004,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) {}
@@ -2947,15 +3017,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
@@ -3404,6 +3472,8 @@ public:
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 */
@@ -3491,6 +3561,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 */
@@ -3573,6 +3645,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 */
@@ -3588,7 +3662,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:
@@ -3597,7 +3671,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)),
@@ -3637,9 +3711,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; }
@@ -3661,6 +3736,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
@@ -3671,7 +3758,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))
@@ -3679,6 +3766,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 */
@@ -3699,7 +3791,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),
@@ -3737,6 +3829,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 */
@@ -3760,7 +3857,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),
@@ -3820,6 +3917,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 */
@@ -3842,7 +3944,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)),
@@ -3889,6 +3991,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 */
@@ -4012,6 +4119,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); }
@@ -4206,6 +4315,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) */
@@ -4535,6 +4646,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 */
@@ -4614,6 +4727,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 */
@@ -4696,6 +4811,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 */
@@ -4768,6 +4885,27 @@ struct InlineAsmRegOrRegClass
location_t locus;
};
+struct LlvmOperand
+{
+ 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:
@@ -4810,14 +4948,14 @@ public:
rust_assert (this->expr != nullptr);
}
- In (const struct In &other)
+ In (const In &other)
{
reg = other.reg;
expr = other.expr->clone_expr ();
}
- In operator= (const struct In &other)
+ In operator= (const In &other)
{
reg = other.reg;
expr = other.expr->clone_expr ();
@@ -4843,14 +4981,14 @@ public:
rust_assert (this->expr != nullptr);
}
- Out (const struct Out &other)
+ Out (const Out &other)
{
reg = other.reg;
late = other.late;
expr = other.expr->clone_expr ();
}
- Out operator= (const struct Out &other)
+ Out operator= (const Out &other)
{
reg = other.reg;
late = other.late;
@@ -4876,14 +5014,14 @@ public:
rust_assert (this->expr != nullptr);
}
- InOut (const struct InOut &other)
+ InOut (const InOut &other)
{
reg = other.reg;
late = other.late;
expr = other.expr->clone_expr ();
}
- InOut operator= (const struct InOut &other)
+ InOut operator= (const InOut &other)
{
reg = other.reg;
late = other.late;
@@ -4913,7 +5051,7 @@ public:
rust_assert (this->out_expr != nullptr);
}
- SplitInOut (const struct SplitInOut &other)
+ SplitInOut (const SplitInOut &other)
{
reg = other.reg;
late = other.late;
@@ -4921,7 +5059,7 @@ public:
out_expr = other.out_expr->clone_expr ();
}
- SplitInOut operator= (const struct SplitInOut &other)
+ SplitInOut operator= (const SplitInOut &other)
{
reg = other.reg;
late = other.late;
@@ -4953,12 +5091,12 @@ public:
{
rust_assert (this->expr != nullptr);
}
- Sym (const struct Sym &other)
+ Sym (const Sym &other)
{
expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
}
- Sym operator= (const struct Sym &other)
+ Sym operator= (const Sym &other)
{
expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
return *this;
@@ -4981,12 +5119,12 @@ public:
if (label_name.has_value ())
this->label_name = label_name.value ();
}
- Label (const struct Label &other)
+ Label (const Label &other)
{
expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
}
- Label operator= (const struct Label &other)
+ Label operator= (const Label &other)
{
expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
return *this;
@@ -5141,6 +5279,7 @@ struct TupleTemplateStr
location_t loc;
std::string symbol;
+ location_t get_locus () { return loc; }
TupleTemplateStr (location_t loc, const std::string &symbol)
: loc (loc), symbol (symbol)
{}
@@ -5209,6 +5348,79 @@ public:
{
return new InlineAsm (*this);
}
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::InlineAsm; }
+};
+
+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-item.h b/gcc/rust/ast/rust-item.h
index 2ae7c44..062f85d 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -434,13 +434,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 +454,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 +473,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 +523,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 +759,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 +898,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 +961,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 */
@@ -1301,6 +1304,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 +1331,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 +1356,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 +1365,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 +1375,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 +1469,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 +1602,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 +1663,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,
@@ -1994,6 +2010,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 +2053,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 +2074,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 +2098,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 +2140,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 +2198,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 +2339,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 +2440,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 +2563,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 +2689,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 +2912,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 +2952,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 +2962,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 +2984,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 +3052,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 +3128,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 +3278,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 +3327,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 +3600,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 +3692,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 76b3b2a..fc01e57 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:
@@ -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; }
@@ -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 06c98cd..8e43ddf 100644
--- a/gcc/rust/ast/rust-path.cc
+++ b/gcc/rust/ast/rust-path.cc
@@ -119,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;
}
@@ -136,8 +136,11 @@ PathExprSegment::as_string () const
}
std::string
-RegularPath::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,16 +152,11 @@ RegularPath::as_string () const
return str;
}
-std::string
-LangItemPath::as_string () const
-{
- // FIXME: Handle #[lang] paths
- rust_unreachable ();
-}
-
SimplePath
-RegularPath::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 ();
@@ -192,18 +190,6 @@ RegularPath::convert_to_simple_path (bool with_opening_scope_resolution) const
}
void
-RegularPath::accept_vis (ASTVisitor &vis)
-{
- vis.visit (*this);
-}
-
-void
-LangItemPath::accept_vis (ASTVisitor &vis)
-{
- vis.visit (*this);
-}
-
-void
PathInExpression::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
@@ -217,7 +203,7 @@ PathInExpression::as_string () const
if (has_opening_scope_resolution)
str = "::";
- return str + path->as_string ();
+ return str + Path::as_string ();
}
std::string
@@ -317,7 +303,7 @@ TypePathFunction::as_string () const
std::string
QualifiedPathInExpression::as_string () const
{
- return path_type.as_string () + "::" + path->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 98fde5a..a4ba93b 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -21,6 +21,7 @@
/* "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"
@@ -55,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
@@ -160,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 ();
@@ -215,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; }
@@ -232,8 +231,6 @@ public:
break;
case Kind::Either:
break;
- case Kind::Error:
- rust_unreachable ();
}
}
@@ -276,8 +273,6 @@ public:
{
switch (get_kind ())
{
- case Kind::Error:
- rust_unreachable ();
case Kind::Either:
return "Ambiguous: " + path.as_string ();
case Kind::Const:
@@ -348,15 +343,15 @@ class ConstGenericParam : public GenericParam
/**
* Default value for the const generic parameter
*/
- GenericArg default_value;
+ tl::optional<GenericArg> default_value;
AST::AttrVec outer_attrs;
location_t locus;
public:
ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type,
- GenericArg default_value, AST::AttrVec outer_attrs,
- 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_attrs (outer_attrs),
locus (locus)
@@ -369,7 +364,7 @@ public:
{}
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; }
@@ -382,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;
@@ -560,17 +555,17 @@ 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 ();
}
};
@@ -585,104 +580,75 @@ public:
Regular,
};
- virtual Kind get_path_kind () const = 0;
-
- Pattern::Kind get_pattern_kind () override final
- {
- return Pattern::Kind::Path;
- }
-
- location_t get_locus () const override final { return locus; }
- NodeId get_node_id () const override final { return node_id; }
-
- std::unique_ptr<Path> clone_path ()
- {
- return std::unique_ptr<Path> (clone_path_impl ());
- }
-
- Pattern *clone_pattern_impl () const override final
- {
- return clone_path_impl ();
- }
-
-protected:
- location_t locus;
- NodeId node_id;
-
- Path (location_t locus, NodeId node_id) : locus (locus), node_id (node_id) {}
-
- virtual Path *clone_path_impl () const = 0;
-};
-
-class RegularPath : public Path
-{
- std::vector<PathExprSegment> segments;
-
-public:
- explicit RegularPath (std::vector<PathExprSegment> &&segments,
- location_t locus, NodeId node_id)
- : Path (locus, node_id), segments (std::move (segments))
+ Path (std::vector<PathExprSegment> segments)
+ : segments (std::move (segments)), lang_item (tl::nullopt),
+ kind (Kind::Regular)
{}
- std::string as_string () const override;
+ 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 (); }
-
- std::vector<PathExprSegment> &get_segments () { return segments; }
-
- const std::vector<PathExprSegment> &get_segments () const { return segments; }
-
- /* Returns whether the path is a single segment (excluding qualified path
- * initial as segment). */
- bool is_single_segment () const { return segments.size () == 1; }
+ 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;
- Path::Kind get_path_kind () const override { return Path::Kind::Regular; }
-
- void accept_vis (ASTVisitor &vis) override;
-
- Path *clone_path_impl () const override
+ /* Returns whether the path is a single segment (excluding qualified path
+ * initial as segment). */
+ bool is_single_segment () const
{
- return new RegularPath (std::vector<PathExprSegment> (segments), locus,
- node_id);
+ rust_assert (kind == Kind::Regular);
+ return segments.size () == 1;
}
-};
-
-class LangItemPath : public Path
-{
- NodeId lang_item;
- // TODO: Add LangItemKind or w/ever here as well
- // TODO: This constructor is wrong
- explicit LangItemPath (NodeId lang_item, location_t locus)
- : Path (locus, lang_item), lang_item (lang_item)
- {}
+ std::string as_string () const override;
- Path::Kind get_path_kind () const override { return Path::Kind::LangItem; }
+ bool is_lang_item () const { return kind == Kind::LangItem; }
- void accept_vis (ASTVisitor &vis) override;
+ // TODO: this seems kinda dodgy
+ 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;
+ }
- Path *clone_path_impl () const override
+ LangItem::Kind get_lang_item () const
{
- return new LangItemPath (lang_item, locus);
+ rust_assert (kind == Kind::LangItem);
+ return *lang_item;
}
- std::string as_string () const override;
+ 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 Pattern, public ExprWithoutBlock
+class PathInExpression : public Path, public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
bool has_opening_scope_resolution;
location_t locus;
NodeId _node_id;
- std::unique_ptr<Path> path;
+
bool marked_for_strip;
public:
@@ -692,61 +658,41 @@ public:
PathInExpression (std::vector<PathExprSegment> path_segments,
std::vector<Attribute> outer_attrs, location_t locus,
bool has_opening_scope_resolution = false)
- : 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 ()),
- path (Rust::make_unique<RegularPath> (std::move (path_segments), locus,
- _node_id)),
marked_for_strip (false)
{}
- PathInExpression (const PathInExpression &other)
- : outer_attrs (other.outer_attrs),
- has_opening_scope_resolution (other.has_opening_scope_resolution),
- locus (other.locus), _node_id (other._node_id),
- path (other.path->clone_path ()),
- marked_for_strip (other.marked_for_strip)
+ 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)
{}
- PathInExpression &operator= (const PathInExpression &other)
- {
- outer_attrs = other.outer_attrs;
- has_opening_scope_resolution = other.has_opening_scope_resolution;
- locus = other.locus;
- _node_id = other._node_id;
- path = other.path->clone_path ();
- marked_for_strip = other.marked_for_strip;
-
- return *this;
- }
-
// 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.
- bool is_error () const
- {
- // FIXME: Cleanup
- if (path->get_path_kind () == Path::Kind::Regular)
- return !static_cast<RegularPath &> (*path).has_segments ();
-
- return false;
- }
+ bool is_error () const { return !has_segments (); }
/* Converts PathInExpression to SimplePath if possible (i.e. no generic
* arguments). Otherwise returns an empty SimplePath. */
SimplePath as_simple_path () const
{
- // FIXME: Cleanup
- if (path->get_path_kind () == Path::Kind::Regular)
- return static_cast<RegularPath &> (*path).convert_to_simple_path (
- has_opening_scope_resolution);
- else
- // FIXME: lang item to simple path?
- rust_unreachable ();
+ /* delegate to parent class as can't access segments. however,
+ * QualifiedPathInExpression conversion to simple path wouldn't make
+ * sense, so the method in the parent class should be protected, not
+ * public. Have to pass in opening scope resolution as parent class has no
+ * access to it.
+ */
+ return convert_to_simple_path (has_opening_scope_resolution);
}
location_t get_locus () const override final { return locus; }
@@ -771,63 +717,18 @@ public:
outer_attrs = std::move (new_attrs);
}
- NodeId get_pattern_node_id () const { return get_node_id (); }
-
- PathExprSegment &get_final_segment ()
- {
- if (path->get_path_kind () == Path::Kind::Regular)
- return static_cast<RegularPath &> (*path).get_segments ().back ();
-
- // lang item segment?
- rust_unreachable ();
- }
-
+ PathExprSegment &get_final_segment () { return get_segments ().back (); }
const PathExprSegment &get_final_segment () const
{
- if (path->get_path_kind () == Path::Kind::Regular)
- return static_cast<RegularPath &> (*path).get_segments ().back ();
-
- // lang item segment?
- rust_unreachable ();
+ return get_segments ().back ();
}
- const std::vector<PathExprSegment> &get_segments () const
+ Expr::Kind get_expr_kind () const override
{
- if (path->get_path_kind () == Path::Kind::Regular)
- return static_cast<RegularPath &> (*path).get_segments ();
-
- rust_unreachable ();
+ return Expr::Kind::PathInExpression;
}
- std::vector<PathExprSegment> &get_segments ()
- {
- if (path->get_path_kind () == Path::Kind::Regular)
- return static_cast<RegularPath &> (*path).get_segments ();
-
- rust_unreachable ();
- }
-
- bool is_single_segment () const
- {
- if (path->get_path_kind () == Path::Kind::Regular)
- return static_cast<RegularPath &> (*path).get_segments ().size () == 1;
-
- return false;
- }
-
- Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
-
protected:
- PathInExpression (std::vector<Attribute> &&outer_attrs,
- bool has_opening_scope_resolution, location_t locus,
- NodeId node_id, std::unique_ptr<Path> &&path,
- bool marked_for_strip)
- : outer_attrs (std::move (outer_attrs)),
- has_opening_scope_resolution (has_opening_scope_resolution),
- locus (locus), _node_id (node_id), path (std::move (path)),
- marked_for_strip (marked_for_strip)
- {}
-
/* Use covariance to implement clone function as returning this object
* rather than base */
PathInExpression *clone_pattern_impl () const final override
@@ -861,7 +762,8 @@ public:
};
private:
- PathIdentSegment ident_segment;
+ tl::optional<LangItem::Kind> lang_item;
+ tl::optional<PathIdentSegment> ident_segment;
location_t locus;
protected:
@@ -891,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 ())
{}
+ 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 ())
{}
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)
{}
@@ -913,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;
@@ -923,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
@@ -943,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 ();
}
};
@@ -984,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,
@@ -1041,7 +989,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;
@@ -1074,8 +1022,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)
{}
@@ -1120,11 +1068,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 ()
@@ -1188,11 +1136,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:
@@ -1217,12 +1164,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),
@@ -1268,15 +1223,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;
}
@@ -1297,9 +1256,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
@@ -1376,12 +1334,12 @@ public:
/* AST node representing a qualified path-in-expression pattern (path that
* allows specifying trait functions) */
-class QualifiedPathInExpression : public Pattern, public ExprWithoutBlock
+class QualifiedPathInExpression : public Path, public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
QualifiedPathType path_type;
-
- std::unique_ptr<Path> path;
+ location_t locus;
+ NodeId _node_id;
public:
std::string as_string () const override;
@@ -1390,16 +1348,9 @@ public:
std::vector<PathExprSegment> path_segments,
std::vector<Attribute> outer_attrs,
location_t locus)
- : outer_attrs (std::move (outer_attrs)),
- path_type (std::move (qual_path_type)),
- path (Rust::make_unique<RegularPath> (
- std::move (path_segments), locus,
- Analysis::Mappings::get ().get_next_node_id ()))
- {}
-
- QualifiedPathInExpression (const QualifiedPathInExpression &other)
- : outer_attrs (other.outer_attrs), path_type (other.path_type),
- path (other.path->clone_path ())
+ : 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 ())
{}
/* TODO: maybe make a shortcut constructor that has QualifiedPathType
@@ -1415,9 +1366,7 @@ public:
{}, UNDEF_LOCATION);
}
- Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
-
- location_t get_locus () const override final { return path->get_locus (); }
+ location_t get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
@@ -1443,30 +1392,11 @@ public:
outer_attrs = std::move (new_attrs);
}
- NodeId get_node_id () const override { return path->get_node_id (); }
-
- const std::vector<PathExprSegment> &get_segments () const
- {
- if (path->get_path_kind () == Path::Kind::Regular)
- return static_cast<RegularPath &> (*path).get_segments ();
-
- rust_unreachable ();
- }
-
- std::vector<PathExprSegment> &get_segments ()
- {
- if (path->get_path_kind () == Path::Kind::Regular)
- return static_cast<RegularPath &> (*path).get_segments ();
-
- rust_unreachable ();
- }
+ NodeId get_node_id () const override { return _node_id; }
- bool is_single_segment () const
+ Expr::Kind get_expr_kind () const override
{
- if (path->get_path_kind () == Path::Kind::Regular)
- return static_cast<RegularPath &> (*path).get_segments ().size () == 1;
-
- return false;
+ return Expr::Kind::QualifiedPathInExpression;
}
protected:
@@ -1498,7 +1428,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:
@@ -1513,7 +1443,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)),
@@ -1560,7 +1490,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;
@@ -1580,11 +1510,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 98fd8e5..fc7b610 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"
diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h
index e8aec34..f843a79 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 20e0232..1bb521d 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -542,7 +542,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;
@@ -553,11 +553,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)
{}
@@ -598,7 +599,8 @@ 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; }