diff --git a/.gitignore b/.gitignore
index 7150fc3b29ca..f044fe16b5f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -71,6 +71,3 @@ stamp-*
/gmp*
/isl*
/gettext*
-
-# ADDITIONS from GCCRS front-end
-libgrust/*/target/
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 835e113aee2c..c7846892d895 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -81,6 +81,7 @@ GRS_OBJS = \
rust/rust-ast-dump.o \
rust/rust-ast-collector.o \
rust/rust-ast-visitor.o \
+ rust/rust-hir-visitor.o \
rust/rust-hir-dump.o \
rust/rust-session-manager.o \
rust/rust-compile.o \
@@ -92,14 +93,15 @@ GRS_OBJS = \
rust/rust-cfg-strip.o \
rust/rust-expand-visitor.o \
rust/rust-ast-builder.o \
- rust/rust-ast-builder-type.o \
rust/rust-derive.o \
+ rust/rust-derive-cmp-common.o \
rust/rust-derive-clone.o \
rust/rust-derive-copy.o \
rust/rust-derive-debug.o \
rust/rust-derive-default.o \
rust/rust-derive-partial-eq.o \
rust/rust-derive-eq.o \
+ rust/rust-derive-ord.o \
rust/rust-derive-hash.o \
rust/rust-proc-macro.o \
rust/rust-macro-invoc-lexer.o \
@@ -123,7 +125,6 @@ GRS_OBJS = \
rust/rust-keyword-values.o \
rust/rust-abi.o \
rust/rust-token-converter.o \
- rust/rust-macro.o \
rust/rust-ast-lower.o \
rust/rust-ast-lower-base.o \
rust/rust-ast-lower-pattern.o \
@@ -237,11 +238,13 @@ GRS_OBJS = \
rust/rust-punycode.o \
rust/rust-unwrap-segment.o \
rust/rust-edition.o \
+ rust/rust-ggc.o \
rust/rust-expand-format-args.o \
rust/rust-lang-item.o \
rust/rust-collect-lang-items.o \
rust/rust-desugar-for-loops.o \
rust/rust-desugar-question-mark.o \
+ rust/rust-desugar-apit.o \
$(END)
# removed object files from here
diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc
deleted file mode 100644
index 13126b440571..000000000000
--- a/gcc/rust/ast/rust-ast-builder-type.cc
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright (C) 2020-2024 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// .
-
-#include "rust-ast-builder-type.h"
-#include "rust-ast-builder.h"
-#include "rust-ast-full.h"
-#include "rust-common.h"
-
-namespace Rust {
-namespace AST {
-
-ASTTypeBuilder::ASTTypeBuilder () : translated (nullptr) {}
-
-Type *
-ASTTypeBuilder::build (Type &type)
-{
- ASTTypeBuilder builder;
- type.accept_vis (builder);
- rust_assert (builder.translated != nullptr);
- return builder.translated;
-}
-
-void
-ASTTypeBuilder::visit (BareFunctionType &fntype)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (TupleType &tuple)
-{
- std::vector > elems;
- for (auto &elem : tuple.get_elems ())
- {
- Type *t = ASTTypeBuilder::build (*elem.get ());
- std::unique_ptr ty (t);
- elems.push_back (std::move (ty));
- }
- translated = new TupleType (std::move (elems), tuple.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (TypePath &path)
-{
- std::vector > segments;
- for (auto &seg : path.get_segments ())
- {
- switch (seg->get_type ())
- {
- case TypePathSegment::REG: {
- const TypePathSegment &segment
- = (const TypePathSegment &) (*seg.get ());
- TypePathSegment *s
- = new TypePathSegment (segment.get_ident_segment (),
- segment.get_separating_scope_resolution (),
- segment.get_locus ());
- std::unique_ptr sg (s);
- segments.push_back (std::move (sg));
- }
- break;
-
- case TypePathSegment::GENERIC: {
- TypePathSegmentGeneric &generic
- = (TypePathSegmentGeneric &) (*seg.get ());
-
- GenericArgs args
- = Builder::new_generic_args (generic.get_generic_args ());
- TypePathSegmentGeneric *s
- = new TypePathSegmentGeneric (generic.get_ident_segment (), false,
- std::move (args),
- generic.get_locus ());
- std::unique_ptr sg (s);
- segments.push_back (std::move (sg));
- }
- break;
-
- case TypePathSegment::FUNCTION: {
- rust_unreachable ();
- // TODO
- // const TypePathSegmentFunction &fn
- // = (const TypePathSegmentFunction &) (*seg.get ());
- }
- break;
- }
- }
-
- translated = new TypePath (std::move (segments), path.get_locus (),
- path.has_opening_scope_resolution_op ());
-}
-
-void
-ASTTypeBuilder::visit (QualifiedPathInType &path)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (ArrayType &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (ReferenceType &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (RawPointerType &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (SliceType &type)
-{
- Type *t = ASTTypeBuilder::build (type.get_elem_type ());
- std::unique_ptr ty (t);
- translated = new SliceType (std::move (ty), type.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (InferredType &type)
-{
- translated = new InferredType (type.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (NeverType &type)
-{
- translated = new NeverType (type.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (TraitObjectTypeOneBound &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (TraitObjectType &type)
-{
- /* TODO */
-}
-
-} // namespace AST
-} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-builder-type.h b/gcc/rust/ast/rust-ast-builder-type.h
deleted file mode 100644
index b67ae3b553ff..000000000000
--- a/gcc/rust/ast/rust-ast-builder-type.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (C) 2020-2024 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// .
-
-#ifndef RUST_AST_BUILDER_TYPE
-#define RUST_AST_BUILDER_TYPE
-
-#include "rust-ast-visitor.h"
-
-namespace Rust {
-namespace AST {
-
-class ASTTypeBuilder : public DefaultASTVisitor
-{
-protected:
- using DefaultASTVisitor::visit;
-
-public:
- static Type *build (Type &type);
-
- void visit (BareFunctionType &fntype) override;
- void visit (TupleType &tuple) override;
- void visit (TypePath &path) override;
- void visit (QualifiedPathInType &path) override;
- void visit (ArrayType &type) override;
- void visit (ReferenceType &type) override;
- void visit (RawPointerType &type) override;
- void visit (SliceType &type) override;
- void visit (InferredType &type) override;
- void visit (NeverType &type) override;
- void visit (TraitObjectTypeOneBound &type) override;
- void visit (TraitObjectType &type) override;
-
-private:
- ASTTypeBuilder ();
-
- Type *translated;
-};
-
-} // namespace AST
-} // namespace Rust
-
-#endif // RUST_AST_BUILDER_TYPE
diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc
index 08c52b155c44..ed10ce7f9a18 100644
--- a/gcc/rust/ast/rust-ast-builder.cc
+++ b/gcc/rust/ast/rust-ast-builder.cc
@@ -18,7 +18,6 @@
#include "rust-ast-builder.h"
#include "optional.h"
-#include "rust-ast-builder-type.h"
#include "rust-ast.h"
#include "rust-common.h"
#include "rust-expr.h"
@@ -29,7 +28,6 @@
#include "rust-pattern.h"
#include "rust-system.h"
#include "rust-token.h"
-#include
namespace Rust {
namespace AST {
@@ -331,6 +329,12 @@ Builder::block () const
return block (std::move (stmts));
}
+std::unique_ptr
+Builder::block (std::unique_ptr &&tail_expr) const
+{
+ return block (tl::nullopt, std::move (tail_expr));
+}
+
std::unique_ptr
Builder::block (std::vector> &&stmts,
std::unique_ptr &&tail_expr) const
@@ -442,6 +446,14 @@ Builder::field_access (std::unique_ptr &&instance,
new FieldAccessExpr (std::move (instance), field, {}, loc));
}
+std::unique_ptr
+Builder::struct_pattern_ident_pattern (std::string field_name,
+ std::unique_ptr &&pattern)
+{
+ return std::make_unique (
+ field_name, std::move (pattern), std::vector (), loc);
+}
+
std::unique_ptr
Builder::wildcard () const
{
@@ -482,9 +494,14 @@ MatchCase
Builder::match_case (std::unique_ptr &&pattern,
std::unique_ptr &&expr)
{
- return MatchCase (match_arm (std::move (pattern)), std::move (expr));
+ return match_case (match_arm (std::move (pattern)), std::move (expr));
}
+MatchCase
+Builder::match_case (MatchArm &&arm, std::unique_ptr &&expr)
+{
+ return MatchCase (std::move (arm), std::move (expr));
+}
std::unique_ptr
Builder::loop (std::vector> &&stmts)
{
@@ -523,11 +540,14 @@ Builder::generic_type_param (
std::vector ());
}
-std::unique_ptr
-Builder::new_type (Type &type)
+std::unique_ptr
+Builder::discriminant_value (std::string binding_name, std::string instance)
{
- Type *t = ASTTypeBuilder::build (type);
- return std::unique_ptr (t);
+ auto intrinsic = ptrify (
+ path_in_expression ({"core", "intrinsics", "discriminant_value"}, true));
+
+ return let (identifier_pattern (binding_name), nullptr,
+ call (std::move (intrinsic), identifier (instance)));
}
std::unique_ptr
@@ -546,6 +566,16 @@ Builder::new_lifetime_param (LifetimeParam ¶m)
return std::unique_ptr (p);
}
+std::unique_ptr
+Builder::new_const_param (ConstGenericParam ¶m) const
+{
+ return std::make_unique (param.get_name (),
+ param.get_type ().clone_type (),
+ param.get_default_value (),
+ param.get_outer_attrs (),
+ param.get_locus ());
+}
+
std::unique_ptr
Builder::new_type_param (
TypeParam ¶m, std::vector> extra_bounds)
@@ -557,7 +587,7 @@ Builder::new_type_param (
std::unique_ptr type = nullptr;
if (param.has_type ())
- type = new_type (param.get_type ());
+ type = param.get_type ().reconstruct ();
for (auto &&extra_bound : extra_bounds)
type_param_bounds.emplace_back (std::move (extra_bound));
@@ -566,7 +596,8 @@ Builder::new_type_param (
{
switch (b->get_bound_type ())
{
- case TypeParamBound::TypeParamBoundType::TRAIT: {
+ case TypeParamBound::TypeParamBoundType::TRAIT:
+ {
const TraitBound &tb = (const TraitBound &) *b.get ();
const TypePath &path = tb.get_type_path ();
@@ -591,7 +622,8 @@ Builder::new_type_param (
{
switch (seg->get_type ())
{
- case TypePathSegment::REG: {
+ case TypePathSegment::REG:
+ {
const TypePathSegment &segment
= (const TypePathSegment &) (*seg.get ());
TypePathSegment *s = new TypePathSegment (
@@ -603,7 +635,8 @@ Builder::new_type_param (
}
break;
- case TypePathSegment::GENERIC: {
+ case TypePathSegment::GENERIC:
+ {
TypePathSegmentGeneric &generic
= (TypePathSegmentGeneric &) (*seg.get ());
@@ -617,7 +650,8 @@ Builder::new_type_param (
}
break;
- case TypePathSegment::FUNCTION: {
+ case TypePathSegment::FUNCTION:
+ {
rust_unreachable ();
// TODO
// const TypePathSegmentFunction &fn
@@ -639,7 +673,8 @@ Builder::new_type_param (
}
break;
- case TypeParamBound::TypeParamBoundType::LIFETIME: {
+ case TypeParamBound::TypeParamBoundType::LIFETIME:
+ {
const Lifetime &l = (const Lifetime &) *b.get ();
auto bl = new Lifetime (l.get_lifetime_type (),
@@ -682,7 +717,7 @@ Builder::new_generic_args (GenericArgs &args)
for (auto &binding : args.get_binding_args ())
{
Type &t = *binding.get_type_ptr ().get ();
- std::unique_ptr ty = new_type (t);
+ std::unique_ptr ty = t.reconstruct ();
GenericArgsBinding b (binding.get_identifier (), std::move (ty),
binding.get_locus ());
binding_args.push_back (std::move (b));
@@ -690,19 +725,25 @@ Builder::new_generic_args (GenericArgs &args)
for (auto &arg : args.get_generic_args ())
{
+ tl::optional new_arg = tl::nullopt;
+
switch (arg.get_kind ())
{
- case GenericArg::Kind::Type: {
- std::unique_ptr ty = new_type (arg.get_type ());
- GenericArg arg = GenericArg::create_type (std::move (ty));
- }
+ case GenericArg::Kind::Type:
+ new_arg = GenericArg::create_type (arg.get_type ().reconstruct ());
break;
-
- default:
- // FIXME
- rust_unreachable ();
+ case GenericArg::Kind::Either:
+ new_arg
+ = GenericArg::create_ambiguous (arg.get_path (), arg.get_locus ());
+ break;
+ case GenericArg::Kind::Const:
+ new_arg
+ = GenericArg::create_const (arg.get_expression ().clone_expr ());
+ // FIXME: Use `reconstruct()` here, not `clone_expr()`
break;
}
+
+ generic_args.emplace_back (*new_arg);
}
return GenericArgs (std::move (lifetime_args), std::move (generic_args),
diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h
index 41ce118e7714..843bab896c74 100644
--- a/gcc/rust/ast/rust-ast-builder.h
+++ b/gcc/rust/ast/rust-ast-builder.h
@@ -24,6 +24,7 @@
#include "rust-ast.h"
#include "rust-item.h"
#include "rust-operators.h"
+#include
namespace Rust {
namespace AST {
@@ -51,6 +52,19 @@ vec (std::unique_ptr &&t1, std::unique_ptr &&t2)
return v;
}
+template
+std::vector>
+vec (std::unique_ptr &&t1, std::unique_ptr &&t2, std::unique_ptr &&t3)
+{
+ auto v = std::vector> ();
+
+ v.emplace_back (std::move (t1));
+ v.emplace_back (std::move (t2));
+ v.emplace_back (std::move (t3));
+
+ return v;
+}
+
/* Pointer-ify something */
template
static std::unique_ptr
@@ -117,6 +131,9 @@ class Builder
/* Create an empty block */
std::unique_ptr block () const;
+ /* Create a block with just a tail expression */
+ std::unique_ptr block (std::unique_ptr &&tail_expr) const;
+
/* Create an early return expression with an optional expression */
std::unique_ptr return_expr (std::unique_ptr &&to_return
= nullptr);
@@ -254,6 +271,10 @@ class Builder
std::unique_ptr field_access (std::unique_ptr &&instance,
std::string field) const;
+ std::unique_ptr
+ struct_pattern_ident_pattern (std::string field_name,
+ std::unique_ptr &&pattern);
+
/* Create a wildcard pattern (`_`) */
std::unique_ptr wildcard () const;
/* Create a reference pattern (`&pattern`) */
@@ -268,6 +289,7 @@ class Builder
MatchArm match_arm (std::unique_ptr &&pattern);
MatchCase match_case (std::unique_ptr &&pattern,
std::unique_ptr &&expr);
+ MatchCase match_case (MatchArm &&arm, std::unique_ptr &&expr);
/* Create a loop expression */
std::unique_ptr loop (std::vector> &&stmts);
@@ -285,11 +307,20 @@ class Builder
std::vector> &&bounds,
std::unique_ptr &&type = nullptr);
- static std::unique_ptr new_type (Type &type);
+ /**
+ * Create a let statement with the discriminant value of a given enum
+ * instance. This helper exists since it is a common operation in a lot of the
+ * derive implementations, and it sucks to repeat all the steps every time.
+ */
+ std::unique_ptr discriminant_value (std::string binding_name,
+ std::string instance = "self");
static std::unique_ptr
new_lifetime_param (LifetimeParam ¶m);
+ std::unique_ptr
+ new_const_param (ConstGenericParam ¶m) const;
+
static std::unique_ptr new_type_param (
TypeParam ¶m,
std::vector> extra_trait_bounds = {});
@@ -298,11 +329,13 @@ class Builder
static GenericArgs new_generic_args (GenericArgs &args);
-private:
- /**
- * Location of the generated AST nodes
- */
+ /* Location of the generated AST nodes */
location_t loc;
+
+private:
+ /* Some constexpr helpers for some of the builders */
+ static constexpr std::initializer_list discriminant_value_path
+ = {"core", "intrinsics", "discriminant_value"};
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index c850e965cf4d..4fe246d7a3ad 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -154,20 +154,24 @@ TokenCollector::visit (Attribute &attrib)
{
switch (attrib.get_attr_input ().get_attr_input_type ())
{
- case AST::AttrInput::AttrInputType::LITERAL: {
+ case AST::AttrInput::AttrInputType::LITERAL:
+ {
visit (static_cast (attrib.get_attr_input ()));
break;
}
- case AST::AttrInput::AttrInputType::MACRO: {
+ case AST::AttrInput::AttrInputType::MACRO:
+ {
visit (static_cast (attrib.get_attr_input ()));
break;
}
- case AST::AttrInput::AttrInputType::META_ITEM: {
+ case AST::AttrInput::AttrInputType::META_ITEM:
+ {
visit (static_cast (
attrib.get_attr_input ()));
break;
}
- case AST::AttrInput::AttrInputType::TOKEN_TREE: {
+ case AST::AttrInput::AttrInputType::TOKEN_TREE:
+ {
visit (static_cast (attrib.get_attr_input ()));
break;
}
@@ -634,7 +638,8 @@ TokenCollector::visit (GenericArg &arg)
case GenericArg::Kind::Type:
visit (arg.get_type ());
break;
- case GenericArg::Kind::Either: {
+ case GenericArg::Kind::Either:
+ {
auto path = arg.get_path ();
push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path)));
}
@@ -789,7 +794,8 @@ TokenCollector::visit (Literal &lit, location_t locus)
push (Rust::Token::make_float (locus, std::move (value),
lit.get_type_hint ()));
break;
- case Literal::LitType::BOOL: {
+ case Literal::LitType::BOOL:
+ {
if (value == Values::Keywords::FALSE_LITERAL)
push (Rust::Token::make (FALSE_LITERAL, locus));
else if (value == Values::Keywords::TRUE_LITERAL)
@@ -864,7 +870,8 @@ TokenCollector::visit (BorrowExpr &expr)
push (Rust::Token::make (MUT, UNDEF_LOCATION));
}
- visit (expr.get_borrowed_expr ());
+ if (expr.has_borrow_expr ())
+ visit (expr.get_borrowed_expr ());
}
void
@@ -1263,13 +1270,29 @@ TokenCollector::visit (BlockExpr &expr)
newline ();
}
+void
+TokenCollector::visit (AnonConst &expr)
+{
+ visit (expr.get_inner_expr ());
+}
+
+void
+TokenCollector::visit (ConstBlock &expr)
+{
+ push (Rust::Token::make (CONST, expr.get_locus ()));
+
+ // The inner expression is already a block expr, so we don't need to add
+ // curlies
+ visit (expr.get_const_expr ());
+}
+
void
TokenCollector::visit (ClosureExprInnerTyped &expr)
{
visit_closure_common (expr);
push (Rust::Token::make (RETURN_TYPE, expr.get_locus ()));
visit (expr.get_return_type ());
- visit (expr.get_definition_block ());
+ visit (expr.get_definition_expr ());
}
void
@@ -1348,6 +1371,13 @@ TokenCollector::visit (ReturnExpr &expr)
visit (expr.get_returned_expr ());
}
+void
+TokenCollector::visit (TryExpr &expr)
+{
+ push (Rust::Token::make (TRY, expr.get_locus ()));
+ visit (expr.get_block_expr ());
+}
+
void
TokenCollector::visit (UnsafeBlockExpr &expr)
{
@@ -1518,7 +1548,95 @@ TokenCollector::visit (AsyncBlockExpr &expr)
void
TokenCollector::visit (InlineAsm &expr)
-{}
+{
+ push (Rust::Token::make_identifier (expr.get_locus (), "asm"));
+ push (Rust::Token::make (EXCLAM, expr.get_locus ()));
+ push (Rust::Token::make (LEFT_PAREN, expr.get_locus ()));
+
+ for (auto &template_str : expr.get_template_strs ())
+ push (Rust::Token::make_string (template_str.get_locus (),
+ std::move (template_str.symbol)));
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+
+ for (auto &operand : expr.get_operands ())
+ {
+ using RegisterType = AST::InlineAsmOperand::RegisterType;
+ switch (operand.get_register_type ())
+ {
+ case RegisterType::In:
+ {
+ visit (operand.get_in ().expr);
+ break;
+ }
+ case RegisterType::Out:
+ {
+ visit (operand.get_out ().expr);
+ break;
+ }
+ case RegisterType::InOut:
+ {
+ visit (operand.get_in_out ().expr);
+ break;
+ }
+ case RegisterType::SplitInOut:
+ {
+ auto split = operand.get_split_in_out ();
+ visit (split.in_expr);
+ visit (split.out_expr);
+ break;
+ }
+ case RegisterType::Const:
+ {
+ visit (operand.get_const ().anon_const.get_inner_expr ());
+ break;
+ }
+ case RegisterType::Sym:
+ {
+ visit (operand.get_sym ().expr);
+ break;
+ }
+ case RegisterType::Label:
+ {
+ visit (operand.get_label ().expr);
+ break;
+ }
+ }
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+
+ for (auto &clobber : expr.get_clobber_abi ())
+ {
+ push (Rust::Token::make_string (expr.get_locus (),
+ std::move (clobber.symbol)));
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+
+ for (auto it = expr.named_args.begin (); it != expr.named_args.end (); ++it)
+ {
+ auto &arg = *it;
+ push (
+ Rust::Token::make_identifier (expr.get_locus (), arg.first.c_str ()));
+ push (Rust::Token::make (EQUAL, expr.get_locus ()));
+ push (Rust::Token::make_identifier (expr.get_locus (),
+ std::to_string (arg.second)));
+
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+
+ for (auto &option : expr.get_options ())
+ {
+ push (Rust::Token::make_identifier (
+ expr.get_locus (), InlineAsm::option_to_string (option).c_str ()));
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+
+ push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ()));
+}
void
TokenCollector::visit (LlvmInlineAsm &expr)
@@ -1695,7 +1813,8 @@ TokenCollector::visit (UseTreeGlob &use_tree)
{
switch (use_tree.get_glob_type ())
{
- case UseTreeGlob::PathType::PATH_PREFIXED: {
+ case UseTreeGlob::PathType::PATH_PREFIXED:
+ {
auto path = use_tree.get_path ();
visit (path);
push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
@@ -1715,7 +1834,8 @@ TokenCollector::visit (UseTreeList &use_tree)
{
switch (use_tree.get_path_type ())
{
- case UseTreeList::PathType::PATH_PREFIXED: {
+ case UseTreeList::PathType::PATH_PREFIXED:
+ {
auto path = use_tree.get_path ();
visit (path);
push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
@@ -1743,7 +1863,8 @@ TokenCollector::visit (UseTreeRebind &use_tree)
visit (path);
switch (use_tree.get_new_bind_type ())
{
- case UseTreeRebind::NewBindType::IDENTIFIER: {
+ case UseTreeRebind::NewBindType::IDENTIFIER:
+ {
push (Rust::Token::make (AS, UNDEF_LOCATION));
auto id = use_tree.get_identifier ().as_string ();
push (
@@ -1964,8 +2085,7 @@ TokenCollector::visit (ConstantItem &item)
}
else
{
- auto id = item.get_identifier ();
- push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
+ push (Rust::Token::make_identifier (item.get_identifier ()));
}
push (Rust::Token::make (COLON, UNDEF_LOCATION));
visit (item.get_type ());
@@ -2370,10 +2490,10 @@ TokenCollector::visit (IdentifierPattern &pattern)
auto id = pattern.get_ident ().as_string ();
push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
- if (pattern.has_pattern_to_bind ())
+ if (pattern.has_subpattern ())
{
push (Rust::Token::make (PATTERN_BIND, UNDEF_LOCATION));
- visit (pattern.get_pattern_to_bind ());
+ visit (pattern.get_subpattern ());
}
}
diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h
index f45e3cc51aee..e8af5878a2cd 100644
--- a/gcc/rust/ast/rust-ast-collector.h
+++ b/gcc/rust/ast/rust-ast-collector.h
@@ -277,6 +277,8 @@ class TokenCollector : public ASTVisitor
void visit (ClosureParam ¶m);
void visit (ClosureExprInner &expr);
void visit (BlockExpr &expr);
+ void visit (AnonConst &expr);
+ void visit (ConstBlock &expr);
void visit (ClosureExprInnerTyped &expr);
void visit (ContinueExpr &expr);
void visit (BreakExpr &expr);
@@ -287,6 +289,7 @@ class TokenCollector : public ASTVisitor
void visit (RangeFromToInclExpr &expr);
void visit (RangeToInclExpr &expr);
void visit (ReturnExpr &expr);
+ void visit (TryExpr &expr);
void visit (BoxExpr &expr);
void visit (UnsafeBlockExpr &expr);
void visit (LoopExpr &expr);
diff --git a/gcc/rust/ast/rust-ast-dump.h b/gcc/rust/ast/rust-ast-dump.h
index 02c99b7ae1ec..0c3875e28233 100644
--- a/gcc/rust/ast/rust-ast-dump.h
+++ b/gcc/rust/ast/rust-ast-dump.h
@@ -49,7 +49,8 @@ class Dump
{
switch (item.get_kind ())
{
- case AST::CollectItem::Kind::Token: {
+ case AST::CollectItem::Kind::Token:
+ {
TokenPtr current = item.get_token ();
if (require_spacing (previous, current))
stream << " ";
@@ -90,7 +91,6 @@ class Dump
} // namespace Rust
// In the global namespace to make it easier to call from debugger
-void
-debug (Rust::AST::Visitable &v);
+void debug (Rust::AST::Visitable &v);
#endif // !RUST_AST_DUMP_H
diff --git a/gcc/rust/ast/rust-ast-formatting.h b/gcc/rust/ast/rust-ast-formatting.h
index 3dfabbcccc60..aace93f7fae8 100644
--- a/gcc/rust/ast/rust-ast-formatting.h
+++ b/gcc/rust/ast/rust-ast-formatting.h
@@ -35,23 +35,18 @@ enum AttrMode
INNER
};
-std::string
-indent_spaces (enum indent_mode mode);
+std::string indent_spaces (enum indent_mode mode);
// Gets a string in a certain delim type.
-std::string
-get_string_in_delims (std::string str_input, DelimType delim_type);
+std::string get_string_in_delims (std::string str_input, DelimType delim_type);
-std::string
-get_mode_dump_desc (AttrMode mode);
+std::string get_mode_dump_desc (AttrMode mode);
// Adds lines below adding attributes
-std::string
-append_attributes (std::vector attrs, AttrMode mode);
+std::string append_attributes (std::vector attrs, AttrMode mode);
// Removes the beginning and end quotes of a quoted string.
-std::string
-unquote_string (std::string input);
+std::string unquote_string (std::string input);
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h
index 9359248aabd5..eb1f3ea890c7 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -115,6 +115,8 @@ struct ClosureParam;
class ClosureExpr;
class ClosureExprInner;
class BlockExpr;
+class AnonConst;
+class ConstBlock;
class ClosureExprInnerTyped;
class ContinueExpr;
class BreakExpr;
@@ -126,6 +128,7 @@ class RangeFullExpr;
class RangeFromToInclExpr;
class RangeToInclExpr;
class ReturnExpr;
+class TryExpr;
class UnsafeBlockExpr;
class LoopLabel;
class BaseLoopExpr;
@@ -146,7 +149,6 @@ class MatchExpr;
class AwaitExpr;
class AsyncBlockExpr;
enum class InlineAsmOption;
-struct AnonConst;
struct InlineAsmRegOrRegClass;
class InlineAsmOperand;
struct InlineAsmPlaceHolder;
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index b6833f69314e..32d5d32e43fe 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -455,6 +455,19 @@ DefaultASTVisitor::visit (AST::BlockExpr &expr)
visit (expr.get_tail_expr ());
}
+void
+DefaultASTVisitor::visit (AST::ConstBlock &expr)
+{
+ visit (expr.get_const_expr ());
+}
+
+void
+DefaultASTVisitor::visit (AST::AnonConst &expr)
+{
+ if (!expr.is_deferred ())
+ visit (expr.get_inner_expr ());
+}
+
void
DefaultASTVisitor::visit (AST::ClosureExprInnerTyped &expr)
{
@@ -462,7 +475,7 @@ DefaultASTVisitor::visit (AST::ClosureExprInnerTyped &expr)
for (auto ¶m : expr.get_params ())
visit (param);
visit (expr.get_return_type ());
- visit (expr.get_definition_block ());
+ visit (expr.get_definition_expr ());
}
void
@@ -537,6 +550,13 @@ DefaultASTVisitor::visit (AST::ReturnExpr &expr)
visit (expr.get_returned_expr ());
}
+void
+DefaultASTVisitor::visit (AST::TryExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit (expr.get_block_expr ());
+}
+
void
DefaultASTVisitor::visit (AST::BoxExpr &expr)
{
@@ -582,7 +602,10 @@ DefaultASTVisitor::visit (AST::WhileLetLoopExpr &expr)
visit_outer_attrs (expr);
for (auto &pattern : expr.get_patterns ())
visit (pattern);
- visit (expr.get_loop_label ());
+
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
+
visit (expr.get_scrutinee_expr ());
visit (expr.get_loop_block ());
}
@@ -680,33 +703,40 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr)
{
switch (operand.get_register_type ())
{
- case RegisterType::In: {
+ case RegisterType::In:
+ {
visit (operand.get_in ().expr);
break;
}
- case RegisterType::Out: {
+ case RegisterType::Out:
+ {
visit (operand.get_out ().expr);
break;
}
- case RegisterType::InOut: {
+ case RegisterType::InOut:
+ {
visit (operand.get_in_out ().expr);
break;
}
- case RegisterType::SplitInOut: {
+ case RegisterType::SplitInOut:
+ {
auto split = operand.get_split_in_out ();
visit (split.in_expr);
visit (split.out_expr);
break;
}
- case RegisterType::Const: {
- visit (operand.get_const ().anon_const.expr);
+ case RegisterType::Const:
+ {
+ visit (operand.get_const ().anon_const.get_inner_expr ());
break;
}
- case RegisterType::Sym: {
+ case RegisterType::Sym:
+ {
visit (operand.get_sym ().expr);
break;
}
- case RegisterType::Label: {
+ case RegisterType::Label:
+ {
visit (operand.get_label ().expr);
break;
}
@@ -755,7 +785,8 @@ DefaultASTVisitor::visit (AST::TypeBoundWhereClauseItem &item)
void
DefaultASTVisitor::visit (AST::Visibility &vis)
{
- visit (vis.get_path ());
+ if (vis.has_path ())
+ visit (vis.get_path ());
}
void
@@ -922,7 +953,7 @@ DefaultASTVisitor::visit (AST::EnumItem &item)
void
DefaultASTVisitor::visit (AST::EnumItemTuple &item)
{
- visit (reinterpret_cast (item));
+ DefaultASTVisitor::visit (static_cast (item));
for (auto &field : item.get_tuple_fields ())
visit (field);
}
@@ -930,7 +961,7 @@ DefaultASTVisitor::visit (AST::EnumItemTuple &item)
void
DefaultASTVisitor::visit (AST::EnumItemStruct &item)
{
- visit (reinterpret_cast (item));
+ DefaultASTVisitor::visit (static_cast (item));
for (auto &field : item.get_struct_fields ())
visit (field);
}
@@ -938,7 +969,7 @@ DefaultASTVisitor::visit (AST::EnumItemStruct &item)
void
DefaultASTVisitor::visit (AST::EnumItemDiscriminant &item)
{
- visit (reinterpret_cast (item));
+ DefaultASTVisitor::visit (static_cast (item));
visit (item.get_expr ());
}
@@ -1179,8 +1210,8 @@ DefaultASTVisitor::visit (AST::LiteralPattern &pattern)
void
DefaultASTVisitor::visit (AST::IdentifierPattern &pattern)
{
- if (pattern.has_pattern_to_bind ())
- visit (pattern.get_pattern_to_bind ());
+ if (pattern.has_subpattern ())
+ visit (pattern.get_subpattern ());
}
void
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index b1fc50465a1a..6111b0548edc 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -104,6 +104,8 @@ class ASTVisitor
virtual void visit (FieldAccessExpr &expr) = 0;
virtual void visit (ClosureExprInner &expr) = 0;
virtual void visit (BlockExpr &expr) = 0;
+ virtual void visit (AnonConst &expr) = 0;
+ virtual void visit (ConstBlock &expr) = 0;
virtual void visit (ClosureExprInnerTyped &expr) = 0;
virtual void visit (ContinueExpr &expr) = 0;
virtual void visit (BreakExpr &expr) = 0;
@@ -114,6 +116,7 @@ class ASTVisitor
virtual void visit (RangeFromToInclExpr &expr) = 0;
virtual void visit (RangeToInclExpr &expr) = 0;
virtual void visit (ReturnExpr &expr) = 0;
+ virtual void visit (TryExpr &expr) = 0;
virtual void visit (BoxExpr &expr) = 0;
virtual void visit (UnsafeBlockExpr &expr) = 0;
virtual void visit (LoopExpr &expr) = 0;
@@ -293,6 +296,8 @@ class DefaultASTVisitor : public ASTVisitor
virtual void visit (AST::FieldAccessExpr &expr) override;
virtual void visit (AST::ClosureExprInner &expr) override;
virtual void visit (AST::BlockExpr &expr) override;
+ virtual void visit (AST::AnonConst &expr) override;
+ virtual void visit (AST::ConstBlock &expr) override;
virtual void visit (AST::ClosureExprInnerTyped &expr) override;
virtual void visit (AST::ContinueExpr &expr) override;
virtual void visit (AST::BreakExpr &expr) override;
@@ -303,6 +308,7 @@ class DefaultASTVisitor : public ASTVisitor
virtual void visit (AST::RangeFromToInclExpr &expr) override;
virtual void visit (AST::RangeToInclExpr &expr) override;
virtual void visit (AST::ReturnExpr &expr) override;
+ virtual void visit (AST::TryExpr &expr) override;
virtual void visit (AST::BoxExpr &expr) override;
virtual void visit (AST::UnsafeBlockExpr &expr) override;
virtual void visit (AST::LoopExpr &expr) override;
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 4e82be420fe1..2b7ee5cb8bf0 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "rust-operators.h"
#include "rust-dir-owner.h"
#include "rust-attribute-values.h"
+#include "rust-macro-invoc-lexer.h"
/* Compilation unit used for various AST-related functions that would make
* the headers too long if they were defined inline and don't receive any
@@ -249,27 +250,31 @@ Attribute::get_traits_to_derive ()
auto &input = get_attr_input ();
switch (input.get_attr_input_type ())
{
- case AST::AttrInput::META_ITEM: {
+ case AST::AttrInput::META_ITEM:
+ {
auto &meta = static_cast (input);
for (auto ¤t : meta.get_items ())
{
// HACK: Find a better way to achieve the downcast.
switch (current->get_kind ())
{
- case AST::MetaItemInner::Kind::MetaItem: {
+ case AST::MetaItemInner::Kind::MetaItem:
+ {
// Let raw pointer go out of scope without freeing, it doesn't
// own the data anyway
auto meta_item
= static_cast (current.get ());
switch (meta_item->get_item_kind ())
{
- case AST::MetaItem::ItemKind::Path: {
+ case AST::MetaItem::ItemKind::Path:
+ {
auto path
= static_cast (meta_item);
result.push_back (path->get_path ());
}
break;
- case AST::MetaItem::ItemKind::Word: {
+ case AST::MetaItem::ItemKind::Word:
+ {
auto word = static_cast (meta_item);
// Convert current word to path
current = std::make_unique (
@@ -620,7 +625,7 @@ ConstantItem::as_string () const
{
std::string str = VisItem::as_string ();
- str += "const " + identifier;
+ str += "const " + identifier.as_string ();
// DEBUG: null pointer check
if (type == nullptr)
@@ -782,7 +787,8 @@ UseTreeGlob::as_string () const
return "*";
case GLOBAL:
return "::*";
- case PATH_PREFIXED: {
+ case PATH_PREFIXED:
+ {
std::string path_str = path.as_string ();
return path_str + "::*";
}
@@ -805,7 +811,8 @@ UseTreeList::as_string () const
case GLOBAL:
path_str = "::{";
break;
- case PATH_PREFIXED: {
+ case PATH_PREFIXED:
+ {
path_str = path.as_string () + "::{";
break;
}
@@ -1271,6 +1278,25 @@ BlockExpr::as_string () const
return str;
}
+std::string
+AnonConst::as_string () const
+{
+ std::string str = "AnonConst: ";
+
+ if (kind == AnonConst::Kind::DeferredInference)
+ str += "_";
+ else
+ str += expr.value ()->as_string ();
+
+ return str;
+}
+
+std::string
+ConstBlock::as_string () const
+{
+ return "ConstBlock: " + expr.as_string ();
+}
+
std::string
TraitImpl::as_string () const
{
@@ -1618,6 +1644,19 @@ ReturnExpr::as_string () const
return str;
}
+std::string
+TryExpr::as_string () const
+{
+ /* TODO: find way to incorporate outer attrs - may have to represent in
+ * different style (i.e. something more like BorrowExpr: \n outer attrs) */
+
+ std::string str ("try ");
+
+ str += block_expr->as_string ();
+
+ return str;
+}
+
std::string
RangeToExpr::as_string () const
{
@@ -2714,7 +2753,7 @@ ImplTraitTypeOneBound::as_string () const
{
std::string str ("ImplTraitTypeOneBound: \n TraitBound: ");
- return str + trait_bound.as_string ();
+ return str + trait_bound->as_string ();
}
std::string
@@ -2736,7 +2775,7 @@ std::string
ArrayType::as_string () const
{
// TODO: rewrite to work with non-linearisable types and exprs
- return "[" + elem_type->as_string () + "; " + size->as_string () + "]";
+ return "[" + elem_type->as_string () + "; " + size.as_string () + "]";
}
std::string
@@ -3477,6 +3516,17 @@ DelimTokenTree::parse_to_meta_item () const
return new AttrInputMetaItemContainer (std::move (meta_items));
}
+AttributeParser::AttributeParser (
+ std::vector> token_stream, int stream_start_pos)
+ : lexer (new MacroInvocLexer (std::move (token_stream))),
+ parser (new Parser (*lexer))
+{
+ if (stream_start_pos)
+ lexer->skip_token (stream_start_pos - 1);
+}
+
+AttributeParser::~AttributeParser () {}
+
std::unique_ptr
AttributeParser::parse_meta_item_inner ()
{
@@ -3518,7 +3568,7 @@ AttributeParser::parse_meta_item_inner ()
return parse_path_meta_item ();
}
- auto ident = peek_token ()->as_string ();
+ auto ident = peek_token ()->get_str ();
auto ident_locus = peek_token ()->get_locus ();
if (is_end_meta_item_tok (peek_token (1)->get_id ()))
@@ -3535,17 +3585,14 @@ AttributeParser::parse_meta_item_inner ()
&& is_end_meta_item_tok (peek_token (3)->get_id ()))
{
// meta name value str syntax
- auto &value_tok = peek_token (2);
- auto value = value_tok->as_string ();
+ const_TokenPtr value_tok = peek_token (2);
+ auto value = value_tok->get_str ();
auto locus = value_tok->get_locus ();
skip_token (2);
- // remove the quotes from the string value
- std::string raw_value = unquote_string (std::move (value));
-
return std::unique_ptr (
- new MetaNameValueStr (ident, ident_locus, std::move (raw_value),
+ new MetaNameValueStr (ident, ident_locus, std::move (value),
locus));
}
else
@@ -3653,14 +3700,16 @@ AttributeParser::parse_path_meta_item ()
switch (peek_token ()->get_id ())
{
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
std::vector> meta_items
= parse_meta_item_seq ();
return std::unique_ptr (
new MetaItemSeq (std::move (path), std::move (meta_items)));
}
- case EQUAL: {
+ case EQUAL:
+ {
skip_token ();
location_t locus = peek_token ()->get_locus ();
@@ -3695,7 +3744,6 @@ AttributeParser::parse_path_meta_item ()
std::vector>
AttributeParser::parse_meta_item_seq ()
{
- int vec_length = token_stream.size ();
std::vector> meta_items;
if (peek_token ()->get_id () != LEFT_PAREN)
@@ -3706,7 +3754,8 @@ AttributeParser::parse_meta_item_seq ()
}
skip_token ();
- while (stream_pos < vec_length && peek_token ()->get_id () != RIGHT_PAREN)
+ while (peek_token ()->get_id () != END_OF_FILE
+ && peek_token ()->get_id () != RIGHT_PAREN)
{
std::unique_ptr inner = parse_meta_item_inner ();
if (inner == nullptr)
@@ -3755,33 +3804,32 @@ DelimTokenTree::to_token_stream () const
Literal
AttributeParser::parse_literal ()
{
- const std::unique_ptr &tok = peek_token ();
+ const_TokenPtr tok = peek_token ();
switch (tok->get_id ())
{
case CHAR_LITERAL:
skip_token ();
- return Literal (tok->as_string (), Literal::CHAR, tok->get_type_hint ());
+ return Literal (tok->get_str (), Literal::CHAR, tok->get_type_hint ());
case STRING_LITERAL:
skip_token ();
- return Literal (tok->as_string (), Literal::STRING,
- tok->get_type_hint ());
+ return Literal (tok->get_str (), Literal::STRING, tok->get_type_hint ());
case BYTE_CHAR_LITERAL:
skip_token ();
- return Literal (tok->as_string (), Literal::BYTE, tok->get_type_hint ());
+ return Literal (tok->get_str (), Literal::BYTE, tok->get_type_hint ());
case BYTE_STRING_LITERAL:
skip_token ();
- return Literal (tok->as_string (), Literal::BYTE_STRING,
+ return Literal (tok->get_str (), Literal::BYTE_STRING,
tok->get_type_hint ());
case RAW_STRING_LITERAL:
skip_token ();
- return Literal (tok->as_string (), Literal::RAW_STRING,
+ return Literal (tok->get_str (), Literal::RAW_STRING,
tok->get_type_hint ());
case INT_LITERAL:
skip_token ();
- return Literal (tok->as_string (), Literal::INT, tok->get_type_hint ());
+ return Literal (tok->get_str (), Literal::INT, tok->get_type_hint ());
case FLOAT_LITERAL:
skip_token ();
- return Literal (tok->as_string (), Literal::FLOAT, tok->get_type_hint ());
+ return Literal (tok->get_str (), Literal::FLOAT, tok->get_type_hint ());
case TRUE_LITERAL:
skip_token ();
return Literal ("true", Literal::BOOL, tok->get_type_hint ());
@@ -3839,12 +3887,12 @@ AttributeParser::parse_simple_path ()
SimplePathSegment
AttributeParser::parse_simple_path_segment ()
{
- const std::unique_ptr &tok = peek_token ();
+ const_TokenPtr tok = peek_token ();
switch (tok->get_id ())
{
case IDENTIFIER:
skip_token ();
- return SimplePathSegment (tok->as_string (), tok->get_locus ());
+ return SimplePathSegment (tok->get_str (), tok->get_locus ());
case SUPER:
skip_token ();
return SimplePathSegment ("super", tok->get_locus ());
@@ -3878,6 +3926,18 @@ AttributeParser::parse_meta_item_lit ()
new MetaItemLitExpr (std::move (lit_expr)));
}
+const_TokenPtr
+AttributeParser::peek_token (int i)
+{
+ return lexer->peek_token (i);
+}
+
+void
+AttributeParser::skip_token (int i)
+{
+ lexer->skip_token (i);
+}
+
bool
AttrInputMetaItemContainer::check_cfg_predicate (const Session &session) const
{
@@ -4512,6 +4572,18 @@ BlockExpr::accept_vis (ASTVisitor &vis)
vis.visit (*this);
}
+void
+AnonConst::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ConstBlock::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
void
ClosureExprInnerTyped::accept_vis (ASTVisitor &vis)
{
@@ -4572,6 +4644,12 @@ ReturnExpr::accept_vis (ASTVisitor &vis)
vis.visit (*this);
}
+void
+TryExpr::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
void
UnsafeBlockExpr::accept_vis (ASTVisitor &vis)
{
@@ -5047,7 +5125,8 @@ FormatArgs::get_outer_attrs ()
rust_unreachable ();
}
-void FormatArgs::set_outer_attrs (std::vector)
+void
+FormatArgs::set_outer_attrs (std::vector)
{
rust_unreachable ();
}
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index aa6ad5066aa1..0d853e744c76 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -62,13 +62,14 @@ class Identifier
return ident == other.ident;
}
+ operator const std::string & () const { return ident; }
+
private:
std::string ident;
location_t loc;
};
-std::ostream &
-operator<< (std::ostream &os, Identifier const &i);
+std::ostream &operator<< (std::ostream &os, Identifier const &i);
namespace AST {
// foward decl: ast visitor
@@ -82,6 +83,38 @@ class Visitable
virtual void accept_vis (ASTVisitor &vis) = 0;
};
+/**
+ * Base function for reconstructing and asserting that the new NodeId is
+ * different from the old NodeId. It then wraps the given pointer into a unique
+ * pointer and returns it.
+ */
+template
+std::unique_ptr
+reconstruct_base (const T *instance)
+{
+ auto *reconstructed = instance->reconstruct_impl ();
+
+ rust_assert (reconstructed->get_node_id () != instance->get_node_id ());
+
+ return std::unique_ptr (reconstructed);
+}
+
+/**
+ * Reconstruct multiple items in a vector
+ */
+template
+std::vector>
+reconstruct_vec (const std::vector> &to_reconstruct)
+{
+ std::vector> reconstructed;
+ reconstructed.reserve (to_reconstruct.size ());
+
+ for (const auto &elt : to_reconstruct)
+ reconstructed.emplace_back (std::unique_ptr (elt->reconstruct_impl ()));
+
+ return reconstructed;
+}
+
// Delimiter types - used in macros and whatever.
enum DelimType
{
@@ -403,15 +436,15 @@ class SimplePath
public:
// Constructor
- SimplePath (std::vector path_segments,
- bool has_opening_scope_resolution = false,
- location_t locus = UNDEF_LOCATION)
+ explicit SimplePath (std::vector path_segments,
+ bool has_opening_scope_resolution = false,
+ location_t locus = UNDEF_LOCATION)
: opening_scope_resolution (has_opening_scope_resolution),
segments (std::move (path_segments)), locus (locus),
node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
- SimplePath (Identifier ident)
+ explicit SimplePath (Identifier ident)
: opening_scope_resolution (false),
segments ({SimplePathSegment (ident.as_string (), ident.get_locus ())}),
locus (ident.get_locus ()),
@@ -1256,6 +1289,8 @@ class Expr : public Visitable
FieldAccess,
Closure,
Block,
+ ConstExpr,
+ ConstBlock,
Continue,
Break,
Range,
@@ -1477,6 +1512,10 @@ class Type : public Visitable
return std::unique_ptr (clone_type_impl ());
}
+ // Similar to `clone_type`, but generates a new instance of the node with a
+ // different NodeId
+ std::unique_ptr reconstruct () const { return reconstruct_base (this); }
+
// virtual destructor
virtual ~Type () {}
@@ -1495,11 +1534,13 @@ class Type : public Visitable
virtual location_t get_locus () const = 0;
NodeId get_node_id () const { return node_id; }
+ virtual Type *reconstruct_impl () const = 0;
protected:
Type () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
+ Type (NodeId node_id) : node_id (node_id) {}
- // Clone function implementation as pure virtual method
+ // Clone and reconstruct function implementations as pure virtual methods
virtual Type *clone_type_impl () const = 0;
NodeId node_id;
@@ -1515,6 +1556,13 @@ class TypeNoBounds : public Type
return std::unique_ptr (clone_type_no_bounds_impl ());
}
+ std::unique_ptr reconstruct () const
+ {
+ return reconstruct_base (this);
+ }
+
+ virtual TypeNoBounds *reconstruct_impl () const override = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0;
@@ -1549,6 +1597,11 @@ class TypeParamBound : public Visitable
return std::unique_ptr (clone_type_param_bound_impl ());
}
+ std::unique_ptr reconstruct () const
+ {
+ return reconstruct_base (this);
+ }
+
virtual std::string as_string () const = 0;
NodeId get_node_id () const { return node_id; }
@@ -1557,10 +1610,14 @@ class TypeParamBound : public Visitable
virtual TypeParamBoundType get_bound_type () const = 0;
+ virtual TypeParamBound *reconstruct_impl () const = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual TypeParamBound *clone_type_param_bound_impl () const = 0;
+ TypeParamBound () : node_id (Analysis::Mappings::get ().get_next_node_id ())
+ {}
TypeParamBound (NodeId node_id) : node_id (node_id) {}
NodeId node_id;
@@ -1622,6 +1679,10 @@ class Lifetime : public TypeParamBound
{
return new Lifetime (node_id, lifetime_type, lifetime_name, locus);
}
+ Lifetime *reconstruct_impl () const override
+ {
+ return new Lifetime (lifetime_type, lifetime_name, locus);
+ }
};
/* Base generic parameter in AST. Abstract - can be represented by a Lifetime
diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc
index cd6be7fbeb9c..306c6f747e2b 100644
--- a/gcc/rust/ast/rust-collect-lang-items.cc
+++ b/gcc/rust/ast/rust-collect-lang-items.cc
@@ -109,5 +109,29 @@ CollectLangItems::visit (AST::EnumItem &item)
DefaultASTVisitor::visit (item);
}
+void
+CollectLangItems::visit (AST::EnumItemTuple &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit (item);
+}
+
+void
+CollectLangItems::visit (AST::EnumItemStruct &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit (item);
+}
+
+void
+CollectLangItems::visit (AST::EnumItemDiscriminant &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit (item);
+}
+
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-collect-lang-items.h b/gcc/rust/ast/rust-collect-lang-items.h
index ddb34a914ed7..ddc7b51313bd 100644
--- a/gcc/rust/ast/rust-collect-lang-items.h
+++ b/gcc/rust/ast/rust-collect-lang-items.h
@@ -50,6 +50,9 @@ class CollectLangItems : public DefaultASTVisitor
void visit (AST::Function &item) override;
void visit (AST::StructStruct &item) override;
void visit (AST::EnumItem &item) override;
+ void visit (AST::EnumItemTuple &item) override;
+ void visit (AST::EnumItemStruct &item) override;
+ void visit (AST::EnumItemDiscriminant &item) override;
private:
template void maybe_add_lang_item (const T &item);
diff --git a/gcc/rust/ast/rust-cond-compilation.h b/gcc/rust/ast/rust-cond-compilation.h
index 610b9046f455..56a5646704a8 100644
--- a/gcc/rust/ast/rust-cond-compilation.h
+++ b/gcc/rust/ast/rust-cond-compilation.h
@@ -42,8 +42,8 @@ class ConfigurationPredicate
protected:
// Clone function impl to be overriden in base classes
- virtual ConfigurationPredicate *
- clone_configuration_predicate_impl () const = 0;
+ virtual ConfigurationPredicate *clone_configuration_predicate_impl () const
+ = 0;
};
// A configuration option - true if option is set, false if option is not set.
diff --git a/gcc/rust/ast/rust-desugar-apit.cc b/gcc/rust/ast/rust-desugar-apit.cc
new file mode 100644
index 000000000000..bca14eef1eab
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-apit.cc
@@ -0,0 +1,522 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// .
+
+#include "rust-desugar-apit.h"
+#include "rust-ast.h"
+#include "rust-type.h"
+
+namespace Rust {
+namespace AST {
+
+class DesugarApitType : public DefaultASTVisitor
+{
+ using DefaultASTVisitor::visit;
+
+public:
+ static std::pair>>
+ Desugar (AST::Type &type)
+ {
+ DesugarApitType visitor (&type);
+ type.accept_vis (visitor);
+ rust_assert (visitor.translated != nullptr);
+ return std::make_pair (visitor.translated,
+ std::move (visitor.implicit_generic_params));
+ }
+
+ // Generate a unique impl trait parameter name
+ static Identifier get_impl_name ()
+ {
+ static size_t counter = 0;
+ return Identifier ("Impl_" + std::to_string (counter++));
+ }
+
+ // these can hold other types
+ void visit (AST::TupleType &tuple) override
+ {
+ for (auto &elem : tuple.get_elems ())
+ {
+ auto &type = *elem.get ();
+ auto desugar = Desugar (type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ continue;
+
+ if (tt != elem.get ())
+ elem = std::unique_ptr (tt);
+
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+ }
+
+ void visit (AST::ArrayType &type) override
+ {
+ auto &element_type = type.get_element_type ();
+ auto desugar = Desugar (*element_type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ if (tt != element_type.get ())
+ element_type = std::unique_ptr (tt);
+
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ void visit (AST::ReferenceType &type) override
+ {
+ // Get a reference to the current type for in-place modification
+ auto &referenced_type = type.get_type_referenced ();
+ auto desugar = Desugar (referenced_type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ // Update the reference type's contents rather than creating a new one
+ if (&referenced_type != tt)
+ {
+ std::unique_ptr new_type_no_bounds (
+ static_cast (tt));
+ type.get_type_ptr () = std::move (new_type_no_bounds);
+ }
+
+ // Collect all the implicit generic parameters we found
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ void visit (AST::RawPointerType &type) override
+ {
+ auto &pointed_type = type.get_type_pointed_to ();
+ auto desugar = Desugar (pointed_type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ // Update the pointer's inner type directly using the new accessor
+ if (&pointed_type != tt)
+ {
+ std::unique_ptr new_type_no_bounds (
+ static_cast (tt));
+ type.get_type_ptr () = std::move (new_type_no_bounds);
+ }
+
+ // Collect all the implicit generic parameters we found
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ void visit (AST::SliceType &type) override
+ {
+ auto &element_type = type.get_elem_type ();
+ auto desugar = Desugar (element_type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ if (&element_type != tt)
+ {
+ std::unique_ptr new_elem_type (tt);
+ type.get_elem_type_ptr () = std::move (new_elem_type);
+ }
+
+ // Collect all the implicit generic parameters we found
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ void visit (AST::ParenthesisedType &type) override
+ {
+ auto &inner_type_ptr = type.get_type_in_parens ();
+ auto desugar = Desugar (*inner_type_ptr);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ if (inner_type_ptr.get () != tt)
+ {
+ std::unique_ptr new_inner_type (tt);
+ inner_type_ptr = std::move (new_inner_type);
+ }
+
+ // Collect all the implicit generic parameters we found
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ // this is where the desugar happens
+ void visit (AST::ImplTraitType &type) override
+ {
+ // Generate a unique name using the static method
+ auto ident = get_impl_name ();
+
+ // Create a type path for the new generic parameter
+ // Create a SimplePathSegment with the identifier string
+ auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ());
+ // Create a vector of SimplePathSegments for SimplePath constructor
+ std::vector simple_segs = {simple_seg};
+ // Create a SimplePath
+ auto simple_path = SimplePath (simple_segs, false, type.get_locus ());
+
+ // Convert to TypePath by creating path segments
+ std::vector> segments;
+ segments.push_back (std::unique_ptr (new TypePathSegment (
+ PathIdentSegment (ident.as_string (), type.get_locus ()), false,
+ type.get_locus ())));
+
+ // Create TypePath from segments
+ auto type_path
+ = new TypePath (std::move (segments), type.get_locus (), false);
+
+ // Convert bounds from impl trait to generic parameter bounds
+ std::vector> bounds;
+ for (auto &bound : type.get_type_param_bounds ())
+ bounds.push_back (bound->clone_type_param_bound ());
+
+ // Create the new generic parameter
+ auto generic_param = std::unique_ptr (
+ new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {},
+ true /*from impl trait*/));
+
+ // Store the generic parameter to be added to the function signature
+ implicit_generic_params.push_back (std::move (generic_param));
+
+ // Replace impl trait with the new type parameter
+ translated = type_path;
+ }
+
+ void visit (AST::ImplTraitTypeOneBound &type) override
+ {
+ // Generate a unique name using the static method
+ auto ident = get_impl_name ();
+
+ // Create a type path for the new generic parameter
+ // Create a SimplePathSegment with the identifier string
+ auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ());
+ // Create a vector of SimplePathSegments for SimplePath constructor
+ std::vector simple_segs = {simple_seg};
+ // Create a SimplePath
+ auto simple_path = SimplePath (simple_segs, false, type.get_locus ());
+
+ // Convert to TypePath by creating path segments
+ std::vector> segments;
+ segments.push_back (std::unique_ptr (new TypePathSegment (
+ PathIdentSegment (ident.as_string (), type.get_locus ()), false,
+ type.get_locus ())));
+
+ // Create TypePath from segments
+ auto type_path
+ = new TypePath (std::move (segments), type.get_locus (), false);
+
+ // Convert the bound to a generic parameter bound
+ std::vector> bounds;
+ bounds.push_back (std::move (type.get_trait_bound ()));
+
+ // Create the new generic parameter
+ auto generic_param = std::unique_ptr (
+ new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {},
+ true /*from impl trait*/));
+
+ // Store the generic parameter to be added to the function signature
+ implicit_generic_params.push_back (std::move (generic_param));
+
+ // Replace impl trait with the new type parameter
+ translated = type_path;
+ }
+
+private:
+ DesugarApitType (AST::Type *base)
+ : translated (base), implicit_generic_params ()
+ {}
+
+ AST::Type *translated;
+ std::vector> implicit_generic_params;
+};
+
+// ---------
+
+class ApitBoundProcessor
+{
+public:
+ ApitBoundProcessor (
+ WhereClause &where_clause,
+ std::vector> &generic_params)
+ : where_clause (where_clause), generic_params (generic_params)
+ {}
+
+ void go (std::vector> &implicit_generics)
+ {
+ // some desugars are more complex so imagine this case
+ //
+ // pub fn foo(_value: impl Bar) -> i32 {
+ // 15
+ // }
+ //
+ // this needs to become:
+ //
+ // pub fn foo(_value: T) -> i32
+ // where
+ // T: Bar,
+ // U: Foo,
+ // {
+ // 15
+ // }
+ //
+ // so we need to walk all the implicit generics and the trait bounds paths
+ // for more generics
+
+ for (auto &implicit_generic : implicit_generics)
+ {
+ switch (implicit_generic->get_kind ())
+ {
+ case GenericParam::Kind::Type:
+ {
+ TypeParam &p
+ = *static_cast (implicit_generic.get ());
+
+ process_type_param (p);
+ generic_params.push_back (std::move (implicit_generic));
+ for (auto &synth : synthetic_params)
+ generic_params.push_back (std::move (synth));
+ synthetic_params.clear ();
+ }
+ break;
+
+ default:
+ generic_params.push_back (std::move (implicit_generic));
+ break;
+ }
+ }
+ }
+
+private:
+ void process_type_param (TypeParam &p)
+ {
+ auto &bounds = p.get_type_param_bounds ();
+ std::vector bounds_to_remove;
+ for (size_t i = 0; i < bounds.size (); i++)
+ {
+ auto &tb = bounds[i];
+ switch (tb->get_bound_type ())
+ {
+ case TypeParamBound::TypeParamBoundType::TRAIT:
+ {
+ TraitBound &ttb = *static_cast (tb.get ());
+ TypePath &path = ttb.get_type_path ();
+ bool deusgared = process_type_path (p, ttb, path);
+ if (deusgared)
+ bounds_to_remove.push_back (i);
+ }
+
+ default:
+ break;
+ }
+ }
+ for (auto it = bounds_to_remove.rbegin (); it != bounds_to_remove.rend ();
+ ++it)
+ bounds.erase (bounds.begin () + *it);
+ }
+
+ bool process_type_path (TypeParam &p, TraitBound &parent, TypePath &path)
+ {
+ bool desugared = false;
+ for (auto &segment : path.get_segments ())
+ {
+ switch (segment->get_type ())
+ {
+ case TypePathSegment::SegmentType::GENERIC:
+ {
+ TypePathSegmentGeneric &seg
+ = *static_cast (segment.get ());
+ desugared |= process_generic_segment (p, parent, path, seg);
+ }
+
+ default:
+ break;
+ }
+ }
+ return desugared;
+ }
+
+ bool process_generic_segment (TypeParam &p, TraitBound &parent,
+ TypePath &path, TypePathSegmentGeneric &seg)
+ {
+ // we need to look for any impl types as default arguments in any generics
+ // and remove this index from the generic arguments by using a where
+ // constraint instead
+
+ std::vector> new_clauses;
+ GenericArgs &generic_args = seg.get_generic_args ();
+ std::vector>
+ bindings_desugared;
+ std::vector &bindings
+ = generic_args.get_binding_args ();
+
+ for (auto &generic : bindings)
+ {
+ auto &t = generic.get_type ();
+ auto translated = DesugarApitType::Desugar (t);
+ auto tt = translated.first;
+
+ auto &implicit_generics = translated.second;
+ if (implicit_generics.empty ())
+ continue;
+
+ if (tt != &t)
+ {
+ bindings_desugared.push_back (generic);
+ generic.get_type_ptr () = std::unique_ptr (tt);
+ }
+
+ for (auto &implicit_generic : implicit_generics)
+ {
+ switch (implicit_generic->get_kind ())
+ {
+ case GenericParam::Kind::Type:
+ {
+ TypeParam &tp
+ = *static_cast (implicit_generic.get ());
+
+ std::vector>
+ type_param_bounds;
+ for (auto &b : tp.get_type_param_bounds ())
+ type_param_bounds.push_back (std::move (b));
+ tp.get_type_param_bounds ().clear ();
+
+ // add synthetic parameter for this
+ synthetic_params.push_back (std::move (implicit_generic));
+
+ auto bound_type_path
+ = get_type_for_identifier (tp.get_type_representation ());
+
+ auto clause = new TypeBoundWhereClauseItem (
+ {}, std::move (bound_type_path),
+ std::move (type_param_bounds), tp.get_locus ());
+ std::unique_ptr clause_item
+ = std::unique_ptr (clause);
+ new_clauses.push_back (std::move (clause_item));
+ }
+ break;
+
+ default:
+ synthetic_params.push_back (std::move (implicit_generic));
+ break;
+ }
+ }
+ }
+
+ std::vector> type_param_bounds;
+ auto bound = std::unique_ptr (new TraitBound (parent));
+ type_param_bounds.push_back (std::move (bound));
+ auto parent_type_path
+ = get_type_for_identifier (p.get_type_representation ());
+ auto clause
+ = new TypeBoundWhereClauseItem ({}, std::move (parent_type_path),
+ std::move (type_param_bounds),
+ parent.get_locus ());
+ std::unique_ptr clause_item
+ = std::unique_ptr (clause);
+ where_clause.get_items ().push_back (std::move (clause_item));
+
+ for (auto &where_item : new_clauses)
+ where_clause.get_items ().push_back (std::move (where_item));
+
+ return !bindings_desugared.empty ();
+ }
+
+ static std::unique_ptr get_type_for_identifier (const Identifier &ident)
+ {
+ auto simple_seg
+ = SimplePathSegment (ident.as_string (), ident.get_locus ());
+ std::vector simple_segs = {simple_seg};
+ auto simple_path = SimplePath (simple_segs, false, ident.get_locus ());
+ std::vector> segments;
+ segments.push_back (std::unique_ptr (new TypePathSegment (
+ PathIdentSegment (ident.as_string (), ident.get_locus ()), false,
+ ident.get_locus ())));
+ auto type_path = new TypePath (std::move (segments), ident.get_locus ());
+ return std::unique_ptr (type_path);
+ }
+
+private:
+ WhereClause &where_clause;
+ std::vector> &generic_params;
+
+ // mutates
+ std::vector> synthetic_params;
+};
+
+// ---------
+
+DesugarApit::DesugarApit () {}
+
+void
+DesugarApit::go (AST::Crate &crate)
+{
+ DefaultASTVisitor::visit (crate);
+}
+
+void
+DesugarApit::visit (AST::Function &function)
+{
+ if (!function.has_function_params ())
+ return;
+
+ auto &fn_params = function.get_function_params ();
+ for (auto ¶m : fn_params)
+ {
+ if (param->is_variadic () || param->is_self ())
+ continue;
+
+ auto *p = param.get ();
+ auto &fp = *static_cast (p);
+ auto &type = fp.get_type ();
+
+ auto translated = DesugarApitType::Desugar (type);
+ auto tt = translated.first;
+
+ auto &implicit_generics = translated.second;
+ if (implicit_generics.empty ())
+ continue;
+
+ if (fp.get_type_ptr ().get () != tt)
+ {
+ fp.get_type_ptr () = std::unique_ptr (tt);
+ }
+
+ ApitBoundProcessor processor (function.get_where_clause (),
+ function.get_generic_params ());
+ processor.go (implicit_generics);
+ }
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/ast/rust-desugar-apit.h
similarity index 66%
rename from gcc/rust/ast/rust-macro.cc
rename to gcc/rust/ast/rust-desugar-apit.h
index 270343872933..07c25e2405cf 100644
--- a/gcc/rust/ast/rust-macro.cc
+++ b/gcc/rust/ast/rust-desugar-apit.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
+// Copyright (C) 2025 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -16,10 +16,27 @@
// along with GCC; see the file COPYING3. If not see
// .
-#include "rust-macro.h"
+#ifndef RUST_DESUGAR_APIT_H
+#define RUST_DESUGAR_APIT_H
+
+#include "rust-ast-visitor.h"
namespace Rust {
namespace AST {
+class DesugarApit : public DefaultASTVisitor
+{
+ using DefaultASTVisitor::visit;
+
+public:
+ DesugarApit ();
+ void go (AST::Crate &);
+
+private:
+ void visit (AST::Function &) override;
+};
+
} // namespace AST
} // namespace Rust
+
+#endif // ! RUST_DESUGAR_APIT_H
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index fdb6360eb3b4..8d650b2ded1f 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -1,6 +1,7 @@
#ifndef RUST_AST_EXPR_H
#define RUST_AST_EXPR_H
+#include "optional.h"
#include "rust-ast.h"
#include "rust-common.h"
#include "rust-path.h"
@@ -395,6 +396,8 @@ class BorrowExpr : public OperatorExpr
return *main_or_left_expr;
}
+ bool has_borrow_expr () const { return main_or_left_expr != nullptr; }
+
bool get_is_mut () const { return mutability == Mutability::Mut; }
Mutability get_mutability () const { return mutability; }
@@ -1160,11 +1163,11 @@ class ArrayElems
// Value array elements
class ArrayElemsValues : public ArrayElems
{
- std::vector > values;
+ std::vector> values;
location_t locus;
public:
- ArrayElemsValues (std::vector > elems, location_t locus)
+ ArrayElemsValues (std::vector> elems, location_t locus)
: ArrayElems (), values (std::move (elems)), locus (locus)
{}
@@ -1192,14 +1195,16 @@ class ArrayElemsValues : public ArrayElems
std::string as_string () const override;
+ location_t get_locus () const { return locus; }
+
void accept_vis (ASTVisitor &vis) override;
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector > &get_values () const
+ const std::vector> &get_values () const
{
return values;
}
- std::vector > &get_values () { return values; }
+ std::vector> &get_values () { return values; }
size_t get_num_values () const { return values.size (); }
@@ -1214,6 +1219,8 @@ class ArrayElemsValues : public ArrayElems
class ArrayElemsCopied : public ArrayElems
{
std::unique_ptr elem_to_copy;
+
+ // TODO: This should be replaced by a ConstExpr
std::unique_ptr num_copies;
location_t locus;
@@ -1246,6 +1253,8 @@ class ArrayElemsCopied : public ArrayElems
std::string as_string () const override;
+ location_t get_locus () const { return locus; }
+
void accept_vis (ASTVisitor &vis) override;
// TODO: is this better? Or is a "vis_block" better?
@@ -1472,7 +1481,7 @@ class TupleExpr : public ExprWithoutBlock
{
std::vector outer_attrs;
std::vector inner_attrs;
- std::vector > tuple_elems;
+ std::vector> tuple_elems;
location_t locus;
// TODO: find another way to store this to save memory?
@@ -1492,7 +1501,7 @@ class TupleExpr : public ExprWithoutBlock
outer_attrs = std::move (new_attrs);
}
- TupleExpr (std::vector > tuple_elements,
+ TupleExpr (std::vector> tuple_elements,
std::vector inner_attribs,
std::vector outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)),
@@ -1543,14 +1552,11 @@ class TupleExpr : public ExprWithoutBlock
bool is_marked_for_strip () const override { return marked_for_strip; }
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector > &get_tuple_elems () const
- {
- return tuple_elems;
- }
- std::vector > &get_tuple_elems ()
+ const std::vector> &get_tuple_elems () const
{
return tuple_elems;
}
+ std::vector> &get_tuple_elems () { return tuple_elems; }
bool is_unit () const { return tuple_elems.size () == 0; }
@@ -1775,6 +1781,8 @@ struct StructBase
std::string as_string () const;
+ location_t get_locus () const { return locus; }
+
// TODO: is this better? Or is a "vis_block" better?
Expr &get_base_struct ()
{
@@ -1972,7 +1980,7 @@ class StructExprFieldIndexValue : public StructExprFieldWithVal
class StructExprStructFields : public StructExprStruct
{
// std::vector fields;
- std::vector > fields;
+ std::vector> fields;
// bool has_struct_base;
StructBase struct_base;
@@ -1985,8 +1993,8 @@ class StructExprStructFields : public StructExprStruct
// Constructor for StructExprStructFields when no struct base is used
StructExprStructFields (
PathInExpression struct_path,
- std::vector > expr_fields,
- location_t locus, StructBase base_struct = StructBase::error (),
+ std::vector> expr_fields, location_t locus,
+ StructBase base_struct = StructBase::error (),
std::vector inner_attribs = std::vector (),
std::vector outer_attribs = std::vector ())
: StructExprStruct (std::move (struct_path), std::move (inner_attribs),
@@ -2023,11 +2031,11 @@ class StructExprStructFields : public StructExprStruct
void accept_vis (ASTVisitor &vis) override;
// TODO: this mutable getter seems really dodgy. Think up better way.
- std::vector > &get_fields ()
+ std::vector> &get_fields ()
{
return fields;
}
- const std::vector > &get_fields () const
+ const std::vector> &get_fields () const
{
return fields;
}
@@ -2084,7 +2092,7 @@ class CallExpr : public ExprWithoutBlock
{
std::vector outer_attrs;
std::unique_ptr function;
- std::vector > params;
+ std::vector> params;
location_t locus;
public:
@@ -2093,7 +2101,7 @@ class CallExpr : public ExprWithoutBlock
std::string as_string () const override;
CallExpr (std::unique_ptr function_expr,
- std::vector > function_params,
+ std::vector> function_params,
std::vector outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)),
function (std::move (function_expr)),
@@ -2150,11 +2158,11 @@ class CallExpr : public ExprWithoutBlock
bool is_marked_for_strip () const override { return function == nullptr; }
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector > &get_params () const
+ const std::vector> &get_params () const
{
return params;
}
- std::vector > &get_params () { return params; }
+ std::vector> &get_params () { return params; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_function_expr ()
@@ -2190,7 +2198,7 @@ class MethodCallExpr : public ExprWithoutBlock
std::vector outer_attrs;
std::unique_ptr receiver;
PathExprSegment method_name;
- std::vector > params;
+ std::vector> params;
location_t locus;
public:
@@ -2198,7 +2206,7 @@ class MethodCallExpr : public ExprWithoutBlock
MethodCallExpr (std::unique_ptr call_receiver,
PathExprSegment method_path,
- std::vector > method_params,
+ std::vector> method_params,
std::vector outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)),
receiver (std::move (call_receiver)),
@@ -2254,11 +2262,11 @@ class MethodCallExpr : public ExprWithoutBlock
bool is_marked_for_strip () const override { return receiver == nullptr; }
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector > &get_params () const
+ const std::vector> &get_params () const
{
return params;
}
- std::vector > &get_params () { return params; }
+ std::vector> &get_params () { return params; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_receiver_expr ()
@@ -2504,6 +2512,8 @@ class ClosureExpr : public ExprWithoutBlock
bool get_has_move () const { return has_move; }
Expr::Kind get_expr_kind () const override { return Expr::Kind::Closure; }
+
+ virtual Expr &get_definition_expr () = 0;
};
// Represents a non-type-specified closure expression AST node
@@ -2563,7 +2573,7 @@ class ClosureExprInner : public ClosureExpr
return closure_inner == nullptr;
}
- Expr &get_definition_expr ()
+ Expr &get_definition_expr () override
{
rust_assert (closure_inner != nullptr);
return *closure_inner;
@@ -2583,7 +2593,7 @@ class BlockExpr : public ExprWithBlock
{
std::vector outer_attrs;
std::vector inner_attrs;
- std::vector > statements;
+ std::vector> statements;
std::unique_ptr expr;
tl::optional label;
location_t start_locus;
@@ -2599,7 +2609,7 @@ class BlockExpr : public ExprWithBlock
// Returns whether the block contains a final expression.
bool has_tail_expr () const { return expr != nullptr; }
- BlockExpr (std::vector > block_statements,
+ BlockExpr (std::vector> block_statements,
std::unique_ptr block_expr,
std::vector inner_attribs,
std::vector outer_attribs,
@@ -2678,11 +2688,11 @@ class BlockExpr : public ExprWithBlock
const std::vector &get_inner_attrs () const { return inner_attrs; }
std::vector &get_inner_attrs () { return inner_attrs; }
- const std::vector > &get_statements () const
+ const std::vector> &get_statements () const
{
return statements;
}
- std::vector > &get_statements () { return statements; }
+ std::vector> &get_statements () { return statements; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_tail_expr ()
@@ -2744,6 +2754,151 @@ class BlockExpr : public ExprWithBlock
}
};
+class AnonConst : public ExprWithBlock
+{
+public:
+ enum class Kind
+ {
+ Explicit,
+ DeferredInference,
+ };
+
+ AnonConst (std::unique_ptr &&expr, location_t locus = UNKNOWN_LOCATION)
+ : ExprWithBlock (), locus (locus), kind (Kind::Explicit),
+ expr (std::move (expr))
+ {
+ rust_assert (this->expr.value ());
+ }
+
+ AnonConst (location_t locus = UNKNOWN_LOCATION)
+ : ExprWithBlock (), locus (locus), kind (Kind::DeferredInference),
+ expr (tl::nullopt)
+ {}
+
+ AnonConst (const AnonConst &other)
+ {
+ node_id = other.node_id;
+ locus = other.locus;
+ kind = other.kind;
+
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
+ }
+
+ AnonConst operator= (const AnonConst &other)
+ {
+ node_id = other.node_id;
+ locus = other.locus;
+ kind = other.kind;
+
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
+
+ return *this;
+ }
+
+ std::string as_string () const override;
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstExpr; }
+
+ location_t get_locus () const override { return locus; }
+
+ Expr &get_inner_expr ()
+ {
+ rust_assert (expr.has_value ());
+ return *expr.value ();
+ }
+
+ NodeId get_node_id () const override { return node_id; }
+
+ /* FIXME: AnonConst are always "internal" and should not have outer attributes
+ * - is that true? Or should we instead call
+ * expr->get_outer_attrs()/expr->set_outer_attrs() */
+
+ std::vector &get_outer_attrs () override
+ {
+ static auto attrs = std::vector ();
+ return attrs;
+ }
+
+ void set_outer_attrs (std::vector) override {}
+
+ /* FIXME: Likewise for mark_for_strip() ? */
+ void mark_for_strip () override {}
+ bool is_marked_for_strip () const override { return false; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ bool is_deferred () const { return kind == Kind::DeferredInference; }
+
+private:
+ location_t locus;
+ Kind kind;
+ tl::optional> expr;
+
+ AnonConst *clone_expr_with_block_impl () const override
+ {
+ return new AnonConst (*this);
+ }
+};
+
+class ConstBlock : public ExprWithBlock
+{
+public:
+ ConstBlock (AnonConst &&expr, location_t locus = UNKNOWN_LOCATION,
+ std::vector &&outer_attrs = {})
+ : ExprWithBlock (), expr (std::move (expr)),
+ outer_attrs (std::move (outer_attrs)), locus (locus)
+ {}
+
+ ConstBlock (const ConstBlock &other)
+ : ExprWithBlock (other), expr (other.expr), outer_attrs (other.outer_attrs),
+ locus (other.locus)
+ {}
+
+ ConstBlock operator= (const ConstBlock &other)
+ {
+ expr = other.expr;
+ node_id = other.node_id;
+ outer_attrs = other.outer_attrs;
+ locus = other.locus;
+
+ return *this;
+ }
+
+ std::string as_string () const override;
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstBlock; }
+
+ AnonConst &get_const_expr () { return expr; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ std::vector &get_outer_attrs () override { return outer_attrs; }
+
+ void set_outer_attrs (std::vector