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-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 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-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/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-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc index 308720ae69ab..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" @@ -82,5 +83,21 @@ CollectLangItems::visit (AST::TraitItemType &item) DefaultASTVisitor::visit (item); } +void +CollectLangItems::visit (AST::Function &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::EnumItem &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-collect-lang-items.h b/gcc/rust/ast/rust-collect-lang-items.h index 552648f04eda..131930f5a742 100644 --- a/gcc/rust/ast/rust-collect-lang-items.h +++ b/gcc/rust/ast/rust-collect-lang-items.h @@ -47,6 +47,8 @@ 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); 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..253bde097d6f --- /dev/null +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -0,0 +1,192 @@ +// 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-path.h" +#include "rust-pattern.h" +#include "rust-stmt.h" +#include "rust-diagnostics.h" +#include "rust-expr.h" +#include "rust-ast-builder.h" +#include "rust-ast-dump.h" + +namespace Rust { +namespace AST { + +DesugarForLoops::DesugarForLoops () {} + +void +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); +} + +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 (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 (std::move (arm), std::move (break_expr)); +} + +MatchCase +DesugarForLoops::DesugarCtx::make_continue_arm () +{ + 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 assignment = std::unique_ptr ( + new AssignmentExpr (std::move (next), builder.identifier ("val"), {}, loc)); + + return MatchCase (std::move (val_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.ref (ctx.builder.identifier ("iter"), true)); + + // 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 { + // ; + // ; + // ; + // + // ; + // } + auto loop = ctx.builder.loop (std::move (loop_stmts)); + + 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), + 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)); +} + +void +DesugarForLoops::maybe_desugar_expr (std::unique_ptr &expr) +{ + if (expr->get_expr_kind () == AST::Expr::Kind::Loop) + { + auto &loop = static_cast (*expr); + + if (loop.get_loop_kind () == AST::BaseLoopExpr::Kind::For) + { + auto &for_loop = static_cast (loop); + + auto desugared = desugar (for_loop); + + replace_for_loop (expr, std::move (desugared)); + } + } +} + +void +DesugarForLoops::visit (AST::BlockExpr &block) +{ + for (auto &stmt : block.get_statements ()) + if (stmt->get_stmt_kind () == AST::Stmt::Kind::Expr) + maybe_desugar_expr (static_cast (*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 new file mode 100644 index 000000000000..9f3967774935 --- /dev/null +++ b/gcc/rust/ast/rust-desugar-for-loops.h @@ -0,0 +1,103 @@ +// 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-builder.h" +#include "rust-ast-visitor.h" +#include "rust-expr.h" + +namespace Rust { +namespace AST { + +// Desugar for-loops into a set of other AST nodes. The desugar is of the +// following form: +// +// ``` +// for 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: + 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 maybe_desugar_expr (std::unique_ptr &expr); + + void visit (AST::BlockExpr &) override; +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DESUGAR_FOR_LOOPS 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..b2120b3d4e7f 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,13 @@ class MacroRulesDefinition : public VisItem is_builtin_rule = true; } - AST::Kind get_ast_kind () const override + MacroKind get_kind () const { return kind; } + + Item::Kind get_item_kind () const override { - return AST::Kind::MACRO_RULES_DEFINITION; + return Item::Kind::MacroRulesDefinition; } - MacroKind get_kind () const { return kind; } - protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -610,11 +611,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 +673,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 +791,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..a64a02df4e37 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), @@ -765,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; } @@ -831,6 +851,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 +1522,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/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) { 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); } 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); 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/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/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index c92c9432a68e..c4864844d043 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 " @@ -414,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 @@ -490,6 +477,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) @@ -500,10 +502,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 (), 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"); } 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..0cd5d7e924e7 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -19,10 +19,12 @@ #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" #include "rust-hir-expr-abstract.h" +#include "rust-system.h" namespace Rust { namespace HIR { @@ -230,15 +232,34 @@ class PathExprSegment // HIR node representing a pattern that involves a "path" - abstract base class class PathPattern : public Pattern { +public: + enum class Kind + { + Segmented, + LangItem + }; + +private: std::vector segments; + tl::optional lang_item; + Kind 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,26 +269,65 @@ 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 + { + if (kind == Kind::LangItem) + { + // rust_fatal_error (UNKNOWN_LOCATION, "[ARTHUR] %s", + // LangItem::ToString (*lang_item).c_str ()); + rust_unreachable (); + } - std::vector &get_segments () { return segments; } + rust_assert (kind == Kind::Segmented); + return segments.size (); + } - const std::vector &get_segments () const { return segments; } + std::vector &get_segments () + { + rust_assert (kind == Kind::Segmented); + return segments; + } - PathExprSegment &get_root_seg () { return segments.at (0); } + const std::vector &get_segments () const + { + rust_assert (kind == Kind::Segmented); + return segments; + } - const PathExprSegment &get_final_segment () const { return segments.back (); } + PathExprSegment &get_root_seg () + { + rust_assert (kind == Kind::Segmented); + return segments.at (0); + } + + const PathExprSegment &get_final_segment () const + { + rust_assert (kind == Kind::Segmented); + return segments.back (); + } PatternType get_pattern_type () const override final { 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; } }; /* HIR node representing a path-in-expression pattern (path that allows generic @@ -288,6 +348,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 () { @@ -641,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; @@ -671,6 +745,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..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) @@ -2187,6 +2191,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 (); 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-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 634523181139..d89b312f65f4 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 ())); @@ -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 @@ -300,7 +301,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 ())); 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 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; diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index d3f341264482..e3264e56d1c5 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,78 @@ 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); + + // 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 + 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); + + query_type(*hir_id, &infered); + + infered = SubstMapper::InferSubst (resolved, expr.get_locus ()); + } + + // FIXME: also we probably need to insert resolved types in the name + // resolver here + } + 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 * @@ -354,13 +416,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 @@ -435,7 +497,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 @@ -492,7 +554,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); diff --git a/gcc/rust/util/rust-lang-item.cc b/gcc/rust/util/rust-lang-item.cc index 0d8a98077d1e..c1cb78fe7079 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 @@ -182,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 bcf41df559e5..4ff723fd0dde 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; @@ -126,6 +135,7 @@ class LangItem static Kind CompoundAssignmentOperatorToLangItem (ArithmeticOrLogicalOperator op); static Kind NegationOperatorToLangItem (NegationOperator op); + static bool IsEnumVariant (Kind type); }; } // namespace Rust