From d96e18a6c39a47e6413c92d328993456cddf425c Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 16 Dec 2024 13:01:13 +0100 Subject: [PATCH 01/35] hir: Add LangItem paths to PathPattern class gcc/rust/ChangeLog: * hir/tree/rust-hir-path.h: Adapt PathPattern to accept lang-item paths. * hir/tree/rust-hir-path.cc: Assert we are dealing with a segmented path, create lang-item constructors. * hir/tree/rust-hir.cc (PathPattern::convert_to_simple_path): Likewise. --- gcc/rust/hir/tree/rust-hir-path.cc | 21 +++++++++ gcc/rust/hir/tree/rust-hir-path.h | 72 ++++++++++++++++++++++++++---- gcc/rust/hir/tree/rust-hir.cc | 2 + 3 files changed, 87 insertions(+), 8 deletions(-) diff --git a/gcc/rust/hir/tree/rust-hir-path.cc b/gcc/rust/hir/tree/rust-hir-path.cc index c8d3079a85e3..097941fff0c6 100644 --- a/gcc/rust/hir/tree/rust-hir-path.cc +++ b/gcc/rust/hir/tree/rust-hir-path.cc @@ -132,6 +132,9 @@ PathExprSegment::operator= (PathExprSegment const &other) void PathPattern::iterate_path_segments (std::function cb) { + // FIXME: Is this necessary? + rust_assert (kind == Kind::Segmented); + for (auto it = segments.begin (); it != segments.end (); it++) { if (!cb (*it)) @@ -149,6 +152,15 @@ PathInExpression::PathInExpression (Analysis::NodeMapping mappings, has_opening_scope_resolution (has_opening_scope_resolution), locus (locus) {} +PathInExpression::PathInExpression (Analysis::NodeMapping mappings, + LangItem::Kind lang_item, location_t locus, + bool has_opening_scope_resolution, + std::vector outer_attrs) + : PathPattern (lang_item), + PathExpr (std::move (mappings), std::move (outer_attrs)), + has_opening_scope_resolution (has_opening_scope_resolution), locus (locus) +{} + bool PathInExpression::is_self () const @@ -341,6 +353,15 @@ QualifiedPathInExpression::QualifiedPathInExpression ( path_type (std::move (qual_path_type)), locus (locus) {} +QualifiedPathInExpression::QualifiedPathInExpression ( + Analysis::NodeMapping mappings, QualifiedPathType qual_path_type, + LangItem::Kind lang_item, location_t locus, + std::vector outer_attrs) + : PathPattern (lang_item), + PathExpr (std::move (mappings), std::move (outer_attrs)), + path_type (std::move (qual_path_type)), locus (locus) +{} + QualifiedPathInType::QualifiedPathInType ( Analysis::NodeMapping mappings, QualifiedPathType qual_path_type, std::unique_ptr associated_segment, diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index df5fd0c4e469..82d4c1f4a1c7 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -19,6 +19,7 @@ #ifndef RUST_HIR_PATH_H #define RUST_HIR_PATH_H +#include "rust-hir-map.h" #include "rust-hir-simple-path.h" #include "rust-hir-type-no-bounds.h" #include "rust-hir-pattern-abstract.h" @@ -231,14 +232,30 @@ class PathExprSegment class PathPattern : public Pattern { std::vector segments; + tl::optional lang_item; + + enum class Kind + { + Segmented, + LangItem + } kind; protected: PathPattern (std::vector segments) - : segments (std::move (segments)) + : segments (std::move (segments)), lang_item (tl::nullopt), + kind (Kind::Segmented) + {} + + PathPattern (LangItem::Kind lang_item) + : segments ({}), lang_item (lang_item), kind (Kind::LangItem) {} // Returns whether path has segments. - bool has_segments () const { return !segments.empty (); } + bool has_segments () const + { + rust_assert (kind == Kind::Segmented); + return !segments.empty (); + } /* Converts path segments to their equivalent SimplePath segments if possible, * and creates a SimplePath from them. */ @@ -248,21 +265,45 @@ class PathPattern : public Pattern public: /* Returns whether the path is a single segment (excluding qualified path * initial as segment). */ - bool is_single_segment () const { return segments.size () == 1; } + bool is_single_segment () const + { + rust_assert (kind == Kind::Segmented); + return segments.size () == 1; + } std::string as_string () const override; void iterate_path_segments (std::function cb); - size_t get_num_segments () const { return segments.size (); } + size_t get_num_segments () const + { + rust_assert (kind == Kind::Segmented); + return segments.size (); + } - std::vector &get_segments () { return segments; } + std::vector &get_segments () + { + rust_assert (kind == Kind::Segmented); + return segments; + } - const std::vector &get_segments () const { return segments; } + const std::vector &get_segments () const + { + rust_assert (kind == Kind::Segmented); + return segments; + } - PathExprSegment &get_root_seg () { return segments.at (0); } + PathExprSegment &get_root_seg () + { + rust_assert (kind == Kind::Segmented); + return segments.at (0); + } - const PathExprSegment &get_final_segment () const { return segments.back (); } + const PathExprSegment &get_final_segment () const + { + rust_assert (kind == Kind::Segmented); + return segments.back (); + } PatternType get_pattern_type () const override final { @@ -288,6 +329,13 @@ class PathInExpression : public PathPattern, public PathExpr std::vector outer_attrs = std::vector ()); + // lang-item Constructor + PathInExpression (Analysis::NodeMapping mappings, LangItem::Kind kind, + location_t locus = UNDEF_LOCATION, + bool has_opening_scope_resolution = false, + std::vector outer_attrs + = std::vector ()); + // Creates an error state path in expression. static PathInExpression create_error () { @@ -671,6 +719,14 @@ class QualifiedPathInExpression : public PathPattern, public PathExpr std::vector outer_attrs = std::vector ()); + // lang-item constructor + QualifiedPathInExpression (Analysis::NodeMapping mappings, + QualifiedPathType qual_path_type, + LangItem::Kind lang_item, + location_t locus = UNDEF_LOCATION, + std::vector outer_attrs + = std::vector ()); + location_t get_locus () const override final { return locus; } void accept_vis (HIRFullVisitor &vis) override; diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index 509a897ce39c..a8acfc69fa7b 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -2187,6 +2187,8 @@ TypeParam::as_string () const AST::SimplePath PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const { + rust_assert (kind == Kind::Segmented); + if (!has_segments ()) { return AST::SimplePath::create_empty (); From da9feedc5d3b8acefefc9ae88a16eebba305ea81 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 16 Dec 2024 14:16:31 +0100 Subject: [PATCH 02/35] wip: fixup? path: Switch PathPattern to enable lang item paths --- gcc/rust/hir/tree/rust-hir-path.h | 17 +++++++++++++---- gcc/rust/hir/tree/rust-hir.cc | 4 ++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index 82d4c1f4a1c7..2af492bcfb20 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -231,14 +231,17 @@ class PathExprSegment // HIR node representing a pattern that involves a "path" - abstract base class class PathPattern : public Pattern { - std::vector segments; - tl::optional lang_item; - +public: enum class Kind { Segmented, LangItem - } kind; + }; + +private: + std::vector segments; + tl::optional lang_item; + Kind kind; protected: PathPattern (std::vector segments) @@ -277,6 +280,10 @@ class PathPattern : public Pattern size_t get_num_segments () const { + if (kind == Kind::LangItem) + rust_fatal_error (UNKNOWN_LOCATION, "[ARTHUR] %s", + LangItem::ToString (*lang_item).c_str ()); + rust_assert (kind == Kind::Segmented); return segments.size (); } @@ -309,6 +316,8 @@ class PathPattern : public Pattern { return PatternType::PATH; } + + Kind get_path_kind () const { return kind; } }; /* HIR node representing a path-in-expression pattern (path that allows generic diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index a8acfc69fa7b..9b3bd145ba18 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -19,6 +19,7 @@ #include "rust-ast-full.h" #include "rust-hir-expr.h" #include "rust-hir-full.h" +#include "rust-hir-path.h" #include "rust-hir-visitor.h" #include "rust-diagnostics.h" @@ -1210,6 +1211,9 @@ ClosureExpr::as_string () const std::string PathPattern::as_string () const { + if (kind == PathPattern::Kind::LangItem) + return LangItem::ToString (*lang_item); + std::string str; for (const auto &segment : segments) From 363a345a3f1d315ffa423d8bb2bbf6f86298750f Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 23 Dec 2024 20:52:42 +0000 Subject: [PATCH 03/35] path: Add get_lang_item_kind() --- gcc/rust/hir/tree/rust-hir-path.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index 2af492bcfb20..3ce54cce30c6 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -24,6 +24,7 @@ #include "rust-hir-type-no-bounds.h" #include "rust-hir-pattern-abstract.h" #include "rust-hir-expr-abstract.h" +#include "rust-system.h" namespace Rust { namespace HIR { @@ -281,8 +282,11 @@ class PathPattern : public Pattern size_t get_num_segments () const { if (kind == Kind::LangItem) - rust_fatal_error (UNKNOWN_LOCATION, "[ARTHUR] %s", - LangItem::ToString (*lang_item).c_str ()); + { + // rust_fatal_error (UNKNOWN_LOCATION, "[ARTHUR] %s", + // LangItem::ToString (*lang_item).c_str ()); + rust_unreachable (); + } rust_assert (kind == Kind::Segmented); return segments.size (); @@ -317,6 +321,12 @@ class PathPattern : public Pattern return PatternType::PATH; } + LangItem::Kind get_lang_item_kind () const + { + rust_assert (kind == Kind::LangItem); + return *lang_item; + } + Kind get_path_kind () const { return kind; } }; From 1616513c46e73f9fa7661e4b6f532fee2722d458 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 16 Dec 2024 14:17:29 +0100 Subject: [PATCH 04/35] lang-item: Add Option::{None, Some}, Iterator::next, IntoIter::into_iter --- gcc/rust/util/rust-lang-item.cc | 6 ++++++ gcc/rust/util/rust-lang-item.h | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/gcc/rust/util/rust-lang-item.cc b/gcc/rust/util/rust-lang-item.cc index 0d8a98077d1e..8b1b1e346474 100644 --- a/gcc/rust/util/rust-lang-item.cc +++ b/gcc/rust/util/rust-lang-item.cc @@ -91,6 +91,12 @@ const BiMap Rust::LangItem::lang_items = {{ {"str", Kind::STR}, {"f32_runtime", Kind::F32_RUNTIME}, {"f64_runtime", Kind::F64_RUNTIME}, + + {"Some", Kind::OPTION_SOME}, + {"None", Kind::OPTION_NONE}, + + {"into_iter", Kind::INTOITER_INTOITER}, + {"next", Kind::ITERATOR_NEXT}, }}; tl::optional diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h index bcf41df559e5..4b0217616783 100644 --- a/gcc/rust/util/rust-lang-item.h +++ b/gcc/rust/util/rust-lang-item.h @@ -26,6 +26,9 @@ namespace Rust { class LangItem { public: + // FIXME: We should clean up that enum to make it more inline with the list of + // lang-items in Rust 1.49 + // https://github.com/rust-lang/rust/blob/1.49.0/compiler/rustc_hir/src/lang_items.rs enum class Kind { // https://github.com/rust-lang/rust/blob/master/library/core/src/ops/arith.rs @@ -116,6 +119,12 @@ class LangItem STR, F32_RUNTIME, F64_RUNTIME, + + OPTION_SOME, + OPTION_NONE, + + INTOITER_INTOITER, + ITERATOR_NEXT, }; static const BiMap lang_items; From f5af730efee18a215e83600354643a1ecc2efcdc Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 18 Dec 2024 12:20:27 +0100 Subject: [PATCH 05/35] lang-items: Collect trait functions that are lang items --- gcc/rust/ast/rust-collect-lang-items.cc | 8 ++++++++ gcc/rust/ast/rust-collect-lang-items.h | 1 + 2 files changed, 9 insertions(+) diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc index 308720ae69ab..50d134a429f5 100644 --- a/gcc/rust/ast/rust-collect-lang-items.cc +++ b/gcc/rust/ast/rust-collect-lang-items.cc @@ -82,5 +82,13 @@ CollectLangItems::visit (AST::TraitItemType &item) DefaultASTVisitor::visit (item); } +void +CollectLangItems::visit (AST::Function &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 552648f04eda..1d021b1d9c50 100644 --- a/gcc/rust/ast/rust-collect-lang-items.h +++ b/gcc/rust/ast/rust-collect-lang-items.h @@ -47,6 +47,7 @@ class CollectLangItems : public DefaultASTVisitor void visit (AST::Trait &item) override; void visit (AST::TraitItemType &item) override; + void visit (AST::Function &item) override; private: template void maybe_add_lang_item (const T &item); From 3537b25a1a0d691a9dd7a499bb8d61e2f62bf688 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 23 Dec 2024 20:52:02 +0000 Subject: [PATCH 06/35] for-loop: Progress on typechecker --- .../typecheck/rust-hir-type-check-path.cc | 48 ++++++++++++++----- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index d3f341264482..1f58a9ae8fb5 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -16,6 +16,9 @@ // along with GCC; see the file COPYING3. If not see // . +#include "rust-diagnostics.h" +#include "rust-hir-map.h" +#include "rust-hir-path.h" #include "rust-hir-type-check-expr.h" #include "rust-hir-type-check-type.h" #include "rust-hir-type-check-item.h" @@ -24,6 +27,7 @@ #include "rust-hir-path-probe.h" #include "rust-type-util.h" #include "rust-hir-type-bounds.h" +#include "rust-hir-item.h" #include "rust-session-manager.h" #include "rust-immutable-name-resolution-context.h" @@ -179,20 +183,42 @@ void TypeCheckExpr::visit (HIR::PathInExpression &expr) { NodeId resolved_node_id = UNKNOWN_NODEID; - size_t offset = -1; - TyTy::BaseType *tyseg = resolve_root_path (expr, &offset, &resolved_node_id); - if (tyseg->get_kind () == TyTy::TypeKind::ERROR) - return; - - bool fully_resolved = offset == expr.get_segments ().size (); - if (fully_resolved) + if (expr.get_path_kind () == HIR::PathPattern::Kind::LangItem) { - infered = tyseg; - return; + if (auto lookup = Analysis::Mappings::get ().lookup_lang_item_node ( + expr.get_lang_item_kind ())) + { + auto hir_id = mappings.lookup_node_to_hir (*lookup); + + TyTy::BaseType *resolved = nullptr; + context->lookup_type (*hir_id, &resolved); + + infered = resolved; + return; + } + else + rust_fatal_error ( + expr.get_locus (), "lang item missing: %s", + LangItem::ToString (expr.get_lang_item_kind ()).c_str ()); } + else + { + size_t offset = -1; + TyTy::BaseType *tyseg + = resolve_root_path (expr, &offset, &resolved_node_id); + if (tyseg->get_kind () == TyTy::TypeKind::ERROR) + return; + + bool fully_resolved = offset == expr.get_segments ().size (); + if (fully_resolved) + { + infered = tyseg; + return; + } - resolve_segments (resolved_node_id, expr.get_segments (), offset, tyseg, - expr.get_mappings (), expr.get_locus ()); + resolve_segments (resolved_node_id, expr.get_segments (), offset, tyseg, + expr.get_mappings (), expr.get_locus ()); + } } TyTy::BaseType * From 5ac584561e6cbe2a891c9b40ab46d67ec4ad2713 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 20 Dec 2024 11:29:32 +0000 Subject: [PATCH 07/35] typecheck-path: Fix typos --- gcc/rust/typecheck/rust-hir-type-check-path.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index 1f58a9ae8fb5..174cee0bcfdd 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -380,13 +380,13 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id, { NodeId resolved_node_id = root_resolved_node_id; TyTy::BaseType *prev_segment = tyseg; - bool reciever_is_generic = prev_segment->get_kind () == TyTy::TypeKind::PARAM; - bool reciever_is_dyn = prev_segment->get_kind () == TyTy::TypeKind::DYNAMIC; + bool receiver_is_generic = prev_segment->get_kind () == TyTy::TypeKind::PARAM; + bool receiver_is_dyn = prev_segment->get_kind () == TyTy::TypeKind::DYNAMIC; for (size_t i = offset; i < segments.size (); i++) { HIR::PathExprSegment &seg = segments.at (i); - bool probe_impls = !reciever_is_generic; + bool probe_impls = !receiver_is_generic; // probe the path is done in two parts one where we search impls if no // candidate is found then we search extensions from traits @@ -461,7 +461,7 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id, } } - if (associated_impl_block != nullptr && !reciever_is_dyn) + if (associated_impl_block != nullptr && !receiver_is_dyn) { // associated types HirId impl_block_id @@ -518,7 +518,7 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id, if (tyseg->get_kind () == TyTy::TypeKind::ERROR) return; } - else if (tyseg->needs_generic_substitutions () && !reciever_is_generic) + else if (tyseg->needs_generic_substitutions () && !receiver_is_generic) { location_t locus = seg.get_locus (); tyseg = SubstMapper::InferSubst (tyseg, locus); From e6addb02bc1dc6f2d578f1046f3b73105121cd42 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 20 Dec 2024 17:11:39 +0000 Subject: [PATCH 08/35] fixup! typos: reciever -> receiver --- gcc/rust/typecheck/rust-hir-path-probe.cc | 4 ++-- gcc/rust/typecheck/rust-hir-path-probe.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc index fa3ef47ebeaa..16976c34989d 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.cc +++ b/gcc/rust/typecheck/rust-hir-path-probe.cc @@ -168,7 +168,7 @@ PathProbeType::Probe (const TyTy::BaseType *receiver, if (!probe_bounds) return probe.candidates; - if (!probe.is_reciever_generic ()) + if (!probe.is_receiver_generic ()) { std::vector> probed_bounds = TypeBoundsProbe::Probe (receiver); @@ -433,7 +433,7 @@ PathProbeType::union_bounds ( } bool -PathProbeType::is_reciever_generic () const +PathProbeType::is_receiver_generic () const { const TyTy::BaseType *root = receiver->get_root (); bool receiver_is_type_param = root->get_kind () == TyTy::TypeKind::PARAM; diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h index b71d8c33fdef..5839a7e02144 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.h +++ b/gcc/rust/typecheck/rust-hir-path-probe.h @@ -145,7 +145,7 @@ class PathProbeType : public TypeCheckBase, public HIR::HIRImplVisitor const std::vector> b) const; - bool is_reciever_generic () const; + bool is_receiver_generic () const; const TyTy::BaseType *receiver; const HIR::PathIdentSegment &search; From e94e755c7c792496d2c180d3f4af518db0604efb Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 20 Dec 2024 17:12:11 +0000 Subject: [PATCH 09/35] hir-dump: Fix more segfaults in the HIR dump --- gcc/rust/hir/rust-hir-dump.cc | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc index a6a880121a1d..56b5f40e2090 100644 --- a/gcc/rust/hir/rust-hir-dump.cc +++ b/gcc/rust/hir/rust-hir-dump.cc @@ -315,6 +315,14 @@ Dump::do_functionparam (FunctionParam &e) void Dump::do_pathpattern (PathPattern &e) { + if (e.get_path_kind () == PathPattern::Kind::LangItem) + { + put_field ("segments", "#[lang = \"" + + LangItem::ToString (e.get_lang_item_kind ()) + + "\"]"); + return; + } + std::string str = ""; for (const auto &segment : e.get_segments ()) @@ -402,9 +410,15 @@ void Dump::do_qualifiedpathtype (QualifiedPathType &e) { do_mappings (e.get_mappings ()); - visit_field ("type", e.get_type ()); + if (e.has_type ()) + visit_field ("type", e.get_type ()); + else + put_field ("type", "none"); - visit_field ("trait", e.get_trait ()); + if (e.has_trait ()) + visit_field ("trait", e.get_trait ()); + else + put_field ("trait", "none"); } void @@ -521,7 +535,10 @@ Dump::do_traitfunctiondecl (TraitFunctionDecl &e) else put_field ("function_params", "empty"); - visit_field ("return_type", e.get_return_type ()); + if (e.has_return_type ()) + visit_field ("return_type", e.get_return_type ()); + else + put_field ("return_type", "none"); if (e.has_where_clause ()) put_field ("where_clause", e.get_where_clause ().as_string ()); @@ -1295,7 +1312,10 @@ Dump::visit (BreakExpr &e) else put_field ("label", "none"); - visit_field ("break_expr ", e.get_expr ()); + if (e.has_break_expr ()) + visit_field ("break_expr ", e.get_expr ()); + else + put_field ("break_expr", "none"); end ("BreakExpr"); } From a431cdb438d132ff6d62ebefbbeda9cd7855ae84 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 23 Dec 2024 21:26:39 +0000 Subject: [PATCH 10/35] for-loop: Setup 100% more substitutions --- gcc/rust/typecheck/rust-hir-type-check-path.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index 174cee0bcfdd..f1e4ca82c45a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -193,8 +193,17 @@ TypeCheckExpr::visit (HIR::PathInExpression &expr) TyTy::BaseType *resolved = nullptr; context->lookup_type (*hir_id, &resolved); + // We can type resolve the path in expression easily as it is a lang + // item path, but we still need to setup the various generics and + // substitutions infered = resolved; - return; + + // FIXME: We probably need to check *if* the type needs substitutions + // or not + infered = SubstMapper::InferSubst (infered, expr.get_locus()); + + // FIXME: also we probably need to insert resolved types in the name + // resolver here } else rust_fatal_error ( From 1f64b2fb97491c9427da6218fa90de5023ea949b Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 20 Dec 2024 18:00:48 +0000 Subject: [PATCH 11/35] move before rust-hir-dump: hir: Add has_{type, trait} methods to QualifiedPathType --- gcc/rust/hir/tree/rust-hir-path.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index 3ce54cce30c6..0cd5d7e924e7 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -708,13 +708,20 @@ class QualifiedPathType Analysis::NodeMapping get_mappings () const { return mappings; } + bool has_type () { return type != nullptr; } + bool has_trait () { return trait != nullptr; } + Type &get_type () { rust_assert (type); return *type; } - TypePath &get_trait () { return *trait; } + TypePath &get_trait () + { + rust_assert (trait); + return *trait; + } bool trait_has_generic_args () const; From ada7ae27c1a9e7f94e98eadc901392bbfdffc588 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 20 Dec 2024 18:08:14 +0000 Subject: [PATCH 12/35] wip: Cleanup our fix to hir-path.cc --- gcc/rust/typecheck/rust-hir-type-check-path.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index f1e4ca82c45a..d281f08e85e2 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -196,11 +196,10 @@ TypeCheckExpr::visit (HIR::PathInExpression &expr) // We can type resolve the path in expression easily as it is a lang // item path, but we still need to setup the various generics and // substitutions - infered = resolved; // FIXME: We probably need to check *if* the type needs substitutions // or not - infered = SubstMapper::InferSubst (infered, expr.get_locus()); + infered = SubstMapper::InferSubst (resolved, expr.get_locus()); // FIXME: also we probably need to insert resolved types in the name // resolver here From 5e7685cf245eeb283cf2583806bf425db49b9021 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Sat, 21 Dec 2024 22:56:52 +0000 Subject: [PATCH 13/35] ast: Add new Kind enums for more precise downcasting This commit adds things like Item::Kind, Expr::Kind, etc, and implements the associated `get_*_kind` functions. It also removes the more generic AST::Kind enum we were using, which was incomplete and painful to use. gcc/rust/ChangeLog: * ast/rust-ast.h: Add new Kind enums, remove Node class. * ast/rust-builtin-ast-nodes.h: Use new Kind enums. * ast/rust-expr.h (class LoopLabel): Likewise. * ast/rust-item.h: Likewise. * ast/rust-macro.h: Likewise. * ast/rust-path.h: Likewise. * expand/rust-macro-builtins-helpers.cc: Likewise. * expand/rust-macro-builtins-utility.cc (MacroBuiltin::concat_handler): Likewise. (MacroBuiltin::stringify_handler): Likewise. * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): Likewise. * resolve/rust-early-name-resolver.cc (EarlyNameResolver::accumulate_escaped_macros): Likewise. (EarlyNameResolver::visit): Likewise. --- gcc/rust/ast/rust-ast.h | 94 +++++++++++++------ gcc/rust/ast/rust-builtin-ast-nodes.h | 2 + gcc/rust/ast/rust-expr.h | 72 +++++++++++++- gcc/rust/ast/rust-item.h | 30 +++++- gcc/rust/ast/rust-macro.h | 33 ++++--- gcc/rust/ast/rust-path.h | 10 ++ .../expand/rust-macro-builtins-helpers.cc | 2 +- .../expand/rust-macro-builtins-utility.cc | 4 +- gcc/rust/resolve/rust-ast-resolve-expr.cc | 2 +- gcc/rust/resolve/rust-early-name-resolver.cc | 10 +- 10 files changed, 204 insertions(+), 55 deletions(-) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index f83c99a57d2d..415b09290272 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -70,16 +70,6 @@ namespace AST { class ASTVisitor; using AttrVec = std::vector; -// The available kinds of AST Nodes -enum class Kind -{ - UNKNOWN, - MODULE, - MACRO_RULES_DEFINITION, - MACRO_INVOCATION, - IDENTIFIER, -}; - class Visitable { public: @@ -87,20 +77,6 @@ class Visitable 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 { @@ -1092,7 +1068,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 +1117,28 @@ class Stmt : public Node 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 clone_item () const { @@ -1221,14 +1219,54 @@ class VisItem : public Item { 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, + Identifier, + FormatArgs, + MacroInvocation, + }; + + virtual Kind get_expr_kind () const = 0; + // Unique pointer custom clone function std::unique_ptr clone_expr () const { @@ -1343,7 +1381,7 @@ class IdentifierExpr : public ExprWithoutBlock 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 +1448,7 @@ class Pattern : public Visitable 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 diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h index 3e21d7e718d6..404d5a209bc5 100644 --- a/gcc/rust/ast/rust-builtin-ast-nodes.h +++ b/gcc/rust/ast/rust-builtin-ast-nodes.h @@ -202,6 +202,8 @@ class FormatArgs : public Expr 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-expr.h b/gcc/rust/ast/rust-expr.h index 483e599652bb..1e6cb8beabb6 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; @@ -117,6 +117,8 @@ class LiteralExpr : public ExprWithoutBlock 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 +367,8 @@ class OperatorExpr : public ExprWithoutBlock { 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 @@ -1090,6 +1094,8 @@ class GroupedExpr : public ExprWithoutBlock 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 +1325,8 @@ class ArrayExpr : public ExprWithoutBlock 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 +1432,8 @@ class ArrayIndexExpr : public ExprWithoutBlock 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 +1530,8 @@ class TupleExpr : public ExprWithoutBlock 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 +1619,8 @@ class TupleIndexExpr : public ExprWithoutBlock 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 +1664,8 @@ class StructExpr : public ExprWithoutBlock { 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! @@ -2131,6 +2147,8 @@ class CallExpr : public ExprWithoutBlock 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 +2252,8 @@ class MethodCallExpr : public ExprWithoutBlock 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 +2339,8 @@ class FieldAccessExpr : public ExprWithoutBlock 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 +2476,8 @@ class ClosureExpr : public ExprWithoutBlock } 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 @@ -2675,6 +2699,8 @@ class BlockExpr : public ExprWithBlock bool has_label () { return !label.is_error (); } LoopLabel &get_label () { return label; } + Expr::Kind get_expr_kind() const override { return Expr::Kind::Block; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2828,6 +2854,8 @@ class ContinueExpr : public ExprWithoutBlock Lifetime &get_label () { 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 * than base */ @@ -2924,6 +2952,8 @@ class BreakExpr : public ExprWithoutBlock LoopLabel &get_label () { 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 * than base */ @@ -2956,6 +2986,8 @@ class RangeExpr : public ExprWithoutBlock { rust_assert (false); } + + Expr::Kind get_expr_kind() const override { return Expr::Kind::Range; } }; // Range from (inclusive) and to (exclusive) expression AST node object @@ -3404,6 +3436,8 @@ class BoxExpr : public ExprWithoutBlock 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 +3525,8 @@ class ReturnExpr : public ExprWithoutBlock 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 +3609,8 @@ class UnsafeBlockExpr : public ExprWithBlock 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 */ @@ -3661,6 +3699,18 @@ class BaseLoopExpr : public ExprWithBlock { 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 @@ -3679,6 +3729,8 @@ class LoopExpr : public BaseLoopExpr 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 */ @@ -3737,6 +3789,8 @@ class WhileLoopExpr : public BaseLoopExpr 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 */ @@ -3820,6 +3874,8 @@ class WhileLetLoopExpr : public BaseLoopExpr 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 */ @@ -3889,6 +3945,8 @@ class ForLoopExpr : public BaseLoopExpr 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 +4070,8 @@ class IfExpr : public ExprWithBlock const std::vector &get_outer_attrs () const { return outer_attrs; } std::vector &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 +4266,8 @@ class IfLetExpr : public ExprWithBlock const std::vector &get_outer_attrs () const { return outer_attrs; } std::vector &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 +4597,8 @@ class MatchExpr : public ExprWithBlock const std::vector &get_match_cases () const { return match_arms; } std::vector &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 +4678,8 @@ class AwaitExpr : public ExprWithoutBlock 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 +4762,8 @@ class AsyncBlockExpr : public ExprWithBlock 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 */ @@ -5209,6 +5277,8 @@ class InlineAsm : public ExprWithoutBlock { return new InlineAsm (*this); } + + Expr::Kind get_expr_kind() const override { return Expr::Kind::InlineAsm; } }; } // namespace AST diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 4e3338a487ce..6f96bc422b8a 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -758,8 +758,6 @@ class Module : public VisItem 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 +897,8 @@ class Module : public VisItem 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 +960,8 @@ class ExternCrate : public VisItem 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 +1303,8 @@ class UseDeclaration : public VisItem 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 */ @@ -1459,6 +1463,8 @@ class Function : public VisItem, public AssociatedItem, public ExternalItem // 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 +1596,8 @@ class TypeAlias : public VisItem, public AssociatedItem 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 +1657,8 @@ class Struct : public VisItem 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> generic_params, @@ -2021,6 +2031,8 @@ class EnumItem : public VisItem 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); } }; @@ -2269,6 +2281,8 @@ class Enum : public VisItem // 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 +2382,8 @@ class Union : public VisItem 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 +2505,8 @@ class ConstantItem : public VisItem, public AssociatedItem 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 +2628,8 @@ class StaticItem : public VisItem 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 */ @@ -2973,6 +2993,8 @@ class Trait : public VisItem AST::TypeParam &get_implicit_self () { return self_param; } + Item::Kind get_item_kind() const override { return Item::Kind::Trait; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -3045,6 +3067,8 @@ class Impl : public VisItem return trait_type; } + Item::Kind get_item_kind() const override { return Item::Kind::Impl; } + protected: // Mega-constructor Impl (std::vector> generic_params, @@ -3930,6 +3954,8 @@ class ExternBlock : public VisItem const std::vector &get_inner_attrs () const { return inner_attrs; } std::vector &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 71cdcf0471ea..d6d31895cfdf 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -29,6 +29,7 @@ namespace Rust { namespace AST { + class MacroFragSpec { public: @@ -572,13 +573,10 @@ class MacroRulesDefinition : public VisItem is_builtin_rule = true; } - AST::Kind get_ast_kind () const override - { - return AST::Kind::MACRO_RULES_DEFINITION; - } - MacroKind get_kind () const { return kind; } + Item::Kind get_item_kind() const override { return Item::Kind::MacroRulesDefinition; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -610,11 +608,6 @@ class MacroInvocation : public TypeNoBounds, 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 +670,6 @@ class MacroInvocation : public TypeNoBounds, 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 +788,21 @@ class MacroInvocation : public TypeNoBounds, 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.h b/gcc/rust/ast/rust-path.h index 93171321ea9c..ca5124ab43e0 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -831,6 +831,11 @@ class PathInExpression : public Pattern, public ExprWithoutBlock Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } + Expr::Kind get_expr_kind () const override + { + return Expr::Kind::PathInExpression; + } + protected: PathInExpression (std::vector &&outer_attrs, bool has_opening_scope_resolution, location_t locus, @@ -1497,6 +1502,11 @@ class QualifiedPathInExpression : public Pattern, public ExprWithoutBlock rust_unreachable (); } + Expr::Kind get_expr_kind () const override + { + return Expr::Kind::QualifiedPathInExpression; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/expand/rust-macro-builtins-helpers.cc b/gcc/rust/expand/rust-macro-builtins-helpers.cc index 686edde23f23..33fe93f68a69 100644 --- a/gcc/rust/expand/rust-macro-builtins-helpers.cc +++ b/gcc/rust/expand/rust-macro-builtins-helpers.cc @@ -36,7 +36,7 @@ check_for_eager_invocations ( std::vector> pending; for (auto &expr : expressions) - if (expr->get_ast_kind () == AST::Kind::MACRO_INVOCATION) + if (expr->get_expr_kind () == AST::Expr::Kind::MacroInvocation) pending.emplace_back (std::unique_ptr ( static_cast (expr->clone_expr ().release ()))); diff --git a/gcc/rust/expand/rust-macro-builtins-utility.cc b/gcc/rust/expand/rust-macro-builtins-utility.cc index aea2902202bb..ff64879c5eae 100644 --- a/gcc/rust/expand/rust-macro-builtins-utility.cc +++ b/gcc/rust/expand/rust-macro-builtins-utility.cc @@ -117,7 +117,7 @@ MacroBuiltin::concat_handler (location_t invoc_locus, for (auto &expr : expanded_expr) { if (!expr->is_literal () - && expr->get_ast_kind () != AST::Kind::MACRO_INVOCATION) + && expr->get_expr_kind () != AST::Expr::Kind::MacroInvocation) { has_error = true; rust_error_at (expr->get_locus (), "expected a literal"); @@ -296,4 +296,4 @@ MacroBuiltin::stringify_handler (location_t invoc_locus, return AST::Fragment ({node}, std::move (token)); } -} // namespace Rust \ No newline at end of file +} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc index 9c2be4a57160..5936cf2c31ef 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc @@ -536,7 +536,7 @@ ResolveExpr::visit (AST::BreakExpr &expr) { bool funny_error = false; auto &break_expr = expr.get_break_expr (); - if (break_expr.get_ast_kind () == AST::Kind::IDENTIFIER) + if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier) { /* This is a break with an expression, and the expression is just a single identifier. See if the identifier is either diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc index 634523181139..2fe01b67f557 100644 --- a/gcc/rust/resolve/rust-early-name-resolver.cc +++ b/gcc/rust/resolve/rust-early-name-resolver.cc @@ -17,7 +17,7 @@ // . #include "rust-early-name-resolver.h" -#include "rust-ast-full.h" +#include "rust-pattern.h" #include "rust-name-resolver.h" #include "rust-macro-builtins.h" #include "rust-attribute-values.h" @@ -53,7 +53,7 @@ EarlyNameResolver::accumulate_escaped_macros (AST::Module &module) scoped (module.get_node_id (), [&module, &escaped_macros, this] { for (auto &item : module.get_items ()) { - if (item->get_ast_kind () == AST::Kind::MODULE) + if (item->get_item_kind () == AST::Item::Kind::Module) { auto &module = *static_cast (item.get ()); auto new_macros = accumulate_escaped_macros (module); @@ -64,7 +64,7 @@ EarlyNameResolver::accumulate_escaped_macros (AST::Module &module) continue; } - if (item->get_ast_kind () == AST::Kind::MACRO_RULES_DEFINITION) + if (item->get_item_kind () == AST::Item::Kind::MacroRulesDefinition) escaped_macros.emplace_back (item->clone_item ()); } }); @@ -113,7 +113,7 @@ EarlyNameResolver::visit (AST::Crate &crate) { auto new_macros = std::vector> (); - if (item->get_ast_kind () == AST::Kind::MODULE) + if (item->get_item_kind () == AST::Item::Kind::Module) new_macros = accumulate_escaped_macros ( *static_cast (item.get ())); @@ -300,7 +300,7 @@ EarlyNameResolver::visit (AST::Module &module) { auto new_macros = std::vector> (); - if (item->get_ast_kind () == AST::Kind::MODULE) + if (item->get_item_kind () == AST::Item::Kind::Module) new_macros = accumulate_escaped_macros ( *static_cast (item.get ())); From 46264a504fc0b0a3c240882c9f0e991b25418ce3 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Sun, 22 Dec 2024 15:59:27 +0000 Subject: [PATCH 14/35] wip: Base for AST for-loop desugar --- gcc/rust/ast/rust-desugar-for-loops.cc | 58 +++++++++++++++++ gcc/rust/ast/rust-desugar-for-loops.h | 86 ++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 gcc/rust/ast/rust-desugar-for-loops.cc create mode 100644 gcc/rust/ast/rust-desugar-for-loops.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 000000000000..21ceff7c94b7 --- /dev/null +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -0,0 +1,58 @@ +// 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 +// . + +#include "rust-desugar-for-loops.h" +#include "rust-ast-visitor.h" +#include "rust-ast.h" +#include "rust-stmt.h" +#include "rust-diagnostics.h" +#include "rust-expr.h" + +namespace Rust { +namespace AST { + +DesugarForLoops::DesugarForLoops () {} + +void +DesugarForLoops::go (AST::Crate &crate) +{ + DefaultASTVisitor::visit (crate); +} + +void +DesugarForLoops::visit (AST::BlockExpr &block) +{ + for (auto &stmt : block.get_statements ()) + { + if (stmt->get_stmt_kind () == AST::Stmt::Kind::Expr) + { + auto &expr = static_cast (*stmt); + + if (expr.get_expr ().get_expr_kind () == AST::Expr::Kind::Loop) + { + auto &loop = static_cast (expr.get_expr ()); + + if (loop.get_loop_kind () == AST::BaseLoopExpr::Kind::For) + rust_error_at (loop.get_locus (), "found a for-loop - yuck"); + } + } + } +} + +} // 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 000000000000..e0ea43cb7f0f --- /dev/null +++ b/gcc/rust/ast/rust-desugar-for-loops.h @@ -0,0 +1,86 @@ +// 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 +// . + +#ifndef RUST_DESUGAR_FOR_LOOPS +#define RUST_DESUGAR_FOR_LOOPS + +#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 in +// ``` +// +// becomes: +// +// ``` +// { +// let result = match ::std::iter::IntoIterator::into_iter() { +// 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 = __next; +// +// ; +// } +// } +// }; +// 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: + void visit (AST::BlockExpr &) override; +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DESUGAR_FOR_LOOPS From 4a7ae36f5913a5f94a0c67183d8344af4833a4ab Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Sun, 22 Dec 2024 15:59:44 +0000 Subject: [PATCH 15/35] fixup: add onto static_dispatch --- gcc/rust/hir/rust-ast-lower.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index c92c9432a68e..e33f5794a621 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -104,7 +104,11 @@ ASTLoweringBlock::visit (AST::BlockExpr &expr) for (auto &s : expr.get_statements ()) { - if (s->get_ast_kind () == AST::Kind::MACRO_INVOCATION) + // FIXME: We basically need to do that check for *every* single node in + // the AST. this isn't realistic and this should be turned into an + // optional, debug-visitor instead, which goes through the entire AST and + // checks if any of the nodes are macro invocations + if (s->get_stmt_kind () == AST::Stmt::Kind::MacroInvocation) rust_fatal_error ( s->get_locus (), "macro invocations should not get lowered to HIR - At " From 15145ddeafd2075b5bf7a223eaf53991327f09ba Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Sat, 21 Dec 2024 22:52:09 +0000 Subject: [PATCH 16/35] wip: Add base for desugaring for-loops during AST --- gcc/rust/Make-lang.in | 1 + gcc/rust/ast/rust-desugar-for-loops.cc | 30 +++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index fe82ab42ec87..c73440692bc1 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -230,6 +230,7 @@ GRS_OBJS = \ rust/rust-expand-format-args.o \ rust/rust-lang-item.o \ rust/rust-collect-lang-items.o \ + rust/rust-desugar-for-loops.o \ $(END) # removed object files from here diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc index 21ceff7c94b7..3a6a459137cf 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.cc +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -19,9 +19,11 @@ #include "rust-desugar-for-loops.h" #include "rust-ast-visitor.h" #include "rust-ast.h" +#include "rust-path.h" #include "rust-stmt.h" #include "rust-diagnostics.h" #include "rust-expr.h" +#include "rust-ast-builder.h" namespace Rust { namespace AST { @@ -34,6 +36,25 @@ DesugarForLoops::go (AST::Crate &crate) DefaultASTVisitor::visit (crate); } +void +replace_for_loop (std::unique_ptr &for_loop, + std::unique_ptr &&expanded) +{ + for_loop = std::move (expanded); +} + +std::unique_ptr +desugar (AST::ForLoopExpr &expr) +{ + auto builder = AST::Builder (expr.get_locus ()); + + auto into_iter + = builder.call (builder.lang_item_path (LangItem::Kind::INTOITER_INTOITER), + expr.get_iterator_expr ().clone_expr ()); + + return into_iter; +} + void DesugarForLoops::visit (AST::BlockExpr &block) { @@ -48,7 +69,14 @@ DesugarForLoops::visit (AST::BlockExpr &block) auto &loop = static_cast (expr.get_expr ()); if (loop.get_loop_kind () == AST::BaseLoopExpr::Kind::For) - rust_error_at (loop.get_locus (), "found a for-loop - yuck"); + { + auto &for_loop = static_cast (loop); + + auto desugared = desugar (for_loop); + + replace_for_loop (expr.get_expr_ptr (), + std::move (desugared)); + } } } } From f369d2fbc555e707a903c07ec7885a273257c8a1 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Sat, 21 Dec 2024 22:52:57 +0000 Subject: [PATCH 17/35] ast-builder: Add more methods This commit adds new methods for building pattern nodes, match expressions and more precise call expressions. gcc/rust/ChangeLog: * ast/rust-ast-builder.cc: Add new functions. * ast/rust-ast-builder.h: Declare them. --- gcc/rust/ast/rust-ast-builder.cc | 90 ++++++++++++++++++++++++++++++++ gcc/rust/ast/rust-ast-builder.h | 29 ++++++++++ 2 files changed, 119 insertions(+) diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 121b8c8d7e0a..5b071b3cd692 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -20,6 +20,7 @@ #include "rust-ast-builder-type.h" #include "rust-common.h" #include "rust-expr.h" +#include "rust-path.h" #include "rust-token.h" #include "rust-make-unique.h" @@ -42,6 +43,33 @@ Builder::call (std::unique_ptr &&path, new CallExpr (std::move (path), std::move (args), {}, loc)); } +std::unique_ptr +Builder::call (std::unique_ptr &&path, + std::vector> &&args) const +{ + return call (std::unique_ptr ( + new PathInExpression (std::move (path), {}, loc)), + std::move (args)); +} + +std::unique_ptr +Builder::call (std::unique_ptr &&path, std::unique_ptr &&arg) const +{ + auto args = std::vector> (); + args.emplace_back (std::move (arg)); + + return call (std::move (path), std::move (args)); +} + +std::unique_ptr +Builder::call (std::unique_ptr &&path, std::unique_ptr &&arg) const +{ + auto args = std::vector> (); + args.emplace_back (std::move (arg)); + + return call (std::move (path), std::move (args)); +} + std::unique_ptr Builder::array (std::vector> &&members) const { @@ -56,6 +84,12 @@ Builder::identifier (std::string name) const return std::unique_ptr (new IdentifierExpr (name, {}, loc)); } +std::unique_ptr +Builder::identifier_pattern (std::string name, bool mut) const +{ + return std::unique_ptr (new IdentifierPattern (name, loc, false, mut)); +} + std::unique_ptr Builder::tuple_idx (std::string receiver, int idx) const { @@ -117,6 +151,22 @@ Builder::path_in_expression (std::vector &&segments) const return PathInExpression (std::move (path_segments), {}, loc); } +PathInExpression +Builder::path_in_expression (LangItem::Kind lang_item) const +{ + return PathInExpression (lang_item, {}, loc); +} + +std::unique_ptr +Builder::block (std::unique_ptr &&stmt, + std::unique_ptr &&tail_expr) const +{ + auto stmts = std::vector>(); + stmts.emplace_back(std::move(stmt)); + + return block(std::move(stmts), std::move(tail_expr)); +} + std::unique_ptr Builder::block (std::vector> &&stmts, std::unique_ptr &&tail_expr) const @@ -189,6 +239,46 @@ Builder::wildcard () const return std::unique_ptr (new WildcardPattern (loc)); } +std::unique_ptr +Builder::lang_item_path (LangItem::Kind kind) const +{ + return std::unique_ptr (new LangItemPath (kind, loc)); +} + +std::unique_ptr +Builder::match (std::unique_ptr &&scrutinee, + std::vector &&cases) +{ + return std::unique_ptr ( + new MatchExpr (std::move (scrutinee), std::move (cases), {}, {}, loc)); +} + +MatchArm +Builder::match_arm (std::unique_ptr &&pattern) +{ + auto patterns = std::vector> (); + patterns.emplace_back (std::move (pattern)); + + return MatchArm (std::move (patterns), loc); +} + +MatchCase +Builder::match_case (std::unique_ptr &&pattern, + std::unique_ptr &&expr) +{ + return MatchCase (match_arm (std::move (pattern)), std::move (expr)); +} + +std::unique_ptr +Builder::loop (std::vector> &&stmts) +{ + auto block = std::unique_ptr ( + new BlockExpr (std::move (stmts), nullptr, {}, {}, LoopLabel::error (), loc, + loc)); + + return std::unique_ptr (new LoopExpr (std::move (block), loc)); +} + std::unique_ptr Builder::new_type (Type &type) { diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index fa258c7dfa82..92f1779cc5a5 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -20,6 +20,7 @@ #define AST_BUILDER_H #include "rust-ast-full.h" +#include "rust-expr.h" namespace Rust { namespace AST { @@ -38,6 +39,7 @@ class Builder /* Create an identifier expression (`variable`) */ std::unique_ptr identifier (std::string name) const; + std::unique_ptr identifier_pattern (std::string name, bool mut = false) const; /* Create a tuple index expression (`receiver.0`) */ std::unique_ptr tuple_idx (std::string receiver, int idx) const; @@ -53,6 +55,9 @@ class Builder std::unique_ptr block (std::vector> &&stmts, std::unique_ptr &&tail_expr = nullptr) const; + std::unique_ptr block (std::unique_ptr &&stmt, + std::unique_ptr &&tail_expr + = nullptr) const; /* Create a let binding with an optional type and initializer (`let : * = `) */ @@ -66,6 +71,12 @@ class Builder */ std::unique_ptr call (std::unique_ptr &&path, std::vector> &&args) const; + std::unique_ptr call (std::unique_ptr &&path, + std::vector> &&args) const; + std::unique_ptr call (std::unique_ptr &&path, + std::unique_ptr &&arg) const; + std::unique_ptr call (std::unique_ptr &&path, + std::unique_ptr &&arg) const; /** * Create an array expression (`[member0, member1, member2]`) @@ -100,6 +111,11 @@ class Builder PathInExpression path_in_expression (std::vector &&segments) const; + /** + * Create a path in expression from a lang item. + */ + PathInExpression path_in_expression (LangItem::Kind lang_item) const; + /* Create a struct expression for unit structs (`S`) */ std::unique_ptr struct_expr_struct (std::string struct_name) const; @@ -122,6 +138,19 @@ class Builder /* Create a wildcard pattern (`_`) */ std::unique_ptr wildcard () const; + /* Create a lang item path usable as a general path */ + std::unique_ptr lang_item_path (LangItem::Kind) const; + + /* Create match expressions and their components */ + std::unique_ptr match (std::unique_ptr &&scrutinee, + std::vector &&cases); + MatchArm match_arm (std::unique_ptr &&pattern); + MatchCase match_case (std::unique_ptr &&pattern, + std::unique_ptr &&expr); + + /* Create a loop expression */ + std::unique_ptr loop (std::vector> &&stmts); + static std::unique_ptr new_type (Type &type); static std::unique_ptr From 5d39f8e680a7dd27ce5e69397769e027ebad83a4 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Sat, 21 Dec 2024 22:53:50 +0000 Subject: [PATCH 18/35] wip: ast: PathInExpression: new constructors? --- gcc/rust/ast/rust-path.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index ca5124ab43e0..001da5f0164a 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -715,6 +715,24 @@ class PathInExpression : public Pattern, public ExprWithoutBlock marked_for_strip (false) {} + PathInExpression (LangItem::Kind lang_item_kind, + std::vector outer_attrs, location_t locus) + : outer_attrs (std::move (outer_attrs)), + has_opening_scope_resolution (false), locus (locus), + _node_id (Analysis::Mappings::get ().get_next_node_id ()), + path (Rust::make_unique (lang_item_kind, locus)), + marked_for_strip (false) + {} + + PathInExpression (std::unique_ptr path, + std::vector outer_attrs, location_t locus, + bool has_opening_scope_resolution = false) + : 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 (std::move (path)), marked_for_strip (false) + {} + PathInExpression (const PathInExpression &other) : outer_attrs (other.outer_attrs), has_opening_scope_resolution (other.has_opening_scope_resolution), From 49fa7b22c0b6c64475ac6a8d0bf5c851ec36c51a Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Sat, 21 Dec 2024 22:54:15 +0000 Subject: [PATCH 19/35] session-manager: Call DesugarForLoops --- gcc/rust/rust-session-manager.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 561ba95d14e5..e870020705f7 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -18,6 +18,7 @@ #include "rust-session-manager.h" #include "rust-collect-lang-items.h" +#include "rust-desugar-for-loops.h" #include "rust-diagnostics.h" #include "rust-hir-pattern-analysis.h" #include "rust-immutable-name-resolution-context.h" @@ -602,6 +603,7 @@ Session::compile_crate (const char *filename) return; AST::CollectLangItems ().go (parsed_crate); + AST::DesugarForLoops ().go(parsed_crate); auto name_resolution_ctx = Resolver2_0::NameResolutionContext (); // expansion pipeline stage From c917367fd5856dcaf1fbc436ba794fc7c0c94769 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 24 Dec 2024 16:13:00 +0000 Subject: [PATCH 20/35] for-loops: Go further! --- gcc/rust/ast/rust-desugar-for-loops.cc | 95 ++++++++++++++++++++++++-- gcc/rust/ast/rust-desugar-for-loops.h | 16 +++++ 2 files changed, 105 insertions(+), 6 deletions(-) diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc index 3a6a459137cf..eb58bb56a10a 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.cc +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -43,14 +43,97 @@ replace_for_loop (std::unique_ptr &for_loop, for_loop = std::move (expanded); } -std::unique_ptr -desugar (AST::ForLoopExpr &expr) +MatchArm +DesugarForLoops::DesugarCtx::make_match_arm (std::unique_ptr &&path) +{ + auto patterns = std::vector> (); + patterns.emplace_back (std::move (path)); + + return MatchArm (std::move (patterns), loc); +} + +MatchCase +DesugarForLoops::DesugarCtx::make_break_arm () +{ + auto arm + = make_match_arm (builder.lang_item_path (LangItem::Kind::OPTION_NONE)); + + auto break_expr = std::unique_ptr ( + new BreakExpr (Lifetime::error (), nullptr, {}, loc)); + + return MatchCase (arm, std::move (break_expr)); +} + +MatchCase +DesugarForLoops::DesugarCtx::make_continue_arm () { - auto builder = AST::Builder (expr.get_locus ()); + // Missing the actual `val` binding + auto arm + = make_match_arm (builder.lang_item_path (LangItem::Kind::OPTION_SOME)); - auto into_iter - = builder.call (builder.lang_item_path (LangItem::Kind::INTOITER_INTOITER), - expr.get_iterator_expr ().clone_expr ()); + auto next = builder.identifier ("__next"); + auto val = builder.identifier ("val"); + + auto assignment = std::unique_ptr ( + new AssignmentExpr (std::move (next), std::move (val), {}, loc)); + + return MatchCase (arm, std::move (assignment)); +} + +std::unique_ptr +DesugarForLoops::DesugarCtx::statementify (std::unique_ptr &&expr) +{ + return std::unique_ptr (new ExprStmt (std::move (expr), loc, true)); +} + +std::unique_ptr +DesugarForLoops::desugar (AST::ForLoopExpr &expr) +{ + auto ctx = DesugarCtx (expr.get_locus ()); + + // IntoIterator::into_iter() + auto into_iter = ctx.builder.call (ctx.builder.lang_item_path ( + LangItem::Kind::INTOITER_INTOITER), + expr.get_iterator_expr ().clone_expr ()); + + // Iterator::next(iter) + auto next_call = ctx.builder.call (ctx.builder.lang_item_path ( + LangItem::Kind::ITERATOR_NEXT), + ctx.builder.identifier ("iter")); + + // None => break, + auto break_arm = ctx.make_break_arm (); + // Some(val) => { __next = val; }, + auto continue_arm = ctx.make_continue_arm (); + + // match { + // + // + // } + 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 ("__next")); + // let = __next; + auto let_pat = ctx.builder.let (expr.get_pattern ().clone_pattern (), nullptr, + ctx.builder.identifier ("__next")); + + auto loop_stmts = std::vector> (); + 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 { + // ; + // ; + // ; + // + // ; + // } + ctx.builder.loop(std::move(loop_stmts)); return into_iter; } diff --git a/gcc/rust/ast/rust-desugar-for-loops.h b/gcc/rust/ast/rust-desugar-for-loops.h index e0ea43cb7f0f..aca26747fcf1 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.h +++ b/gcc/rust/ast/rust-desugar-for-loops.h @@ -19,6 +19,7 @@ #ifndef RUST_DESUGAR_FOR_LOOPS #define RUST_DESUGAR_FOR_LOOPS +#include "rust-ast-builder.h" #include "rust-ast-visitor.h" #include "rust-expr.h" @@ -77,6 +78,21 @@ class DesugarForLoops : public DefaultASTVisitor 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); + MatchCase make_break_arm (); + MatchCase make_continue_arm (); + std::unique_ptr statementify(std::unique_ptr &&expr); + }; + + std::unique_ptr desugar (AST::ForLoopExpr &expr); + void visit (AST::BlockExpr &) override; }; From 4392b2c0d2ebb3a39fa3d33e4bb9f9fb6ea7dc7e Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 23 Dec 2024 10:25:38 +0000 Subject: [PATCH 21/35] for-loops: more desugar --- gcc/rust/ast/rust-desugar-for-loops.cc | 52 +++++++++++++++++++------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc index eb58bb56a10a..2c70094da23e 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.cc +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -20,6 +20,7 @@ #include "rust-ast-visitor.h" #include "rust-ast.h" #include "rust-path.h" +#include "rust-pattern.h" #include "rust-stmt.h" #include "rust-diagnostics.h" #include "rust-expr.h" @@ -55,29 +56,37 @@ DesugarForLoops::DesugarCtx::make_match_arm (std::unique_ptr &&path) MatchCase DesugarForLoops::DesugarCtx::make_break_arm () { - auto arm - = make_match_arm (builder.lang_item_path (LangItem::Kind::OPTION_NONE)); + auto arm = make_match_arm (std::unique_ptr (new PathInExpression ( + builder.path_in_expression (LangItem::Kind::OPTION_NONE)))); auto break_expr = std::unique_ptr ( new BreakExpr (Lifetime::error (), nullptr, {}, loc)); - return MatchCase (arm, std::move (break_expr)); + return MatchCase (std::move (arm), std::move (break_expr)); } MatchCase DesugarForLoops::DesugarCtx::make_continue_arm () { - // Missing the actual `val` binding - auto arm - = make_match_arm (builder.lang_item_path (LangItem::Kind::OPTION_SOME)); + auto val = builder.identifier_pattern ("val"); + + auto patterns = std::vector> (); + patterns.emplace_back (std::move (val)); + + auto pattern_item = std::unique_ptr ( + new TupleStructItemsNoRange (std::move (patterns))); + auto pattern = std::unique_ptr (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 ("__next"); - auto val = builder.identifier ("val"); auto assignment = std::unique_ptr ( - new AssignmentExpr (std::move (next), std::move (val), {}, loc)); + new AssignmentExpr (std::move (next), builder.identifier ("val"), {}, loc)); - return MatchCase (arm, std::move (assignment)); + return MatchCase (std::move (val_arm), std::move (assignment)); } std::unique_ptr @@ -97,9 +106,9 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr) expr.get_iterator_expr ().clone_expr ()); // Iterator::next(iter) - auto next_call = ctx.builder.call (ctx.builder.lang_item_path ( - LangItem::Kind::ITERATOR_NEXT), - ctx.builder.identifier ("iter")); + auto next_call = ctx.builder.call ( + ctx.builder.lang_item_path (LangItem::Kind::ITERATOR_NEXT), + ctx.builder.ref (ctx.builder.identifier ("iter"), true)); // None => break, auto break_arm = ctx.make_break_arm (); @@ -135,7 +144,24 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr) // } ctx.builder.loop(std::move(loop_stmts)); - return into_iter; + auto mut_iter_pattern = ctx.builder.identifier_pattern ("iter"); + auto match_iter + = ctx.builder.match (std::move (into_iter), + {ctx.builder.match_case (std::move (mut_iter_pattern), + std::move (loop))}); + + auto let_result = ctx.builder.let (ctx.builder.identifier_pattern ("result"), + nullptr, std::move (match_iter)); + auto result_return = ctx.builder.identifier ("result"); + + // return ctx.builder.block (std::move (let_result), std::move + // (result_return)); + auto desugar + = ctx.builder.block (std::move (let_result), std::move (result_return)); + + AST::Dump::debug (*desugar); + + return desugar; } void From 0197e1cc563fe9180c5e901356a4666537037b32 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 23 Dec 2024 10:27:13 +0000 Subject: [PATCH 22/35] lang-items: Collect enum variants as lang items --- gcc/rust/ast/rust-collect-lang-items.cc | 9 +++++++++ gcc/rust/ast/rust-collect-lang-items.h | 1 + 2 files changed, 10 insertions(+) diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc index 50d134a429f5..dba2deb3c7f4 100644 --- a/gcc/rust/ast/rust-collect-lang-items.cc +++ b/gcc/rust/ast/rust-collect-lang-items.cc @@ -19,6 +19,7 @@ #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" @@ -90,5 +91,13 @@ CollectLangItems::visit (AST::Function &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 index 1d021b1d9c50..131930f5a742 100644 --- a/gcc/rust/ast/rust-collect-lang-items.h +++ b/gcc/rust/ast/rust-collect-lang-items.h @@ -48,6 +48,7 @@ class CollectLangItems : public DefaultASTVisitor void visit (AST::Trait &item) override; void visit (AST::TraitItemType &item) override; void visit (AST::Function &item) override; + void visit (AST::EnumItem &item) override; private: template void maybe_add_lang_item (const T &item); From ebdbedd9b38c495043261a1805cb2cef944e1b2b Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 23 Dec 2024 10:58:41 +0000 Subject: [PATCH 23/35] wip: Adapt more visitors to LangItem PathInExprs --- gcc/rust/ast/rust-ast-visitor.cc | 6 ++++-- gcc/rust/expand/rust-cfg-strip.cc | 10 +++++++--- gcc/rust/expand/rust-expand-visitor.cc | 7 ++++--- gcc/rust/resolve/rust-ast-resolve-path.cc | 14 ++++++++++++++ gcc/rust/resolve/rust-early-name-resolver.cc | 7 ++++--- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index e60f5ca9b85d..2b70659ae233 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -100,8 +100,10 @@ void DefaultASTVisitor::visit (AST::PathInExpression &path) { visit_outer_attrs (path); - for (auto &segment : path.get_segments ()) - visit (segment); + + if (path.get_path ().get_path_kind () != AST::Path::Kind::LangItem) + for (auto &segment : path.get_segments ()) + visit (segment); } void diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index 33fb64f0ff2d..f65be66a4d8a 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -19,6 +19,7 @@ #include "rust-cfg-strip.h" #include "rust-ast-full.h" #include "rust-ast-visitor.h" +#include "rust-path.h" #include "rust-session-manager.h" #include "rust-attribute-values.h" @@ -434,10 +435,13 @@ CfgStrip::visit (AST::PathInExpression &path) return; } - for (auto &segment : path.get_segments ()) + if (path.get_path ().get_path_kind () != AST::Path::Kind::LangItem) { - if (segment.has_generic_args ()) - maybe_strip_generic_args (segment.get_generic_args ()); + for (auto &segment : path.get_segments ()) + { + if (segment.has_generic_args ()) + maybe_strip_generic_args (segment.get_generic_args ()); + } } } diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index e40597e3bc89..0a636abac771 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -477,9 +477,10 @@ ExpandVisitor::visit (AST::MacroInvocation ¯o_invoc) void ExpandVisitor::visit (AST::PathInExpression &path) { - for (auto &segment : path.get_segments ()) - if (segment.has_generic_args ()) - expand_generic_args (segment.get_generic_args ()); + if (path.get_path ().get_path_kind () != AST::Path::Kind::LangItem) + for (auto &segment : path.get_segments ()) + if (segment.has_generic_args ()) + expand_generic_args (segment.get_generic_args ()); } void diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc index b50f94f6c283..8571dedc36a5 100644 --- a/gcc/rust/resolve/rust-ast-resolve-path.cc +++ b/gcc/rust/resolve/rust-ast-resolve-path.cc @@ -18,6 +18,7 @@ #include "rust-ast-resolve-path.h" #include "rust-ast-resolve-type.h" +#include "rust-hir-map.h" #include "rust-path.h" namespace Rust { @@ -49,6 +50,19 @@ ResolvePath::go (AST::SimplePath &expr) NodeId ResolvePath::resolve_path (AST::PathInExpression &expr) { + if (expr.get_path ().get_path_kind () == AST::Path::Kind::LangItem) + { + auto lang_item = static_cast (expr.get_path ()); + + if (auto lookup = Analysis::Mappings::get ().lookup_lang_item_node ( + lang_item.get_lang_item_kind ())) + return *lookup; + + rust_fatal_error ( + expr.get_locus (), "undeclared lang item: %qs", + LangItem::ToString (lang_item.get_lang_item_kind ()).c_str ()); + } + NodeId resolved_node_id = UNKNOWN_NODEID; NodeId module_scope_id = resolver->peek_current_module_scope (); NodeId previous_resolved_node_id = module_scope_id; diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc index 2fe01b67f557..d89b312f65f4 100644 --- a/gcc/rust/resolve/rust-early-name-resolver.cc +++ b/gcc/rust/resolve/rust-early-name-resolver.cc @@ -156,9 +156,10 @@ EarlyNameResolver::visit (AST::ConstGenericParam &) void EarlyNameResolver::visit (AST::PathInExpression &path) { - for (auto &segment : path.get_segments ()) - if (segment.has_generic_args ()) - resolve_generic_args (segment.get_generic_args ()); + if (path.get_path ().get_path_kind () != AST::Path::Kind::LangItem) + for (auto &segment : path.get_segments ()) + if (segment.has_generic_args ()) + resolve_generic_args (segment.get_generic_args ()); } void From 4a6238348b3d2ef4b952180fe768d8d6ba0e3556 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 23 Dec 2024 10:59:52 +0000 Subject: [PATCH 24/35] lower: Lower LangItem PathInExprs properly --- gcc/rust/hir/rust-ast-lower.cc | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index e33f5794a621..7efcff9801f1 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -494,6 +494,21 @@ ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr) void ASTLowerPathInExpression::visit (AST::PathInExpression &expr) { + auto crate_num = mappings.get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings.get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + if (expr.get_path ().get_path_kind () == AST::Path::Kind::LangItem) + { + auto lang_item = static_cast (expr.get_path ()); + + translated + = new HIR::PathInExpression (mapping, lang_item.get_lang_item_kind (), + expr.get_locus (), false); + return; + } + std::vector path_segments; auto &segments = expr.get_segments (); for (auto &s : segments) @@ -504,10 +519,6 @@ ASTLowerPathInExpression::visit (AST::PathInExpression &expr) HIR::PathExprSegment *lowered_seg = &path_segments.back (); mappings.insert_hir_path_expr_seg (lowered_seg); } - auto crate_num = mappings.get_current_crate (); - Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), - mappings.get_next_hir_id (crate_num), - UNKNOWN_LOCAL_DEFID); translated = new HIR::PathInExpression (mapping, std::move (path_segments), expr.get_locus (), From b2a7d6ac7e61367680a6ea8735e9ab324d8f5424 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 23 Dec 2024 11:00:51 +0000 Subject: [PATCH 25/35] tychck: format --- gcc/rust/typecheck/rust-hir-type-check-path.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index d281f08e85e2..dac8694e292b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -199,7 +199,7 @@ TypeCheckExpr::visit (HIR::PathInExpression &expr) // FIXME: We probably need to check *if* the type needs substitutions // or not - infered = SubstMapper::InferSubst (resolved, expr.get_locus()); + infered = SubstMapper::InferSubst (resolved, expr.get_locus ()); // FIXME: also we probably need to insert resolved types in the name // resolver here From eb15aa8a5b98a5817cc0ca10707480b9d33606ee Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 23 Dec 2024 16:43:35 +0000 Subject: [PATCH 26/35] lang-items: Add LangItem::IsEnumVariant gcc/rust/ChangeLog: * util/rust-lang-item.cc (LangItem::IsEnumVariant): New function. * util/rust-lang-item.h: New function. --- gcc/rust/util/rust-lang-item.cc | 6 ++++++ gcc/rust/util/rust-lang-item.h | 1 + 2 files changed, 7 insertions(+) diff --git a/gcc/rust/util/rust-lang-item.cc b/gcc/rust/util/rust-lang-item.cc index 8b1b1e346474..c1cb78fe7079 100644 --- a/gcc/rust/util/rust-lang-item.cc +++ b/gcc/rust/util/rust-lang-item.cc @@ -188,4 +188,10 @@ LangItem::NegationOperatorToLangItem (NegationOperator op) rust_unreachable (); } +bool +LangItem::IsEnumVariant (LangItem::Kind type) +{ + return type == Kind::OPTION_NONE || type == Kind::OPTION_SOME; +} + } // namespace Rust diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h index 4b0217616783..4ff723fd0dde 100644 --- a/gcc/rust/util/rust-lang-item.h +++ b/gcc/rust/util/rust-lang-item.h @@ -135,6 +135,7 @@ class LangItem static Kind CompoundAssignmentOperatorToLangItem (ArithmeticOrLogicalOperator op); static Kind NegationOperatorToLangItem (NegationOperator op); + static bool IsEnumVariant (Kind type); }; } // namespace Rust From 59996eb84c70f6bad19ad625feedfc9fcc5e7a3d Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 23 Dec 2024 16:44:17 +0000 Subject: [PATCH 27/35] wip: Typechecker langitem paths more better --- .../typecheck/rust-hir-type-check-path.cc | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index dac8694e292b..8cf8c9ccac83 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -190,16 +190,42 @@ TypeCheckExpr::visit (HIR::PathInExpression &expr) { auto hir_id = mappings.lookup_node_to_hir (*lookup); - TyTy::BaseType *resolved = nullptr; - context->lookup_type (*hir_id, &resolved); - // We can type resolve the path in expression easily as it is a lang // item path, but we still need to setup the various generics and // substitutions // FIXME: We probably need to check *if* the type needs substitutions // or not - infered = SubstMapper::InferSubst (resolved, expr.get_locus ()); + if (LangItem::IsEnumVariant (expr.get_lang_item_kind ())) + { + std::pair enum_item_lookup + = mappings.lookup_hir_enumitem (*hir_id); + bool enum_item_ok = enum_item_lookup.first != nullptr + && enum_item_lookup.second != nullptr; + rust_assert (enum_item_ok); + + HirId variant_id + = enum_item_lookup.second->get_mappings ().get_hirid (); + + HIR::EnumItem *enum_item = enum_item_lookup.second; + resolved_node_id = enum_item->get_mappings ().get_nodeid (); + + // insert the id of the variant we are resolved to + context->insert_variant_definition ( + expr.get_mappings ().get_hirid (), variant_id); + + query_type(variant_id, &infered); + infered = SubstMapper::InferSubst (infered, expr.get_locus ()); + } + else + { + TyTy::BaseType *resolved = nullptr; + context->lookup_type (*hir_id, &resolved); + + rust_assert (resolved); + + infered = SubstMapper::InferSubst (resolved, expr.get_locus ()); + } // FIXME: also we probably need to insert resolved types in the name // resolver here From b8e6b9af51f531e9ff1a6cb9bcb0abc1888e4061 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 23 Dec 2024 16:45:24 +0000 Subject: [PATCH 28/35] rust-macro.h: Format --- gcc/rust/ast/rust-macro.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index d6d31895cfdf..b2120b3d4e7f 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -575,7 +575,10 @@ class MacroRulesDefinition : public VisItem MacroKind get_kind () const { return kind; } - Item::Kind get_item_kind() const override { return Item::Kind::MacroRulesDefinition; } + Item::Kind get_item_kind () const override + { + return Item::Kind::MacroRulesDefinition; + } protected: /* Use covariance to implement clone function as returning this object rather From 807430708a9292b13779944cbe9c7fad2dea17ac Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 23 Dec 2024 17:04:14 +0000 Subject: [PATCH 29/35] desugar? --- gcc/rust/ast/rust-desugar-for-loops.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc index 2c70094da23e..609142de53b5 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.cc +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -142,7 +142,7 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr) // // ; // } - ctx.builder.loop(std::move(loop_stmts)); + auto loop = ctx.builder.loop (std::move (loop_stmts)); auto mut_iter_pattern = ctx.builder.identifier_pattern ("iter"); auto match_iter From 1e2337dacea48fb668ca0814aa166f8d990bb45f Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Sun, 22 Dec 2024 20:04:16 +0000 Subject: [PATCH 30/35] wip: split me up --- gcc/rust/ast/rust-ast-collector.cc | 19 +++++++++++++++++-- gcc/rust/ast/rust-desugar-for-loops.cc | 4 +++- gcc/rust/ast/rust-path.h | 2 ++ gcc/rust/hir/rust-ast-lower.cc | 19 +------------------ 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 8f66742d1196..e6d623b493d2 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -21,6 +21,7 @@ #include "rust-expr.h" #include "rust-item.h" #include "rust-keyword-values.h" +#include "rust-path.h" #include "rust-system.h" #include "rust-token.h" @@ -553,11 +554,25 @@ TokenCollector::visit (PathExprSegment &segment) void TokenCollector::visit (PathInExpression &path) { - if (path.opening_scope_resolution ()) + if (path.get_path ().get_path_kind () == Path::Kind::LangItem) { - push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ())); + auto lang_item = static_cast (path.get_path ()); + + 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 ( + lang_item.get_lang_item_kind ()))); + push (Rust::Token::make (TokenId::RIGHT_SQUARE, path.get_locus ())); + + return; } + if (path.opening_scope_resolution ()) + push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ())); + visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION); } diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc index 609142de53b5..c7b61ade5707 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.cc +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -25,6 +25,7 @@ #include "rust-diagnostics.h" #include "rust-expr.h" #include "rust-ast-builder.h" +#include "rust-ast-dump.h" namespace Rust { namespace AST { @@ -133,7 +134,8 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr) 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_stmts.emplace_back ( + ctx.statementify (expr.get_loop_block ().clone_expr ())); // loop { // ; diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 001da5f0164a..a64a02df4e37 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -783,6 +783,8 @@ class PathInExpression : public Pattern, public ExprWithoutBlock location_t get_locus () const override final { return locus; } + Path& get_path() { return *path; } + void accept_vis (ASTVisitor &vis) override; void mark_for_strip () override { marked_for_strip = true; } diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index 7efcff9801f1..c4864844d043 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -418,24 +418,7 @@ ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr) void ASTLoweringExprWithBlock::visit (AST::ForLoopExpr &expr) { - // TODO FIXME - - // HIR::BlockExpr *loop_block - // = ASTLoweringBlock::translate (expr.get_loop_block ().get (), - // &terminated); - // HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ()); - // HIR::Expr *iterator_expr - // = ASTLoweringExpr::translate (expr.get_iterator_expr ().get (), - // &terminated); - // HIR::Pattern *loop_pattern - // = ASTLoweringPattern::translate (expr.get_pattern ().get ()); - - // auto crate_num = mappings->get_current_crate (); - // Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), - // mappings->get_next_hir_id (crate_num), - // UNKNOWN_LOCAL_DEFID); - - gcc_unreachable (); + rust_unreachable(); } void From ae3c3097370ff338997e1c73aff429dca4df7d49 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 24 Dec 2024 11:21:10 +0000 Subject: [PATCH 31/35] [cleanup]: path-compile: Resolve lang item paths properly --- gcc/rust/backend/rust-compile-resolve-path.cc | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 5f6ba7cce433..1e2ebbcd9c7a 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -23,6 +23,7 @@ #include "rust-compile-implitem.h" #include "rust-compile-expr.h" #include "rust-hir-map.h" +#include "rust-hir-path.h" #include "rust-hir-trait-resolve.h" #include "rust-hir-path-probe.h" #include "rust-compile-extern.h" @@ -35,14 +36,28 @@ namespace Compile { void ResolvePathRef::visit (HIR::QualifiedPathInExpression &expr) { - resolved = resolve (expr.get_final_segment ().get_segment (), - expr.get_mappings (), expr.get_locus (), true); + auto final_segment = HIR::PathIdentSegment::create_error (); + if (expr.get_path_kind () == HIR::PathPattern::Kind::LangItem) + final_segment + = HIR::PathIdentSegment (LangItem::ToString (expr.get_lang_item_kind ())); + else + final_segment = expr.get_final_segment ().get_segment (); + + resolved + = resolve (final_segment, expr.get_mappings (), expr.get_locus (), true); } void ResolvePathRef::visit (HIR::PathInExpression &expr) { - resolved = resolve (expr.get_final_segment ().get_segment (), + auto final_segment = HIR::PathIdentSegment::create_error (); + if (expr.get_path_kind () == HIR::PathPattern::Kind::LangItem) + final_segment + = HIR::PathIdentSegment (LangItem::ToString (expr.get_lang_item_kind ())); + else + final_segment = expr.get_final_segment ().get_segment (); + + resolved = resolve (final_segment, expr.get_mappings (), expr.get_locus (), false); } From 45a9d781fecd1ad8f9f3cf4a517bee6c66d0e09c Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 24 Dec 2024 11:44:06 +0000 Subject: [PATCH 32/35] for-loops: Close! they're an infinite loop rn --- gcc/rust/ast/rust-desugar-for-loops.cc | 47 ++++++++++++-------------- gcc/rust/ast/rust-desugar-for-loops.h | 3 +- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc index c7b61ade5707..253bde097d6f 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.cc +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -146,7 +146,7 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr) // } auto loop = ctx.builder.loop (std::move (loop_stmts)); - auto mut_iter_pattern = ctx.builder.identifier_pattern ("iter"); + auto mut_iter_pattern = ctx.builder.identifier_pattern ("iter", true); auto match_iter = ctx.builder.match (std::move (into_iter), {ctx.builder.match_case (std::move (mut_iter_pattern), @@ -156,42 +156,37 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr) nullptr, std::move (match_iter)); auto result_return = ctx.builder.identifier ("result"); - // return ctx.builder.block (std::move (let_result), std::move - // (result_return)); - auto desugar - = ctx.builder.block (std::move (let_result), std::move (result_return)); - - AST::Dump::debug (*desugar); - - return desugar; + return ctx.builder.block (std::move (let_result), std::move (result_return)); } void -DesugarForLoops::visit (AST::BlockExpr &block) +DesugarForLoops::maybe_desugar_expr (std::unique_ptr &expr) { - for (auto &stmt : block.get_statements ()) + if (expr->get_expr_kind () == AST::Expr::Kind::Loop) { - if (stmt->get_stmt_kind () == AST::Stmt::Kind::Expr) - { - auto &expr = static_cast (*stmt); - - if (expr.get_expr ().get_expr_kind () == AST::Expr::Kind::Loop) - { - auto &loop = static_cast (expr.get_expr ()); + auto &loop = static_cast (*expr); - if (loop.get_loop_kind () == AST::BaseLoopExpr::Kind::For) - { - auto &for_loop = static_cast (loop); + if (loop.get_loop_kind () == AST::BaseLoopExpr::Kind::For) + { + auto &for_loop = static_cast (loop); - auto desugared = desugar (for_loop); + auto desugared = desugar (for_loop); - replace_for_loop (expr.get_expr_ptr (), - std::move (desugared)); - } - } + 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 (*stmt).get_expr_ptr ()); + + if (block.has_tail_expr ()) + maybe_desugar_expr (block.get_tail_expr_ptr ()); +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-desugar-for-loops.h b/gcc/rust/ast/rust-desugar-for-loops.h index aca26747fcf1..9f3967774935 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.h +++ b/gcc/rust/ast/rust-desugar-for-loops.h @@ -88,10 +88,11 @@ class DesugarForLoops : public DefaultASTVisitor MatchArm make_match_arm (std::unique_ptr &&pattern); MatchCase make_break_arm (); MatchCase make_continue_arm (); - std::unique_ptr statementify(std::unique_ptr &&expr); + std::unique_ptr statementify (std::unique_ptr &&expr); }; std::unique_ptr desugar (AST::ForLoopExpr &expr); + void maybe_desugar_expr (std::unique_ptr &expr); void visit (AST::BlockExpr &) override; }; From 9337460240d6fff0ced21aca503d65e9537f557a Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 24 Dec 2024 11:45:09 +0000 Subject: [PATCH 33/35] backend: Allow everything as a match scrutinee [rework] --- gcc/rust/backend/rust-compile-expr.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 7323413bfce2..fab2d4ba7b01 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -31,6 +31,7 @@ #include "convert.h" #include "print-tree.h" #include "rust-system.h" +#include "rust-tyty.h" namespace Rust { namespace Compile { @@ -1007,11 +1008,13 @@ check_match_scrutinee (HIR::MatchExpr &expr, Context *ctx) } TyTy::TypeKind scrutinee_kind = scrutinee_expr_tyty->get_kind (); - rust_assert ((TyTy::is_primitive_type_kind (scrutinee_kind) - && scrutinee_kind != TyTy::TypeKind::NEVER) - || scrutinee_kind == TyTy::TypeKind::ADT - || scrutinee_kind == TyTy::TypeKind::TUPLE - || scrutinee_kind == TyTy::TypeKind::REF); + rust_debug_loc(expr.get_locus(), "[ARTHUR] check scrutinee: type: %s, %s", TyTy::TypeKindFormat::to_string(scrutinee_kind).c_str(), scrutinee_expr_tyty->as_string().c_str()); + + // rust_assert ((TyTy::is_primitive_type_kind (scrutinee_kind) + // && scrutinee_kind != TyTy::TypeKind::NEVER) + // || scrutinee_kind == TyTy::TypeKind::ADT + // || scrutinee_kind == TyTy::TypeKind::TUPLE + // || scrutinee_kind == TyTy::TypeKind::REF); if (scrutinee_kind == TyTy::TypeKind::FLOAT) { From 079736a9459d6044415b6f4d31fd29222d0ccbc2 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 24 Dec 2024 11:45:25 +0000 Subject: [PATCH 34/35] hack: Work around MarkLive for lang items --- gcc/rust/checks/lints/rust-lint-marklive.cc | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/gcc/rust/checks/lints/rust-lint-marklive.cc b/gcc/rust/checks/lints/rust-lint-marklive.cc index 91550c7a568f..1b3b3d661e50 100644 --- a/gcc/rust/checks/lints/rust-lint-marklive.cc +++ b/gcc/rust/checks/lints/rust-lint-marklive.cc @@ -22,6 +22,8 @@ #include "rust-lint-marklive.h" #include "options.h" #include "rust-hir-full.h" +#include "rust-hir-map.h" +#include "rust-hir-path.h" #include "rust-name-resolver.h" #include "rust-immutable-name-resolution-context.h" #include "rust-system.h" @@ -97,17 +99,25 @@ MarkLive::go (HIR::Crate &) void MarkLive::visit (HIR::PathInExpression &expr) { + auto is_lang_item = expr.get_path_kind () == HIR::PathPattern::Kind::LangItem; + // We should iterate every path segment in order to mark the struct which // is used in expression like Foo::bar(), we should mark the Foo alive. - expr.iterate_path_segments ([&] (HIR::PathExprSegment &seg) -> bool { - return visit_path_segment (seg); - }); + if (!is_lang_item) + expr.iterate_path_segments ([&] (HIR::PathExprSegment &seg) -> bool { + return visit_path_segment (seg); + }); // after iterate the path segments, we should mark functions and associated // functions alive. NodeId ast_node_id = expr.get_mappings ().get_nodeid (); NodeId ref_node_id = UNKNOWN_NODEID; - find_ref_node_id (ast_node_id, ref_node_id); + + if (is_lang_item) + ref_node_id = *Analysis::Mappings::get ().lookup_lang_item_node ( + expr.get_lang_item_kind ()); + else + find_ref_node_id (ast_node_id, ref_node_id); // node back to HIR tl::optional hid = mappings.lookup_node_to_hir (ref_node_id); From 58743859f5410dcca598c4e4ebf701573dafe2cc Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 24 Dec 2024 11:45:46 +0000 Subject: [PATCH 35/35] wip: typecheck: query type just to make sure? --- gcc/rust/typecheck/rust-hir-type-check-path.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index 8cf8c9ccac83..e3264e56d1c5 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -224,6 +224,8 @@ TypeCheckExpr::visit (HIR::PathInExpression &expr) rust_assert (resolved); + query_type(*hir_id, &infered); + infered = SubstMapper::InferSubst (resolved, expr.get_locus ()); }