diff --git a/gcc/rust/ChangeLog b/gcc/rust/ChangeLog index 2a5219d2fe0..380c0d862c3 100644 --- a/gcc/rust/ChangeLog +++ b/gcc/rust/ChangeLog @@ -2775,7 +2775,7 @@ 2025-03-21 Owen Avery - * resolve/rust-name-resolver.cc: Include options.txt. + * resolve/rust-name-resolver.cc: Include options.h. (Resolver::insert_resolved_name): Assert that name resolution 2.0 is disabled. (Resolver::lookup_resolved_name): Likewise. diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 1c58bc88e9c..bc6c55cf8cd 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -144,17 +144,7 @@ GRS_OBJS = \ rust/rust-ice-finalizer.o \ rust/rust-late-name-resolver-2.0.o \ rust/rust-immutable-name-resolution-context.o \ - rust/rust-early-name-resolver.o \ rust/rust-name-resolver.o \ - rust/rust-ast-resolve.o \ - rust/rust-ast-resolve-base.o \ - rust/rust-ast-resolve-item.o \ - rust/rust-ast-resolve-pattern.o \ - rust/rust-ast-resolve-expr.o \ - rust/rust-ast-resolve-type.o \ - rust/rust-ast-resolve-path.o \ - rust/rust-ast-resolve-stmt.o \ - rust/rust-ast-resolve-struct-expr-field.o \ rust/rust-forever-stack.o \ rust/rust-hir-type-check.o \ rust/rust-privacy-check.o \ diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index ed10ce7f9a1..600a4a66e06 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -276,6 +276,63 @@ Builder::type_path (LangItem::Kind lang_item) const return type_path (type_path_segment (lang_item)); } +TypePath +Builder::type_path_core (std::vector> &&segments) const +{ + bool opening_scope; + + auto &mappings = Analysis::Mappings::get (); + if (mappings.get_current_crate_name () == "core") + { + segments.emplace (segments.cbegin (), type_path_segment ("crate")); + opening_scope = false; + } + else + { + segments.emplace (segments.cbegin (), type_path_segment ("core")); + opening_scope = true; + } + + return TypePath (std::move (segments), loc, opening_scope); +} + +TypePath +Builder::type_path_core (std::vector &&segments) const +{ + auto type_segments = std::vector> (); + type_segments.reserve (segments.size () + 1); + bool opening_scope; + + auto &mappings = Analysis::Mappings::get (); + if (mappings.get_current_crate_name () == "core") + { + type_segments.emplace_back (type_path_segment ("crate")); + opening_scope = false; + } + else + { + type_segments.emplace_back (type_path_segment ("core")); + opening_scope = true; + } + + for (auto &&seg : segments) + type_segments.emplace_back (type_path_segment (seg)); + + return TypePath (std::move (type_segments), loc, opening_scope); +} + +TypePath +Builder::type_path_core (std::initializer_list segments) const +{ + std::vector segments_out; + segments_out.reserve (segments.size ()); + + for (auto seg : segments) + segments_out.emplace_back (seg); + + return type_path_core (std::move (segments_out)); +} + std::unique_ptr Builder::reference_type (std::unique_ptr &&inner_type, bool mutability) const @@ -301,6 +358,31 @@ Builder::path_in_expression (LangItem::Kind lang_item) const return PathInExpression (lang_item, {}, loc); } +PathInExpression +Builder::path_in_expression_core (std::vector &&segments) const +{ + auto path_segments = std::vector (); + path_segments.reserve (segments.size () + 1); + bool opening_scope; + + auto &mappings = Analysis::Mappings::get (); + if (mappings.get_current_crate_name () == "core") + { + path_segments.emplace_back (path_segment ("crate")); + opening_scope = false; + } + else + { + path_segments.emplace_back (path_segment ("core")); + opening_scope = true; + } + + for (auto &&seg : segments) + path_segments.emplace_back (path_segment (seg)); + + return PathInExpression (std::move (path_segments), {}, loc, opening_scope); +} + PathInExpression Builder::variant_path (const std::string &enum_path, const std::string &variant) const @@ -544,7 +626,7 @@ std::unique_ptr Builder::discriminant_value (std::string binding_name, std::string instance) { auto intrinsic = ptrify ( - path_in_expression ({"core", "intrinsics", "discriminant_value"}, true)); + path_in_expression_core ({"intrinsics", "discriminant_value"})); return let (identifier_pattern (binding_name), nullptr, call (std::move (intrinsic), identifier (instance))); diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index 843bab896c7..a86606ab1c0 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -220,6 +220,14 @@ class Builder TypePath type_path (std::string type) const; TypePath type_path (LangItem::Kind lang_item) const; + /** + * Creates a type path relative to libcore + * Either `::core...` or `crate...` + */ + TypePath type_path_core (std::vector> &&segments) const; + TypePath type_path_core (std::vector &&segments) const; + TypePath type_path_core (std::initializer_list segments) const; + std::unique_ptr reference_type (std::unique_ptr &&inner_type, bool mutability = false) const; @@ -237,6 +245,12 @@ class Builder */ PathInExpression path_in_expression (LangItem::Kind lang_item) const; + /** + * Create a path in expression relative to libcore + * Either `::core...` or `crate...` + */ + PathInExpression path_in_expression_core (std::vector &&segments) const; + /* Create the path to an enum's variant (`Result::Ok`) */ PathInExpression variant_path (const std::string &enum_path, const std::string &variant) const; @@ -331,11 +345,6 @@ class Builder /* Location of the generated AST nodes */ location_t loc; - -private: - /* Some constexpr helpers for some of the builders */ - static constexpr std::initializer_list discriminant_value_path - = {"core", "intrinsics", "discriminant_value"}; }; } // namespace AST diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 677c2472e6f..7d45d6d610f 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -840,13 +840,13 @@ TokenCollector::visit (MetaItemLitExpr &item) } void -TokenCollector::visit (MetaItemPathLit &item) +TokenCollector::visit (MetaItemPathExpr &item) { auto path = item.get_path (); - auto lit = item.get_literal (); + auto &expr = item.get_expr (); visit (path); - push (Rust::Token::make (COLON, item.get_locus ())); - visit (lit); + push (Rust::Token::make (EQUAL, item.get_locus ())); + visit (expr); } void @@ -3013,6 +3013,13 @@ TokenCollector::visit (AST::FormatArgs &fmt) __FILE__, __LINE__); } +void +TokenCollector::visit (AST::FormatArgsEager &fmt) +{ + rust_sorry_at (fmt.get_locus (), "%s:%u: unimplemented FormatArgsEager visitor", + __FILE__, __LINE__); +} + void TokenCollector::visit (AST::OffsetOf &offset_of) { diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index 9ffbfced47d..2daceba1d2f 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -246,7 +246,7 @@ class TokenCollector : public ASTVisitor void visit (AttrInputLiteral &attr_input); void visit (AttrInputMacro &attr_input); void visit (MetaItemLitExpr &meta_item); - void visit (MetaItemPathLit &meta_item); + void visit (MetaItemPathExpr &meta_item); void visit (BorrowExpr &expr); void visit (DereferenceExpr &expr); void visit (ErrorPropagationExpr &expr); @@ -405,6 +405,7 @@ class TokenCollector : public ASTVisitor void visit (BareFunctionType &type); void visit (FormatArgs &fmt); + void visit (FormatArgsEager &fmt); void visit (OffsetOf &offset_of); }; } // namespace AST diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index 1dfb25c4363..d2e4bee8cd5 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -78,7 +78,7 @@ class LiteralExpr; class AttrInputLiteral; class AttrInputMacro; class MetaItemLitExpr; -class MetaItemPathLit; +class MetaItemPathExpr; class OperatorExpr; class BorrowExpr; class DereferenceExpr; @@ -272,6 +272,7 @@ class BareFunctionType; // rust-builtin-ast-nodes.h class FormatArgs; +class FormatArgsEager; } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 88dc24b570c..18ecd7a74a4 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -224,10 +224,10 @@ DefaultASTVisitor::visit (AST::SimplePath &path) } void -DefaultASTVisitor::visit (AST::MetaItemPathLit &meta_item) +DefaultASTVisitor::visit (AST::MetaItemPathExpr &meta_item) { visit (meta_item.get_path ()); - visit (meta_item.get_literal ()); + visit (meta_item.get_expr ()); } void @@ -1505,6 +1505,15 @@ DefaultASTVisitor::visit (AST::FormatArgs &) // FIXME: Do we have anything to do? any subnodes to visit? Probably, right? } +void +DefaultASTVisitor::visit (AST::FormatArgsEager &fmt) +{ + // FIXME: Do we have anything to do? any subnodes to visit? Probably, right? + + // we need this to resolve/expand macros, at least + visit (fmt.get_template ()); +} + void DefaultASTVisitor::visit (AST::OffsetOf &offset_of) { diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index a5469cccb42..e8128dfd84e 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -73,7 +73,7 @@ class ASTVisitor virtual void visit (AttrInputLiteral &attr_input) = 0; virtual void visit (AttrInputMacro &attr_input) = 0; virtual void visit (MetaItemLitExpr &meta_item) = 0; - virtual void visit (MetaItemPathLit &meta_item) = 0; + virtual void visit (MetaItemPathExpr &meta_item) = 0; virtual void visit (BorrowExpr &expr) = 0; virtual void visit (DereferenceExpr &expr) = 0; virtual void visit (ErrorPropagationExpr &expr) = 0; @@ -240,6 +240,7 @@ class ASTVisitor // special AST nodes for certain builtin macros such as `asm!()` virtual void visit (FormatArgs &fmt) = 0; + virtual void visit (FormatArgsEager &fmt) = 0; virtual void visit (OffsetOf &fmt) = 0; // TODO: rust-cond-compilation.h visiting? not currently used @@ -270,7 +271,7 @@ class DefaultASTVisitor : public ASTVisitor virtual void visit (AST::AttrInputLiteral &attr_input) override; virtual void visit (AST::AttrInputMacro &attr_input) override; virtual void visit (AST::MetaItemLitExpr &meta_item) override; - virtual void visit (AST::MetaItemPathLit &meta_item) override; + virtual void visit (AST::MetaItemPathExpr &meta_item) override; virtual void visit (AST::BorrowExpr &expr) override; virtual void visit (AST::DereferenceExpr &expr) override; virtual void visit (AST::ErrorPropagationExpr &expr) override; @@ -413,6 +414,7 @@ class DefaultASTVisitor : public ASTVisitor virtual void visit (AST::FunctionParam ¶m) override; virtual void visit (AST::VariadicParam ¶m) override; virtual void visit (AST::FormatArgs &fmt) override; + virtual void visit (AST::FormatArgsEager &fmt) override; virtual void visit (AST::OffsetOf &fmt) override; template void visit (T &node) { node.accept_vis (*this); } diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 20a41d72cdf..306a0cc3381 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -288,7 +288,7 @@ Attribute::get_traits_to_derive () break; case AST::MetaItem::ItemKind::ListPaths: case AST::MetaItem::ItemKind::NameValueStr: - case AST::MetaItem::ItemKind::PathLit: + case AST::MetaItem::ItemKind::PathExpr: case AST::MetaItem::ItemKind::Seq: case AST::MetaItem::ItemKind::ListNameValueStr: default: @@ -3531,9 +3531,9 @@ std::unique_ptr AttributeParser::parse_meta_item_inner () { // if first tok not identifier, not a "special" case one - if (peek_token ()->get_id () != IDENTIFIER) + if (lexer->peek_token ()->get_id () != IDENTIFIER) { - switch (peek_token ()->get_id ()) + switch (lexer->peek_token ()->get_id ()) { case CHAR_LITERAL: case STRING_LITERAL: @@ -3554,42 +3554,43 @@ AttributeParser::parse_meta_item_inner () return parse_path_meta_item (); default: - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "unrecognised token '%s' in meta item", - get_token_description (peek_token ()->get_id ())); + get_token_description ( + lexer->peek_token ()->get_id ())); return nullptr; } } // else, check for path - if (peek_token (1)->get_id () == SCOPE_RESOLUTION) + if (lexer->peek_token (1)->get_id () == SCOPE_RESOLUTION) { // path return parse_path_meta_item (); } - auto ident = peek_token ()->get_str (); - auto ident_locus = peek_token ()->get_locus (); + auto ident = lexer->peek_token ()->get_str (); + auto ident_locus = lexer->peek_token ()->get_locus (); - if (is_end_meta_item_tok (peek_token (1)->get_id ())) + if (is_end_meta_item_tok (lexer->peek_token (1)->get_id ())) { // meta word syntax - skip_token (); + lexer->skip_token (); return std::unique_ptr (new MetaWord (ident, ident_locus)); } - if (peek_token (1)->get_id () == EQUAL) + if (lexer->peek_token (1)->get_id () == EQUAL) { // maybe meta name value str syntax - check next 2 tokens - if (peek_token (2)->get_id () == STRING_LITERAL - && is_end_meta_item_tok (peek_token (3)->get_id ())) + if (lexer->peek_token (2)->get_id () == STRING_LITERAL + && is_end_meta_item_tok (lexer->peek_token (3)->get_id ())) { // meta name value str syntax - const_TokenPtr value_tok = peek_token (2); + const_TokenPtr value_tok = lexer->peek_token (2); auto value = value_tok->get_str (); auto locus = value_tok->get_locus (); - skip_token (2); + lexer->skip_token (2); return std::unique_ptr ( new MetaNameValueStr (ident, ident_locus, std::move (value), @@ -3602,16 +3603,16 @@ AttributeParser::parse_meta_item_inner () } } - if (peek_token (1)->get_id () != LEFT_PAREN) + if (lexer->peek_token (1)->get_id () != LEFT_PAREN) { - rust_error_at (peek_token (1)->get_locus (), + rust_error_at (lexer->peek_token (1)->get_locus (), "unexpected token '%s' after identifier in attribute", - get_token_description (peek_token (1)->get_id ())); + get_token_description (lexer->peek_token (1)->get_id ())); return nullptr; } // is it one of those special cases like not? - if (peek_token ()->get_id () == IDENTIFIER) + if (lexer->peek_token ()->get_id () == IDENTIFIER) { return parse_path_meta_item (); } @@ -3690,15 +3691,15 @@ AttributeParser::is_end_meta_item_tok (TokenId id) const std::unique_ptr AttributeParser::parse_path_meta_item () { - SimplePath path = parse_simple_path (); + SimplePath path = parser->parse_simple_path (); if (path.is_empty ()) { - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "failed to parse simple path in attribute"); return nullptr; } - switch (peek_token ()->get_id ()) + switch (lexer->peek_token ()->get_id ()) { case LEFT_PAREN: { @@ -3710,31 +3711,26 @@ AttributeParser::parse_path_meta_item () } case EQUAL: { - skip_token (); + lexer->skip_token (); - location_t locus = peek_token ()->get_locus (); - Literal lit = parse_literal (); - if (lit.is_error ()) - { - rust_error_at (peek_token ()->get_locus (), - "failed to parse literal in attribute"); - return nullptr; - } - LiteralExpr expr (std::move (lit), {}, locus); - // stream_pos++; - /* shouldn't be required anymore due to parsing literal actually - * skipping the token */ - return std::unique_ptr ( - new MetaItemPathLit (std::move (path), std::move (expr))); + std::unique_ptr expr = parser->parse_expr ({}); + + // handle error + // parse_expr should already emit an error and return nullptr + if (!expr) + return nullptr; + + return std::unique_ptr ( + new MetaItemPathExpr (std::move (path), std::move (expr))); } case COMMA: // just simple path return std::unique_ptr ( new MetaItemPath (std::move (path))); default: - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "unrecognised token '%s' in meta item", - get_token_description (peek_token ()->get_id ())); + get_token_description (lexer->peek_token ()->get_id ())); return nullptr; } } @@ -3746,39 +3742,39 @@ AttributeParser::parse_meta_item_seq () { std::vector> meta_items; - if (peek_token ()->get_id () != LEFT_PAREN) + if (lexer->peek_token ()->get_id () != LEFT_PAREN) { - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "missing left paren in delim token tree"); return {}; } - skip_token (); + lexer->skip_token (); - while (peek_token ()->get_id () != END_OF_FILE - && peek_token ()->get_id () != RIGHT_PAREN) + while (lexer->peek_token ()->get_id () != END_OF_FILE + && lexer->peek_token ()->get_id () != RIGHT_PAREN) { std::unique_ptr inner = parse_meta_item_inner (); if (inner == nullptr) { - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "failed to parse inner meta item in attribute"); return {}; } meta_items.push_back (std::move (inner)); - if (peek_token ()->get_id () != COMMA) + if (lexer->peek_token ()->get_id () != COMMA) break; - skip_token (); + lexer->skip_token (); } - if (peek_token ()->get_id () != RIGHT_PAREN) + if (lexer->peek_token ()->get_id () != RIGHT_PAREN) { - rust_error_at (peek_token ()->get_locus (), + rust_error_at (lexer->peek_token ()->get_locus (), "missing right paren in delim token tree"); return {}; } - skip_token (); + lexer->skip_token (); return meta_items; } @@ -3801,141 +3797,19 @@ DelimTokenTree::to_token_stream () const return tokens; } -Literal -AttributeParser::parse_literal () -{ - const_TokenPtr tok = peek_token (); - switch (tok->get_id ()) - { - case CHAR_LITERAL: - skip_token (); - return Literal (tok->get_str (), Literal::CHAR, tok->get_type_hint ()); - case STRING_LITERAL: - skip_token (); - return Literal (tok->get_str (), Literal::STRING, tok->get_type_hint ()); - case BYTE_CHAR_LITERAL: - skip_token (); - return Literal (tok->get_str (), Literal::BYTE, tok->get_type_hint ()); - case BYTE_STRING_LITERAL: - skip_token (); - return Literal (tok->get_str (), Literal::BYTE_STRING, - tok->get_type_hint ()); - case RAW_STRING_LITERAL: - skip_token (); - return Literal (tok->get_str (), Literal::RAW_STRING, - tok->get_type_hint ()); - case INT_LITERAL: - skip_token (); - return Literal (tok->get_str (), Literal::INT, tok->get_type_hint ()); - case FLOAT_LITERAL: - skip_token (); - return Literal (tok->get_str (), Literal::FLOAT, tok->get_type_hint ()); - case TRUE_LITERAL: - skip_token (); - return Literal ("true", Literal::BOOL, tok->get_type_hint ()); - case FALSE_LITERAL: - skip_token (); - return Literal ("false", Literal::BOOL, tok->get_type_hint ()); - default: - rust_error_at (tok->get_locus (), "expected literal - found '%s'", - get_token_description (tok->get_id ())); - return Literal::create_error (); - } -} - -SimplePath -AttributeParser::parse_simple_path () -{ - bool has_opening_scope_res = false; - if (peek_token ()->get_id () == SCOPE_RESOLUTION) - { - has_opening_scope_res = true; - skip_token (); - } - - std::vector segments; - - SimplePathSegment segment = parse_simple_path_segment (); - if (segment.is_error ()) - { - rust_error_at ( - peek_token ()->get_locus (), - "failed to parse simple path segment in attribute simple path"); - return SimplePath::create_empty (); - } - segments.push_back (std::move (segment)); - - while (peek_token ()->get_id () == SCOPE_RESOLUTION) - { - skip_token (); - - SimplePathSegment segment = parse_simple_path_segment (); - if (segment.is_error ()) - { - rust_error_at ( - peek_token ()->get_locus (), - "failed to parse simple path segment in attribute simple path"); - return SimplePath::create_empty (); - } - segments.push_back (std::move (segment)); - } - segments.shrink_to_fit (); - - return SimplePath (std::move (segments), has_opening_scope_res); -} - -SimplePathSegment -AttributeParser::parse_simple_path_segment () -{ - const_TokenPtr tok = peek_token (); - switch (tok->get_id ()) - { - case IDENTIFIER: - skip_token (); - return SimplePathSegment (tok->get_str (), tok->get_locus ()); - case SUPER: - skip_token (); - return SimplePathSegment ("super", tok->get_locus ()); - case SELF: - skip_token (); - return SimplePathSegment ("self", tok->get_locus ()); - case CRATE: - skip_token (); - return SimplePathSegment ("crate", tok->get_locus ()); - case DOLLAR_SIGN: - if (peek_token (1)->get_id () == CRATE) - { - skip_token (1); - return SimplePathSegment ("$crate", tok->get_locus ()); - } - gcc_fallthrough (); - default: - rust_error_at (tok->get_locus (), - "unexpected token '%s' in simple path segment", - get_token_description (tok->get_id ())); - return SimplePathSegment::create_error (); - } -} - std::unique_ptr AttributeParser::parse_meta_item_lit () { - location_t locus = peek_token ()->get_locus (); - LiteralExpr lit_expr (parse_literal (), {}, locus); - return std::unique_ptr ( - new MetaItemLitExpr (std::move (lit_expr))); -} + std::unique_ptr lit_expr = parser->parse_literal_expr ({}); -const_TokenPtr -AttributeParser::peek_token (int i) -{ - return lexer->peek_token (i); -} + // TODO: return nullptr instead? + if (!lit_expr) + lit_expr = std::unique_ptr ( + new LiteralExpr (Literal::create_error (), {}, + lexer->peek_token ()->get_locus ())); -void -AttributeParser::skip_token (int i) -{ - lexer->skip_token (i); + return std::unique_ptr ( + new MetaItemLitExpr (std::move (*lit_expr))); } bool @@ -4144,10 +4018,12 @@ MetaNameValueStr::check_cfg_predicate (const Session &session) const } bool -MetaItemPathLit::check_cfg_predicate (const Session &session) const +MetaItemPathExpr::check_cfg_predicate (const Session &session) const { + // TODO: proper error + rust_assert (expr->is_literal ()); return session.options.target_data.has_key_value_pair (path.as_string (), - lit.as_string ()); + expr->as_string ()); } std::vector> @@ -4235,10 +4111,12 @@ MetaListNameValueStr::to_attribute () const } Attribute -MetaItemPathLit::to_attribute () const +MetaItemPathExpr::to_attribute () const { + // TODO: make this work in more cases? or add an error + rust_assert (expr->is_literal ()); return Attribute (path, std::unique_ptr ( - new AttrInputLiteral (lit))); + new AttrInputLiteral (static_cast (*expr)))); } std::vector @@ -4406,7 +4284,7 @@ MetaItemLitExpr::accept_vis (ASTVisitor &vis) } void -MetaItemPathLit::accept_vis (ASTVisitor &vis) +MetaItemPathExpr::accept_vis (ASTVisitor &vis) { vis.visit (*this); } @@ -5152,6 +5030,59 @@ FormatArgs::clone_expr_impl () const return new FormatArgs (*this); } +void +FormatArgsEager::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +std::string +FormatArgsEager::as_string () const +{ + // FIXME(Arthur): Improve + return "FormatArgsEager"; +} + +bool +FormatArgsEager::is_expr_without_block () const +{ + return false; +} + +void +FormatArgsEager::mark_for_strip () +{ + marked_for_strip = true; +} + +bool +FormatArgsEager::is_marked_for_strip () const +{ + return marked_for_strip; +} + +std::vector & +FormatArgsEager::get_outer_attrs () +{ + rust_unreachable (); +} + +void +FormatArgsEager::set_outer_attrs (std::vector) +{ + rust_unreachable (); +} + +FormatArgsEager * +FormatArgsEager::clone_expr_impl () const +{ + // based on FormatArgs::clone_expr_impl + // TODO: should this be happening? + rust_debug_loc (get_locus (), "[ARTHUR/OWEN] cloning FormatArgsEager!"); + + return new FormatArgsEager (*this); +} + std::vector & OffsetOf::get_outer_attrs () { diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index a367c5dd0c3..527abae8741 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1073,7 +1073,7 @@ class MetaItem : public MetaItemInner Path, Word, NameValueStr, - PathLit, + PathExpr, Seq, ListPaths, ListNameValueStr, @@ -1091,7 +1091,7 @@ class MetaItem : public MetaItemInner class MetaItemLitExpr; // Forward decl - defined in rust-expr.h -class MetaItemPathLit; +class MetaItemPathExpr; // Forward decl - defined in rust-macro.h class MetaItemPath; @@ -1308,6 +1308,7 @@ class Expr : public Visitable LlvmInlineAsm, Identifier, FormatArgs, + FormatArgsEager, OffsetOf, MacroInvocation, Borrow, diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h index 2893e7b4676..7e54d3b239b 100644 --- a/gcc/rust/ast/rust-builtin-ast-nodes.h +++ b/gcc/rust/ast/rust-builtin-ast-nodes.h @@ -225,6 +225,70 @@ class FormatArgs : public Expr virtual Expr *clone_expr_impl () const override; }; +// a FormatArgs which hasn't had its first argument parsed yet +// used to handle eager expansion +class FormatArgsEager final : public Expr +{ +public: + using Newline = FormatArgs::Newline; + + FormatArgsEager (location_t loc, std::unique_ptr &&template_expr, + FormatArguments &&arguments, Newline newline) + : loc (loc), template_expr (std::move (template_expr)), + arguments (std::move (arguments)), newline (newline) + {} + + FormatArgsEager (const FormatArgsEager &other): Expr (other), loc (other.loc), template_expr (other.template_expr->clone_expr ()), arguments (other.arguments), newline (other.newline) {} + + FormatArgsEager &operator= (const FormatArgsEager &other) + { + Expr::operator= (other); + loc = other.loc; + template_expr = other.template_expr->clone_expr (); + arguments = other.arguments; + newline = other.newline; + return *this; + } + + FormatArgsEager (FormatArgsEager &&other) = default; + FormatArgsEager &operator= (FormatArgsEager &&other) = default; + + void accept_vis (AST::ASTVisitor &vis) override; + + const Expr &get_template () const { return *template_expr; } + + Expr &get_template () { return *template_expr; } + + std::unique_ptr &get_template_ptr () { return template_expr; } + + const FormatArguments &get_arguments () const { return arguments; } + + FormatArguments &get_arguments () { return arguments; } + + virtual location_t get_locus () const override { return loc; } + + Newline get_newline () const { return newline; } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::FormatArgsEager; } + +private: + location_t loc; + std::unique_ptr template_expr; + FormatArguments arguments; + Newline newline; + + bool marked_for_strip = false; + +protected: + virtual std::string as_string () const override; + virtual bool is_expr_without_block () const override; + virtual void mark_for_strip () override; + virtual bool is_marked_for_strip () const override; + virtual std::vector &get_outer_attrs () override; + virtual void set_outer_attrs (std::vector) override; + virtual FormatArgsEager *clone_expr_impl () const override; +}; + /** * The node associated with the builtin offset_of!() macro */ diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index c8f776481b5..d4d0942c512 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -249,36 +249,49 @@ class MetaItemLitExpr : public MetaItemInner } }; -// more generic meta item "path = lit" form -class MetaItemPathLit : public MetaItem +// more generic meta item "path = expr" form +class MetaItemPathExpr : public MetaItem { SimplePath path; - LiteralExpr lit; + std::unique_ptr expr; public: - MetaItemPathLit (SimplePath path, LiteralExpr lit_expr) - : path (std::move (path)), lit (std::move (lit_expr)) + MetaItemPathExpr (SimplePath path, std::unique_ptr expr) + : path (std::move (path)), expr (std::move (expr)) {} + MetaItemPathExpr (const MetaItemPathExpr &other): MetaItem (other), path (other.path), expr (other.expr->clone_expr ()) {} + + MetaItemPathExpr &operator= (const MetaItemPathExpr &other) + { + MetaItem::operator= (other); + path = other.path; + expr = other.expr->clone_expr (); + return *this; + } + + MetaItemPathExpr (MetaItemPathExpr &&) = default; + MetaItemPathExpr &operator= (MetaItemPathExpr &&) = default; + SimplePath get_path () const { return path; } SimplePath &get_path () { return path; } - LiteralExpr get_literal () const { return lit; } + const Expr &get_expr () const { return *expr; } - LiteralExpr &get_literal () { return lit; } + Expr &get_expr () { return *expr; } std::string as_string () const override { - return path.as_string () + " = " + lit.as_string (); + return path.as_string () + " = " + expr->as_string (); } MetaItem::ItemKind get_item_kind () const override { - return MetaItem::ItemKind::PathLit; + return MetaItem::ItemKind::PathExpr; } - // There are two Locations in MetaItemPathLit (path and lit_expr), + // There are two Locations in MetaItemPathExpr (path and expr), // we have no idea use which of them, just simply return UNKNOWN_LOCATION // now. // Maybe we will figure out when we really need the location in the future. @@ -294,9 +307,9 @@ class MetaItemPathLit : public MetaItem protected: // Use covariance to implement clone function as returning this type - MetaItemPathLit *clone_meta_item_inner_impl () const override + MetaItemPathExpr *clone_meta_item_inner_impl () const override { - return new MetaItemPathLit (*this); + return new MetaItemPathExpr (*this); } }; diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index d32acf30669..416507501ac 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -1137,21 +1137,10 @@ struct AttributeParser std::unique_ptr parse_meta_item_inner (); // Returns whether token can end a meta item. bool is_end_meta_item_tok (TokenId id) const; - // Parses a simple path. - SimplePath parse_simple_path (); - // Parses a segment of a simple path (but not scope resolution operator). - SimplePathSegment parse_simple_path_segment (); // Parses a MetaItemLitExpr. std::unique_ptr parse_meta_item_lit (); - // Parses a literal. - Literal parse_literal (); // Parses a meta item that begins with a simple path. std::unique_ptr parse_path_meta_item (); - - // TODO: should this be const? - const_TokenPtr peek_token (int i = 0); - - void skip_token (int i = 0); }; } // namespace AST } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index 73c34b269b7..7fa270a6b29 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -33,6 +33,7 @@ #include "rust-compile-implitem.h" #include "rust-attribute-values.h" #include "rust-immutable-name-resolution-context.h" +#include "rust-ggc.h" #include "fold-const.h" #include "stringpool.h" @@ -46,11 +47,43 @@ namespace Rust { namespace Compile { -bool inline should_mangle_item (const tree fndecl) +tl::optional inline get_unmangled_name (const std::string &function_name, const AST::AttrVec &attrs) { - return lookup_attribute (Values::Attributes::NO_MANGLE, - DECL_ATTRIBUTES (fndecl)) - == NULL_TREE; + tl::optional set_name; + for (auto &attr : attrs) + { + auto name = attr.get_path ().as_string (); + if (name == Values::Attributes::NO_MANGLE) + { + // TODO: better errors + rust_assert (!set_name.has_value ()); + set_name = function_name; + + if (attr.has_attr_input ()) + { + rust_error_at (attr.get_locus (), + "attribute % does not accept any arguments"); + } + + } + else if (name == Values::Attributes::LINK_NAME) + { + // TODO: better errors + rust_assert (!set_name.has_value ()); + + rust_assert (attr.has_attr_input ()); + auto &input = attr.get_attr_input (); + + rust_assert (input.get_attr_input_type () == AST::AttrInput::AttrInputType::LITERAL); + auto &literal = static_cast (input).get_literal (); + + rust_assert (literal.get_lit_type () == AST::Literal::LitType::STRING || literal.get_lit_type () == AST::Literal::LitType::RAW_STRING); + // TODO: special handling for STRING/RAW_STRING? + set_name = literal.as_string (); + } + } + + return set_name; } void @@ -84,8 +117,6 @@ HIRCompileBase::setup_fndecl (tree fndecl, bool is_main_entry_point, bool is_cold = attr.get_path ().as_string () == Values::Attributes::COLD; bool is_link_section = attr.get_path ().as_string () == Values::Attributes::LINK_SECTION; - bool no_mangle - = attr.get_path ().as_string () == Values::Attributes::NO_MANGLE; bool is_deprecated = attr.get_path ().as_string () == Values::Attributes::DEPRECATED; bool is_proc_macro @@ -116,10 +147,6 @@ HIRCompileBase::setup_fndecl (tree fndecl, bool is_main_entry_point, { handle_deprecated_attribute_on_fndecl (fndecl, attr); } - else if (no_mangle) - { - handle_no_mangle_attribute_on_fndecl (fndecl, attr); - } else if (is_proc_macro) { handle_bang_proc_macro_attribute_on_fndecl (fndecl, attr); @@ -272,22 +299,6 @@ HIRCompileBase::handle_link_section_attribute_on_fndecl ( set_decl_section_name (fndecl, msg_str.c_str ()); } -void -HIRCompileBase::handle_no_mangle_attribute_on_fndecl ( - tree fndecl, const AST::Attribute &attr) -{ - if (attr.has_attr_input ()) - { - rust_error_at (attr.get_locus (), - "attribute % does not accept any arguments"); - return; - } - - DECL_ATTRIBUTES (fndecl) - = tree_cons (get_identifier (Values::Attributes::NO_MANGLE), NULL_TREE, - DECL_ATTRIBUTES (fndecl)); -} - void HIRCompileBase::handle_deprecated_attribute_on_fndecl ( tree fndecl, const AST::Attribute &attr) @@ -708,7 +719,6 @@ HIRCompileBase::compile_function ( /* So that 'MAIN_NAME_P' works. */ main_identifier_node = get_identifier (ir_symbol_name.c_str ()); } - std::string asm_name = fn_name; unsigned int flags = 0; tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name, @@ -719,12 +729,10 @@ HIRCompileBase::compile_function ( setup_abi_options (fndecl, get_abi (outer_attrs, qualifiers)); // conditionally mangle the function name - bool should_mangle = should_mangle_item (fndecl); - if (!is_main_fn && should_mangle) - asm_name = ctx->mangle_item (fntype, canonical_path); - SET_DECL_ASSEMBLER_NAME (fndecl, - get_identifier_with_length (asm_name.data (), - asm_name.length ())); + auto unmangled = is_main_fn ? "main" : get_unmangled_name (fn_name, outer_attrs); + GGC::Ident asm_name = unmangled ? *unmangled : ctx->mangle_item (fntype, canonical_path); + + SET_DECL_ASSEMBLER_NAME (fndecl, asm_name.as_tree ()); // insert into the context ctx->insert_function_decl (fntype, fndecl); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h index e2cc2ddb0d8..10367a93238 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h @@ -75,7 +75,6 @@ struct BuilderContext // External context. Resolver::TypeCheckContext &tyctx; - Resolver::Resolver &resolver; // BIR output BasicBlocks basic_blocks; @@ -102,9 +101,7 @@ struct BuilderContext FreeRegions fn_free_regions{{}}; public: - BuilderContext () - : tyctx (*Resolver::TypeCheckContext::get ()), - resolver (*Resolver::Resolver::get ()) + BuilderContext () : tyctx (*Resolver::TypeCheckContext::get ()) { basic_blocks.emplace_back (); // StartBB } @@ -403,69 +400,43 @@ class AbstractBuilder template NodeId resolve_label (T &expr) { - NodeId resolved_label; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto res = nr_ctx.lookup (expr.get_mappings ().get_nodeid ()); - rust_assert (res.has_value ()); - resolved_label = res.value (); - } - else - { - bool ok = ctx.resolver.lookup_resolved_label ( - expr.get_mappings ().get_nodeid (), &resolved_label); - rust_assert (ok); - } - return resolved_label; + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + auto res = nr_ctx.lookup (expr.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + + return *res; } template PlaceId resolve_variable (T &variable) { - NodeId variable_id; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ()); - rust_assert (res.has_value ()); - variable_id = res.value (); - } - else - { - bool ok = ctx.resolver.lookup_resolved_name ( - variable.get_mappings ().get_nodeid (), &variable_id); - rust_assert (ok); - } - return ctx.place_db.lookup_variable (variable_id); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + + return ctx.place_db.lookup_variable (*res); } template PlaceId resolve_variable_or_fn (T &variable, TyTy::BaseType *ty) { ty = (ty) ? ty : lookup_type (variable); + // Unlike variables, // functions do not have to be declared in PlaceDB before use. - NodeId variable_id; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ()); - rust_assert (res.has_value ()); - variable_id = res.value (); - } - else - { - bool ok = ctx.resolver.lookup_resolved_name ( - variable.get_mappings ().get_nodeid (), &variable_id); - rust_assert (ok); - } if (ty->is ()) return ctx.place_db.get_constant (ty); - else - return ctx.place_db.lookup_or_add_variable (variable_id, ty); + + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + + return ctx.place_db.lookup_or_add_variable (*res, ty); } protected: // Implicit conversions. diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc index 5291276a7a3..3b94cbf3f1b 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc @@ -35,12 +35,11 @@ Resolver::resolve (HIR::Crate &crate) { PrivacyContext ctx; auto &mappings = Analysis::Mappings::get (); - auto resolver = Rust::Resolver::Resolver::get (); auto ty_ctx = ::Rust::Resolver::TypeCheckContext::get (); - VisibilityResolver (mappings, *resolver).go (crate); + VisibilityResolver (mappings).go (crate); PubRestrictedVisitor (mappings).go (crate); - PrivacyReporter (mappings, *resolver, *ty_ctx).go (crate); + PrivacyReporter (mappings, *ty_ctx).go (crate); auto visitor = ReachabilityVisitor (ctx, *ty_ctx); diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc index 4af9639c38f..57fa39c8580 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc @@ -28,10 +28,8 @@ namespace Rust { namespace Privacy { PrivacyReporter::PrivacyReporter ( - Analysis::Mappings &mappings, Resolver::Resolver &resolver, - const Rust::Resolver::TypeCheckContext &ty_ctx) - : mappings (mappings), resolver (resolver), ty_ctx (ty_ctx), - current_module (tl::nullopt) + Analysis::Mappings &mappings, const Rust::Resolver::TypeCheckContext &ty_ctx) + : mappings (mappings), ty_ctx (ty_ctx), current_module (tl::nullopt) {} // Find a proc_macro, proc_macro_derive or proc_macro_attribute @@ -94,30 +92,10 @@ static bool is_child_module (Analysis::Mappings &mappings, NodeId parent, NodeId possible_child) { - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - return nr_ctx.values.is_module_descendant (parent, possible_child); - } - - auto children = mappings.lookup_module_children (parent); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (!children) - return false; - - // Visit all toplevel children - for (auto &child : *children) - if (child == possible_child) - return true; - - // Now descend recursively in the child module tree - for (auto &child : *children) - if (is_child_module (mappings, child, possible_child)) - return true; - - return false; + return nr_ctx.values.is_module_descendant (parent, possible_child); } // FIXME: This function needs a lot of refactoring @@ -127,17 +105,11 @@ PrivacyReporter::check_for_privacy_violation (const NodeId &use_id, { NodeId ref_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) - { auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); if (auto id = nr_ctx.lookup (use_id)) ref_node_id = *id; - } - // FIXME: Don't assert here - we might be dealing with a type - else if (!resolver.lookup_resolved_name (use_id, &ref_node_id)) - resolver.lookup_resolved_type (use_id, &ref_node_id); // FIXME: Assert here. For now, we return since this causes issues when // checking inferred types (#1260) diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h index 72716a6aa8a..cc48f9ada0e 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h @@ -38,7 +38,6 @@ class PrivacyReporter : public HIR::HIRExpressionVisitor, { public: PrivacyReporter (Analysis::Mappings &mappings, - Rust::Resolver::Resolver &resolver, const Rust::Resolver::TypeCheckContext &ty_ctx); /** @@ -157,7 +156,6 @@ types virtual void visit (HIR::ExprStmt &stmt); Analysis::Mappings &mappings; - Rust::Resolver::Resolver &resolver; const Rust::Resolver::TypeCheckContext &ty_ctx; // `None` means we're in the root module - the crate diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc index c59763d7378..dfaed1b340d 100644 --- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc +++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc @@ -22,15 +22,11 @@ #include "rust-hir-item.h" #include "rust-immutable-name-resolution-context.h" -// for flag_name_resolution_2_0 -#include "options.h" - namespace Rust { namespace Privacy { -VisibilityResolver::VisibilityResolver (Analysis::Mappings &mappings, - Resolver::Resolver &resolver) - : mappings (mappings), resolver (resolver) +VisibilityResolver::VisibilityResolver (Analysis::Mappings &mappings) + : mappings (mappings) {} void @@ -64,27 +60,20 @@ VisibilityResolver::resolve_module_path (const HIR::SimplePath &restriction, = Error (restriction.get_locus (), "cannot use non-module path as privacy restrictor"); - NodeId ref_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (auto id = nr_ctx.lookup (ast_node_id)) - { - ref_node_id = *id; - } - else - { - invalid_path.emit (); - return false; - } + NodeId ref_node_id; + if (auto id = nr_ctx.lookup (ast_node_id)) + { + ref_node_id = *id; } - else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) + else { invalid_path.emit (); return false; } + // FIXME: Add a hint here if we can find the path in another scope, such as // a type or something else // TODO: For the hint, can we point to the original item's definition if diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h index 4dfba4cb86b..4252b285330 100644 --- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h +++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h @@ -33,8 +33,7 @@ namespace Privacy { class VisibilityResolver : public HIR::HIRVisItemVisitor { public: - VisibilityResolver (Analysis::Mappings &mappings, - Rust::Resolver::Resolver &resolver); + VisibilityResolver (Analysis::Mappings &mappings); /** * Perform visibility resolving on an entire crate @@ -93,7 +92,6 @@ class VisibilityResolver : public HIR::HIRVisItemVisitor private: Analysis::Mappings &mappings; - Rust::Resolver::Resolver &resolver; DefId current_module; }; diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc index c40f9db7d2c..57c02b6e2c1 100644 --- a/gcc/rust/checks/errors/rust-const-checker.cc +++ b/gcc/rust/checks/errors/rust-const-checker.cc @@ -24,16 +24,10 @@ #include "rust-system.h" #include "rust-immutable-name-resolution-context.h" -// for flag_name_resolution_2_0 -#include "options.h" - namespace Rust { namespace HIR { -ConstChecker::ConstChecker () - : resolver (*Resolver::Resolver::get ()), - mappings (Analysis::Mappings::get ()) -{} +ConstChecker::ConstChecker () : mappings (Analysis::Mappings::get ()) {} void ConstChecker::go (HIR::Crate &crate) @@ -358,8 +352,6 @@ ConstChecker::visit (CallExpr &expr) NodeId ast_node_id = expr.get_fnexpr ().get_mappings ().get_nodeid (); NodeId ref_node_id; - if (flag_name_resolution_2_0) - { auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); @@ -367,10 +359,6 @@ ConstChecker::visit (CallExpr &expr) ref_node_id = *id; else return; - } - // We don't care about types here - else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) - return; if (auto definition_id = mappings.lookup_node_to_hir (ref_node_id)) { diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h index eb63095a225..e34d56aece8 100644 --- a/gcc/rust/checks/errors/rust-const-checker.h +++ b/gcc/rust/checks/errors/rust-const-checker.h @@ -72,7 +72,6 @@ class ConstChecker : public HIRFullVisitor std::vector> ¶m, ConstGenericCtx context); StackedContexts const_context; - Resolver::Resolver &resolver; Analysis::Mappings &mappings; virtual void visit (Lifetime &lifetime) override; diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/rust-feature.cc index 071d3f8c0d9..70c3227e4c9 100644 --- a/gcc/rust/checks/errors/rust-feature.cc +++ b/gcc/rust/checks/errors/rust-feature.cc @@ -84,6 +84,89 @@ const std::map Feature::name_hash_map = { {"exclusive_range_pattern", Feature::Name::EXCLUSIVE_RANGE_PATTERN}, {"prelude_import", Feature::Name::PRELUDE_IMPORT}, {"min_specialization", Feature::Name::MIN_SPECIALIZATION}, + // unhandled features + {"aarch64_target_feature", Feature::Name::AARCH64_TARGET_FEATURE}, + {"abi_unadjusted", Feature::Name::ABI_UNADJUSTED}, + {"adx_target_feature", Feature::Name::ADX_TARGET_FEATURE}, + {"allow_internal_unstable", Feature::Name::ALLOW_INTERNAL_UNSTABLE}, + {"arbitrary_self_types", Feature::Name::ARBITRARY_SELF_TYPES}, + {"arm_target_feature", Feature::Name::ARM_TARGET_FEATURE}, + {"asm", Feature::Name::ASM}, + {"avx512_target_feature", Feature::Name::AVX512_TARGET_FEATURE}, + {"cfg_target_has_atomic", Feature::Name::CFG_TARGET_HAS_ATOMIC}, + {"cmpxchg16b_target_feature", Feature::Name::CMPXCHG16B_TARGET_FEATURE}, + {"const_align_of_val", Feature::Name::CONST_ALIGN_OF_VAL}, + {"const_alloc_layout", Feature::Name::CONST_ALLOC_LAYOUT}, + {"const_caller_location", Feature::Name::CONST_CALLER_LOCATION}, + {"const_cell_into_inner", Feature::Name::CONST_CELL_INTO_INNER}, + {"const_checked_int_methods", Feature::Name::CONST_CHECKED_INT_METHODS}, + {"const_discriminant", Feature::Name::CONST_DISCRIMINANT}, + {"const_euclidean_int_methods", Feature::Name::CONST_EUCLIDEAN_INT_METHODS}, + {"const_float_bits_conv", Feature::Name::CONST_FLOAT_BITS_CONV}, + {"const_float_classify", Feature::Name::CONST_FLOAT_CLASSIFY}, + {"const_fn", Feature::Name::CONST_FN}, + {"const_fn_floating_point_arithmetic", Feature::Name::CONST_FN_FLOATING_POINT_ARITHMETIC}, + {"const_fn_fn_ptr_basics", Feature::Name::CONST_FN_FN_PTR_BASICS}, + {"const_fn_transmute", Feature::Name::CONST_FN_TRANSMUTE}, + {"const_fn_union", Feature::Name::CONST_FN_UNION}, + {"const_generics", Feature::Name::CONST_GENERICS}, + {"const_int_pow", Feature::Name::CONST_INT_POW}, + {"const_int_unchecked_arith", Feature::Name::CONST_INT_UNCHECKED_ARITH}, + {"const_likely", Feature::Name::CONST_LIKELY}, + {"const_mut_refs", Feature::Name::CONST_MUT_REFS}, + {"const_option", Feature::Name::CONST_OPTION}, + {"const_overflowing_int_methods", Feature::Name::CONST_OVERFLOWING_INT_METHODS}, + {"const_panic", Feature::Name::CONST_PANIC}, + {"const_pin", Feature::Name::CONST_PIN}, + {"const_precise_live_drops", Feature::Name::CONST_PRECISE_LIVE_DROPS}, + {"const_ptr_offset", Feature::Name::CONST_PTR_OFFSET}, + {"const_ptr_offset_from", Feature::Name::CONST_PTR_OFFSET_FROM}, + {"const_raw_ptr_comparison", Feature::Name::CONST_RAW_PTR_COMPARISON}, + {"const_size_of_val", Feature::Name::CONST_SIZE_OF_VAL}, + {"const_slice_from_raw_parts", Feature::Name::CONST_SLICE_FROM_RAW_PARTS}, + {"const_slice_ptr_len", Feature::Name::CONST_SLICE_PTR_LEN}, + {"const_type_id", Feature::Name::CONST_TYPE_ID}, + {"const_type_name", Feature::Name::CONST_TYPE_NAME}, + {"const_unreachable_unchecked", Feature::Name::CONST_UNREACHABLE_UNCHECKED}, + {"constctlz", Feature::Name::CONSTCTLZ}, + {"custom_inner_attributes", Feature::Name::CUSTOM_INNER_ATTRIBUTES}, + {"doc_cfg", Feature::Name::DOC_CFG}, + {"doc_spotlight", Feature::Name::DOC_SPOTLIGHT}, + {"duration_consts_2", Feature::Name::DURATION_CONSTS_2}, + {"duration_saturating_ops", Feature::Name::DURATION_SATURATING_OPS}, + {"exhaustive_patterns", Feature::Name::EXHAUSTIVE_PATTERNS}, + {"external_doc", Feature::Name::EXTERNAL_DOC}, + {"f16c_target_feature", Feature::Name::F16C_TARGET_FEATURE}, + {"fundamental", Feature::Name::FUNDAMENTAL}, + {"hexagon_target_feature", Feature::Name::HEXAGON_TARGET_FEATURE}, + {"int_error_matching", Feature::Name::INT_ERROR_MATCHING}, + {"link_llvm_intrinsics", Feature::Name::LINK_LLVM_INTRINSICS}, + {"llvm_asm", Feature::Name::LLVM_ASM}, + {"mips_target_feature", Feature::Name::MIPS_TARGET_FEATURE}, + {"never_type", Feature::Name::NEVER_TYPE}, + {"nll", Feature::Name::NLL}, + {"no_niche", Feature::Name::NO_NICHE}, + {"or_patterns", Feature::Name::OR_PATTERNS}, + {"platform_intrinsics", Feature::Name::PLATFORM_INTRINSICS}, + {"powerpc_target_feature", Feature::Name::POWERPC_TARGET_FEATURE}, + {"repr_simd", Feature::Name::REPR_SIMD}, + {"rtm_target_feature", Feature::Name::RTM_TARGET_FEATURE}, + {"simd_ffi", Feature::Name::SIMD_FFI}, + {"slice_ptr_get", Feature::Name::SLICE_PTR_GET}, + {"sse4a_target_feature", Feature::Name::SSE4A_TARGET_FEATURE}, + {"staged_api", Feature::Name::STAGED_API}, + {"std_internals", Feature::Name::STD_INTERNALS}, + {"stmt_expr_attributes", Feature::Name::STMT_EXPR_ATTRIBUTES}, + {"str_split_as_str", Feature::Name::STR_SPLIT_AS_STR}, + {"str_split_inclusive_as_str", Feature::Name::STR_SPLIT_INCLUSIVE_AS_STR}, + {"tbm_target_feature", Feature::Name::TBM_TARGET_FEATURE}, + {"transparent_unions", Feature::Name::TRANSPARENT_UNIONS}, + {"try_blocks", Feature::Name::TRY_BLOCKS}, + {"unboxed_closures", Feature::Name::UNBOXED_CLOSURES}, + {"unsafe_block_in_unsafe_fn", Feature::Name::UNSAFE_BLOCK_IN_UNSAFE_FN}, + {"unwind_attributes", Feature::Name::UNWIND_ATTRIBUTES}, + {"variant_count", Feature::Name::VARIANT_COUNT}, + {"wasm_target_feature", Feature::Name::WASM_TARGET_FEATURE}, }; tl::optional diff --git a/gcc/rust/checks/errors/rust-feature.h b/gcc/rust/checks/errors/rust-feature.h index e7cb0afc689..6ce15b7db75 100644 --- a/gcc/rust/checks/errors/rust-feature.h +++ b/gcc/rust/checks/errors/rust-feature.h @@ -52,6 +52,88 @@ class Feature EXCLUSIVE_RANGE_PATTERN, PRELUDE_IMPORT, MIN_SPECIALIZATION, + AARCH64_TARGET_FEATURE, + ABI_UNADJUSTED, + ADX_TARGET_FEATURE, + ALLOW_INTERNAL_UNSTABLE, + ARBITRARY_SELF_TYPES, + ARM_TARGET_FEATURE, + ASM, + AVX512_TARGET_FEATURE, + CFG_TARGET_HAS_ATOMIC, + CMPXCHG16B_TARGET_FEATURE, + CONST_ALIGN_OF_VAL, + CONST_ALLOC_LAYOUT, + CONST_CALLER_LOCATION, + CONST_CELL_INTO_INNER, + CONST_CHECKED_INT_METHODS, + CONST_DISCRIMINANT, + CONST_EUCLIDEAN_INT_METHODS, + CONST_FLOAT_BITS_CONV, + CONST_FLOAT_CLASSIFY, + CONST_FN, + CONST_FN_FLOATING_POINT_ARITHMETIC, + CONST_FN_FN_PTR_BASICS, + CONST_FN_TRANSMUTE, + CONST_FN_UNION, + CONST_GENERICS, + CONST_INT_POW, + CONST_INT_UNCHECKED_ARITH, + CONST_LIKELY, + CONST_MUT_REFS, + CONST_OPTION, + CONST_OVERFLOWING_INT_METHODS, + CONST_PANIC, + CONST_PIN, + CONST_PRECISE_LIVE_DROPS, + CONST_PTR_OFFSET, + CONST_PTR_OFFSET_FROM, + CONST_RAW_PTR_COMPARISON, + CONST_SIZE_OF_VAL, + CONST_SLICE_FROM_RAW_PARTS, + CONST_SLICE_PTR_LEN, + CONST_TYPE_ID, + CONST_TYPE_NAME, + CONST_UNREACHABLE_UNCHECKED, + CONSTCTLZ, + CUSTOM_INNER_ATTRIBUTES, + DOC_CFG, + DOC_SPOTLIGHT, + DURATION_CONSTS_2, + DURATION_SATURATING_OPS, + EXHAUSTIVE_PATTERNS, + EXTERNAL_DOC, + F16C_TARGET_FEATURE, + FUNDAMENTAL, + HEXAGON_TARGET_FEATURE, + INT_ERROR_MATCHING, + LINK_LLVM_INTRINSICS, + LLVM_ASM, + MIPS_TARGET_FEATURE, + NEVER_TYPE, + NLL, + NO_NICHE, + OR_PATTERNS, + PLATFORM_INTRINSICS, + POWERPC_TARGET_FEATURE, + REPR_SIMD, + RTM_TARGET_FEATURE, + SIMD_FFI, + SLICE_PTR_GET, + SSE4A_TARGET_FEATURE, + STAGED_API, + STD_INTERNALS, + STMT_EXPR_ATTRIBUTES, + STR_SPLIT_AS_STR, + STR_SPLIT_INCLUSIVE_AS_STR, + TBM_TARGET_FEATURE, + TRANSPARENT_UNIONS, + TRY_BLOCKS, + UNBOXED_CLOSURES, + UNSAFE_BLOCK_IN_UNSAFE_FN, + UNWIND_ATTRIBUTES, + VARIANT_COUNT, + WASM_TARGET_FEATURE, }; const std::string &as_string () { return m_name_str; } diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc index 25669713a00..513b1c2d1a6 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc @@ -28,15 +28,11 @@ #include "rust-tyty.h" #include "rust-immutable-name-resolution-context.h" -// for flag_name_resolution_2_0 -#include "options.h" - namespace Rust { namespace Analysis { PatternChecker::PatternChecker () : tyctx (*Resolver::TypeCheckContext::get ()), - resolver (*Resolver::Resolver::get ()), mappings (Analysis::Mappings::get ()) {} @@ -238,8 +234,7 @@ PatternChecker::visit (CallExpr &expr) NodeId ast_node_id = expr.get_fnexpr ().get_mappings ().get_nodeid (); NodeId ref_node_id; - if (flag_name_resolution_2_0) - { + auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); @@ -247,9 +242,6 @@ PatternChecker::visit (CallExpr &expr) ref_node_id = *id; else return; - } - else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) - return; if (auto definition_id = mappings.lookup_node_to_hir (ref_node_id)) { diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h index dd44abca527..e148cc1ab48 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h @@ -46,7 +46,6 @@ class PatternChecker : public HIR::HIRFullVisitor private: Resolver::TypeCheckContext &tyctx; - Resolver::Resolver &resolver; Analysis::Mappings &mappings; virtual void visit (Lifetime &lifetime) override; diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc index 405c59be096..c2e60e3f5be 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.cc +++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc @@ -25,15 +25,11 @@ #include "rust-system.h" #include "rust-immutable-name-resolution-context.h" -// for flag_name_resolution_2_0 -#include "options.h" - namespace Rust { namespace HIR { UnsafeChecker::UnsafeChecker () : context (*Resolver::TypeCheckContext::get ()), - resolver (*Resolver::Resolver::get ()), mappings (Analysis::Mappings::get ()) {} @@ -220,23 +216,15 @@ UnsafeChecker::visit (PathInExpression &path) NodeId ast_node_id = path.get_mappings ().get_nodeid (); NodeId ref_node_id; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto resolved = nr_ctx.lookup (ast_node_id); + auto resolved = nr_ctx.lookup (ast_node_id); - if (!resolved.has_value ()) - return; + if (!resolved.has_value ()) + return; - ref_node_id = resolved.value (); - } - else - { - if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) - return; - } + ref_node_id = resolved.value (); if (auto definition_id = mappings.lookup_node_to_hir (ref_node_id)) { @@ -434,26 +422,15 @@ UnsafeChecker::visit (CallExpr &expr) NodeId ast_node_id = expr.get_fnexpr ().get_mappings ().get_nodeid (); NodeId ref_node_id; - // There are no unsafe types, and functions are defined in the name resolver. - // If we can't find the name, then we're dealing with a type and should return - // early. - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto resolved = nr_ctx.lookup (ast_node_id); + auto resolved = nr_ctx.lookup (ast_node_id); - if (!resolved.has_value ()) - return; + if (!resolved.has_value ()) + return; - ref_node_id = resolved.value (); - } - else - { - if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) - return; - } + ref_node_id = resolved.value (); if (auto definition_id = mappings.lookup_node_to_hir (ref_node_id)) { diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h index dc3b482f15b..197c2e8d057 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.h +++ b/gcc/rust/checks/errors/rust-unsafe-checker.h @@ -54,7 +54,6 @@ class UnsafeChecker : public HIRFullVisitor StackedContexts unsafe_context; Resolver::TypeCheckContext &context; - Resolver::Resolver &resolver; Analysis::Mappings &mappings; virtual void visit (Lifetime &lifetime) override; diff --git a/gcc/rust/checks/lints/rust-lint-marklive.cc b/gcc/rust/checks/lints/rust-lint-marklive.cc index af7535a9826..80c30e0c343 100644 --- a/gcc/rust/checks/lints/rust-lint-marklive.cc +++ b/gcc/rust/checks/lints/rust-lint-marklive.cc @@ -163,21 +163,14 @@ MarkLive::visit_path_segment (HIR::PathExprSegment seg) // // We should mark them alive all and ignoring other kind of segments. // If the segment we dont care then just return false is fine - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + if (auto id = nr_ctx.lookup (ast_node_id)) + ref_node_id = *id; + else + return false; - if (auto id = nr_ctx.lookup (ast_node_id)) - ref_node_id = *id; - else - return false; - } - else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - { - if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id)) - return false; - } if (auto hid = mappings.lookup_node_to_hir (ref_node_id)) { mark_hir_id (*hid); @@ -250,21 +243,13 @@ MarkLive::visit (HIR::TupleIndexExpr &expr) void MarkLive::visit (HIR::TypeAlias &alias) { - NodeId ast_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (auto id = nr_ctx.lookup ( - alias.get_type_aliased ().get_mappings ().get_nodeid ())) - ast_node_id = *id; - } - else - { - resolver->lookup_resolved_type ( - alias.get_type_aliased ().get_mappings ().get_nodeid (), &ast_node_id); - } + NodeId ast_node_id = UNKNOWN_NODEID; + if (auto id + = nr_ctx.lookup (alias.get_type_aliased ().get_mappings ().get_nodeid ())) + ast_node_id = *id; if (auto hid = mappings.lookup_node_to_hir (ast_node_id)) mark_hir_id (*hid); @@ -285,27 +270,13 @@ MarkLive::mark_hir_id (HirId id) void MarkLive::find_ref_node_id (NodeId ast_node_id, NodeId &ref_node_id) { - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - nr_ctx.lookup (ast_node_id).map ([&ref_node_id] (NodeId resolved) { - ref_node_id = resolved; - }); - } + if (auto res = nr_ctx.lookup (ast_node_id)) + ref_node_id = *res; else - { - if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - { - if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id)) - { - bool ok - = resolver->lookup_resolved_misc (ast_node_id, &ref_node_id); - rust_assert (ok); - } - } - } + rust_unreachable (); } } // namespace Analysis diff --git a/gcc/rust/checks/lints/rust-lint-marklive.h b/gcc/rust/checks/lints/rust-lint-marklive.h index 86d96fc9367..6b3dafd64e4 100644 --- a/gcc/rust/checks/lints/rust-lint-marklive.h +++ b/gcc/rust/checks/lints/rust-lint-marklive.h @@ -277,11 +277,9 @@ class MarkLive : public MarkLiveBase std::set liveSymbols; std::set scannedSymbols; Analysis::Mappings &mappings; - Resolver::Resolver *resolver; Resolver::TypeCheckContext *tyctx; MarkLive (std::vector worklist) : worklist (worklist), mappings (Analysis::Mappings::get ()), - resolver (Resolver::Resolver::get ()), tyctx (Resolver::TypeCheckContext::get ()){}; void mark_hir_id (HirId); diff --git a/gcc/rust/checks/lints/rust-lint-scan-deadcode.h b/gcc/rust/checks/lints/rust-lint-scan-deadcode.h index 0fc203b0318..bacf8f69352 100644 --- a/gcc/rust/checks/lints/rust-lint-scan-deadcode.h +++ b/gcc/rust/checks/lints/rust-lint-scan-deadcode.h @@ -135,12 +135,10 @@ class ScanDeadcode : public MarkLiveBase private: std::set live_symbols; - Resolver::Resolver *resolver; Analysis::Mappings &mappings; ScanDeadcode (std::set &live_symbols) - : live_symbols (live_symbols), resolver (Resolver::Resolver::get ()), - mappings (Analysis::Mappings::get ()){}; + : live_symbols (live_symbols), mappings (Analysis::Mappings::get ()){}; bool should_warn (HirId hirId) { diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index 58d80716009..de78e178dfa 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -23,6 +23,8 @@ #include "rust-session-manager.h" #include "rust-attribute-values.h" +#include "rust-ast-collector.h" + namespace Rust { /** @@ -39,6 +41,10 @@ fails_cfg (const AST::AttrVec &attrs) if (attr.get_path () == Values::Attributes::CFG && !attr.check_cfg_predicate (session)) return true; + // TODO: have testing mode + // for now, just remove all #[test] functions + if (attr.get_path () == Values::Attributes::TEST) + return true; } return false; } @@ -85,6 +91,10 @@ fails_cfg_with_expand (AST::AttrVec &attrs) attr.as_string ().c_str ()); } } + // TODO: have testing mode + // for now, just remove all #[test] functions + else if (attr.get_path () == Values::Attributes::TEST) + return true; } return false; } @@ -709,9 +719,32 @@ CfgStrip::visit (AST::AssignmentExpr &expr) void CfgStrip::visit (AST::CompoundAssignmentExpr &expr) { + //if (expr.get_left_expr ().get_expr_kind () == AST::Expr::Kind::Block) + // rust_error_at (expr.get_left_expr ().get_locus (), "unexpected block expr"); + + static int reenter_count = 0; + static int hit = 0; + + if (++reenter_count == 5) + {rust_error_at (expr.get_locus (), "nested 5x"); hit = 4;} /* outer attributes never allowed before these. while cannot strip * two direct descendant expressions, can strip ones below that */ AST::DefaultASTVisitor::visit (expr); + --reenter_count; + + if (hit && !--hit) + { + std::string out; + AST::TokenCollector collector; + collector.visit (expr); + auto tokens = collector.collect_tokens (); + for (auto &tok : tokens) + { + out += " "; + out += tok->as_string (); + } + rust_error_at (expr.get_locus (), "full: %s", out.c_str ()); + } // ensure that they are not marked for strip if (expr.get_left_expr ().is_marked_for_strip ()) diff --git a/gcc/rust/expand/rust-derive-debug.cc b/gcc/rust/expand/rust-derive-debug.cc index a0bf9d86972..3324c689c6d 100644 --- a/gcc/rust/expand/rust-derive-debug.cc +++ b/gcc/rust/expand/rust-derive-debug.cc @@ -55,10 +55,10 @@ DeriveDebug::stub_debug_fn () auto self = builder.self_ref_param (); auto return_type - = ptrify (builder.type_path ({"core", "fmt", "Result"}, true)); + = ptrify (builder.type_path_core ({"fmt", "Result"})); auto mut_fmt_type_inner - = ptrify (builder.type_path ({"core", "fmt", "Formatter"}, true)); + = ptrify (builder.type_path_core ({"fmt", "Formatter"})); auto mut_fmt_type = builder.reference_type (std::move (mut_fmt_type_inner), true); @@ -81,7 +81,7 @@ DeriveDebug::stub_derive_impl ( { auto trait_items = vec (stub_debug_fn ()); - auto debug = builder.type_path ({"core", "fmt", "Debug"}, true); + auto debug = builder.type_path_core ({"fmt", "Debug"}); auto generics = setup_impl_generics (name, type_generics, builder.trait_bound (debug)); diff --git a/gcc/rust/expand/rust-derive-default.cc b/gcc/rust/expand/rust-derive-default.cc index 26ee5461095..fa81554da32 100644 --- a/gcc/rust/expand/rust-derive-default.cc +++ b/gcc/rust/expand/rust-derive-default.cc @@ -42,7 +42,7 @@ DeriveDefault::go (Item &item) std::unique_ptr DeriveDefault::default_call (std::unique_ptr &&type) { - auto default_trait = builder.type_path ({"core", "default", "Default"}, true); + auto default_trait = builder.type_path_core ({"default", "Default"}); auto default_fn = builder.qualified_path_in_expression (std::move (type), default_trait, @@ -69,7 +69,7 @@ DeriveDefault::default_impl ( std::unique_ptr &&default_fn, std::string name, const std::vector> &type_generics) { - auto default_path = builder.type_path ({"core", "default", "Default"}, true); + auto default_path = builder.type_path_core ({"default", "Default"}); auto trait_items = vec (std::move (default_fn)); diff --git a/gcc/rust/expand/rust-derive-eq.cc b/gcc/rust/expand/rust-derive-eq.cc index 7da137fb5c2..19f670d174f 100644 --- a/gcc/rust/expand/rust-derive-eq.cc +++ b/gcc/rust/expand/rust-derive-eq.cc @@ -61,7 +61,7 @@ std::unique_ptr DeriveEq::assert_param_is_eq () { auto eq_bound = std::unique_ptr ( - new TraitBound (builder.type_path ({"core", "cmp", "Eq"}, true), loc)); + new TraitBound (builder.type_path_core ({"cmp", "Eq"}), loc)); auto sized_bound = std::unique_ptr ( new TraitBound (builder.type_path (LangItem::Kind::SIZED), loc, false, @@ -113,9 +113,9 @@ DeriveEq::eq_impls ( const std::vector> &type_generics) { // We create two copies of the type-path to avoid duplicate NodeIds - auto eq = builder.type_path ({"core", "cmp", "Eq"}, true); + auto eq = builder.type_path_core ({"cmp", "Eq"}); auto eq_bound - = builder.trait_bound (builder.type_path ({"core", "cmp", "Eq"}, true)); + = builder.trait_bound (builder.type_path_core ({"cmp", "Eq"})); auto steq = builder.type_path (LangItem::Kind::STRUCTURAL_TEQ); diff --git a/gcc/rust/expand/rust-derive-hash.cc b/gcc/rust/expand/rust-derive-hash.cc index 94aede2fe03..ca9f2ef7bc2 100644 --- a/gcc/rust/expand/rust-derive-hash.cc +++ b/gcc/rust/expand/rust-derive-hash.cc @@ -42,7 +42,7 @@ std::unique_ptr DeriveHash::hash_call (std::unique_ptr &&value) { auto hash - = builder.path_in_expression ({"core", "hash", "Hash", "hash"}, true); + = builder.path_in_expression_core ({"hash", "Hash", "hash"}); return builder.call (ptrify (hash), vec (std::move (value), @@ -64,7 +64,7 @@ DeriveHash::hash_fn (std::unique_ptr &&block) auto params = vec (builder.self_ref_param (), std::move (state_param)); auto bounds = vec ( - builder.trait_bound (builder.type_path ({"core", "hash", "Hasher"}, true))); + builder.trait_bound (builder.type_path_core ({"hash", "Hasher"}))); auto generics = vec ( builder.generic_type_param (DeriveHash::state_type, std::move (bounds))); @@ -77,7 +77,7 @@ DeriveHash::hash_impl ( std::unique_ptr &&hash_fn, std::string name, const std::vector> &type_generics) { - auto hash_path = builder.type_path ({"core", "hash", "Hash"}, true); + auto hash_path = builder.type_path_core ({"hash", "Hash"}); auto trait_items = vec (std::move (hash_fn)); diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc index afc4b71676a..bf597d22874 100644 --- a/gcc/rust/expand/rust-derive-ord.cc +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -42,8 +42,8 @@ std::unique_ptr DeriveOrd::cmp_call (std::unique_ptr &&self_expr, std::unique_ptr &&other_expr) { - auto cmp_fn_path = builder.path_in_expression ( - {"core", "cmp", trait (ordering), fn (ordering)}, true); + auto cmp_fn_path = builder.path_in_expression_core ( + {"cmp", trait (ordering), fn (ordering)}); return builder.call (ptrify (cmp_fn_path), vec (builder.ref (std::move (self_expr)), @@ -58,10 +58,10 @@ DeriveOrd::cmp_impl ( auto fn = cmp_fn (std::move (fn_block), type_name); auto trait = ordering == Ordering::Partial ? "PartialOrd" : "Ord"; - auto trait_path = builder.type_path ({"core", "cmp", trait}, true); + auto trait_path = builder.type_path_core ({"cmp", trait}); auto trait_bound - = builder.trait_bound (builder.type_path ({"core", "cmp", trait}, true)); + = builder.trait_bound (builder.type_path_core ({"cmp", trait})); auto trait_items = vec (std::move (fn)); @@ -78,7 +78,7 @@ std::unique_ptr DeriveOrd::cmp_fn (std::unique_ptr &&block, Identifier type_name) { // Ordering - auto return_type = builder.type_path ({"core", "cmp", "Ordering"}, true); + auto return_type = builder.type_path_core ({"cmp", "Ordering"}); // In the case of PartialOrd, we return an Option if (ordering == Ordering::Partial) @@ -87,13 +87,11 @@ DeriveOrd::cmp_fn (std::unique_ptr &&block, Identifier type_name) auto generic_seg = builder.type_path_segment_generic ( "Option", GenericArgs ({}, {generic}, {}, loc)); - auto core = builder.type_path_segment ("core"); auto option = builder.type_path_segment ("option"); return_type - = builder.type_path (vec (std::move (core), std::move (option), - std::move (generic_seg)), - true); + = builder.type_path_core (vec (std::move (option), + std::move (generic_seg))); } // &self, other: &Self @@ -113,7 +111,7 @@ std::unique_ptr DeriveOrd::make_equal () { std::unique_ptr equal = ptrify ( - builder.path_in_expression ({"core", "cmp", "Ordering", "Equal"}, true)); + builder.path_in_expression_core ({"cmp", "Ordering", "Equal"})); // We need to wrap the pattern in Option::Some if we are doing partial // ordering @@ -148,8 +146,7 @@ DeriveOrd::recursive_match (std::vector &&members) if (members.empty ()) { std::unique_ptr value = ptrify ( - builder.path_in_expression ({"core", "cmp", "Ordering", "Equal"}, - true)); + builder.path_in_expression_core ({"cmp", "Ordering", "Equal"})); if (ordering == Ordering::Partial) value = builder.call (ptrify (builder.path_in_expression ( diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h index 283b4434dd3..18e97472c37 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -118,7 +118,7 @@ class DeriveVisitor : public AST::ASTVisitor virtual void visit (LiteralExpr &expr) override final{}; virtual void visit (AttrInputLiteral &attr_input) override final{}; virtual void visit (MetaItemLitExpr &meta_item) override final{}; - virtual void visit (MetaItemPathLit &meta_item) override final{}; + virtual void visit (MetaItemPathExpr &meta_item) override final{}; virtual void visit (BorrowExpr &expr) override final{}; virtual void visit (DereferenceExpr &expr) override final{}; virtual void visit (ErrorPropagationExpr &expr) override final{}; @@ -256,6 +256,7 @@ class DeriveVisitor : public AST::ASTVisitor virtual void visit (FunctionParam ¶m) override final{}; virtual void visit (VariadicParam ¶m) override final{}; virtual void visit (FormatArgs ¶m) override final{}; + virtual void visit (FormatArgsEager ¶m) override final{}; virtual void visit (OffsetOf ¶m) override final{}; }; diff --git a/gcc/rust/expand/rust-expand-format-args.cc b/gcc/rust/expand/rust-expand-format-args.cc index bda28dd61ce..56ea9a74efe 100644 --- a/gcc/rust/expand/rust-expand-format-args.cc +++ b/gcc/rust/expand/rust-expand-format-args.cc @@ -36,10 +36,10 @@ format_arg (const AST::Builder &builder, std::unique_ptr &&to_format, const std::string &trait) { auto formatter_fn = std::unique_ptr (new AST::PathInExpression ( - builder.path_in_expression ({"core", "fmt", trait, "fmt"}))); + builder.path_in_expression_core ({"fmt", trait, "fmt"}))); auto path = std::unique_ptr (new AST::PathInExpression ( - builder.path_in_expression ({"core", "fmt", "ArgumentV1", "new"}))); + builder.path_in_expression_core ({"fmt", "ArgumentV1", "new"}))); auto args = std::vector> (); args.emplace_back (std::move (to_format)); @@ -65,9 +65,38 @@ get_trait_name (ffi::FormatSpec format_specifier) return it->second; } -tl::optional -expand_format_args (AST::FormatArgs &fmt, - std::vector> &&tokens) +tl::optional> +expand_format_args_eager (AST::FormatArgsEager &fmt_eager) +{ + if (!fmt_eager.get_template ().is_literal ()) + { + if (fmt_eager.get_template ().get_expr_kind () != AST::Expr::Kind::MacroInvocation) + rust_error_at (fmt_eager.get_locus (), "format argument must be a string literal"); + return tl::nullopt; + } + + auto &literal = static_cast (fmt_eager.get_template ()); + + // TODO: is special handling for RAW_STRING needed? + rust_assert (literal.get_lit_type () == AST::Literal::STRING || literal.get_lit_type () == AST::Literal::RAW_STRING); + + // TODO: does this handle escapes in STRING properly? + auto fmt_str = literal.get_literal ().as_string (); + + bool append_newline = fmt_eager.get_newline () == AST::FormatArgs::Newline::Yes; + + if (append_newline) + fmt_str += '\n'; + + auto pieces = Fmt::Pieces::collect (fmt_str, append_newline, Fmt::ffi::ParseMode::Format); + + auto fmt_args_node = AST::FormatArgs (fmt_eager.get_locus (), std::move (pieces), std::move (fmt_eager.get_arguments ())); + + return Fmt::expand_format_args (fmt_args_node); +} + +std::unique_ptr +expand_format_args (AST::FormatArgs &fmt) { auto loc = fmt.get_locus (); auto builder = AST::Builder (loc); @@ -123,7 +152,7 @@ expand_format_args (AST::FormatArgs &fmt, auto args_slice = builder.ref (builder.array (std::move (args_array))); auto final_path = std::make_unique ( - builder.path_in_expression ({"core", "fmt", "Arguments", "new_v1"})); + builder.path_in_expression_core ({"fmt", "Arguments", "new_v1"})); auto final_args = std::vector> (); final_args.emplace_back (std::move (pieces)); final_args.emplace_back (std::move (args_slice)); @@ -131,9 +160,7 @@ expand_format_args (AST::FormatArgs &fmt, auto final_call = builder.call (std::move (final_path), std::move (final_args)); - auto node = AST::SingleASTNode (std::move (final_call)); - - return AST::Fragment ({node}, std::move (tokens)); + return final_call; } } // namespace Fmt diff --git a/gcc/rust/expand/rust-expand-format-args.h b/gcc/rust/expand/rust-expand-format-args.h index 2692ef9a404..44ac5285643 100644 --- a/gcc/rust/expand/rust-expand-format-args.h +++ b/gcc/rust/expand/rust-expand-format-args.h @@ -19,15 +19,18 @@ #ifndef RUST_EXPAND_FORMAT_ARGS_H #define RUST_EXPAND_FORMAT_ARGS_H -#include "optional.h" +#include "rust-system.h" #include "rust-ast-fragment.h" +#include "optional.h" namespace Rust { namespace Fmt { -tl::optional -expand_format_args (AST::FormatArgs &fmt, - std::vector> &&tokens); +tl::optional> +expand_format_args_eager (AST::FormatArgsEager &fmt_eager); + +std::unique_ptr +expand_format_args (AST::FormatArgs &fmt); } // namespace Fmt } // namespace Rust diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index 69959b541c7..8af195cae13 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -23,6 +23,7 @@ #include "rust-ast.h" #include "rust-type.h" #include "rust-derive.h" +#include "rust-expand-format-args.h" namespace Rust { @@ -538,7 +539,7 @@ ExpandVisitor::visit (AST::MetaItemLitExpr &) {} void -ExpandVisitor::visit (AST::MetaItemPathLit &) +ExpandVisitor::visit (AST::MetaItemPathExpr &) {} void @@ -1018,6 +1019,20 @@ ExpandVisitor::visit (AST::SelfParam ¶m) maybe_expand_type (param.get_type_ptr ()); } +void +ExpandVisitor::visit (AST::FormatArgsEager &fmt) +{ + maybe_expand_expr (fmt.get_template_ptr ()); + auto res = Fmt::expand_format_args_eager (fmt); + if (res.has_value ()) + { + // TODO: is it alright to have an empty token list? + std::vector> fragment_tokens; + + expander.set_expanded_fragment (AST::Fragment ({AST::SingleASTNode (std::move (*res))}, std::move(fragment_tokens))); + } +} + template void ExpandVisitor::expand_inner_attribute (T &item, AST::SimplePath &path) diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h index ef78404ae6b..3d9331fa08a 100644 --- a/gcc/rust/expand/rust-expand-visitor.h +++ b/gcc/rust/expand/rust-expand-visitor.h @@ -35,7 +35,7 @@ bool is_derive (AST::Attribute &attr); */ bool is_builtin (AST::Attribute &attr); -class ExpandVisitor : public AST::DefaultASTVisitor +class ExpandVisitor : public AST::ASTVisitor { public: ExpandVisitor (MacroExpander &expander) : expander (expander) {} @@ -209,29 +209,57 @@ class ExpandVisitor : public AST::DefaultASTVisitor void visit (AST::AttrInputLiteral &) override; void visit (AST::AttrInputMacro &) override; void visit (AST::MetaItemLitExpr &) override; - void visit (AST::MetaItemPathLit &) override; - void visit (AST::ErrorPropagationExpr &expr) override; + void visit (AST::MetaItemPathExpr &) override; + void visit (AST::BorrowExpr &) override; + void visit (AST::DereferenceExpr &) override; + void visit (AST::ErrorPropagationExpr &) override; + void visit (AST::NegationExpr &) override; void visit (AST::ArithmeticOrLogicalExpr &expr) override; void visit (AST::ComparisonExpr &expr) override; void visit (AST::LazyBooleanExpr &expr) override; + void visit (AST::TypeCastExpr &expr) override; void visit (AST::AssignmentExpr &expr) override; void visit (AST::CompoundAssignmentExpr &expr) override; void visit (AST::GroupedExpr &expr) override; + void visit (AST::ArrayElemsValues &expr) override; + void visit (AST::ArrayElemsCopied &expr) override; + void visit (AST::ArrayExpr &expr) override; + void visit (AST::ArrayIndexExpr &expr) override; + void visit (AST::TupleExpr &expr) override; + void visit (AST::TupleIndexExpr &expr) override; void visit (AST::StructExprStruct &expr) override; + void visit (AST::StructExprFieldIdentifierValue &expr) override; + void visit (AST::StructExprFieldIndexValue &expr) override; + void visit (AST::CallExpr &expr) override; void visit (AST::MethodCallExpr &expr) override; + void visit (AST::FieldAccessExpr &expr) override; void visit (AST::ClosureExprInner &expr) override; void visit (AST::BlockExpr &expr) override; + void visit (AST::AnonConst &expr) override; + void visit (AST::ConstBlock &expr) override; void visit (AST::ClosureExprInnerTyped &expr) override; void visit (AST::ContinueExpr &expr) override; + void visit (AST::BreakExpr &expr) override; + void visit (AST::RangeFromToExpr &expr) override; + void visit (AST::RangeFromExpr &expr) override; + void visit (AST::RangeToExpr &expr) override; + void visit (AST::RangeFromToInclExpr &expr) override; + void visit (AST::RangeToInclExpr &expr) override; + void visit (AST::ReturnExpr &expr) override; + void visit (AST::BoxExpr &expr) override; + void visit (AST::WhileLoopExpr &expr) override; + void visit (AST::WhileLetLoopExpr &expr) override; + void visit (AST::ForLoopExpr &expr) override; void visit (AST::IfExpr &expr) override; void visit (AST::IfExprConseqElse &expr) override; void visit (AST::IfLetExpr &expr) override; void visit (AST::IfLetExprConseqElse &expr) override; void visit (AST::MatchExpr &expr) override; + void visit (AST::AwaitExpr &expr) override; void visit (AST::TypeParam ¶m) override; void visit (AST::LifetimeWhereClauseItem &) override; void visit (AST::TypeBoundWhereClauseItem &item) override; @@ -277,6 +305,9 @@ class ExpandVisitor : public AST::DefaultASTVisitor void visit (AST::FunctionParam &type) override; void visit (AST::SelfParam &type) override; + // expand these if possible + void visit (AST::FormatArgsEager &fmt) override; + template void expand_inner_attribute (T &item, AST::SimplePath &Path); diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc index 61222dbeacb..c084c746728 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.cc +++ b/gcc/rust/expand/rust-macro-builtins-asm.cc @@ -1127,6 +1127,11 @@ parse_llvm_clobbers (LlvmAsmContext &ctx) } parser.skip_token (STRING_LITERAL); token = parser.peek_current_token (); + if (token->get_id () == COMMA) + { + parser.skip_token (COMMA); + token = parser.peek_current_token (); + } } } diff --git a/gcc/rust/expand/rust-macro-builtins-format-args.cc b/gcc/rust/expand/rust-macro-builtins-format-args.cc index b20c8495320..6414a4de530 100644 --- a/gcc/rust/expand/rust-macro-builtins-format-args.cc +++ b/gcc/rust/expand/rust-macro-builtins-format-args.cc @@ -24,7 +24,7 @@ namespace Rust { struct FormatArgsInput { - std::string format_str; + std::unique_ptr format_expr; AST::FormatArguments args; // bool is_literal? }; @@ -48,28 +48,10 @@ format_args_parse_arguments (AST::MacroInvocData &invoc) auto args = AST::FormatArguments (); auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser); - std::unique_ptr format_expr = nullptr; - - // TODO: Handle the case where we're not parsing a string literal (macro - // invocation for e.g.) - switch (parser.peek_current_token ()->get_id ()) - { - case STRING_LITERAL: - case RAW_STRING_LITERAL: - format_expr = parser.parse_literal_expr (); - default: - // do nothing - ; - } - + + auto format_expr = parser.parse_expr (); rust_assert (format_expr); - // TODO(Arthur): Clean this up - if we haven't parsed a string literal but a - // macro invocation, what do we do here? return a tl::unexpected? - auto format_str = static_cast (*format_expr) - .get_literal () - .as_string (); - // TODO: Allow implicit captures ONLY if the the first arg is a string literal // and not a macro invocation @@ -126,7 +108,7 @@ format_args_parse_arguments (AST::MacroInvocData &invoc) // we need to skip commas, don't we? } - return FormatArgsInput{std::move (format_str), std::move (args)}; + return FormatArgsInput{std::move (format_expr), std::move (args)}; } tl::optional @@ -144,67 +126,9 @@ MacroBuiltin::format_args_handler (location_t invoc_locus, return tl::nullopt; } - // TODO(Arthur): We need to handle this - // // if it is not a literal, it's an eager macro invocation - return it - // if (!fmt_expr->is_literal ()) - // { - // auto token_tree = invoc.get_delim_tok_tree (); - // return AST::Fragment ({AST::SingleASTNode (std::move (fmt_expr))}, - // token_tree.to_token_stream ()); - // } - - // TODO(Arthur): Handle this as well - raw strings are special for the - // format_args parser auto fmt_str = static_cast - // (*fmt_arg.get ()); Switch on the format string to know if the string is raw - // or cooked switch (fmt_str.get_lit_type ()) - // { - // // case AST::Literal::RAW_STRING: - // case AST::Literal::STRING: - // break; - // case AST::Literal::CHAR: - // case AST::Literal::BYTE: - // case AST::Literal::BYTE_STRING: - // case AST::Literal::INT: - // case AST::Literal::FLOAT: - // case AST::Literal::BOOL: - // case AST::Literal::ERROR: - // rust_unreachable (); - // } - - bool append_newline = nl == AST::FormatArgs::Newline::Yes; - - auto fmt_str = std::move (input->format_str); - if (append_newline) - fmt_str += '\n'; - - auto pieces = Fmt::Pieces::collect (fmt_str, append_newline, - Fmt::ffi::ParseMode::Format); - - // TODO: - // do the transformation into an AST::FormatArgs node - // return that - // expand it during lowering - - // TODO: we now need to take care of creating `unfinished_literal`? this is - // for creating the `template` - - auto fmt_args_node = AST::FormatArgs (invoc_locus, std::move (pieces), - std::move (input->args)); - - auto expanded - = Fmt::expand_format_args (fmt_args_node, - invoc.get_delim_tok_tree ().to_token_stream ()); - - if (!expanded.has_value ()) - return AST::Fragment::create_error (); - - return *expanded; - - // auto node = std::unique_ptr (fmt_args_node); - // auto single_node = AST::SingleASTNode (std::move (node)); - - // return AST::Fragment ({std::move (single_node)}, - // invoc.get_delim_tok_tree ().to_token_stream ()); + auto node = AST::SingleASTNode (std::unique_ptr (new AST::FormatArgsEager (invoc_locus, std::move (input->format_expr), std::move (input->args), nl))); + + return AST::Fragment ({std::move (node)}, invoc.get_delim_tok_tree ().to_token_stream ()); } } // namespace Rust diff --git a/gcc/rust/expand/rust-macro-builtins-helpers.cc b/gcc/rust/expand/rust-macro-builtins-helpers.cc index 864379a3ffa..26fc027e640 100644 --- a/gcc/rust/expand/rust-macro-builtins-helpers.cc +++ b/gcc/rust/expand/rust-macro-builtins-helpers.cc @@ -110,9 +110,9 @@ std::unique_ptr try_extract_string_literal_from_fragment (const location_t &parent_locus, std::unique_ptr &node) { - auto maybe_lit = static_cast (node.get ()); + AST::LiteralExpr *maybe_lit; if (!node || !node->is_literal () - || maybe_lit->get_lit_type () != AST::Literal::STRING) + || (maybe_lit = static_cast (node.get ()))->get_lit_type () != AST::Literal::STRING) { rust_error_at (parent_locus, "argument must be a string literal"); if (node) diff --git a/gcc/rust/expand/rust-macro-builtins-helpers.h b/gcc/rust/expand/rust-macro-builtins-helpers.h index 32cf58fd1be..ce63017b004 100644 --- a/gcc/rust/expand/rust-macro-builtins-helpers.h +++ b/gcc/rust/expand/rust-macro-builtins-helpers.h @@ -22,7 +22,6 @@ #include "rust-ast.h" #include "rust-cfg-strip.h" #include "rust-diagnostics.h" -#include "rust-early-name-resolver.h" #include "rust-expr.h" #include "rust-lex.h" #include "rust-macro-builtins.h" diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc index a7ae2207985..948f3893abd 100644 --- a/gcc/rust/expand/rust-macro-builtins.cc +++ b/gcc/rust/expand/rust-macro-builtins.cc @@ -29,7 +29,6 @@ #include "rust-ast.h" #include "rust-cfg-strip.h" #include "rust-diagnostics.h" -#include "rust-early-name-resolver.h" #include "rust-expr.h" #include "rust-lex.h" #include "rust-macro-invoc-lexer.h" diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 4c54ceff98a..7e12fa80ed7 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -27,7 +27,6 @@ #include "rust-macro.h" #include "rust-parse.h" #include "rust-cfg-strip.h" -#include "rust-early-name-resolver.h" #include "rust-proc-macro.h" #include "rust-token-tree-desugar.h" @@ -335,9 +334,6 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, void MacroExpander::expand_crate () { - NodeId scope_node_id = crate.get_node_id (); - resolver->get_macro_scope ().push (scope_node_id); - /* fill macro/decorator map from init list? not sure where init list comes * from? */ @@ -961,7 +957,8 @@ transcribe_expression (Parser &parser) auto &lexer = parser.get_token_source (); auto start = lexer.get_offs (); - auto expr = parser.parse_expr (); + auto attrs = parser.parse_outer_attributes (); + auto expr = parser.parse_expr (std::move (attrs)); if (expr == nullptr) return AST::Fragment::create_error (); diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index 360294c6bf9..185d50ffb46 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -27,7 +27,6 @@ #include "rust-ast.h" #include "rust-macro.h" #include "rust-hir-map.h" -#include "rust-early-name-resolver.h" #include "rust-name-resolver.h" #include "rust-macro-invoc-lexer.h" #include "rust-proc-macro-invoc-lexer.h" @@ -300,8 +299,7 @@ struct MacroExpander : cfg (cfg), crate (crate), session (session), sub_stack (SubstitutionScope ()), expanded_fragment (AST::Fragment::create_error ()), - has_changed_flag (false), resolver (Resolver::Resolver::get ()), - mappings (Analysis::Mappings::get ()) + has_changed_flag (false), mappings (Analysis::Mappings::get ()) {} ~MacroExpander () = default; @@ -513,7 +511,6 @@ struct MacroExpander tl::optional last_invoc; public: - Resolver::Resolver *resolver; Analysis::Mappings &mappings; }; diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index 09f4b930963..408d5cf00c9 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -136,7 +136,7 @@ void ASTLoweringBase::visit (AST::MetaItemLitExpr &) {} void -ASTLoweringBase::visit (AST::MetaItemPathLit &) +ASTLoweringBase::visit (AST::MetaItemPathExpr &) {} void ASTLoweringBase::visit (AST::BorrowExpr &) @@ -578,6 +578,10 @@ void ASTLoweringBase::visit (AST::FormatArgs &fmt) {} +void +ASTLoweringBase::visit (AST::FormatArgsEager &fmt) +{} + void ASTLoweringBase::visit (AST::OffsetOf &offset_of) {} diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index af21c40d5c5..1c323df8441 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -106,7 +106,7 @@ class ASTLoweringBase : public AST::ASTVisitor virtual void visit (AST::AttrInputLiteral &attr_input) override; virtual void visit (AST::AttrInputMacro &attr_input) override; virtual void visit (AST::MetaItemLitExpr &meta_item) override; - virtual void visit (AST::MetaItemPathLit &meta_item) override; + virtual void visit (AST::MetaItemPathExpr &meta_item) override; virtual void visit (AST::BorrowExpr &expr) override; virtual void visit (AST::DereferenceExpr &expr) override; virtual void visit (AST::NegationExpr &expr) override; @@ -266,6 +266,7 @@ class ASTLoweringBase : public AST::ASTVisitor virtual void visit (AST::SelfParam ¶m) override; virtual void visit (AST::FormatArgs &fmt) override; + virtual void visit (AST::FormatArgsEager &fmt) override; virtual void visit (AST::OffsetOf &offset_of) override; protected: diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt index d9824f1a5ac..8db436d30f2 100644 --- a/gcc/rust/lang.opt +++ b/gcc/rust/lang.opt @@ -204,10 +204,6 @@ Enum(frust_compile_until) String(compilation) Value(12) EnumValue Enum(frust_compile_until) String(end) Value(13) -frust-name-resolution-2.0 -Rust Var(flag_name_resolution_2_0) Init(1) -Use the temporary and experimental name resolution pipeline instead of the stable one - frust-borrowcheck Rust Var(flag_borrowcheck) Use the WIP borrow checker. diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 63bbf8ebf0f..d0d415b51c6 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -212,6 +212,11 @@ template class Parser std::unique_ptr parse_macro_invocation (AST::AttrVec outer_attrs); + /* + * This has to be public for parsing expressions with outer attributes + */ + AST::AttrVec parse_outer_attributes (); + private: void skip_after_semicolon (); void skip_after_end (); @@ -228,7 +233,6 @@ template class Parser // AST-related stuff - maybe move or something? AST::Attribute parse_inner_attribute (); - AST::AttrVec parse_outer_attributes (); AST::Attribute parse_outer_attribute (); std::unique_ptr parse_attr_input (); std::tuple, location_t> @@ -779,6 +783,10 @@ template class Parser } ~InlineModuleStackScope () { parser.inline_module_stack.pop_back (); } }; + + // don't want to make things *only* AttributeParser uses public + // TODO: fold more of AttributeParser into Parser? + friend class ::Rust::AST::AttributeParser; }; std::string extract_module_path (const AST::AttrVec &inner_attrs, diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc deleted file mode 100644 index 6b57c6d62a8..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ /dev/null @@ -1,691 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#include "rust-ast-resolve-base.h" -#include "rust-ast-resolve-expr.h" -#include "rust-ast-resolve-path.h" -#include "rust-item.h" -#include "rust-path.h" - -namespace Rust { -namespace Resolver { - -bool -ResolverBase::resolve_visibility (const AST::Visibility &vis) -{ - if (vis.has_path ()) - { - auto path = vis.get_path (); - ResolvePath::go (path); - - // Do we need to lookup something here? - // Is it just about resolving the names correctly so we can look them up - // later? - } - - return true; -} - -// Default visitors implementations - -void -ResolverBase::visit (AST::Token &) -{} - -void -ResolverBase::visit (AST::DelimTokenTree &) -{} - -void -ResolverBase::visit (AST::AttrInputMetaItemContainer &) -{} - -void -ResolverBase::visit (AST::IdentifierExpr &) -{} - -void -ResolverBase::visit (AST::Lifetime &) -{} - -void -ResolverBase::visit (AST::LifetimeParam &) -{} - -void -ResolverBase::visit (AST::ConstGenericParam &) -{} - -void -ResolverBase::visit (AST::PathInExpression &) -{} - -void -ResolverBase::visit (AST::TypePathSegment &) -{} - -void -ResolverBase::visit (AST::TypePathSegmentGeneric &) -{} - -void -ResolverBase::visit (AST::TypePathSegmentFunction &) -{} - -void -ResolverBase::visit (AST::TypePath &) -{} - -void -ResolverBase::visit (AST::QualifiedPathInExpression &) -{} - -void -ResolverBase::visit (AST::QualifiedPathInType &) -{} - -void -ResolverBase::visit (AST::LiteralExpr &) -{} - -void -ResolverBase::visit (AST::AttrInputLiteral &) -{} - -void -ResolverBase::visit (AST::AttrInputMacro &) -{} - -void -ResolverBase::visit (AST::MetaItemLitExpr &) -{} - -void -ResolverBase::visit (AST::MetaItemPathLit &) -{} - -void -ResolverBase::visit (AST::BorrowExpr &) -{} - -void -ResolverBase::visit (AST::DereferenceExpr &) -{} - -void -ResolverBase::visit (AST::ErrorPropagationExpr &) -{} - -void -ResolverBase::visit (AST::NegationExpr &) -{} - -void -ResolverBase::visit (AST::ArithmeticOrLogicalExpr &) -{} - -void -ResolverBase::visit (AST::ComparisonExpr &) -{} - -void -ResolverBase::visit (AST::LazyBooleanExpr &) -{} - -void -ResolverBase::visit (AST::TypeCastExpr &) -{} - -void -ResolverBase::visit (AST::AssignmentExpr &) -{} - -void -ResolverBase::visit (AST::CompoundAssignmentExpr &) -{} - -void -ResolverBase::visit (AST::GroupedExpr &) -{} - -void -ResolverBase::visit (AST::ArrayElemsValues &) -{} - -void -ResolverBase::visit (AST::ArrayElemsCopied &) -{} - -void -ResolverBase::visit (AST::ArrayExpr &) -{} - -void -ResolverBase::visit (AST::ArrayIndexExpr &) -{} - -void -ResolverBase::visit (AST::TupleExpr &) -{} - -void -ResolverBase::visit (AST::TupleIndexExpr &) -{} - -void -ResolverBase::visit (AST::StructExprStruct &) -{} - -void -ResolverBase::visit (AST::StructExprFieldIdentifier &) -{} - -void -ResolverBase::visit (AST::StructExprFieldIdentifierValue &) -{} - -void -ResolverBase::visit (AST::StructExprFieldIndexValue &) -{} - -void -ResolverBase::visit (AST::StructExprStructFields &) -{} - -void -ResolverBase::visit (AST::StructExprStructBase &) -{} - -void -ResolverBase::visit (AST::CallExpr &) -{} - -void -ResolverBase::visit (AST::MethodCallExpr &) -{} - -void -ResolverBase::visit (AST::FieldAccessExpr &) -{} - -void -ResolverBase::visit (AST::ClosureExprInner &) -{} - -void -ResolverBase::visit (AST::BlockExpr &) -{} - -void -ResolverBase::visit (AST::AnonConst &) -{} - -void -ResolverBase::visit (AST::ConstBlock &) -{} - -void -ResolverBase::visit (AST::ClosureExprInnerTyped &) -{} - -void -ResolverBase::visit (AST::ContinueExpr &) -{} - -void -ResolverBase::visit (AST::BreakExpr &) -{} - -void -ResolverBase::visit (AST::RangeFromToExpr &) -{} - -void -ResolverBase::visit (AST::RangeFromExpr &) -{} - -void -ResolverBase::visit (AST::RangeToExpr &) -{} - -void -ResolverBase::visit (AST::RangeFullExpr &) -{} - -void -ResolverBase::visit (AST::RangeFromToInclExpr &) -{} - -void -ResolverBase::visit (AST::RangeToInclExpr &) -{} - -void -ResolverBase::visit (AST::BoxExpr &) -{} - -void -ResolverBase::visit (AST::ReturnExpr &) -{} - -void -ResolverBase::visit (AST::TryExpr &) -{} - -void -ResolverBase::visit (AST::UnsafeBlockExpr &) -{} - -void -ResolverBase::visit (AST::LoopExpr &) -{} - -void -ResolverBase::visit (AST::WhileLoopExpr &) -{} - -void -ResolverBase::visit (AST::WhileLetLoopExpr &) -{} - -void -ResolverBase::visit (AST::ForLoopExpr &) -{} - -void -ResolverBase::visit (AST::IfExpr &) -{} - -void -ResolverBase::visit (AST::IfExprConseqElse &) -{} - -void -ResolverBase::visit (AST::IfLetExpr &) -{} - -void -ResolverBase::visit (AST::IfLetExprConseqElse &) -{} - -void -ResolverBase::visit (AST::MatchExpr &) -{} - -void -ResolverBase::visit (AST::AwaitExpr &) -{} - -void -ResolverBase::visit (AST::AsyncBlockExpr &) -{} - -void -ResolverBase::visit (AST::InlineAsm &) -{} - -void -ResolverBase::visit (AST::LlvmInlineAsm &) -{} - -void -ResolverBase::visit (AST::TypeParam &) -{} - -void -ResolverBase::visit (AST::LifetimeWhereClauseItem &) -{} - -void -ResolverBase::visit (AST::TypeBoundWhereClauseItem &) -{} - -void -ResolverBase::visit (AST::Module &) -{} - -void -ResolverBase::visit (AST::ExternCrate &) -{} - -void -ResolverBase::visit (AST::UseTreeGlob &) -{} - -void -ResolverBase::visit (AST::UseTreeList &) -{} - -void -ResolverBase::visit (AST::UseTreeRebind &) -{} - -void -ResolverBase::visit (AST::UseDeclaration &) -{} - -void -ResolverBase::visit (AST::Function &) -{} - -void -ResolverBase::visit (AST::TypeAlias &) -{} - -void -ResolverBase::visit (AST::StructStruct &) -{} - -void -ResolverBase::visit (AST::TupleStruct &) -{} - -void -ResolverBase::visit (AST::EnumItem &) -{} - -void -ResolverBase::visit (AST::EnumItemTuple &) -{} - -void -ResolverBase::visit (AST::EnumItemStruct &) -{} - -void -ResolverBase::visit (AST::EnumItemDiscriminant &) -{} - -void -ResolverBase::visit (AST::Enum &) -{} - -void -ResolverBase::visit (AST::Union &) -{} - -void -ResolverBase::visit (AST::ConstantItem &) -{} - -void -ResolverBase::visit (AST::StaticItem &) -{} - -void -ResolverBase::visit (AST::TraitItemConst &) -{} - -void -ResolverBase::visit (AST::TraitItemType &) -{} - -void -ResolverBase::visit (AST::Trait &) -{} - -void -ResolverBase::visit (AST::InherentImpl &) -{} - -void -ResolverBase::visit (AST::TraitImpl &) -{} - -void -ResolverBase::visit (AST::ExternalTypeItem &) -{} - -void -ResolverBase::visit (AST::ExternalStaticItem &) -{} - -void -ResolverBase::visit (AST::ExternBlock &) -{} - -void -ResolverBase::visit (AST::MacroMatchFragment &) -{} - -void -ResolverBase::visit (AST::MacroMatchRepetition &) -{} - -void -ResolverBase::visit (AST::MacroMatcher &) -{} - -void -ResolverBase::visit (AST::MacroRulesDefinition &) -{} - -void -ResolverBase::visit (AST::MacroInvocation &) -{} - -void -ResolverBase::visit (AST::MetaItemPath &) -{} - -void -ResolverBase::visit (AST::MetaItemSeq &) -{} - -void -ResolverBase::visit (AST::MetaWord &) -{} - -void -ResolverBase::visit (AST::MetaNameValueStr &) -{} - -void -ResolverBase::visit (AST::MetaListPaths &) -{} - -void -ResolverBase::visit (AST::MetaListNameValueStr &) -{} - -void -ResolverBase::visit (AST::LiteralPattern &) -{} - -void -ResolverBase::visit (AST::IdentifierPattern &) -{} - -void -ResolverBase::visit (AST::WildcardPattern &) -{} - -void -ResolverBase::visit (AST::RestPattern &) -{} - -void -ResolverBase::visit (AST::RangePatternBoundLiteral &) -{} - -void -ResolverBase::visit (AST::RangePatternBoundPath &) -{} - -void -ResolverBase::visit (AST::RangePatternBoundQualPath &) -{} - -void -ResolverBase::visit (AST::RangePattern &) -{} - -void -ResolverBase::visit (AST::ReferencePattern &) -{} - -void -ResolverBase::visit (AST::StructPatternFieldTuplePat &) -{} - -void -ResolverBase::visit (AST::StructPatternFieldIdentPat &) -{} - -void -ResolverBase::visit (AST::StructPatternFieldIdent &) -{} - -void -ResolverBase::visit (AST::StructPattern &) -{} - -void -ResolverBase::visit (AST::TupleStructItemsNoRange &) -{} - -void -ResolverBase::visit (AST::TupleStructItemsRange &) -{} - -void -ResolverBase::visit (AST::TupleStructPattern &) -{} - -void -ResolverBase::visit (AST::TuplePatternItemsMultiple &) -{} - -void -ResolverBase::visit (AST::TuplePatternItemsRanged &) -{} - -void -ResolverBase::visit (AST::TuplePattern &) -{} - -void -ResolverBase::visit (AST::GroupedPattern &) -{} - -void -ResolverBase::visit (AST::SlicePatternItemsNoRest &) -{} - -void -ResolverBase::visit (AST::SlicePatternItemsHasRest &) -{} - -void -ResolverBase::visit (AST::SlicePattern &) -{} - -void -ResolverBase::visit (AST::AltPattern &) -{} - -void -ResolverBase::visit (AST::EmptyStmt &) -{} - -void -ResolverBase::visit (AST::LetStmt &) -{} - -void -ResolverBase::visit (AST::ExprStmt &) -{} - -void -ResolverBase::visit (AST::TraitBound &) -{} - -void -ResolverBase::visit (AST::ImplTraitType &) -{} - -void -ResolverBase::visit (AST::TraitObjectType &) -{} - -void -ResolverBase::visit (AST::ParenthesisedType &) -{} - -void -ResolverBase::visit (AST::ImplTraitTypeOneBound &) -{} - -void -ResolverBase::visit (AST::TraitObjectTypeOneBound &) -{} - -void -ResolverBase::visit (AST::TupleType &) -{} - -void -ResolverBase::visit (AST::NeverType &) -{} - -void -ResolverBase::visit (AST::RawPointerType &) -{} - -void -ResolverBase::visit (AST::ReferenceType &) -{} - -void -ResolverBase::visit (AST::ArrayType &) -{} - -void -ResolverBase::visit (AST::SliceType &) -{} - -void -ResolverBase::visit (AST::InferredType &) -{} - -void -ResolverBase::visit (AST::BareFunctionType &) -{} - -void -ResolverBase::visit (AST::SelfParam &) -{} - -void -ResolverBase::visit (AST::VariadicParam &) -{} - -void -ResolverBase::visit (AST::FunctionParam &) -{} - -void -ResolverBase::visit (AST::FormatArgs &fmt) -{} - -void -ResolverBase::visit (AST::OffsetOf &offset_of) -{} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h deleted file mode 100644 index febfc6126d5..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_AST_RESOLVE_BASE_H -#define RUST_AST_RESOLVE_BASE_H - -#include "rust-ast-visitor.h" -#include "rust-ast.h" -#include "rust-builtin-ast-nodes.h" -#include "rust-expr.h" -#include "rust-name-resolver.h" -#include "rust-diagnostics.h" -#include "rust-location.h" - -namespace Rust { -namespace Resolver { -inline void -redefined_error (const rich_location &loc) -{ - rust_error_at (loc, "redefined multiple times"); -} - -class ResolverBase : public AST::ASTVisitor -{ -public: - virtual ~ResolverBase () {} - - void visit (AST::Token &); - void visit (AST::DelimTokenTree &); - void visit (AST::AttrInputMetaItemContainer &); - void visit (AST::IdentifierExpr &); - void visit (AST::Lifetime &); - void visit (AST::LifetimeParam &); - void visit (AST::ConstGenericParam &); - void visit (AST::PathInExpression &); - void visit (AST::TypePathSegment &); - void visit (AST::TypePathSegmentGeneric &); - void visit (AST::TypePathSegmentFunction &); - void visit (AST::TypePath &); - void visit (AST::QualifiedPathInExpression &); - void visit (AST::QualifiedPathInType &); - void visit (AST::LiteralExpr &); - void visit (AST::AttrInputLiteral &); - void visit (AST::AttrInputMacro &); - void visit (AST::MetaItemLitExpr &); - void visit (AST::MetaItemPathLit &); - void visit (AST::BorrowExpr &); - void visit (AST::DereferenceExpr &); - void visit (AST::ErrorPropagationExpr &); - void visit (AST::NegationExpr &); - void visit (AST::ArithmeticOrLogicalExpr &); - void visit (AST::ComparisonExpr &); - void visit (AST::LazyBooleanExpr &); - void visit (AST::TypeCastExpr &); - void visit (AST::AssignmentExpr &); - void visit (AST::CompoundAssignmentExpr &); - void visit (AST::GroupedExpr &); - void visit (AST::ArrayElemsValues &); - void visit (AST::ArrayElemsCopied &); - void visit (AST::ArrayExpr &); - void visit (AST::ArrayIndexExpr &); - void visit (AST::TupleExpr &); - void visit (AST::TupleIndexExpr &); - void visit (AST::StructExprStruct &); - void visit (AST::StructExprFieldIdentifier &); - void visit (AST::StructExprFieldIdentifierValue &); - void visit (AST::StructExprFieldIndexValue &); - void visit (AST::StructExprStructFields &); - void visit (AST::StructExprStructBase &); - void visit (AST::CallExpr &); - void visit (AST::MethodCallExpr &); - void visit (AST::FieldAccessExpr &); - void visit (AST::ClosureExprInner &); - void visit (AST::BlockExpr &); - void visit (AST::AnonConst &); - void visit (AST::ConstBlock &); - void visit (AST::ClosureExprInnerTyped &); - void visit (AST::ContinueExpr &); - void visit (AST::BreakExpr &); - void visit (AST::RangeFromToExpr &); - void visit (AST::RangeFromExpr &); - void visit (AST::RangeToExpr &); - void visit (AST::RangeFullExpr &); - void visit (AST::RangeFromToInclExpr &); - void visit (AST::RangeToInclExpr &); - void visit (AST::BoxExpr &); - void visit (AST::ReturnExpr &); - void visit (AST::TryExpr &); - void visit (AST::UnsafeBlockExpr &); - void visit (AST::LoopExpr &); - void visit (AST::WhileLoopExpr &); - void visit (AST::WhileLetLoopExpr &); - void visit (AST::ForLoopExpr &); - void visit (AST::IfExpr &); - void visit (AST::IfExprConseqElse &); - void visit (AST::IfLetExpr &); - void visit (AST::IfLetExprConseqElse &); - - void visit (AST::MatchExpr &); - void visit (AST::AwaitExpr &); - void visit (AST::AsyncBlockExpr &); - void visit (AST::InlineAsm &); - void visit (AST::LlvmInlineAsm &); - - void visit (AST::TypeParam &); - - void visit (AST::LifetimeWhereClauseItem &); - void visit (AST::TypeBoundWhereClauseItem &); - void visit (AST::Module &); - void visit (AST::ExternCrate &); - - void visit (AST::UseTreeGlob &); - void visit (AST::UseTreeList &); - void visit (AST::UseTreeRebind &); - void visit (AST::UseDeclaration &); - void visit (AST::Function &); - void visit (AST::TypeAlias &); - void visit (AST::StructStruct &); - void visit (AST::TupleStruct &); - void visit (AST::EnumItem &); - void visit (AST::EnumItemTuple &); - void visit (AST::EnumItemStruct &); - void visit (AST::EnumItemDiscriminant &); - void visit (AST::Enum &); - void visit (AST::Union &); - void visit (AST::ConstantItem &); - void visit (AST::StaticItem &); - void visit (AST::TraitItemConst &); - void visit (AST::TraitItemType &); - void visit (AST::Trait &); - void visit (AST::InherentImpl &); - void visit (AST::TraitImpl &); - - void visit (AST::ExternalTypeItem &); - void visit (AST::ExternalStaticItem &); - void visit (AST::ExternBlock &); - - void visit (AST::MacroMatchFragment &); - void visit (AST::MacroMatchRepetition &); - void visit (AST::MacroMatcher &); - void visit (AST::MacroRulesDefinition &); - void visit (AST::MacroInvocation &); - void visit (AST::MetaItemPath &); - void visit (AST::MetaItemSeq &); - void visit (AST::MetaWord &); - void visit (AST::MetaNameValueStr &); - void visit (AST::MetaListPaths &); - void visit (AST::MetaListNameValueStr &); - - void visit (AST::LiteralPattern &); - void visit (AST::IdentifierPattern &); - void visit (AST::WildcardPattern &); - void visit (AST::RestPattern &); - - void visit (AST::RangePatternBoundLiteral &); - void visit (AST::RangePatternBoundPath &); - void visit (AST::RangePatternBoundQualPath &); - void visit (AST::RangePattern &); - void visit (AST::ReferencePattern &); - - void visit (AST::StructPatternFieldTuplePat &); - void visit (AST::StructPatternFieldIdentPat &); - void visit (AST::StructPatternFieldIdent &); - void visit (AST::StructPattern &); - - void visit (AST::TupleStructItemsNoRange &); - void visit (AST::TupleStructItemsRange &); - void visit (AST::TupleStructPattern &); - - void visit (AST::TuplePatternItemsMultiple &); - void visit (AST::TuplePatternItemsRanged &); - void visit (AST::TuplePattern &); - void visit (AST::GroupedPattern &); - void visit (AST::SlicePatternItemsNoRest &); - void visit (AST::SlicePatternItemsHasRest &); - void visit (AST::SlicePattern &); - void visit (AST::AltPattern &); - - void visit (AST::EmptyStmt &); - void visit (AST::LetStmt &); - void visit (AST::ExprStmt &); - - void visit (AST::TraitBound &); - void visit (AST::ImplTraitType &); - void visit (AST::TraitObjectType &); - void visit (AST::ParenthesisedType &); - void visit (AST::ImplTraitTypeOneBound &); - void visit (AST::TraitObjectTypeOneBound &); - void visit (AST::TupleType &); - void visit (AST::NeverType &); - void visit (AST::RawPointerType &); - void visit (AST::ReferenceType &); - void visit (AST::ArrayType &); - void visit (AST::SliceType &); - void visit (AST::InferredType &); - void visit (AST::BareFunctionType &); - void visit (AST::FunctionParam ¶m); - void visit (AST::VariadicParam ¶m); - void visit (AST::SelfParam ¶m); - - void visit (AST::FormatArgs &fmt); - void visit (AST::OffsetOf &offset_of); - -protected: - ResolverBase () - : resolver (Resolver::get ()), mappings (Analysis::Mappings::get ()), - resolved_node (UNKNOWN_NODEID) - {} - - /** - * Resolve a visibility's path through the name resolver - */ - bool resolve_visibility (const AST::Visibility &vis); - - Resolver *resolver; - Analysis::Mappings &mappings; - NodeId resolved_node; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_BASE_H diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc deleted file mode 100644 index ffce8ba7600..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ /dev/null @@ -1,816 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#include "rust-ast-resolve-expr.h" -#include "rust-ast-resolve-stmt.h" -#include "rust-ast-resolve-struct-expr-field.h" -#include "rust-ast-resolve-type.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-path.h" -#include "rust-expr.h" -#include "rust-ice-finalizer.h" - -namespace Rust { -namespace Resolver { - -void -ResolveExpr::go (AST::Expr &expr, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, bool funny_error) -{ - ResolveExpr resolver (prefix, canonical_prefix, funny_error); - expr.accept_vis (resolver); -} - -void -ResolveExpr::visit (AST::TupleIndexExpr &expr) -{ - ResolveExpr::go (expr.get_tuple_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::TupleExpr &expr) -{ - if (expr.is_unit ()) - return; - - for (auto &elem : expr.get_tuple_elems ()) - ResolveExpr::go (*elem, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::PathInExpression &expr) -{ - ResolvePath::go (expr); -} - -void -ResolveExpr::visit (AST::QualifiedPathInExpression &expr) -{ - ResolvePath::go (expr); -} - -void -ResolveExpr::visit (AST::ReturnExpr &expr) -{ - if (expr.has_returned_expr ()) - ResolveExpr::go (expr.get_returned_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::CallExpr &expr) -{ - ResolveExpr::go (expr.get_function_expr (), prefix, canonical_prefix); - for (auto ¶m : expr.get_params ()) - ResolveExpr::go (*param, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::MethodCallExpr &expr) -{ - ResolveExpr::go (expr.get_receiver_expr (), prefix, canonical_prefix); - - if (expr.get_method_name ().has_generic_args ()) - { - AST::GenericArgs &args = expr.get_method_name ().get_generic_args (); - ResolveGenericArgs::go (args, prefix, canonical_prefix); - } - - auto const &in_params = expr.get_params (); - for (auto ¶m : in_params) - ResolveExpr::go (*param, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ErrorPropagationExpr &expr) -{ - ResolveExpr::go (expr.get_propagating_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::AssignmentExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IdentifierExpr &expr) -{ - if (resolver->get_name_scope ().lookup ( - CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()), - &resolved_node)) - { - resolver->insert_resolved_name (expr.get_node_id (), resolved_node); - } - else if (resolver->get_type_scope ().lookup ( - CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()), - &resolved_node)) - { - resolver->insert_resolved_type (expr.get_node_id (), resolved_node); - } - else if (funny_error) - { - /* This was a "break rust" or "break gcc", and the identifier failed to - resolve. Emit a funny ICE. We set the finalizer to our custom one, - and use the lower-level emit_diagnostic () instead of the more common - internal_error_no_backtrace () in order to pass our locus. */ - diagnostic_text_finalizer (global_dc) = funny_ice_text_finalizer; - emit_diagnostic (DK_ICE_NOBT, expr.get_locus (), -1, - "are you trying to break %s? how dare you?", - expr.as_string ().c_str ()); - } - else - { - rust_error_at (expr.get_locus (), ErrorCode::E0425, - "cannot find value %qs in this scope", - expr.as_string ().c_str ()); - } -} - -void -ResolveExpr::visit (AST::ArithmeticOrLogicalExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::CompoundAssignmentExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ComparisonExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::LazyBooleanExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::NegationExpr &expr) -{ - ResolveExpr::go (expr.get_negated_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::TypeCastExpr &expr) -{ - ResolveType::go (expr.get_type_to_cast_to ()); - ResolveExpr::go (expr.get_casted_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IfExpr &expr) -{ - ResolveExpr::go (expr.get_condition_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IfExprConseqElse &expr) -{ - ResolveExpr::go (expr.get_condition_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_else_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IfLetExpr &expr) -{ - ResolveExpr::go (expr.get_value_expr (), prefix, canonical_prefix); - - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // We know expr.get_patterns () has one pattern at most - // so there's no reason to handle it like an AltPattern. - std::vector bindings - = {PatternBinding (PatternBoundCtx::Product, std::set ())}; - - for (auto &pattern : expr.get_patterns ()) - { - PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings); - } - - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::IfLetExprConseqElse &expr) -{ - ResolveExpr::go (expr.get_value_expr (), prefix, canonical_prefix); - - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // We know expr.get_patterns () has one pattern at most - // so there's no reason to handle it like an AltPattern. - std::vector bindings - = {PatternBinding (PatternBoundCtx::Product, std::set ())}; - - for (auto &pattern : expr.get_patterns ()) - { - PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings); - } - - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_else_block (), prefix, canonical_prefix); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::BlockExpr &expr) -{ - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (expr.has_label ()) - { - auto label = expr.get_label (); - if (label.get_lifetime ().get_lifetime_type () - != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - auto label_name = label.get_lifetime ().get_lifetime_name (); - auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); - resolver->get_label_scope ().insert ( - CanonicalPath::new_seg (label.get_node_id (), label_name), - label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - - for (auto &s : expr.get_statements ()) - { - if (s->is_item ()) - ResolveStmt::go (*s, prefix, canonical_prefix, - CanonicalPath::create_empty ()); - } - - for (auto &s : expr.get_statements ()) - { - if (!s->is_item ()) - ResolveStmt::go (*s, prefix, canonical_prefix, - CanonicalPath::create_empty ()); - } - - if (expr.has_tail_expr ()) - ResolveExpr::go (expr.get_tail_expr (), prefix, canonical_prefix); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::AnonConst &expr) -{ - ResolveExpr::go (expr.get_inner_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ConstBlock &expr) -{ - ResolveExpr::go (expr.get_const_expr (), prefix, canonical_prefix); -} - -void -translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - const auto &operands = expr.get_operands (); - using RegisterType = AST::InlineAsmOperand::RegisterType; - for (auto &operand : operands) - { - switch (operand.get_register_type ()) - { - case RegisterType::In: - { - auto in = operand.get_in (); - ResolveExpr::go (*in.expr, prefix, canonical_prefix); - break; - } - case RegisterType::Out: - { - auto out = operand.get_out (); - ResolveExpr::go (*out.expr, prefix, canonical_prefix); - break; - } - case RegisterType::InOut: - { - auto in_out = operand.get_in_out (); - ResolveExpr::go (*in_out.expr, prefix, canonical_prefix); - break; - } - case RegisterType::SplitInOut: - { - auto split_in_out = operand.get_split_in_out (); - ResolveExpr::go (*split_in_out.in_expr, prefix, canonical_prefix); - ResolveExpr::go (*split_in_out.out_expr, prefix, canonical_prefix); - break; - } - case RegisterType::Const: - { - auto anon_const = operand.get_const ().anon_const; - ResolveExpr::go (anon_const.get_inner_expr (), prefix, - canonical_prefix); - break; - } - case RegisterType::Sym: - { - auto sym = operand.get_sym (); - ResolveExpr::go (*sym.expr, prefix, canonical_prefix); - break; - } - case RegisterType::Label: - { - auto label = operand.get_label (); - ResolveExpr::go (*label.expr, prefix, canonical_prefix); - break; - } - } - } -} -void -ResolveExpr::visit (AST::InlineAsm &expr) -{ - translate_operand (expr, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::LlvmInlineAsm &expr) -{ - for (auto &output : expr.get_outputs ()) - ResolveExpr::go (*output.expr, prefix, canonical_prefix); - - for (auto &input : expr.get_inputs ()) - ResolveExpr::go (*input.expr, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::UnsafeBlockExpr &expr) -{ - expr.get_block_expr ().accept_vis (*this); -} - -void -ResolveExpr::visit (AST::ArrayElemsValues &elems) -{ - for (auto &elem : elems.get_values ()) - ResolveExpr::go (*elem, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ArrayExpr &expr) -{ - expr.get_array_elems ()->accept_vis (*this); -} - -void -ResolveExpr::visit (AST::ArrayIndexExpr &expr) -{ - ResolveExpr::go (expr.get_array_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_index_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ArrayElemsCopied &expr) -{ - ResolveExpr::go (expr.get_num_copies (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_elem_to_copy (), prefix, canonical_prefix); -} - -// this this an empty struct constructor like 'S {}' -void -ResolveExpr::visit (AST::StructExprStruct &struct_expr) -{ - ResolveExpr::go (struct_expr.get_struct_name (), prefix, canonical_prefix); -} - -// this this a struct constructor with fields -void -ResolveExpr::visit (AST::StructExprStructFields &struct_expr) -{ - ResolveExpr::go (struct_expr.get_struct_name (), prefix, canonical_prefix); - - if (struct_expr.has_struct_base ()) - { - AST::StructBase &base = struct_expr.get_struct_base (); - ResolveExpr::go (base.get_base_struct (), prefix, canonical_prefix); - } - - auto const &struct_fields = struct_expr.get_fields (); - for (auto &struct_field : struct_fields) - { - ResolveStructExprField::go (*struct_field, prefix, canonical_prefix); - } -} - -void -ResolveExpr::visit (AST::GroupedExpr &expr) -{ - ResolveExpr::go (expr.get_expr_in_parens (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::FieldAccessExpr &expr) -{ - ResolveExpr::go (expr.get_receiver_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::LoopExpr &expr) -{ - if (expr.has_loop_label ()) - { - auto label = expr.get_loop_label (); - if (label.get_lifetime ().get_lifetime_type () - != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - auto label_name = label.get_lifetime ().get_lifetime_name (); - auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); - resolver->get_label_scope ().insert ( - CanonicalPath::new_seg (expr.get_node_id (), label_name), - label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::BreakExpr &expr) -{ - if (expr.has_label ()) - { - auto label = expr.get_label_unchecked ().get_lifetime (); - if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - NodeId resolved_node = UNKNOWN_NODEID; - if (!resolver->get_label_scope ().lookup ( - CanonicalPath::new_seg (label.get_node_id (), - label.get_lifetime_name ()), - &resolved_node)) - { - rust_error_at (label.get_locus (), ErrorCode::E0426, - "use of undeclared label %qs", - label.as_string ().c_str ()); - return; - } - resolver->insert_resolved_label (label.get_node_id (), resolved_node); - } - - if (expr.has_break_expr ()) - { - bool funny_error = false; - auto &break_expr = expr.get_break_expr (); - 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 - "rust" or "gcc", in which case we have "break rust" or "break - gcc", and so may need to emit our funny error. We cannot yet - emit the error here though, because the identifier may still - be in scope, and ICE'ing on valid programs would not be very - funny. */ - std::string ident - = static_cast (break_expr).as_string (); - if (ident == "rust" || ident == "gcc") - funny_error = true; - } - ResolveExpr::go (break_expr, prefix, canonical_prefix, funny_error); - } -} - -void -ResolveExpr::visit (AST::WhileLoopExpr &expr) -{ - if (expr.has_loop_label ()) - { - auto label = expr.get_loop_label (); - if (label.get_lifetime ().get_lifetime_type () - != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - auto label_name = label.get_lifetime ().get_lifetime_name (); - auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); - resolver->get_label_scope ().insert ( - CanonicalPath::new_seg (label.get_node_id (), label_name), - label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - - ResolveExpr::go (expr.get_predicate_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ForLoopExpr &expr) -{ - if (expr.has_loop_label ()) - { - auto label = expr.get_loop_label (); - if (label.get_lifetime ().get_lifetime_type () - != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - auto label_name = label.get_lifetime ().get_lifetime_name (); - auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); - resolver->get_label_scope ().insert ( - CanonicalPath::new_seg (label.get_node_id (), label_name), - label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - - // this needs a new rib to contain the pattern - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // resolve the expression - PatternDeclaration::go (expr.get_pattern (), Rib::ItemType::Var); - ResolveExpr::go (expr.get_iterator_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix); - - // done - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::ContinueExpr &expr) -{ - if (expr.has_label ()) - { - auto label = expr.get_label_unchecked (); - if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - NodeId resolved_node = UNKNOWN_NODEID; - if (!resolver->get_label_scope ().lookup ( - CanonicalPath::new_seg (label.get_node_id (), - label.get_lifetime_name ()), - &resolved_node)) - { - rust_error_at (expr.get_label_unchecked ().get_locus (), - ErrorCode::E0426, "use of undeclared label %qs", - label.as_string ().c_str ()); - return; - } - resolver->insert_resolved_label (label.get_node_id (), resolved_node); - } -} - -void -ResolveExpr::visit (AST::BorrowExpr &expr) -{ - ResolveExpr::go (expr.get_borrowed_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::DereferenceExpr &expr) -{ - ResolveExpr::go (expr.get_dereferenced_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::MatchExpr &expr) -{ - ResolveExpr::go (expr.get_scrutinee_expr (), prefix, canonical_prefix); - for (auto &match_case : expr.get_match_cases ()) - { - // each arm is in its own scope - NodeId scope_node_id = match_case.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // resolve - AST::MatchArm &arm = match_case.get_arm (); - if (arm.has_match_arm_guard ()) - ResolveExpr::go (arm.get_guard_expr (), prefix, canonical_prefix); - - // We know expr.get_patterns () has one pattern at most - // so there's no reason to handle it like an AltPattern. - std::vector bindings - = {PatternBinding (PatternBoundCtx::Product, std::set ())}; - - // insert any possible new patterns - for (auto &pattern : arm.get_patterns ()) - { - PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings); - } - - // resolve the body - ResolveExpr::go (match_case.get_expr (), prefix, canonical_prefix); - - // done - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - } -} - -void -ResolveExpr::visit (AST::RangeFromToExpr &expr) -{ - ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::RangeFromExpr &expr) -{ - ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::RangeToExpr &expr) -{ - ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::RangeFullExpr &) -{ - // nothing to do -} - -void -ResolveExpr::visit (AST::RangeFromToInclExpr &expr) -{ - ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ClosureExprInner &expr) -{ - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - std::vector bindings - = {PatternBinding (PatternBoundCtx::Product, std::set ())}; - - for (auto &p : expr.get_params ()) - { - resolve_closure_param (p, bindings); - } - - resolver->push_closure_context (expr.get_node_id ()); - - ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix); - - resolver->pop_closure_context (); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::ClosureExprInnerTyped &expr) -{ - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - std::vector bindings - = {PatternBinding (PatternBoundCtx::Product, std::set ())}; - - for (auto &p : expr.get_params ()) - { - resolve_closure_param (p, bindings); - } - - ResolveType::go (expr.get_return_type ()); - - resolver->push_closure_context (expr.get_node_id ()); - - ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix); - - resolver->pop_closure_context (); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::resolve_closure_param (AST::ClosureParam ¶m, - std::vector &bindings) -{ - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, bindings); - - if (param.has_type_given ()) - ResolveType::go (param.get_type ()); -} - -ResolveExpr::ResolveExpr (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, - bool funny_error) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix), - funny_error (funny_error) -{} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h deleted file mode 100644 index aad16050417..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_AST_RESOLVE_EXPR_H -#define RUST_AST_RESOLVE_EXPR_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-expr.h" - -namespace Rust { -namespace Resolver { - -class ResolveExpr : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::Expr &expr, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, - bool funny_error = false); - - void visit (AST::TupleIndexExpr &expr) override; - void visit (AST::TupleExpr &expr) override; - void visit (AST::PathInExpression &expr) override; - void visit (AST::QualifiedPathInExpression &expr) override; - void visit (AST::ReturnExpr &expr) override; - void visit (AST::CallExpr &expr) override; - void visit (AST::MethodCallExpr &expr) override; - void visit (AST::AssignmentExpr &expr) override; - void visit (AST::IdentifierExpr &expr) override; - void visit (AST::ArithmeticOrLogicalExpr &expr) override; - void visit (AST::CompoundAssignmentExpr &expr) override; - void visit (AST::ComparisonExpr &expr) override; - void visit (AST::LazyBooleanExpr &expr) override; - void visit (AST::NegationExpr &expr) override; - void visit (AST::TypeCastExpr &expr) override; - void visit (AST::IfExpr &expr) override; - void visit (AST::IfExprConseqElse &expr) override; - void visit (AST::IfLetExpr &expr) override; - void visit (AST::IfLetExprConseqElse &expr) override; - void visit (AST::BlockExpr &expr) override; - void visit (AST::AnonConst &expr) override; - void visit (AST::ConstBlock &expr) override; - void visit (AST::InlineAsm &expr) override; - void visit (AST::LlvmInlineAsm &expr) override; - void visit (AST::UnsafeBlockExpr &expr) override; - void visit (AST::ArrayElemsValues &elems) override; - void visit (AST::ArrayExpr &expr) override; - void visit (AST::ArrayIndexExpr &expr) override; - void visit (AST::ArrayElemsCopied &elems) override; - void visit (AST::StructExprStruct &struct_expr) override; - void visit (AST::StructExprStructFields &struct_expr) override; - void visit (AST::GroupedExpr &expr) override; - void visit (AST::FieldAccessExpr &expr) override; - void visit (AST::LoopExpr &expr) override; - void visit (AST::BreakExpr &expr) override; - void visit (AST::WhileLoopExpr &expr) override; - void visit (AST::ForLoopExpr &expr) override; - void visit (AST::ContinueExpr &expr) override; - void visit (AST::BorrowExpr &expr) override; - void visit (AST::DereferenceExpr &expr) override; - void visit (AST::MatchExpr &expr) override; - void visit (AST::RangeFromToExpr &expr) override; - void visit (AST::RangeFromExpr &expr) override; - void visit (AST::RangeToExpr &expr) override; - void visit (AST::RangeFullExpr &expr) override; - void visit (AST::RangeFromToInclExpr &expr) override; - void visit (AST::ClosureExprInner &expr) override; - void visit (AST::ClosureExprInnerTyped &expr) override; - void visit (AST::ErrorPropagationExpr &expr) override; - -protected: - void resolve_closure_param (AST::ClosureParam ¶m, - std::vector &bindings); - -private: - ResolveExpr (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, bool funny_error); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; - bool funny_error; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_EXPR_H diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc deleted file mode 100644 index 1d5ebed9969..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ /dev/null @@ -1,1247 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#include "rust-ast-resolve-item.h" -#include "rust-ast-full-decls.h" -#include "rust-ast-resolve-toplevel.h" -#include "rust-ast-resolve-type.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-path.h" - -#include "rust-item.h" -#include "selftest.h" - -namespace Rust { -namespace Resolver { - -ResolveTraitItems::ResolveTraitItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) -{} - -void -ResolveTraitItems::go (AST::AssociatedItem *item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - if (item->is_marked_for_strip ()) - return; - - ResolveTraitItems resolver (prefix, canonical_prefix); - item->accept_vis (resolver); -} - -void -ResolveTraitItems::visit (AST::Function &function) -{ - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (function.get_node_id (), cpath); - - NodeId scope_node_id = function.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - // self turns into (self: Self) as a function param - std::vector bindings - = {PatternBinding (PatternBoundCtx::Product, std::set ())}; - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto &p : function.get_function_params ()) - { - if (p->is_variadic ()) - { - auto param = static_cast (*p); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - else if (p->is_self ()) - { - auto ¶m = static_cast (*p); - // FIXME: which location should be used for Rust::Identifier `self`? - AST::IdentifierPattern self_pattern ( - param.get_node_id (), {"self"}, param.get_locus (), - param.get_has_ref (), param.get_is_mut (), - std::unique_ptr (nullptr)); - - PatternDeclaration::go (self_pattern, Rib::ItemType::Param); - - if (param.has_type ()) - { - // This shouldn't happen the parser should already error for this - rust_assert (!param.get_has_ref ()); - ResolveType::go (param.get_type ()); - } - else - { - // here we implicitly make self have a type path of Self - std::vector> segments; - segments.push_back (std::unique_ptr ( - new AST::TypePathSegment ("Self", false, param.get_locus ()))); - - AST::TypePath self_type_path (std::move (segments), - param.get_locus ()); - ResolveType::go (self_type_path); - } - } - else - { - auto ¶m = static_cast (*p); - ResolveType::go (param.get_type ()); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - } - - if (function.has_where_clause ()) - ResolveWhereClause::Resolve (function.get_where_clause ()); - - // trait items have an optional body - if (function.has_body ()) - ResolveExpr::go (*function.get_definition ().value (), path, cpath); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} -void -ResolveTraitItems::visit (AST::TraitItemType &type) -{ - auto decl = CanonicalPath::new_seg (type.get_node_id (), - type.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (type.get_node_id (), cpath); - - for (auto &bound : type.get_type_param_bounds ()) - ResolveTypeBound::go (*bound); -} - -void -ResolveTraitItems::visit (AST::TraitItemConst &constant) -{ - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - - ResolveType::go (constant.get_type ()); - - if (constant.has_expr ()) - ResolveExpr::go (constant.get_expr (), path, cpath); -} - -ResolveItem::ResolveItem (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) -{} - -void -ResolveItem::go (AST::Item &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveItem resolver (prefix, canonical_prefix); - item.accept_vis (resolver); -} - -void -ResolveItem::visit (AST::TypeAlias &alias) -{ - auto talias - = CanonicalPath::new_seg (alias.get_node_id (), - alias.get_new_type_name ().as_string ()); - auto path = prefix.append (talias); - auto cpath = canonical_prefix.append (talias); - mappings.insert_canonical_path (alias.get_node_id (), cpath); - - NodeId scope_node_id = alias.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (alias.has_generics ()) - ResolveGenericParams::go (alias.get_generic_params (), prefix, - canonical_prefix); - - if (alias.has_where_clause ()) - ResolveWhereClause::Resolve (alias.get_where_clause ()); - - ResolveType::go (alias.get_type_aliased ()); - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::Module &module) -{ - auto mod = CanonicalPath::new_seg (module.get_node_id (), - module.get_name ().as_string ()); - auto path = prefix.append (mod); - auto cpath = canonical_prefix.append (mod); - mappings.insert_canonical_path (module.get_node_id (), cpath); - - resolve_visibility (module.get_visibility ()); - - NodeId scope_node_id = module.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // FIXME: Should we reinsert a child here? Any reason we ResolveTopLevel::go - // in ResolveTopLevel::visit (AST::Module) as well as here? - for (auto &item : module.get_items ()) - ResolveTopLevel::go (*item, CanonicalPath::create_empty (), cpath); - - resolver->push_new_module_scope (module.get_node_id ()); - for (auto &item : module.get_items ()) - ResolveItem::go (*item, path, cpath); - - resolver->pop_module_scope (); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveItem::visit (AST::TupleStruct &struct_decl) -{ - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolve_visibility (struct_decl.get_visibility ()); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - if (struct_decl.has_where_clause ()) - ResolveWhereClause::Resolve (struct_decl.get_where_clause ()); - - for (AST::TupleField &field : struct_decl.get_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - resolve_visibility (field.get_visibility ()); - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::Enum &enum_decl) -{ - auto decl = CanonicalPath::new_seg (enum_decl.get_node_id (), - enum_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (enum_decl.get_node_id (), cpath); - - resolve_visibility (enum_decl.get_visibility ()); - - NodeId scope_node_id = enum_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (enum_decl.has_generics ()) - ResolveGenericParams::go (enum_decl.get_generic_params (), prefix, - canonical_prefix); - - if (enum_decl.has_where_clause ()) - ResolveWhereClause::Resolve (enum_decl.get_where_clause ()); - - /* The actual fields are inside the variants. */ - for (auto &variant : enum_decl.get_variants ()) - ResolveItem::go (*variant, path, cpath); - - resolver->get_type_scope ().pop (); -} - -/* EnumItem doesn't need to be handled, no fields. */ -void -ResolveItem::visit (AST::EnumItem &item) -{ - // Since at this point we cannot have visibilities on enum items anymore, we - // can skip handling them - - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); -} - -void -ResolveItem::visit (AST::EnumItemTuple &item) -{ - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - for (auto &field : item.get_tuple_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } -} - -void -ResolveItem::visit (AST::EnumItemStruct &item) -{ - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - for (auto &field : item.get_struct_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } -} - -void -ResolveItem::visit (AST::EnumItemDiscriminant &item) -{ - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - ResolveExpr::go (item.get_expr (), path, cpath); -} - -void -ResolveItem::visit (AST::StructStruct &struct_decl) -{ - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolve_visibility (struct_decl.get_visibility ()); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - if (struct_decl.has_where_clause ()) - ResolveWhereClause::Resolve (struct_decl.get_where_clause ()); - - for (AST::StructField &field : struct_decl.get_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - resolve_visibility (field.get_visibility ()); - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::Union &union_decl) -{ - auto decl - = CanonicalPath::new_seg (union_decl.get_node_id (), - union_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (union_decl.get_node_id (), cpath); - - resolve_visibility (union_decl.get_visibility ()); - - NodeId scope_node_id = union_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (union_decl.has_generics ()) - ResolveGenericParams::go (union_decl.get_generic_params (), prefix, - canonical_prefix); - - if (union_decl.has_where_clause ()) - ResolveWhereClause::Resolve (union_decl.get_where_clause ()); - - for (AST::StructField &field : union_decl.get_variants ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::StaticItem &var) -{ - auto decl = CanonicalPath::new_seg (var.get_node_id (), - var.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (var.get_node_id (), cpath); - - ResolveType::go (var.get_type ()); - ResolveExpr::go (var.get_expr (), path, cpath); -} - -void -ResolveItem::visit (AST::ConstantItem &constant) -{ - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - - resolve_visibility (constant.get_visibility ()); - - ResolveType::go (constant.get_type ()); - if (constant.has_expr ()) - ResolveExpr::go (constant.get_expr (), path, cpath); -} - -void -ResolveItem::visit (AST::Function &function) -{ - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - mappings.insert_canonical_path (function.get_node_id (), cpath); - - resolve_visibility (function.get_visibility ()); - - NodeId scope_node_id = function.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - // resolve any where clause items - if (function.has_where_clause ()) - ResolveWhereClause::Resolve (function.get_where_clause ()); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - if (function.has_self_param ()) - { - // self turns into (self: Self) as a function param - AST::Param &s_param = function.get_self_param (); - auto &self_param = static_cast (s_param); - - // FIXME: which location should be used for Rust::Identifier `self`? - AST::IdentifierPattern self_pattern ( - self_param.get_node_id (), {"self"}, self_param.get_locus (), - self_param.get_has_ref (), self_param.get_is_mut (), - std::unique_ptr (nullptr)); - PatternDeclaration::go (self_pattern, Rib::ItemType::Param); - - if (self_param.has_type ()) - { - // This shouldn't happen the parser should already error for this - rust_assert (!self_param.get_has_ref ()); - ResolveType::go (self_param.get_type ()); - } - else - { - // here we implicitly make self have a type path of Self - std::vector> segments; - segments.push_back (std::unique_ptr ( - new AST::TypePathSegment ("Self", false, self_param.get_locus ()))); - - AST::TypePath self_type_path (std::move (segments), - self_param.get_locus ()); - ResolveType::go (self_type_path); - } - } - - std::vector bindings - = {PatternBinding (PatternBoundCtx::Product, std::set ())}; - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto &p : function.get_function_params ()) - { - if (p->is_variadic ()) - { - auto ¶m = static_cast (*p); - if (param.has_pattern ()) - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - else if (p->is_self ()) - { - auto ¶m = static_cast (*p); - if (param.has_type ()) - ResolveType::go (param.get_type ()); - } - else - { - auto ¶m = static_cast (*p); - ResolveType::go (param.get_type ()); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - } - - // resolve the function body - ResolveExpr::go (*function.get_definition ().value (), path, cpath); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveItem::visit (AST::InherentImpl &impl_block) -{ - NodeId scope_node_id = impl_block.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - - resolve_visibility (impl_block.get_visibility ()); - - if (impl_block.has_generics ()) - ResolveGenericParams::go (impl_block.get_generic_params (), prefix, - canonical_prefix); - - // resolve any where clause items - if (impl_block.has_where_clause ()) - ResolveWhereClause::Resolve (impl_block.get_where_clause ()); - - // FIXME this needs to be protected behind nominal type-checks see: - // rustc --explain E0118 - // issue #2634 - ResolveType::go (impl_block.get_type ()); - - // Setup paths - CanonicalPath self_cpath = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (impl_block.get_type (), self_cpath); - if (!ok) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - rust_debug ("AST::InherentImpl resolve Self: {%s}", - self_cpath.get ().c_str ()); - - CanonicalPath impl_type = self_cpath; - CanonicalPath impl_type_seg - = CanonicalPath::inherent_impl_seg (impl_block.get_node_id (), impl_type); - CanonicalPath impl_prefix = prefix.append (impl_type_seg); - - // see https://godbolt.org/z/a3vMbsT6W - CanonicalPath cpath = CanonicalPath::create_empty (); - if (canonical_prefix.size () <= 1) - { - cpath = impl_prefix; - } - else - { - cpath = canonical_prefix.append (impl_type_seg); - } - - // done setup paths - - auto Self - = CanonicalPath::get_big_self (impl_block.get_type ().get_node_id ()); - - resolver->get_type_scope ().insert (Self, - impl_block.get_type ().get_node_id (), - impl_block.get_type ().get_locus ()); - - for (auto &impl_item : impl_block.get_impl_items ()) - { - rust_debug ( - "AST::InherentImpl resolve_impl_item: impl_prefix={%s} cpath={%s}", - impl_prefix.get ().c_str (), cpath.get ().c_str ()); - resolve_impl_item (*impl_item, impl_prefix, cpath); - } - - resolver->get_type_scope ().peek ()->clear_name ( - Self, impl_block.get_type ().get_node_id ()); - - resolver->get_type_scope ().pop (); - resolver->get_name_scope ().pop (); -} - -void -ResolveItem::visit (AST::TraitImpl &impl_block) -{ - NodeId scope_node_id = impl_block.get_node_id (); - - resolve_visibility (impl_block.get_visibility ()); - - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (impl_block.has_generics ()) - ResolveGenericParams::go (impl_block.get_generic_params (), prefix, - canonical_prefix); - - // resolve any where clause items - if (impl_block.has_where_clause ()) - ResolveWhereClause::Resolve (impl_block.get_where_clause ()); - - // CanonicalPath canonical_trait_type = CanonicalPath::create_empty (); - NodeId trait_resolved_node = ResolveType::go (impl_block.get_trait_path ()); - if (trait_resolved_node == UNKNOWN_NODEID) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - // CanonicalPath canonical_impl_type = CanonicalPath::create_empty (); - NodeId type_resolved_node = ResolveType::go (impl_block.get_type ()); - if (type_resolved_node == UNKNOWN_NODEID) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - bool ok = true; - - // setup paths - CanonicalPath canonical_trait_type = CanonicalPath::create_empty (); - - ok = ResolveTypeToCanonicalPath::go (impl_block.get_trait_path (), - canonical_trait_type); - if (!ok) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - rust_debug ("AST::TraitImpl resolve trait type: {%s}", - canonical_trait_type.get ().c_str ()); - - CanonicalPath canonical_impl_type = CanonicalPath::create_empty (); - ok = ResolveTypeToCanonicalPath::go (impl_block.get_type (), - canonical_impl_type); - if (!ok) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - rust_debug ("AST::TraitImpl resolve self: {%s}", - canonical_impl_type.get ().c_str ()); - - // raw paths - CanonicalPath impl_type_seg = canonical_impl_type; - CanonicalPath trait_type_seg = canonical_trait_type; - CanonicalPath projection - = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (), - trait_type_seg, impl_type_seg); - CanonicalPath impl_prefix = prefix.append (projection); - - // setup canonical-path - CanonicalPath canonical_projection - = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (), - canonical_trait_type, - canonical_impl_type); - CanonicalPath cpath = CanonicalPath::create_empty (); - if (canonical_prefix.size () <= 1) - { - cpath = canonical_projection; - } - else - { - cpath = canonical_prefix.append (canonical_projection); - } - - // DONE setup canonical-path - - auto Self - = CanonicalPath::get_big_self (impl_block.get_type ().get_node_id ()); - - resolver->get_type_scope ().insert (Self, - impl_block.get_type ().get_node_id (), - impl_block.get_type ().get_locus ()); - - for (auto &impl_item : impl_block.get_impl_items ()) - { - rust_debug ( - "AST::TraitImpl resolve_impl_item: impl_prefix={%s} cpath={%s}", - impl_prefix.get ().c_str (), cpath.get ().c_str ()); - resolve_impl_item (*impl_item, impl_prefix, cpath); - } - - Rib *r = resolver->get_type_scope ().peek (); - r->clear_name (Self, impl_block.get_type ().get_node_id ()); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveItem::visit (AST::Trait &trait) -{ - NodeId scope_node_id = trait.get_node_id (); - - resolve_visibility (trait.get_visibility ()); - - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - - ResolveGenericParams::go_single (trait.get_implicit_self (), prefix, - canonical_prefix); - ResolveGenericParams::go (trait.get_generic_params (), prefix, - canonical_prefix); - - // Self is an implicit TypeParam so lets mark it as such - resolver->get_type_scope ().append_reference_for_def ( - trait.get_node_id (), trait.get_implicit_self ().get_node_id ()); - - if (trait.has_type_param_bounds ()) - { - for (auto &bound : trait.get_type_param_bounds ()) - { - ResolveTypeBound::go (*bound); - } - } - - // resolve any where clause items - if (trait.has_where_clause ()) - ResolveWhereClause::Resolve (trait.get_where_clause ()); - - // resolve the paths - CanonicalPath path = CanonicalPath::create_empty (); - CanonicalPath cpath = CanonicalPath::create_empty (); - // - - for (auto &item : trait.get_trait_items ()) - { - ResolveTraitItems::go (item.get (), path, cpath); - } - - resolver->get_type_scope ().pop (); - resolver->get_name_scope ().pop (); -} - -void -ResolveItem::visit (AST::ExternBlock &extern_block) -{ - resolve_visibility (extern_block.get_visibility ()); - - for (auto &item : extern_block.get_extern_items ()) - { - resolve_extern_item (*item); - } -} - -void -ResolveItem::resolve_impl_item (AST::AssociatedItem &item, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveImplItems::go (item, prefix, canonical_prefix); -} - -void -ResolveItem::resolve_extern_item (AST::ExternalItem &item) -{ - ResolveExternItem::go (item, prefix, canonical_prefix); -} - -static void flatten_glob (const AST::UseTreeGlob &glob, - std::vector &imports); -static void flatten_rebind (const AST::UseTreeRebind &glob, - std::vector &imports); -static void flatten_list (const AST::UseTreeList &glob, - std::vector &imports); - -static void -flatten (const AST::UseTree *tree, std::vector &imports) -{ - switch (tree->get_kind ()) - { - case AST::UseTree::Glob: - { - auto glob = static_cast (tree); - flatten_glob (*glob, imports); - break; - } - case AST::UseTree::Rebind: - { - auto rebind = static_cast (tree); - flatten_rebind (*rebind, imports); - break; - } - case AST::UseTree::List: - { - auto list = static_cast (tree); - flatten_list (*list, imports); - break; - } - break; - } -} - -static void -flatten_glob (const AST::UseTreeGlob &glob, std::vector &imports) -{ - if (glob.has_path ()) - imports.emplace_back (glob.get_path (), true, std::string ()); -} - -static void -flatten_rebind (const AST::UseTreeRebind &rebind, std::vector &imports) -{ - auto path = rebind.get_path (); - - std::string label; - if (rebind.has_identifier ()) - label = rebind.get_identifier ().as_string (); - else - label = path.get_final_segment ().as_string (); - - imports.emplace_back (path, false, label); -} - -static void -flatten_list (const AST::UseTreeList &list, std::vector &imports) -{ - auto prefix = AST::SimplePath::create_empty (); - if (list.has_path ()) - prefix = list.get_path (); - - for (const auto &tree : list.get_trees ()) - { - // append imports to the main list, then modify them in-place - auto start_idx = imports.size (); - flatten (tree.get (), imports); - - for (auto import = imports.begin () + start_idx; import != imports.end (); - import++) - { - // avoid duplicate node ids - auto prefix_copy - = AST::SimplePath ({}, prefix.has_opening_scope_resolution (), - prefix.get_locus ()); - for (auto &seg : prefix.get_segments ()) - prefix_copy.get_segments ().push_back ( - AST::SimplePathSegment (seg.get_segment_name (), - seg.get_locus ())); - - import->add_prefix (std::move (prefix_copy)); - } - } -} - -void -Import::add_prefix (AST::SimplePath prefix) -{ - AST::SimplePath old_path (std::move (path)); - path = std::move (prefix); - std::move (old_path.get_segments ().begin (), old_path.get_segments ().end (), - std::back_inserter (path.get_segments ())); -} - -/** - * Flatten a UseDeclaration's UseTree into multiple simple paths to resolve. - * - * Given the following use declarations: - * ``` - * use some::path::to_resolve; #1 - * use some::path::to_glob::*; #2 - * use some::path::{one, two}; #2 - * ``` - * - * In the first case, we simply want to return a vector with a single - * SimplePath: - * [some::path::to_resolve] - * - * In the second case, we want to resolve the glob's "origin path": - * [some::path::to_glob] - * - * Finally in the third case, we want to create two SimplePaths to resolve: - * [some::path::one, some::path::two] - */ -static std::vector -flatten_use_dec_to_imports (const AST::UseDeclaration &use_item) -{ - auto imports = std::vector (); - - const auto &tree = use_item.get_tree (); - flatten (tree.get (), imports); - - return imports; -} - -void -ResolveItem::visit (AST::UseDeclaration &use_item) -{ - std::vector to_resolve = flatten_use_dec_to_imports (use_item); - - // FIXME: I think this does not actually resolve glob use-decls and is going - // the wrong way about it. RFC #1560 specifies the following: - // - // > When we find a glob import, we have to record a 'back link', so that when - // a public name is added for the supplying module, we can add it for the - // importing module. - // - // Which is the opposite of what we're doing if I understand correctly? - - NodeId current_module = resolver->peek_current_module_scope (); - for (auto &import : to_resolve) - { - auto &path = import.get_path (); - - rust_debug ("resolving use-decl path: [%s]", path.as_string ().c_str ()); - NodeId resolved_node_id = ResolvePath::go (path); - bool ok = resolved_node_id != UNKNOWN_NODEID; - if (!ok) - continue; - - if (import.is_glob ()) - continue; - - auto decl = CanonicalPath::new_seg (resolved_node_id, import.get_name ()); - mappings.insert_module_child_item (current_module, decl); - - resolver->get_type_scope ().insert (decl, resolved_node_id, - path.get_locus (), - Rib::ItemType::Type); - rust_debug ("use-decl rexporting: [%s]", decl.get ().c_str ()); - } -} - -ResolveImplItems::ResolveImplItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolveItem (prefix, canonical_prefix) -{} - -void -ResolveImplItems::go (AST::AssociatedItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - if (item.is_marked_for_strip ()) - return; - - ResolveImplItems resolver (prefix, canonical_prefix); - item.accept_vis (resolver); -} - -void -ResolveImplItems::visit (AST::TypeAlias &alias) -{ - ResolveItem::visit (alias); - - resolve_visibility (alias.get_visibility ()); - - // FIXME this stops the erronious unused decls which will be fixed later on - resolver->get_type_scope ().append_reference_for_def (alias.get_node_id (), - alias.get_node_id ()); -} - -void -ResolveExternItem::go (AST::ExternalItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveExternItem resolver (prefix, canonical_prefix); - item.accept_vis (resolver); -} - -void -ResolveExternItem::visit (AST::Function &function) -{ - NodeId scope_node_id = function.get_node_id (); - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - mappings.insert_canonical_path (function.get_node_id (), cpath); - - resolve_visibility (function.get_visibility ()); - - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // resolve the generics - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto ¶m : function.get_function_params ()) - if (!param->is_variadic ()) - { - auto &p = static_cast (*param); - ResolveType::go (p.get_type ()); - } - - // done - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExternItem::visit (AST::ExternalStaticItem &item) -{ - resolve_visibility (item.get_visibility ()); - - ResolveType::go (item.get_type ()); -} - -} // namespace Resolver -} // namespace Rust - -#if CHECKING_P - -namespace selftest { - -static void -rust_flatten_nested_glob (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto foobar = Rust::AST::SimplePath ({foo, bar}); - - auto glob - = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED, - foobar, UNDEF_LOCATION); - - auto imports = std::vector (); - Rust::Resolver::flatten_glob (glob, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); -} - -static void -rust_flatten_glob (void) -{ - auto frob = Rust::AST::SimplePath::from_str ("frobulator", UNDEF_LOCATION); - - auto glob - = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED, - frob, UNDEF_LOCATION); - - auto imports = std::vector (); - Rust::Resolver::flatten_glob (glob, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path (), "frobulator"); -} - -static void -rust_flatten_rebind_none (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto foobar = Rust::AST::SimplePath ({foo, bar}); - - auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, - foobar, UNDEF_LOCATION); - - auto imports = std::vector (); - Rust::Resolver::flatten_rebind (rebind, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); -} - -static void -rust_flatten_rebind (void) -{ - auto frob = Rust::AST::SimplePath::from_str ("frobulator", UNDEF_LOCATION); - - auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER, - frob, UNDEF_LOCATION, {"saindoux"}); - - auto imports = std::vector (); - Rust::Resolver::flatten_rebind (rebind, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path (), "frobulator"); - ASSERT_EQ (imports[0].get_name (), "saindoux"); -} - -static void -rust_flatten_rebind_nested (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto baz = Rust::AST::SimplePathSegment ("baz", UNDEF_LOCATION); - - auto foo_bar_baz = Rust::AST::SimplePath ({foo, bar, baz}); - - auto rebind - = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER, - foo_bar_baz, UNDEF_LOCATION, {"saindoux"}); - - auto imports = std::vector (); - Rust::Resolver::flatten_rebind (rebind, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz"); - ASSERT_EQ (imports[0].get_name (), "saindoux"); -} - -static void -rust_flatten_list (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto foo_bar = Rust::AST::SimplePath ({foo, bar}); - - auto baz = Rust::AST::SimplePath::from_str ("baz", UNDEF_LOCATION); - auto bul = Rust::AST::SimplePath::from_str ("bul", UNDEF_LOCATION); - - // use foo::bar::{baz, bul}; - - auto use0 = std::unique_ptr ( - new Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, baz, - UNDEF_LOCATION)); - auto use1 = std::unique_ptr ( - new Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, bul, - UNDEF_LOCATION)); - - auto uses = std::vector> (); - uses.emplace_back (std::move (use0)); - uses.emplace_back (std::move (use1)); - - auto list - = Rust::AST::UseTreeList (Rust::AST::UseTreeList::PATH_PREFIXED, foo_bar, - std::move (uses), UNDEF_LOCATION); - - auto imports = std::vector (); - Rust::Resolver::flatten_list (list, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 2); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz"); - ASSERT_EQ (imports[1].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[1].get_path ().get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (imports[1].get_path ().get_segments ()[2].as_string (), "bul"); -} - -static void -rust_use_dec_flattening (void) -{ - rust_flatten_glob (); - rust_flatten_nested_glob (); - rust_flatten_rebind_none (); - rust_flatten_rebind (); - rust_flatten_rebind_nested (); - rust_flatten_list (); -} - -void -rust_simple_path_resolve_test (void) -{ - rust_use_dec_flattening (); -} - -} // namespace selftest - -#endif // CHECKING_P diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h deleted file mode 100644 index d31f910c4b1..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_AST_RESOLVE_ITEM_H -#define RUST_AST_RESOLVE_ITEM_H - -#include "rust-ast-full-decls.h" -#include "rust-ast-resolve-base.h" - -#include "config.h" - -namespace Rust { -namespace Resolver { - -class ResolveTraitItems : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::AssociatedItem *item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::Function &type) override; - void visit (AST::TraitItemType &type) override; - void visit (AST::TraitItemConst &constant) override; - -private: - ResolveTraitItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class ResolveItem : public ResolverBase -{ -public: - using Rust::Resolver::ResolverBase::visit; - - static void go (AST::Item &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::TypeAlias &alias) override; - void visit (AST::Module &module) override; - void visit (AST::TupleStruct &struct_decl) override; - void visit (AST::Enum &enum_decl) override; - /* EnumItem doesn't need to be handled, no fields. */ - void visit (AST::EnumItem &item) override; - void visit (AST::EnumItemTuple &item) override; - void visit (AST::EnumItemStruct &item) override; - void visit (AST::EnumItemDiscriminant &item) override; - void visit (AST::StructStruct &struct_decl) override; - void visit (AST::Union &union_decl) override; - void visit (AST::StaticItem &var) override; - void visit (AST::ConstantItem &constant) override; - void visit (AST::Function &function) override; - void visit (AST::InherentImpl &impl_block) override; - void visit (AST::TraitImpl &impl_block) override; - void visit (AST::Trait &trait) override; - void visit (AST::ExternBlock &extern_block) override; - void visit (AST::UseDeclaration &) override; - -protected: - void resolve_impl_item (AST::AssociatedItem &item, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - void resolve_extern_item (AST::ExternalItem &item); - - ResolveItem (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class ResolveImplItems : public ResolveItem -{ - using Rust::Resolver::ResolveItem::visit; - -public: - static void go (AST::AssociatedItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::TypeAlias &alias) override; - -private: - ResolveImplItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); -}; - -class ResolveExternItem : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::ExternalItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::Function &function) override; - void visit (AST::ExternalStaticItem &item) override; - -private: - ResolveExternItem (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) - {} - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class Import -{ -public: - Import (AST::SimplePath path, bool is_glob, std::string name) - : path (path), is_glob_f (is_glob), name (name) - {} - - AST::SimplePath &get_path () { return path; } - - const AST::SimplePath &get_path () const { return path; } - - bool is_glob () const { return is_glob_f; } - - const std::string &get_name () const { return name; } - - void add_prefix (AST::SimplePath prefix); - -private: - AST::SimplePath path; - bool is_glob_f; - std::string name; -}; - -} // namespace Resolver -} // namespace Rust - -#if CHECKING_P - -namespace selftest { -extern void rust_simple_path_resolve_test (void); -} // namespace selftest - -#endif // CHECKING_P - -#endif // RUST_AST_RESOLVE_ITEM_H diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc deleted file mode 100644 index fb6715d9528..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-path.cc +++ /dev/null @@ -1,558 +0,0 @@ -// Copyright (C) 2020-2024 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#include "rust-ast-resolve-path.h" -#include "rust-ast-resolve-type.h" -#include "rust-hir-map.h" -#include "rust-path.h" - -namespace Rust { -namespace Resolver { - -ResolvePath::ResolvePath () : ResolverBase () {} - -NodeId -ResolvePath::go (AST::PathInExpression &expr) -{ - ResolvePath resolver; - return resolver.resolve_path (expr); -} - -NodeId -ResolvePath::go (AST::QualifiedPathInExpression &expr) -{ - ResolvePath resolver; - return resolver.resolve_path (expr); -} - -NodeId -ResolvePath::go (AST::SimplePath &expr) -{ - ResolvePath resolver; - return resolver.resolve_path (expr); -} - -NodeId -ResolvePath::resolve_path (AST::PathInExpression &expr) -{ - if (expr.is_lang_item ()) - return Analysis::Mappings::get ().get_lang_item_node ( - expr.get_lang_item ()); - - NodeId resolved_node_id = UNKNOWN_NODEID; - NodeId module_scope_id = resolver->peek_current_module_scope (); - NodeId previous_resolved_node_id = module_scope_id; - for (size_t i = 0; i < expr.get_segments ().size (); i++) - { - auto &segment = expr.get_segments ().at (i); - const AST::PathIdentSegment &ident_seg = segment.get_ident_segment (); - bool is_first_segment = i == 0; - resolved_node_id = UNKNOWN_NODEID; - - bool in_middle_of_path = i > 0; - if (in_middle_of_path && segment.is_lower_self_seg ()) - { - rust_error_at (segment.get_locus (), ErrorCode::E0433, - "%qs in paths can only be used in start position", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - - NodeId crate_scope_id = resolver->peek_crate_module_scope (); - if (segment.is_crate_path_seg ()) - { - // what is the current crate scope node id? - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - continue; - } - else if (segment.is_super_path_seg ()) - { - if (module_scope_id == crate_scope_id) - { - rust_error_at (segment.get_locus (), - "cannot use % at the crate scope"); - return UNKNOWN_NODEID; - } - - module_scope_id = resolver->peek_parent_module_scope (); - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - continue; - } - - // resolve any generic args - if (segment.has_generic_args ()) - ResolveGenericArgs::go (segment.get_generic_args ()); - - // logic is awkward here there are a few cases - // - // T::Default - // mod::foo::impl_item - // super::super::module::item - // self - // self::foo - // self::foo::baz - // - // T::Default we can only resolve the T and cant do anything about Default - // its dependant on associated types - // - // mod::foo::impl_item - // we can resolve mod::foo but nothing about impl_item but we need to - // _always resolve generic arguments - // - // self is a simple single lookup - // - // we have module_scope_id for the next module_scope to lookup - // resolved_node_id is the thing we have resolve this segment to - // - // new algo? - // we can only use module resolution when the previous segment is either - // unknown or equal to this module_scope_id - // - // can only use old resolution when previous segment is unkown - - if (is_first_segment) - { - // name scope first - NodeId resolved_node = UNKNOWN_NODEID; - const CanonicalPath path - = CanonicalPath::new_seg (segment.get_node_id (), - ident_seg.as_string ()); - if (resolver->get_name_scope ().lookup (path, &resolved_node)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment.get_node_id (), - resolved_node); - resolved_node_id = resolved_node; - } - // check the type scope - else if (resolver->get_type_scope ().lookup (path, &resolved_node)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - resolved_node_id = resolved_node; - } - else if (segment.is_lower_self_seg ()) - { - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - continue; - } - else - { - // no error handling here since we might be able to resolve via - // the module hierarchy and handle errors at the end - } - } - - if (resolved_node_id == UNKNOWN_NODEID - && previous_resolved_node_id == module_scope_id) - { - tl::optional resolved_child - = mappings.lookup_module_child (module_scope_id, - ident_seg.as_string ()); - if (resolved_child.has_value ()) - { - NodeId resolved_node = resolved_child->get_node_id (); - if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment.get_node_id (), - resolved_node); - } - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - } - else - { - rust_error_at (segment.get_locus (), - "Cannot find path %<%s%> in this scope", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - } - } - - bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID; - if (did_resolve_segment) - { - if (mappings.node_is_module (resolved_node_id) - || mappings.node_is_crate (resolved_node_id)) - { - module_scope_id = resolved_node_id; - } - previous_resolved_node_id = resolved_node_id; - } - else if (is_first_segment) - { - rust_error_at (segment.get_locus (), ErrorCode::E0433, - "Cannot find path %<%s%> in this scope", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - } - - resolved_node = resolved_node_id; - if (resolved_node_id != UNKNOWN_NODEID) - { - // name scope first - if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_name (expr.get_node_id (), - resolved_node_id); - } - // check the type scope - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_type (expr.get_node_id (), - resolved_node_id); - } - else - { - rust_unreachable (); - } - } - return resolved_node_id; -} - -NodeId -ResolvePath::resolve_path (AST::QualifiedPathInExpression &expr) -{ - auto &root_segment = expr.get_qualified_path_type (); - ResolveType::go (root_segment.get_type ()); - if (root_segment.has_as_clause ()) - ResolveType::go (root_segment.get_as_type_path ()); - - for (auto &segment : expr.get_segments ()) - { - // we cant actually do anything with the segment itself since this is all - // the job of the type system to figure it out but we can resolve any - // generic arguments used - if (segment.has_generic_args ()) - ResolveGenericArgs::go (segment.get_generic_args ()); - } - - // cannot fully resolve a qualified path as it is dependant on associated - // items - return UNKNOWN_NODEID; -} - -NodeId -ResolvePath::resolve_path (AST::SimplePath &expr) -{ - NodeId crate_scope_id = resolver->peek_crate_module_scope (); - NodeId module_scope_id = resolver->peek_current_module_scope (); - - NodeId previous_resolved_node_id = UNKNOWN_NODEID; - NodeId resolved_node_id = UNKNOWN_NODEID; - for (size_t i = 0; i < expr.get_segments ().size (); i++) - { - AST::SimplePathSegment &segment = expr.get_segments ().at (i); - bool is_first_segment = i == 0; - bool is_final_segment = i >= (expr.get_segments ().size () - 1); - resolved_node_id = UNKNOWN_NODEID; - - if (segment.is_crate_path_seg ()) - { - // what is the current crate scope node id? - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - resolved_node_id = module_scope_id; - - continue; - } - else if (segment.is_super_path_seg ()) - { - if (!is_first_segment) - { - rust_error_at ( - segment.get_locus (), ErrorCode::E0433, - "% in paths can only be used in start position"); - return UNKNOWN_NODEID; - } - if (module_scope_id == crate_scope_id) - { - rust_error_at (segment.get_locus (), - "cannot use % at the crate scope"); - return UNKNOWN_NODEID; - } - - module_scope_id = resolver->peek_parent_module_scope (); - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - resolved_node_id = module_scope_id; - - continue; - } - - tl::optional resolved_child - = mappings.lookup_module_child (module_scope_id, - segment.get_segment_name ()); - if (resolved_child.has_value ()) - { - NodeId resolved_node = resolved_child->get_node_id (); - if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment.get_node_id (), - resolved_node); - } - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - } - else - { - rust_error_at (segment.get_locus (), - "Cannot find path %<%s%> in this scope", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - } - - if (resolved_node_id == UNKNOWN_NODEID && is_first_segment) - { - // name scope first - NodeId resolved_node = UNKNOWN_NODEID; - const CanonicalPath path - = CanonicalPath::new_seg (segment.get_node_id (), - segment.get_segment_name ()); - if (resolver->get_name_scope ().lookup (path, &resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment.get_node_id (), - resolved_node); - } - // check the type scope - else if (resolver->get_type_scope ().lookup (path, &resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - } - } - - // if we still have not resolved and this is the final segment and the - // final segment is self its likely the case: pub use - // - // result::Result::{self, Err, Ok}; - // - // Then the resolved_node_id is just the previous one so long as it is a - // resolved node id - // rust_debug_loc (segment.get_locus (), - // "trying to resolve seg: [%s] first [%s] last [%s]", - // segment.get_segment_name ().c_str (), - // is_first_segment ? "true" : "false", - // is_final_segment ? "true" : "false"); - if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment - && is_final_segment && segment.is_lower_self_seg ()) - resolved_node_id = previous_resolved_node_id; - - // final check - if (resolved_node_id == UNKNOWN_NODEID) - { - rust_error_at (segment.get_locus (), - "cannot find simple path segment %<%s%> in this scope", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - - if (mappings.node_is_module (resolved_node_id)) - { - module_scope_id = resolved_node_id; - } - - previous_resolved_node_id = resolved_node_id; - } - - resolved_node = resolved_node_id; - if (resolved_node_id != UNKNOWN_NODEID) - { - // name scope first - if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_name (expr.get_node_id (), - resolved_node_id); - } - // check the type scope - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_type (expr.get_node_id (), - resolved_node_id); - } - else - { - rust_unreachable (); - } - } - return resolved_node_id; -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-path.h b/gcc/rust/resolve/rust-ast-resolve-path.h deleted file mode 100644 index cddb54a0a6e..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-path.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_AST_RESOLVE_PATH_H -#define RUST_AST_RESOLVE_PATH_H - -#include "rust-ast-resolve-base.h" - -namespace Rust { -namespace Resolver { - -class ResolvePath : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static NodeId go (AST::PathInExpression &expr); - static NodeId go (AST::QualifiedPathInExpression &expr); - static NodeId go (AST::SimplePath &expr); - -private: - ResolvePath (); - - NodeId resolve_path (AST::PathInExpression &expr); - NodeId resolve_path (AST::QualifiedPathInExpression &expr); - NodeId resolve_path (AST::SimplePath &expr); - - void - resolve_simple_path_segments (CanonicalPath prefix, size_t offs, - const std::vector &segs, - NodeId expr_node_id, location_t expr_locus); -}; - -} // namespace Resolver -} // namespace Rust - -#endif // !RUST_AST_RESOLVE_PATH_H diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc deleted file mode 100644 index 3b80f9f0508..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc +++ /dev/null @@ -1,419 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-path.h" - -namespace Rust { -namespace Resolver { - -void -PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type) -{ - std::vector bindings - = {PatternBinding (PatternBoundCtx::Product, std::set ())}; - PatternDeclaration::go (pattern, type, bindings); -} - -void -PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type, - std::vector &bindings) -{ - PatternDeclaration resolver (bindings, type); - pattern.accept_vis (resolver); - - for (auto &map_entry : resolver.missing_bindings) - { - auto ident = map_entry.first; // key - auto info = map_entry.second; // value - - rust_error_at (info.get_locus (), ErrorCode::E0408, - "variable '%s' is not bound in all patterns", - ident.as_string ().c_str ()); - } - - for (auto &map_entry : resolver.inconsistent_bindings) - { - auto ident = map_entry.first; // key - auto info = map_entry.second; // value - - rust_error_at ( - info.get_locus (), ErrorCode::E0409, - "variable '%s' is bound inconsistently across pattern alternatives", - ident.as_string ().c_str ()); - } -} - -void -PatternDeclaration::visit (AST::IdentifierPattern &pattern) -{ - if (pattern.has_subpattern ()) - { - pattern.get_subpattern ().accept_vis (*this); - } - - Mutability mut = pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm; - add_new_binding (pattern.get_ident (), pattern.get_node_id (), - BindingTypeInfo (mut, pattern.get_is_ref (), - pattern.get_locus ())); -} - -void -PatternDeclaration::visit (AST::GroupedPattern &pattern) -{ - pattern.get_pattern_in_parens ().accept_vis (*this); -} - -void -PatternDeclaration::visit (AST::ReferencePattern &pattern) -{ - pattern.get_referenced_pattern ().accept_vis (*this); -} - -void -PatternDeclaration::visit (AST::PathInExpression &pattern) -{ - ResolvePath::go (pattern); -} - -void -PatternDeclaration::visit (AST::TupleStructPattern &pattern) -{ - ResolvePath::go (pattern.get_path ()); - - AST::TupleStructItems &items = pattern.get_items (); - switch (items.get_item_type ()) - { - case AST::TupleStructItems::RANGE: - { - // TODO - rust_unreachable (); - } - break; - - case AST::TupleStructItems::NO_RANGE: - { - auto &items_no_range - = static_cast (items); - - for (auto &inner_pattern : items_no_range.get_patterns ()) - { - inner_pattern->accept_vis (*this); - } - } - break; - } -} - -void -PatternDeclaration::visit (AST::StructPattern &pattern) -{ - ResolvePath::go (pattern.get_path ()); - - auto &struct_pattern_elems = pattern.get_struct_pattern_elems (); - for (auto &field : struct_pattern_elems.get_struct_pattern_fields ()) - { - switch (field->get_item_type ()) - { - case AST::StructPatternField::ItemType::TUPLE_PAT: - { - AST::StructPatternFieldTuplePat &tuple - = static_cast (*field); - - tuple.get_index_pattern ().accept_vis (*this); - } - break; - - case AST::StructPatternField::ItemType::IDENT_PAT: - { - AST::StructPatternFieldIdentPat &ident - = static_cast (*field); - - ident.get_ident_pattern ().accept_vis (*this); - } - break; - - case AST::StructPatternField::ItemType::IDENT: - { - auto &ident = static_cast (*field); - - Mutability mut - = ident.is_mut () ? Mutability::Mut : Mutability::Imm; - - add_new_binding (ident.get_identifier (), ident.get_node_id (), - BindingTypeInfo (mut, ident.is_ref (), - ident.get_locus ())); - } - break; - } - } -} - -void -PatternDeclaration::visit (AST::TuplePattern &pattern) -{ - auto &items = pattern.get_items (); - switch (items.get_pattern_type ()) - { - case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: - { - auto &ref = static_cast ( - pattern.get_items ()); - - for (auto &p : ref.get_patterns ()) - p->accept_vis (*this); - } - break; - - case AST::TuplePatternItems::TuplePatternItemType::RANGED: - { - auto &ref - = static_cast (pattern.get_items ()); - - for (auto &p : ref.get_lower_patterns ()) - p->accept_vis (*this); - for (auto &p : ref.get_upper_patterns ()) - p->accept_vis (*this); - } - break; - } -} - -void -PatternDeclaration::visit (AST::AltPattern &pattern) -{ - // push a new set of 'Or' bindings to the stack. Accounts for the - // alternatives. e.g. in `p_0 | p_1`, bindings to the same identifier between - // p_0 and p_1 shouldn't cause an error. - bindings_with_ctx.push_back ( - PatternBinding (PatternBoundCtx::Or, std::set ())); - - // This is a hack to avoid creating a separate visitor class for the - // consistency checks. We empty out the binding_info_map before each iteration - // to separate between the alts' binding_maps. And right after the alt - // visit... - auto tmp_binding_map = binding_info_map; - binding_info_map.clear (); - - std::vector alts_binding_maps; - - for (auto &alt : pattern.get_alts ()) - { - // before this visit, the binding_info_map is guaranteed to be empty - rust_assert (binding_info_map.empty ()); - - // push a new `Product` context to correctly reject multiple bindings - // within this single alt. - bindings_with_ctx.push_back ( - PatternBinding (PatternBoundCtx::Product, std::set ())); - - alt->accept_vis (*this); - - // ...the binding_info_map is (potentially) populated. We copy it to the - // vector, and empty it out to be ready for the next iteration. And after - // all the iterations are finished... - alts_binding_maps.push_back (binding_info_map); - binding_info_map.clear (); - - // Remove the last (i.e. `Product`) context and add the bindings from the - // visited alt to the one before last (i.e. `Or`). Now (after checking - // with the alt internally), the bindings from this alt will reside in the - // `Or` context. - auto last_bound_idents = bindings_with_ctx.back ().idents; - bindings_with_ctx.pop_back (); - - for (auto &ident : last_bound_idents) - { - bindings_with_ctx.back ().idents.insert (ident); - } - } - - // Now we can finally check for consistency. - check_bindings_consistency (alts_binding_maps); - - // Now we remove the `Or` context we pushed earlier. - // e.g. in `(a, (p_0 | p_1), c)`: after finishing up inside the alt pattern, - // we return to the tuple (`Product`) context and push the new bindings. - auto idents = bindings_with_ctx.back ().idents; - bindings_with_ctx.pop_back (); - for (auto &ident : idents) - bindings_with_ctx.back ().idents.insert (ident.as_string ()); - - // ...we repopulate the binding_info_map correctly (the initial bindings - // stored in the tmp_binding_map + all the bindings from all the alts) - binding_info_map = tmp_binding_map; - for (auto &alt_map : alts_binding_maps) - for (auto &map_entry : alt_map) - binding_info_map.insert (map_entry); -} - -void -PatternDeclaration::add_new_binding (Identifier ident, NodeId node_id, - BindingTypeInfo info) -{ - bool has_binding_ctx = bindings_with_ctx.size () > 0; - rust_assert (has_binding_ctx); - - bool identifier_or_bound = false, identifier_product_bound = false; - - for (auto binding : bindings_with_ctx) - { - bool identifier_bound_here - = (binding.idents.find (ident) != binding.idents.end ()); - if (identifier_bound_here) - { - identifier_product_bound |= binding.ctx == PatternBoundCtx::Product; - identifier_or_bound |= binding.ctx == PatternBoundCtx::Or; - } - } - - if (identifier_product_bound) - { - if (type == Rib::ItemType::Param) - { - rust_error_at (info.get_locus (), ErrorCode::E0415, - "identifier '%s' is bound more than once in the " - "same parameter list", - ident.as_string ().c_str ()); - } - else - { - rust_error_at ( - info.get_locus (), ErrorCode::E0416, - "identifier '%s' is bound more than once in the same pattern", - ident.as_string ().c_str ()); - } - - return; - } - - if (!identifier_or_bound) - { - bindings_with_ctx.back ().idents.insert (ident); - resolver->get_name_scope ().insert ( - CanonicalPath::new_seg (node_id, ident.as_string ()), node_id, - info.get_locus (), type); - } - - binding_info_map.insert ({ident, info}); -} - -// Verifies that all the alts in an AltPattern have the same set of bindings -// with the same mutability and reference states. -void -PatternDeclaration::check_bindings_consistency ( - std::vector &binding_maps) -{ - for (size_t i = 0; i < binding_maps.size (); i++) - { - auto &outer_bindings_map = binding_maps[i]; - - for (size_t j = 0; j < binding_maps.size (); j++) - { - // skip comparing the current outer map with itself. - if (j == i) - continue; - - auto &inner_bindings_map = binding_maps[j]; - - // iterate over the inner map entries and check if they exist in outer - // map - for (auto map_entry : inner_bindings_map) - { - auto ident = map_entry.first; // key - auto inner_info = map_entry.second; // value - bool ident_is_outer_bound = outer_bindings_map.count (ident); - - if (!ident_is_outer_bound && !missing_bindings.count (ident)) - missing_bindings.insert ({ident, inner_info}); - - else if (outer_bindings_map.count (ident) - && outer_bindings_map[ident] != inner_info - && !inconsistent_bindings.count (ident)) - inconsistent_bindings.insert ({ident, inner_info}); - } - } - } -} - -static void -resolve_range_pattern_bound (AST::RangePatternBound &bound) -{ - switch (bound.get_bound_type ()) - { - case AST::RangePatternBound::RangePatternBoundType::LITERAL: - // Nothing to resolve for a literal. - break; - - case AST::RangePatternBound::RangePatternBoundType::PATH: - { - auto &ref = static_cast (bound); - - ResolvePath::go (ref.get_path ()); - } - break; - - case AST::RangePatternBound::RangePatternBoundType::QUALPATH: - { - auto &ref = static_cast (bound); - - ResolvePath::go (ref.get_qualified_path ()); - } - break; - } -} - -void -PatternDeclaration::visit (AST::RangePattern &pattern) -{ - resolve_range_pattern_bound (pattern.get_upper_bound ()); - resolve_range_pattern_bound (pattern.get_lower_bound ()); -} - -void -PatternDeclaration::visit (AST::SlicePattern &pattern) -{ - auto &items = pattern.get_items (); - switch (items.get_pattern_type ()) - { - case AST::SlicePatternItems::SlicePatternItemType::NO_REST: - { - auto &ref - = static_cast (pattern.get_items ()); - - for (auto &p : ref.get_patterns ()) - p->accept_vis (*this); - } - break; - - case AST::SlicePatternItems::SlicePatternItemType::HAS_REST: - { - auto &ref - = static_cast (pattern.get_items ()); - - for (auto &p : ref.get_lower_patterns ()) - p->accept_vis (*this); - for (auto &p : ref.get_upper_patterns ()) - p->accept_vis (*this); - } - break; - } -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h deleted file mode 100644 index 876de160783..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.h +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_AST_RESOLVE_PATTERN_H -#define RUST_AST_RESOLVE_PATTERN_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-full.h" - -namespace Rust { -namespace Resolver { - -// Specifies whether the set of already bound patterns are related by 'Or' or -// 'Product'. Used to check for multiple bindings to the same identifier. -enum PatternBoundCtx -{ - // A product pattern context (e.g. struct and tuple patterns) - Product, - // An or-pattern context (e.g. p_0 | p_1 | ...) - Or, -}; - -struct PatternBinding -{ - PatternBoundCtx ctx; - std::set idents; - - PatternBinding (PatternBoundCtx ctx, std::set idents) - : ctx (ctx), idents (idents) - {} -}; - -// Info that gets stored in the map. Helps us detect if two bindings to the same -// identifier have different mutability or ref states. -class BindingTypeInfo -{ - Mutability mut; - bool is_ref; - location_t locus; - -public: - BindingTypeInfo (Mutability mut, bool is_ref, location_t locus) - : mut (mut), is_ref (is_ref), locus (locus) - {} - - BindingTypeInfo (BindingTypeInfo const &other) - : mut (other.mut), is_ref (other.is_ref), locus (other.get_locus ()) - {} - - BindingTypeInfo (){}; - - location_t get_locus () const { return locus; } - Mutability get_mut () const { return mut; } - bool get_is_ref () const { return is_ref; } - - BindingTypeInfo operator= (BindingTypeInfo const &other) - { - mut = other.mut; - is_ref = other.is_ref; - locus = other.get_locus (); - - return *this; - } - - bool operator== (BindingTypeInfo const &other) - { - return mut == other.mut && is_ref == other.is_ref; - } - - bool operator!= (BindingTypeInfo const &other) - { - return !BindingTypeInfo::operator== (other); - } -}; - -typedef std::map BindingMap; - -class PatternDeclaration : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::Pattern &pattern, Rib::ItemType type); - static void go (AST::Pattern &pattern, Rib::ItemType type, - std::vector &bindings); - - void visit (AST::IdentifierPattern &pattern) override; - void visit (AST::GroupedPattern &pattern) override; - void visit (AST::ReferencePattern &pattern) override; - void visit (AST::PathInExpression &pattern) override; - void visit (AST::StructPattern &pattern) override; - void visit (AST::TupleStructPattern &pattern) override; - void visit (AST::TuplePattern &pattern) override; - void visit (AST::RangePattern &pattern) override; - void visit (AST::AltPattern &pattern) override; - void visit (AST::SlicePattern &pattern) override; - - void add_new_binding (Identifier ident, NodeId node_id, BindingTypeInfo info); - void check_bindings_consistency (std::vector &binding_maps); - -private: - PatternDeclaration (std::vector &bindings_with_ctx, - Rib::ItemType type) - : ResolverBase (), bindings_with_ctx (bindings_with_ctx), type (type) - {} - - // To avoid having a separate visitor for consistency checks, we store - // bindings in two forms: - - // 1) Bindings as a vector of context-related sets. - // Used for checking multiple bindings to the same identifier (i.e. E0415, - // E0416). - std::vector &bindings_with_ctx; - - // 2) Bindings as a map between identifiers and binding info. - // Used for checking consistency between alt patterns (i.e. E0408, E0409). - BindingMap binding_info_map; - - // we need to insert the missing and inconsistent bindings (found in - // check_bindings_consistency) into maps to avoid duplication of error - // messages. - BindingMap inconsistent_bindings; - BindingMap missing_bindings; - - Rib::ItemType type; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_PATTERN_H diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.cc b/gcc/rust/resolve/rust-ast-resolve-stmt.cc deleted file mode 100644 index bfba302d29d..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.cc +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#include "rust-ast-resolve-toplevel.h" -#include "rust-ast-resolve-item.h" -#include "rust-ast-resolve-stmt.h" -#include "rust-ast-resolve-implitem.h" - -namespace Rust { -namespace Resolver { - -void -ResolveStmt::visit (AST::ExternBlock &extern_block) -{ - resolve_visibility (extern_block.get_visibility ()); - for (auto &item : extern_block.get_extern_items ()) - { - ResolveToplevelExternItem::go (*item, CanonicalPath::create_empty ()); - ResolveExternItem::go (*item, prefix, canonical_prefix); - } -} - -void -ResolveStmt::visit (AST::Trait &trait) -{ - ResolveTopLevel::go (trait, prefix, canonical_prefix); - ResolveItem::go (trait, prefix, canonical_prefix); -} - -void -ResolveStmt::visit (AST::InherentImpl &impl_block) -{ - ResolveTopLevel::go (impl_block, prefix, canonical_prefix); - ResolveItem::go (impl_block, prefix, canonical_prefix); -} - -void -ResolveStmt::visit (AST::TraitImpl &impl_block) -{ - ResolveTopLevel::go (impl_block, prefix, canonical_prefix); - ResolveItem::go (impl_block, prefix, canonical_prefix); -} - -void -ResolveStmt::visit (AST::StaticItem &var) -{ - auto decl = CanonicalPath::new_seg (var.get_node_id (), - var.get_identifier ().as_string ()); - auto path = decl; - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (var.get_node_id (), cpath); - - resolver->get_name_scope ().insert ( - path, var.get_node_id (), var.get_locus (), false, Rib::ItemType::Static, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, var.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - ResolveType::go (var.get_type ()); - ResolveExpr::go (var.get_expr (), path, cpath); -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h deleted file mode 100644 index d7145112c82..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ /dev/null @@ -1,408 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_AST_RESOLVE_STMT_H -#define RUST_AST_RESOLVE_STMT_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-resolve-type.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-expr.h" -#include "rust-item.h" - -namespace Rust { -namespace Resolver { - -class ResolveStmt : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::Stmt &stmt, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, - const CanonicalPath &enum_prefix) - { - if (stmt.is_marked_for_strip ()) - return; - - ResolveStmt resolver (prefix, canonical_prefix, enum_prefix); - stmt.accept_vis (resolver); - } - - void visit (AST::ExprStmt &stmt) override - { - ResolveExpr::go (stmt.get_expr (), prefix, canonical_prefix); - } - - void visit (AST::ConstantItem &constant) override - { - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - - resolver->get_name_scope ().insert ( - path, constant.get_node_id (), constant.get_locus (), false, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - ResolveType::go (constant.get_type ()); - if (constant.has_expr ()) - ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix); - } - - void visit (AST::LetStmt &stmt) override - { - if (stmt.has_init_expr ()) - ResolveExpr::go (stmt.get_init_expr (), prefix, canonical_prefix); - - if (stmt.has_else_expr ()) - ResolveExpr::go (stmt.get_else_expr (), prefix, canonical_prefix); - - PatternDeclaration::go (stmt.get_pattern (), Rib::ItemType::Var); - if (stmt.has_type ()) - ResolveType::go (stmt.get_type ()); - } - - void visit (AST::TupleStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, struct_decl.get_node_id (), struct_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - for (AST::TupleField &field : struct_decl.get_fields ()) - ResolveType::go (field.get_field_type ()); - - resolver->get_type_scope ().pop (); - } - - void visit (AST::Enum &enum_decl) override - { - auto decl - = CanonicalPath::new_seg (enum_decl.get_node_id (), - enum_decl.get_identifier ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (enum_decl.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, enum_decl.get_node_id (), enum_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, enum_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = enum_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (enum_decl.has_generics ()) - ResolveGenericParams::go (enum_decl.get_generic_params (), prefix, - canonical_prefix); - - for (auto &variant : enum_decl.get_variants ()) - ResolveStmt::go (*variant, path, canonical_prefix, path); - - resolver->get_type_scope ().pop (); - } - - void visit (AST::EnumItem &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - // Done, no fields. - } - - void visit (AST::EnumItemTuple &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - for (auto &field : item.get_tuple_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - } - - void visit (AST::EnumItemStruct &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - for (auto &field : item.get_struct_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - } - - void visit (AST::EnumItemDiscriminant &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - // Done, no fields. - } - - void visit (AST::StructStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, struct_decl.get_node_id (), struct_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - for (AST::StructField &field : struct_decl.get_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); - } - - void visit (AST::Union &union_decl) override - { - auto decl - = CanonicalPath::new_seg (union_decl.get_node_id (), - union_decl.get_identifier ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (union_decl.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, union_decl.get_node_id (), union_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, union_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = union_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (union_decl.has_generics ()) - ResolveGenericParams::go (union_decl.get_generic_params (), prefix, - canonical_prefix); - - for (AST::StructField &field : union_decl.get_variants ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); - } - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (function.get_node_id (), cpath); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = function.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - std::vector bindings - = {PatternBinding (PatternBoundCtx::Product, std::set ())}; - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto &p : function.get_function_params ()) - { - if (p->is_variadic ()) - { - auto ¶m = static_cast (*p); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - - else if (p->is_self ()) - { - auto ¶m = static_cast (*p); - ResolveType::go (param.get_type ()); - } - else - { - auto ¶m = static_cast (*p); - - ResolveType::go (param.get_type ()); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - } - - // resolve the function body - ResolveExpr::go (*function.get_definition ().value (), path, cpath); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - } - - void visit (AST::ExternBlock &extern_block) override; - void visit (AST::Trait &trait) override; - void visit (AST::InherentImpl &impl_block) override; - void visit (AST::TraitImpl &impl_block) override; - void visit (AST::StaticItem &var) override; - -private: - ResolveStmt (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, - const CanonicalPath &enum_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix), - enum_prefix (enum_prefix) - {} - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; - - /* item declaration statements are not given a canonical path, but enum items - * (variants) do inherit the enum path/identifier name. */ - const CanonicalPath &enum_prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_STMT_H diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc deleted file mode 100644 index 9b38e6a8a44..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#include "rust-ast-resolve-struct-expr-field.h" -#include "rust-ast-resolve-expr.h" - -namespace Rust { -namespace Resolver { - -void -ResolveStructExprField::go (AST::StructExprField &field, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveStructExprField resolver (prefix, canonical_prefix); - field.accept_vis (resolver); -} - -ResolveStructExprField::ResolveStructExprField ( - const CanonicalPath &prefix, const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) -{} - -void -ResolveStructExprField::visit (AST::StructExprFieldIdentifierValue &field) -{ - ResolveExpr::go (field.get_value (), prefix, canonical_prefix); -} - -void -ResolveStructExprField::visit (AST::StructExprFieldIndexValue &field) -{ - ResolveExpr::go (field.get_value (), prefix, canonical_prefix); -} - -void -ResolveStructExprField::visit (AST::StructExprFieldIdentifier &field) -{ - AST::IdentifierExpr expr (field.get_field_name (), {}, field.get_locus ()); - expr.set_node_id (field.get_node_id ()); - - ResolveExpr::go (expr, prefix, canonical_prefix); -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h deleted file mode 100644 index 87fa60dcc6d..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_AST_RESOLVE_STRUCT_EXPR_FIELD -#define RUST_AST_RESOLVE_STRUCT_EXPR_FIELD - -#include "rust-ast-resolve-base.h" - -namespace Rust { -namespace Resolver { - -// this resolves values being assigned not that the field actually exists yet. - -class ResolveStructExprField : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::StructExprField &field, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::StructExprFieldIdentifierValue &field) override; - - void visit (AST::StructExprFieldIndexValue &field) override; - - void visit (AST::StructExprFieldIdentifier &field) override; - -private: - ResolveStructExprField (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_STRUCT_EXPR_FIELD diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h deleted file mode 100644 index f52fb8a4d16..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ /dev/null @@ -1,500 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_AST_RESOLVE_TOPLEVEL_H -#define RUST_AST_RESOLVE_TOPLEVEL_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-resolve-implitem.h" -#include "rust-name-resolver.h" - -namespace Rust { -namespace Resolver { - -class ResolveTopLevel : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::Item &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - if (item.is_marked_for_strip ()) - return; - - ResolveTopLevel resolver (prefix, canonical_prefix); - item.accept_vis (resolver); - - NodeId current_module = resolver.resolver->peek_current_module_scope (); - resolver.mappings.insert_child_item_to_parent_module_mapping ( - item.get_node_id (), current_module); - } - - void visit (AST::Module &module) override - { - auto mod = CanonicalPath::new_seg (module.get_node_id (), - module.get_name ().as_string ()); - auto path = prefix.append (mod); - auto cpath = canonical_prefix.append (mod); - - resolver->get_name_scope ().insert ( - path, module.get_node_id (), module.get_locus (), false, - Rib::ItemType::Module, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, module.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, mod); - mappings.insert_module_child (current_module, module.get_node_id ()); - - resolver->push_new_module_scope (module.get_node_id ()); - for (auto &item : module.get_items ()) - ResolveTopLevel::go (*item, path, cpath); - - resolver->pop_module_scope (); - - mappings.insert_canonical_path (module.get_node_id (), cpath); - } - - void visit (AST::TypeAlias &alias) override - { - auto talias - = CanonicalPath::new_seg (alias.get_node_id (), - alias.get_new_type_name ().as_string ()); - auto path = prefix.append (talias); - auto cpath = canonical_prefix.append (talias); - - resolver->get_type_scope ().insert ( - path, alias.get_node_id (), alias.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, alias.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, talias); - mappings.insert_canonical_path (alias.get_node_id (), cpath); - } - - void visit (AST::TupleStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, struct_decl.get_node_id (), struct_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - } - - void visit (AST::Enum &enum_decl) override - { - auto decl - = CanonicalPath::new_seg (enum_decl.get_node_id (), - enum_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, enum_decl.get_node_id (), enum_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, enum_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - resolver->push_new_module_scope (enum_decl.get_node_id ()); - for (auto &variant : enum_decl.get_variants ()) - ResolveTopLevel::go (*variant, path, cpath); - - resolver->pop_module_scope (); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (enum_decl.get_node_id (), cpath); - } - - void visit (AST::EnumItem &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::EnumItemTuple &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::EnumItemStruct &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::EnumItemDiscriminant &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::StructStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - auto duplicate_item - = [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }; - - resolver->get_type_scope ().insert (path, struct_decl.get_node_id (), - struct_decl.get_locus (), false, - Rib::ItemType::Type, duplicate_item); - - if (struct_decl.is_unit_struct ()) - resolver->get_name_scope ().insert (path, struct_decl.get_node_id (), - struct_decl.get_locus (), false, - Rib::ItemType::Type, duplicate_item); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - } - - void visit (AST::Union &union_decl) override - { - auto decl - = CanonicalPath::new_seg (union_decl.get_node_id (), - union_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, union_decl.get_node_id (), union_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, union_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (union_decl.get_node_id (), cpath); - } - - void visit (AST::StaticItem &var) override - { - auto decl = CanonicalPath::new_seg (var.get_node_id (), - var.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, var.get_node_id (), var.get_locus (), false, Rib::ItemType::Static, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, var.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (var.get_node_id (), cpath); - } - - void visit (AST::ConstantItem &constant) override - { - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, constant.get_node_id (), constant.get_locus (), false, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - } - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (function.get_node_id (), cpath); - } - - void visit (AST::InherentImpl &impl_block) override - { - std::string raw_impl_type_path = impl_block.get_type ().as_string (); - CanonicalPath impl_type_seg - = CanonicalPath::new_seg (impl_block.get_type ().get_node_id (), - raw_impl_type_path); - - CanonicalPath impl_type - = CanonicalPath::inherent_impl_seg (impl_block.get_node_id (), - impl_type_seg); - CanonicalPath impl_prefix = prefix.append (impl_type_seg); - - for (auto &impl_item : impl_block.get_impl_items ()) - ResolveToplevelImplItem::go (*impl_item, impl_prefix); - } - - void visit (AST::TraitImpl &impl_block) override - { - std::string raw_impl_type_path = impl_block.get_type ().as_string (); - CanonicalPath impl_type_seg - = CanonicalPath::new_seg (impl_block.get_type ().get_node_id (), - raw_impl_type_path); - - std::string raw_trait_type_path = impl_block.get_trait_path ().as_string (); - CanonicalPath trait_type_seg - = CanonicalPath::new_seg (impl_block.get_trait_path ().get_node_id (), - raw_trait_type_path); - - CanonicalPath projection - = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (), - trait_type_seg, - impl_type_seg); - CanonicalPath impl_prefix = prefix.append (projection); - - resolver->get_name_scope ().insert ( - impl_prefix, impl_block.get_node_id (), impl_block.get_locus (), false, - Rib::ItemType::TraitImpl, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, impl_block.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - for (auto &impl_item : impl_block.get_impl_items ()) - ResolveToplevelImplItem::go (*impl_item, impl_prefix); - } - - void visit (AST::Trait &trait) override - { - auto decl = CanonicalPath::new_seg (trait.get_node_id (), - trait.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, trait.get_node_id (), trait.get_locus (), false, - Rib::ItemType::Trait, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, trait.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - for (auto &item : trait.get_trait_items ()) - ResolveTopLevelTraitItems::go (item.get (), path, cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (trait.get_node_id (), cpath); - } - - void visit (AST::ExternBlock &extern_block) override - { - for (auto &item : extern_block.get_extern_items ()) - { - ResolveToplevelExternItem::go (*item, prefix); - } - } - - void visit (AST::ExternCrate &extern_crate) override - { - if (extern_crate.is_marked_for_strip ()) - return; - - NodeId resolved_crate = UNKNOWN_NODEID; - if (extern_crate.references_self ()) - { - CrateNum crate_num = mappings.get_current_crate (); - resolved_crate = mappings.crate_num_to_nodeid (crate_num).value (); - } - else - { - auto cnum - = mappings.lookup_crate_name (extern_crate.get_referenced_crate ()); - if (!cnum) - { - rust_error_at (extern_crate.get_locus (), "unknown crate %qs", - extern_crate.get_referenced_crate ().c_str ()); - return; - } - if (auto resolved = mappings.crate_num_to_nodeid (*cnum)) - resolved_crate = resolved.value (); - else - { - rust_internal_error_at (extern_crate.get_locus (), - "failed to resolve crate to nodeid"); - return; - } - } - - if (resolved_crate == UNKNOWN_NODEID) - { - rust_error_at (extern_crate.get_locus (), "failed to resolve crate"); - return; - } - - // mark the node as resolved - resolver->insert_resolved_name (extern_crate.get_node_id (), - resolved_crate); - CanonicalPath decl - = extern_crate.has_as_clause () - ? CanonicalPath::new_seg (extern_crate.get_node_id (), - extern_crate.get_as_clause ()) - : CanonicalPath::new_seg (extern_crate.get_node_id (), - extern_crate.get_referenced_crate ()); - - resolver->get_type_scope ().insert ( - decl, resolved_crate, extern_crate.get_locus (), false, - Rib::ItemType::ExternCrate, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, extern_crate.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - } - -private: - ResolveTopLevel (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) - {} - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_TOPLEVEL_H diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc deleted file mode 100644 index a0402289afc..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ /dev/null @@ -1,785 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#include "rust-ast-resolve-type.h" -#include "rust-ast-resolve-expr.h" -#include "rust-canonical-path.h" -#include "rust-type.h" -#include "rust-hir-map.h" - -namespace Rust { -namespace Resolver { - -// rust-ast-resolve-type.h - -NodeId -ResolveType::go (AST::Type &type) -{ - ResolveType resolver; - type.accept_vis (resolver); - return resolver.resolved_node; -} - -void -ResolveType::visit (AST::BareFunctionType &fntype) -{ - for (auto ¶m : fntype.get_function_params ()) - ResolveType::go (param.get_type ()); - - if (fntype.has_return_type ()) - ResolveType::go (fntype.get_return_type ()); -} - -void -ResolveType::visit (AST::TupleType &tuple) -{ - if (tuple.is_unit_type ()) - { - resolved_node = resolver->get_unit_type_node_id (); - return; - } - - for (auto &elem : tuple.get_elems ()) - ResolveType::go (*elem); -} - -void -ResolveType::visit (AST::TypePath &path) -{ - ResolveRelativeTypePath::go (path, resolved_node); -} - -void -ResolveType::visit (AST::QualifiedPathInType &path) -{ - ResolveRelativeQualTypePath::go (path); -} - -void -ResolveType::visit (AST::ArrayType &type) -{ - type.get_elem_type ().accept_vis (*this); - ResolveExpr::go (type.get_size_expr (), CanonicalPath::create_empty (), - CanonicalPath::create_empty ()); -} - -void -ResolveType::visit (AST::TraitObjectTypeOneBound &type) -{ - ResolveTypeBound::go (type.get_trait_bound ()); -} - -void -ResolveType::visit (AST::TraitObjectType &type) -{ - for (auto &bound : type.get_type_param_bounds ()) - { - /* NodeId bound_resolved_id = */ - ResolveTypeBound::go (*bound); - } -} - -void -ResolveType::visit (AST::ParenthesisedType &type) -{ - resolved_node = ResolveType::go (*type.get_type_in_parens ()); -} - -void -ResolveType::visit (AST::ReferenceType &type) -{ - resolved_node = ResolveType::go (type.get_type_referenced ()); -} - -void -ResolveType::visit (AST::RawPointerType &type) -{ - resolved_node = ResolveType::go (type.get_type_pointed_to ()); -} - -void -ResolveType::visit (AST::InferredType &) -{ - // nothing to do -} - -void -ResolveType::visit (AST::NeverType &) -{ - resolved_node = resolver->get_never_type_node_id (); -} - -void -ResolveType::visit (AST::SliceType &type) -{ - resolved_node = ResolveType::go (type.get_elem_type ()); -} - -void -ResolveType::visit (AST::ImplTraitType &type) -{ - for (auto &bound : type.get_type_param_bounds ()) - ResolveTypeBound::go (*bound); -} - -void -ResolveType::visit (AST::ImplTraitTypeOneBound &type) -{ - ResolveTypeBound::go (*type.get_trait_bound ().get ()); -} - -// resolve relative type-paths - -bool -ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) -{ - auto resolver = Resolver::get (); - auto &mappings = Analysis::Mappings::get (); - - NodeId module_scope_id = resolver->peek_current_module_scope (); - NodeId previous_resolved_node_id = module_scope_id; - for (size_t i = 0; i < path.get_segments ().size (); i++) - { - auto &segment = path.get_segments ().at (i); - bool is_first_segment = i == 0; - NodeId crate_scope_id = resolver->peek_crate_module_scope (); - auto ident_string = segment->is_lang_item () - ? LangItem::PrettyString (segment->get_lang_item ()) - : segment->get_ident_segment ().as_string (); - - resolved_node_id = UNKNOWN_NODEID; - - if (segment->is_lang_item ()) - { - resolved_node_id = Analysis::Mappings::get ().get_lang_item_node ( - segment->get_lang_item ()); - previous_resolved_node_id = resolved_node_id; - } - else - { - bool in_middle_of_path = i > 0; - if (in_middle_of_path && segment->is_lower_self_seg ()) - { - rust_error_at (segment->get_locus (), ErrorCode::E0433, - "%qs in paths can only be used in start position", - segment->as_string ().c_str ()); - return false; - } - - if (segment->is_crate_path_seg ()) - { - // what is the current crate scope node id? - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - resolver->insert_resolved_name (segment->get_node_id (), - module_scope_id); - - continue; - } - else if (segment->is_super_path_seg ()) - { - if (module_scope_id == crate_scope_id) - { - rust_error_at (segment->get_locus (), - "cannot use super at the crate scope"); - return false; - } - - module_scope_id = resolver->peek_parent_module_scope (); - previous_resolved_node_id = module_scope_id; - resolver->insert_resolved_name (segment->get_node_id (), - module_scope_id); - continue; - } - } - - switch (segment->get_type ()) - { - case AST::TypePathSegment::SegmentType::GENERIC: - { - AST::TypePathSegmentGeneric *s - = static_cast (segment.get ()); - if (s->has_generic_args ()) - ResolveGenericArgs::go (s->get_generic_args ()); - } - break; - - case AST::TypePathSegment::SegmentType::REG: - // nothing to do - break; - - case AST::TypePathSegment::SegmentType::FUNCTION: - AST::TypePathSegmentFunction *fnseg - = static_cast (segment.get ()); - - AST::TypePathFunction &fn = fnseg->get_type_path_function (); - for (auto ¶m : fn.get_params ()) - { - ResolveType::go (*param); - } - - if (fn.has_return_type ()) - { - ResolveType::go (fn.get_return_type ()); - } - - break; - } - - if (is_first_segment) - { - // name scope first - NodeId resolved_node = UNKNOWN_NODEID; - const CanonicalPath path - = CanonicalPath::new_seg (segment->get_node_id (), ident_string); - if (resolver->get_type_scope ().lookup (path, &resolved_node)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment->get_node_id (), - resolved_node); - resolved_node_id = resolved_node; - } - else if (resolver->get_name_scope ().lookup (path, &resolved_node)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment->get_node_id (), - resolved_node); - resolved_node_id = resolved_node; - } - else if (!segment->is_lang_item () && segment->is_lower_self_seg ()) - { - // what is the current crate scope node id? - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment->get_node_id (), - module_scope_id); - - continue; - } - } - - if (resolved_node_id == UNKNOWN_NODEID - && previous_resolved_node_id == module_scope_id) - { - tl::optional resolved_child - = mappings.lookup_module_child (module_scope_id, ident_string); - if (resolved_child.has_value ()) - { - NodeId resolved_node = resolved_child->get_node_id (); - if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment->get_node_id (), - resolved_node); - } - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment->get_node_id (), - resolved_node); - } - else - { - rust_error_at (segment->get_locus (), - "Cannot find path %qs in this scope", - segment->as_string ().c_str ()); - return false; - } - } - } - - bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID; - if (did_resolve_segment) - { - if (mappings.node_is_module (resolved_node_id) - || mappings.node_is_crate (resolved_node_id)) - { - module_scope_id = resolved_node_id; - } - previous_resolved_node_id = resolved_node_id; - } - else if (is_first_segment) - { - rust_error_at (segment->get_locus (), ErrorCode::E0412, - "could not resolve type path %qs", - segment->get_ident_segment ().as_string ().c_str ()); - return false; - } - } - - if (resolved_node_id != UNKNOWN_NODEID) - { - // name scope first - if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (path.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_name (path.get_node_id (), - resolved_node_id); - } - // check the type scope - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (path.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_type (path.get_node_id (), - resolved_node_id); - } - else - { - rust_unreachable (); - } - } - - return true; -} - -// qualified type paths - -ResolveRelativeQualTypePath::ResolveRelativeQualTypePath () - : failure_flag (false) -{} - -bool -ResolveRelativeQualTypePath::go (AST::QualifiedPathInType &path) -{ - ResolveRelativeQualTypePath o; - - // resolve the type and trait path - auto &qualified_path = path.get_qualified_path_type (); - if (!o.resolve_qual_seg (qualified_path)) - return false; - - // qualified types are similar to other paths in that we cannot guarantee - // that we can resolve the path at name resolution. We must look up - // associated types and type information to figure this out properly - - std::unique_ptr &associated - = path.get_associated_segment (); - - associated->accept_vis (o); - if (o.failure_flag) - return false; - - for (auto &seg : path.get_segments ()) - { - seg->accept_vis (o); - if (o.failure_flag) - return false; - } - - return true; -} - -bool -ResolveRelativeQualTypePath::resolve_qual_seg (AST::QualifiedPathType &seg) -{ - if (seg.is_error ()) - { - rust_error_at (seg.get_locus (), "segment has error: %s", - seg.as_string ().c_str ()); - return false; - } - - auto &type = seg.get_type (); - ResolveType::go (type); - - if (seg.has_as_clause ()) - ResolveType::go (seg.get_as_type_path ()); - - return true; -} - -void -ResolveRelativeQualTypePath::visit (AST::TypePathSegmentGeneric &seg) -{ - if (seg.is_error ()) - { - failure_flag = true; - rust_error_at (seg.get_locus (), "segment has error: %s", - seg.as_string ().c_str ()); - return; - } - - ResolveGenericArgs::go (seg.get_generic_args ()); -} - -void -ResolveRelativeQualTypePath::visit (AST::TypePathSegment &seg) -{ - if (seg.is_error ()) - { - failure_flag = true; - rust_error_at (seg.get_locus (), "segment has error: %s", - seg.as_string ().c_str ()); - return; - } -} - -// resolve to canonical path - -bool -ResolveTypeToCanonicalPath::go (AST::Type &type, CanonicalPath &result) -{ - ResolveTypeToCanonicalPath resolver; - type.accept_vis (resolver); - result = resolver.result; - return !resolver.result.is_empty (); -} - -void -ResolveTypeToCanonicalPath::visit (AST::TypePath &path) -{ - NodeId resolved_node = UNKNOWN_NODEID; - if (!resolver->lookup_resolved_name (path.get_node_id (), &resolved_node)) - { - resolver->lookup_resolved_type (path.get_node_id (), &resolved_node); - } - - if (resolved_node == UNKNOWN_NODEID) - return; - - if (auto type_path = mappings.lookup_canonical_path (resolved_node)) - { - auto &final_seg = path.get_segments ().back (); - switch (final_seg->get_type ()) - { - case AST::TypePathSegment::SegmentType::GENERIC: - { - AST::TypePathSegmentGeneric *s - = static_cast (final_seg.get ()); - - std::vector args; - if (s->has_generic_args ()) - { - ResolveGenericArgs::go (s->get_generic_args ()); - for (auto &generic : s->get_generic_args ().get_generic_args ()) - { - // FIXME: What do we want to do here in case there is a - // constant or an ambiguous const generic? - // TODO: At that point, will all generics have been - // disambiguated? Can we thus canonical resolve types and - // const and `rust_unreachable` on ambiguous types? - // This is probably fine as we just want to canonicalize - // types, right? - if (generic.get_kind () == AST::GenericArg::Kind::Type) - { - CanonicalPath arg = CanonicalPath::create_empty (); - bool ok - = ResolveTypeToCanonicalPath::go (generic.get_type (), - arg); - if (ok) - args.push_back (std::move (arg)); - } - } - } - - result = *type_path; - if (!args.empty ()) - { - // append this onto the path - std::string buf; - for (size_t i = 0; i < args.size (); i++) - { - bool has_next = (i + 1) < args.size (); - const auto &arg = args.at (i); - - buf += arg.get (); - if (has_next) - buf += ", "; - } - - std::string arg_seg = "<" + buf + ">"; - CanonicalPath argument_seg - = CanonicalPath::new_seg (s->get_node_id (), arg_seg); - result = result.append (argument_seg); - } - } - break; - - default: - result = *type_path; - break; - } - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::ReferenceType &type) -{ - CanonicalPath path = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (type.get_type_referenced (), path); - if (ok) - { - std::string ref_type_str = type.is_mut () ? "mut" : ""; - std::string ref_path = "&" + ref_type_str + " " + path.get (); - result = CanonicalPath::new_seg (type.get_node_id (), ref_path); - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::RawPointerType &type) -{ - CanonicalPath path = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (type.get_type_pointed_to (), path); - if (ok) - { - std::string ptr_type_str - = type.get_pointer_type () == AST::RawPointerType::CONST ? "const" - : "mut"; - std::string ptr_path = "*" + ptr_type_str + " " + path.get (); - result = CanonicalPath::new_seg (type.get_node_id (), ptr_path); - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::SliceType &type) -{ - CanonicalPath path = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (type.get_elem_type (), path); - if (ok) - { - std::string slice_path = "[" + path.get () + "]"; - result = CanonicalPath::new_seg (type.get_node_id (), slice_path); - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::TraitObjectTypeOneBound &type) -{ - CanonicalPath path = CanonicalPath::create_empty (); - bool ok - = ResolveTypeToCanonicalPath::go (type.get_trait_bound ().get_type_path (), - path); - if (ok) - { - std::string slice_path = ""; - result = CanonicalPath::new_seg (type.get_node_id (), slice_path); - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::TraitObjectType &type) -{ - rust_assert (!type.get_type_param_bounds ().empty ()); - - auto &first_bound = type.get_type_param_bounds ().front (); - - // Is it allowed or even possible to have a lifetime bound as a first bound? - if (first_bound->get_bound_type () == AST::TraitBound::LIFETIME) - rust_unreachable (); - - auto &trait = static_cast (*first_bound); - - CanonicalPath path = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (trait.get_type_path (), path); - - // right? - rust_assert (ok); - - auto slice_path = "get_bound_type ()) - { - case AST::TypeParamBound::TRAIT: - { - auto bound_path = CanonicalPath::create_empty (); - - auto &bound_type_path - = static_cast (*additional_bound) - .get_type_path (); - bool ok - = ResolveTypeToCanonicalPath::go (bound_type_path, bound_path); - - if (!ok) - continue; - - str = bound_path.get (); - break; - } - case AST::TypeParamBound::LIFETIME: - rust_unreachable (); - break; - } - slice_path += " + " + str; - } - - slice_path += ">"; - - result = CanonicalPath::new_seg (type.get_node_id (), slice_path); -} - -void -ResolveTypeToCanonicalPath::visit (AST::NeverType &type) -{ - result = CanonicalPath::new_seg (type.get_node_id (), "!"); -} - -void -ResolveTypeToCanonicalPath::visit (AST::TupleType &type) -{ - if (!type.is_unit_type ()) - rust_unreachable (); - - result = CanonicalPath::new_seg (type.get_node_id (), "()"); -} - -ResolveTypeToCanonicalPath::ResolveTypeToCanonicalPath () - : ResolverBase (), result (CanonicalPath::create_empty ()) -{} - -bool -ResolveGenericArgs::is_const_value_name (const CanonicalPath &path) -{ - NodeId resolved; - auto found = resolver->get_name_scope ().lookup (path, &resolved); - - return found; -} - -bool -ResolveGenericArgs::is_type_name (const CanonicalPath &path) -{ - NodeId resolved; - auto found = resolver->get_type_scope ().lookup (path, &resolved); - - return found; -} - -void -ResolveGenericArgs::disambiguate (AST::GenericArg &arg) -{ - auto path = canonical_prefix.append ( - CanonicalPath::new_seg (UNKNOWN_NODEID, arg.get_path ())); - - auto is_type = is_type_name (path); - auto is_value = is_const_value_name (path); - - // In case we cannot find anything, we resolve the ambiguity to a type. - // This causes the typechecker to error out properly and when necessary. - // But types also take priority over const values in the case of - // ambiguities, hence the weird control flow - if (is_type || (!is_type && !is_value)) - arg = arg.disambiguate_to_type (); - else if (is_value) - arg = arg.disambiguate_to_const (); -} - -void -ResolveGenericArgs::resolve_disambiguated_generic (AST::GenericArg &arg) -{ - switch (arg.get_kind ()) - { - case AST::GenericArg::Kind::Const: - ResolveExpr::go (arg.get_expression (), prefix, canonical_prefix); - break; - case AST::GenericArg::Kind::Type: - ResolveType::go (arg.get_type ()); - break; - default: - rust_unreachable (); - } -} -void -ResolveGenericArgs::go (AST::GenericArgs &generic_args) -{ - auto empty = CanonicalPath::create_empty (); - - go (generic_args, empty, empty); -} - -void -ResolveGenericArgs::go (AST::GenericArgs &generic_args, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - auto resolver = ResolveGenericArgs (prefix, canonical_prefix); - - for (auto &arg : generic_args.get_generic_args ()) - { - if (arg.get_kind () == AST::GenericArg::Kind::Either) - resolver.disambiguate (arg); - - resolver.resolve_disambiguated_generic (arg); - } - - for (auto &binding : generic_args.get_binding_args ()) - { - ResolveType::go (binding.get_type ()); - } -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h deleted file mode 100644 index f1481fcc65e..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_AST_RESOLVE_TYPE_H -#define RUST_AST_RESOLVE_TYPE_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-resolve-expr.h" -#include "rust-diagnostics.h" -#include "rust-hir-map.h" -#include "rust-path.h" -#include "rust-type.h" -#include "util/rust-hir-map.h" - -namespace Rust { -namespace Resolver { - -class ResolveRelativeTypePath -{ -public: - static bool go (AST::TypePath &path, NodeId &resolved_node_id); -}; - -class ResolveRelativeQualTypePath : public ResolverBase -{ - using ResolverBase::visit; - -public: - static bool go (AST::QualifiedPathInType &path); - - void visit (AST::TypePathSegmentGeneric &seg) override; - - void visit (AST::TypePathSegment &seg) override; - -protected: - bool resolve_qual_seg (AST::QualifiedPathType &seg); - -private: - ResolveRelativeQualTypePath (); - - bool failure_flag; -}; - -class ResolveType : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static NodeId go (AST::Type &type); - - void visit (AST::BareFunctionType &fntype) override; - void visit (AST::TupleType &tuple) override; - void visit (AST::TypePath &path) override; - void visit (AST::QualifiedPathInType &path) override; - void visit (AST::ArrayType &type) override; - void visit (AST::ReferenceType &type) override; - void visit (AST::InferredType &type) override; - void visit (AST::NeverType &type) override; - void visit (AST::RawPointerType &type) override; - void visit (AST::TraitObjectTypeOneBound &type) override; - void visit (AST::TraitObjectType &type) override; - void visit (AST::ParenthesisedType &type) override; - void visit (AST::SliceType &type) override; - void visit (AST::ImplTraitType &type) override; - void visit (AST::ImplTraitTypeOneBound &type) override; - -private: - ResolveType () : ResolverBase () {} -}; - -class ResolveTypeBound : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static NodeId go (AST::TypeParamBound &type) - { - ResolveTypeBound resolver; - type.accept_vis (resolver); - return resolver.resolved_node; - }; - - void visit (AST::TraitBound &bound) override - { - resolved_node = ResolveType::go (bound.get_type_path ()); - } - -private: - ResolveTypeBound () : ResolverBase () {} -}; - -class ResolveGenericParams : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (std::vector> ¶ms, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - ResolveGenericParams resolver (prefix, canonical_prefix); - - // this needs to be done in two phases as they can be used and defined later - // in bounds - for (auto ¶m : params) - param->accept_vis (resolver); - - resolver.first_pass = false; - - for (auto ¶m : params) - param->accept_vis (resolver); - } - - static void go_single (AST::GenericParam ¶m, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - ResolveGenericParams resolver (prefix, canonical_prefix); - - param.accept_vis (resolver); - resolver.first_pass = false; - param.accept_vis (resolver); - } - - void visit (AST::ConstGenericParam ¶m) override - { - if (first_pass) - ResolveType::go (param.get_type ()); - else if (param.has_default_value ()) - ResolveExpr::go (param.get_default_value_unchecked ().get_expression (), - prefix, canonical_prefix); - } - - void visit (AST::TypeParam ¶m) override - { - if (first_pass) - { - // if it has a type lets resolve it - if (param.has_type ()) - ResolveType::go (param.get_type ()); - - auto seg = CanonicalPath::new_seg ( - param.get_node_id (), param.get_type_representation ().as_string ()); - resolver->get_type_scope ().insert ( - seg, param.get_node_id (), param.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (param.get_locus (), - "generic param defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - - mappings.insert_canonical_path (param.get_node_id (), seg); - } - else if (param.has_type_param_bounds ()) - { - for (auto &bound : param.get_type_param_bounds ()) - ResolveTypeBound::go (*bound); - } - } - -private: - ResolveGenericParams (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), first_pass (true), prefix (prefix), - canonical_prefix (canonical_prefix) - {} - - bool first_pass; - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class ResolveWhereClause : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void Resolve (AST::WhereClause &where_clause) - { - ResolveWhereClause r; - for (auto &clause : where_clause.get_items ()) - clause->accept_vis (r); - } - - void visit (AST::TypeBoundWhereClauseItem &item) override - { - ResolveType::go (item.get_type ()); - if (item.has_type_param_bounds ()) - { - for (auto &bound : item.get_type_param_bounds ()) - { - ResolveTypeBound::go (*bound); - } - } - } - -private: - ResolveWhereClause () : ResolverBase () {} -}; - -class ResolveTypeToCanonicalPath : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static bool go (AST::Type &type, CanonicalPath &result); - - void visit (AST::TypePath &path) override; - - void visit (AST::ReferenceType &type) override; - - void visit (AST::RawPointerType &type) override; - - void visit (AST::SliceType &type) override; - - void visit (AST::TraitObjectTypeOneBound &type) override; - - void visit (AST::TraitObjectType &type) override; - - void visit (AST::NeverType &type) override; - - void visit (AST::TupleType &type) override; - -private: - ResolveTypeToCanonicalPath (); - - CanonicalPath result; -}; - -class ResolveGenericArgs : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::GenericArgs &generic_args); - static void go (AST::GenericArgs &generic_args, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - -private: - ResolveGenericArgs (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) - {} - - bool is_type_name (const CanonicalPath &path); - bool is_const_value_name (const CanonicalPath &path); - - /** - * Resolve a disambiguated generic arg - */ - void disambiguate (AST::GenericArg &arg); - - /** - * Resolve a disambiguated generic arg - */ - void resolve_disambiguated_generic (AST::GenericArg &arg); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_TYPE_H diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc deleted file mode 100644 index 2208f7046a7..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#include "rust-ast-resolve.h" -#include "rust-ast-full.h" -#include "rust-tyty.h" -#include "rust-ast-resolve-toplevel.h" -#include "rust-ast-resolve-item.h" -#include "rust-ast-resolve-expr.h" -#include "rust-ast-resolve-struct-expr-field.h" - -extern bool saw_errors (void); - -namespace Rust { -namespace Resolver { - -// NameResolution - -NameResolution * -NameResolution::get () -{ - static NameResolution *instance; - if (instance == nullptr) - instance = new NameResolution (); - - return instance; -} - -NameResolution::NameResolution () - : resolver (Resolver::get ()), mappings (Analysis::Mappings::get ()) -{ - // these are global - resolver->get_type_scope ().push (mappings.get_next_node_id ()); - resolver->insert_builtin_types (resolver->get_type_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); -} - -void -NameResolution::Resolve (AST::Crate &crate) -{ - auto resolver = get (); - resolver->go (crate); -} - -void -NameResolution::go (AST::Crate &crate) -{ - // lookup current crate name - CrateNum cnum = mappings.get_current_crate (); - - // Clones the crate name instead of references due to gcc's possibly - // dangling references warnings - const auto crate_name = mappings.get_crate_name (cnum).value (); - - // setup the ribs - NodeId scope_node_id = crate.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // get the root segment - CanonicalPath crate_prefix - = CanonicalPath::new_seg (scope_node_id, crate_name); - crate_prefix.set_crate_num (cnum); - - // setup a dummy crate node - resolver->get_name_scope ().insert ( - CanonicalPath::new_seg (crate.get_node_id (), "__$$crate__"), - crate.get_node_id (), UNDEF_LOCATION); - - // setup the root scope - resolver->push_new_module_scope (scope_node_id); - - // first gather the top-level namespace names then we drill down so this - // allows for resolving forward declarations since an impl block might have - // a Self type Foo which is defined after the impl block for example. - for (auto &item : crate.items) - ResolveTopLevel::go (*item, CanonicalPath::create_empty (), crate_prefix); - - // FIXME remove this - if (saw_errors ()) - { - resolver->pop_module_scope (); - return; - } - - // next we can drill down into the items and their scopes - for (auto &item : crate.items) - ResolveItem::go (*item, CanonicalPath::create_empty (), crate_prefix); - - // done - resolver->pop_module_scope (); -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve.h b/gcc/rust/resolve/rust-ast-resolve.h deleted file mode 100644 index a4ad7188496..00000000000 --- a/gcc/rust/resolve/rust-ast-resolve.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_AST_RESOLVE_H -#define RUST_AST_RESOLVE_H - -#include "rust-name-resolver.h" -#include "rust-hir-map.h" - -namespace Rust { -namespace Resolver { - -class NameResolution -{ -public: - static void Resolve (AST::Crate &crate); - - static NameResolution *get (); - - ~NameResolution () {} - -private: - void go (AST::Crate &crate); - - NameResolution (); - - Resolver *resolver; - Analysis::Mappings &mappings; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_H diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 4fd1dd265b6..252a0498d19 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -62,6 +62,8 @@ Early::go (AST::Crate &crate) // us dirty = toplevel.is_dirty (); + + std::cout << "# TOPLEVEL IS " << (dirty ? "" : "NOT ") << "DIRTY" << std::endl; // We now proceed with resolving macros, which can be nested in almost any // items textual_scope.push (); diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc deleted file mode 100644 index fc9a26ccac0..00000000000 --- a/gcc/rust/resolve/rust-early-name-resolver.cc +++ /dev/null @@ -1,589 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#include "rust-early-name-resolver.h" -#include "rust-pattern.h" -#include "rust-name-resolver.h" -#include "rust-macro-builtins.h" -#include "rust-attribute-values.h" - -namespace Rust { -namespace Resolver { - -// Check if a module contains the `#[macro_use]` attribute -static bool -is_macro_use_module (const AST::Module &mod) -{ - for (const auto &attr : mod.get_outer_attrs ()) - if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE) - return true; - - return false; -} - -std::vector> -EarlyNameResolver::accumulate_escaped_macros (AST::Module &module) -{ - if (!is_macro_use_module (module)) - return {}; - - // Parse the module's items if they haven't been expanded and the file - // should be parsed (i.e isn't hidden behind an untrue or impossible cfg - // directive) - if (module.get_kind () == AST::Module::UNLOADED) - module.load_items (); - - std::vector> escaped_macros; - - scoped (module.get_node_id (), [&module, &escaped_macros, this] { - for (auto &item : module.get_items ()) - { - if (item->get_item_kind () == AST::Item::Kind::Module) - { - auto &module = *static_cast (item.get ()); - auto new_macros = accumulate_escaped_macros (module); - - std::move (new_macros.begin (), new_macros.end (), - std::back_inserter (escaped_macros)); - - continue; - } - - if (item->get_item_kind () == AST::Item::Kind::MacroRulesDefinition) - escaped_macros.emplace_back (item->clone_item ()); - } - }); - - return escaped_macros; -} - -EarlyNameResolver::EarlyNameResolver () - : current_scope (UNKNOWN_NODEID), resolver (*Resolver::get ()), - mappings (Analysis::Mappings::get ()) -{} - -void -EarlyNameResolver::go (AST::Crate &crate) -{ - visit (crate); -} - -void -EarlyNameResolver::resolve_generic_args (AST::GenericArgs &generic_args) -{ - for (auto &arg : generic_args.get_generic_args ()) - arg.accept_vis (*this); - - for (auto &arg : generic_args.get_binding_args ()) - arg.get_type ().accept_vis (*this); -} - -void -EarlyNameResolver::resolve_qualified_path_type (AST::QualifiedPathType &path) -{ - path.get_type ().accept_vis (*this); - - if (path.has_as_clause ()) - path.get_as_type_path ().accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::Crate &crate) -{ - std::vector> new_items; - auto items = crate.take_items (); - - scoped (crate.get_node_id (), [&items, &new_items, this] { - for (auto &&item : items) - { - auto new_macros = std::vector> (); - - if (item->get_item_kind () == AST::Item::Kind::Module) - new_macros = accumulate_escaped_macros ( - *static_cast (item.get ())); - - new_items.emplace_back (std::move (item)); - std::move (new_macros.begin (), new_macros.end (), - std::back_inserter (new_items)); - } - }); - - crate.set_items (std::move (new_items)); - - scoped (crate.get_node_id (), [&crate, this] () { - for (auto &item : crate.items) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::DelimTokenTree &) -{} - -void -EarlyNameResolver::visit (AST::AttrInputMetaItemContainer &) -{} - -void -EarlyNameResolver::visit (AST::IdentifierExpr &) -{} - -void -EarlyNameResolver::visit (AST::LifetimeParam &) -{} - -void -EarlyNameResolver::visit (AST::ConstGenericParam &) -{} - -// FIXME: ARTHUR: Do we need to perform macro resolution for paths as well? -// std::arch::asm!()? -void -EarlyNameResolver::visit (AST::PathInExpression &path) -{ - if (!path.is_lang_item ()) - for (auto &segment : path.get_segments ()) - if (segment.has_generic_args ()) - resolve_generic_args (segment.get_generic_args ()); -} - -void -EarlyNameResolver::visit (AST::TypePathSegmentGeneric &segment) -{ - if (segment.has_generic_args ()) - resolve_generic_args (segment.get_generic_args ()); -} - -void -EarlyNameResolver::visit (AST::QualifiedPathInExpression &path) -{ - resolve_qualified_path_type (path.get_qualified_path_type ()); - - for (auto &segment : path.get_segments ()) - if (segment.has_generic_args ()) - resolve_generic_args (segment.get_generic_args ()); -} - -void -EarlyNameResolver::visit (AST::QualifiedPathInType &path) -{ - resolve_qualified_path_type (path.get_qualified_path_type ()); - - for (auto &segment : path.get_segments ()) - segment->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::LiteralExpr &) -{} - -void -EarlyNameResolver::visit (AST::AttrInputLiteral &) -{} - -void -EarlyNameResolver::visit (AST::AttrInputMacro &) -{} - -void -EarlyNameResolver::visit (AST::MetaItemLitExpr &) -{} - -void -EarlyNameResolver::visit (AST::MetaItemPathLit &) -{} - -void -EarlyNameResolver::visit (AST::StructExprStruct &) -{} - -void -EarlyNameResolver::visit (AST::StructExprFieldIdentifier &) -{} - -void -EarlyNameResolver::visit (AST::StructExprStructBase &) -{} - -void -EarlyNameResolver::visit (AST::BlockExpr &expr) -{ - scoped (expr.get_node_id (), [&expr, this] () { - for (auto &stmt : expr.get_statements ()) - stmt->accept_vis (*this); - - if (expr.has_tail_expr ()) - expr.get_tail_expr ().accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::ContinueExpr &) -{} - -void -EarlyNameResolver::visit (AST::RangeFullExpr &) -{} - -void -EarlyNameResolver::visit (AST::ForLoopExpr &expr) -{ - scoped (expr.get_node_id (), [&expr, this] () { - expr.get_pattern ().accept_vis (*this); - expr.get_iterator_expr ().accept_vis (*this); - expr.get_loop_block ().accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::IfLetExpr &expr) -{ - expr.get_value_expr ().accept_vis (*this); - - scoped (expr.get_node_id (), - [&expr, this] () { expr.get_if_block ().accept_vis (*this); }); -} - -void -EarlyNameResolver::visit (AST::MatchExpr &expr) -{ - expr.get_scrutinee_expr ().accept_vis (*this); - - scoped (expr.get_node_id (), [&expr, this] () { - for (auto &arm : expr.get_match_cases ()) - { - scoped (arm.get_node_id (), [&arm, this] () { - if (arm.get_arm ().has_match_arm_guard ()) - arm.get_arm ().get_guard_expr ().accept_vis (*this); - - for (auto &pattern : arm.get_arm ().get_patterns ()) - pattern->accept_vis (*this); - - arm.get_expr ().accept_vis (*this); - }); - } - }); -} - -void -EarlyNameResolver::visit (AST::LifetimeWhereClauseItem &) -{} - -void -EarlyNameResolver::visit (AST::Module &module) -{ - if (module.get_kind () == AST::Module::UNLOADED) - module.load_items (); - - // so we need to only go "one scope down" for fetching macros. Macros within - // functions are still scoped only within that function. But we have to be - // careful because nested modules with #[macro_use] actually works! - std::vector> new_items; - auto items = module.take_items (); - - scoped (module.get_node_id (), [&items, &new_items, this] { - for (auto &&item : items) - { - auto new_macros = std::vector> (); - - if (item->get_item_kind () == AST::Item::Kind::Module) - new_macros = accumulate_escaped_macros ( - *static_cast (item.get ())); - - new_items.emplace_back (std::move (item)); - std::move (new_macros.begin (), new_macros.end (), - std::back_inserter (new_items)); - } - }); - - module.set_items (std::move (new_items)); - - scoped (module.get_node_id (), [&module, this] () { - for (auto &item : module.get_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::ExternCrate &) -{} - -void -EarlyNameResolver::visit (AST::UseTreeGlob &) -{} - -void -EarlyNameResolver::visit (AST::UseTreeList &) -{} - -void -EarlyNameResolver::visit (AST::UseTreeRebind &) -{} - -void -EarlyNameResolver::visit (AST::UseDeclaration &) -{} - -void -EarlyNameResolver::visit (AST::EnumItem &) -{} - -void -EarlyNameResolver::visit (AST::Union &) -{} - -void -EarlyNameResolver::visit (AST::TraitItemType &) -{} - -void -EarlyNameResolver::visit (AST::Trait &trait) -{ - // shouldn't need to visit trait.get_implicit_self () - - for (auto &generic : trait.get_generic_params ()) - generic->accept_vis (*this); - - scoped (trait.get_node_id (), [&trait, this] () { - for (auto &item : trait.get_trait_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::InherentImpl &impl) -{ - impl.get_type ().accept_vis (*this); - - for (auto &generic : impl.get_generic_params ()) - generic->accept_vis (*this); - - scoped (impl.get_node_id (), [&impl, this] () { - for (auto &item : impl.get_impl_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::TraitImpl &impl) -{ - impl.get_type ().accept_vis (*this); - - for (auto &generic : impl.get_generic_params ()) - generic->accept_vis (*this); - - scoped (impl.get_node_id (), [&impl, this] () { - for (auto &item : impl.get_impl_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::ExternalTypeItem &item) -{ - // nothing to do? -} - -void -EarlyNameResolver::visit (AST::ExternBlock &block) -{ - scoped (block.get_node_id (), [&block, this] () { - for (auto &item : block.get_extern_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::MacroMatchRepetition &) -{} - -void -EarlyNameResolver::visit (AST::MacroMatcher &) -{} - -void -EarlyNameResolver::visit (AST::MacroRulesDefinition &rules_def) -{ - auto path = CanonicalPath::new_seg (rules_def.get_node_id (), - rules_def.get_rule_name ().as_string ()); - resolver.get_macro_scope ().insert (path, rules_def.get_node_id (), - rules_def.get_locus ()); - - /* Since the EarlyNameResolver runs multiple time (fixed point algorithm) - * we could be inserting the same macro def over and over again until we - * implement some optimizations */ - // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead - if (mappings.lookup_macro_def (rules_def.get_node_id ())) - return; - - mappings.insert_macro_def (&rules_def); - rust_debug_loc (rules_def.get_locus (), "inserting macro def: [%s]", - path.get ().c_str ()); -} - -void -EarlyNameResolver::visit (AST::MacroInvocation &invoc) -{ - auto &invoc_data = invoc.get_invoc_data (); - auto has_semicolon = invoc.has_semicolon (); - - if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin) - for (auto &pending_invoc : invoc.get_pending_eager_invocations ()) - pending_invoc->accept_vis (*this); - - // ?? - // switch on type of macro: - // - '!' syntax macro (inner switch) - // - procedural macro - "A token-based function-like macro" - // - 'macro_rules' (by example/pattern-match) macro? or not? "an - // AST-based function-like macro" - // - else is unreachable - // - attribute syntax macro (inner switch) - // - procedural macro attribute syntax - "A token-based attribute - // macro" - // - legacy macro attribute syntax? - "an AST-based attribute macro" - // - non-macro attribute: mark known - // - else is unreachable - // - derive macro (inner switch) - // - derive or legacy derive - "token-based" vs "AST-based" - // - else is unreachable - // - derive container macro - unreachable - - // lookup the rules for this macro - NodeId resolved_node = UNKNOWN_NODEID; - NodeId source_node = UNKNOWN_NODEID; - if (has_semicolon) - source_node = invoc.get_macro_node_id (); - else - source_node = invoc.get_node_id (); - auto seg - = CanonicalPath::new_seg (source_node, invoc_data.get_path ().as_string ()); - - bool found = resolver.get_macro_scope ().lookup (seg, &resolved_node); - if (!found) - { - rust_error_at (invoc.get_locus (), ErrorCode::E0433, - "could not resolve macro invocation %qs", - seg.get ().c_str ()); - return; - } - - // lookup the rules - auto rules_def = mappings.lookup_macro_def (resolved_node); - - auto &outer_attrs = rules_def.value ()->get_outer_attrs (); - bool is_builtin - = std::any_of (outer_attrs.begin (), outer_attrs.end (), - [] (AST::Attribute attr) { - return attr.get_path () - == Values::Attributes::RUSTC_BUILTIN_MACRO; - }); - - if (is_builtin) - { - auto builtin_kind = builtin_macro_from_string ( - rules_def.value ()->get_rule_name ().as_string ()); - invoc.map_to_builtin (builtin_kind.value ()); - } - - auto attributes = rules_def.value ()->get_outer_attrs (); - - /* Since the EarlyNameResolver runs multiple time (fixed point algorithm) - * we could be inserting the same macro def over and over again until we - * implement some optimizations */ - // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead - if (mappings.lookup_macro_invocation (invoc)) - return; - - mappings.insert_macro_invocation (invoc, *rules_def); -} - -// FIXME: ARTHUR: Do we need to resolve these as well here? - -void -EarlyNameResolver::visit (AST::MetaItemPath &) -{} - -void -EarlyNameResolver::visit (AST::MetaItemSeq &) -{} - -void -EarlyNameResolver::visit (AST::MetaNameValueStr &) -{} - -void -EarlyNameResolver::visit (AST::MetaListPaths &) -{} - -void -EarlyNameResolver::visit (AST::MetaListNameValueStr &) -{} - -void -EarlyNameResolver::visit (AST::RangePatternBoundLiteral &) -{} - -void -EarlyNameResolver::visit (AST::RangePatternBoundPath &) -{} - -void -EarlyNameResolver::visit (AST::RangePatternBoundQualPath &) -{} - -void -EarlyNameResolver::visit (AST::StructPatternFieldIdent &) -{} - -void -EarlyNameResolver::visit (AST::StructPattern &) -{} - -void -EarlyNameResolver::visit (AST::TupleStructPattern &pattern) -{ - pattern.get_items ().accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TupleType &) -{} - -void -EarlyNameResolver::visit (AST::RawPointerType &) -{} - -void -EarlyNameResolver::visit (AST::ReferenceType &) -{} - -void -EarlyNameResolver::visit (AST::ArrayType &) -{} - -void -EarlyNameResolver::visit (AST::SliceType &) -{} - -void -EarlyNameResolver::visit (AST::InferredType &) -{} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h deleted file mode 100644 index 26fc84d52dc..00000000000 --- a/gcc/rust/resolve/rust-early-name-resolver.h +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . - -#ifndef RUST_EARLY_NAME_RESOLVER_H -#define RUST_EARLY_NAME_RESOLVER_H - -#include "rust-name-resolver.h" -#include "rust-system.h" -#include "rust-ast.h" -#include "rust-ast-visitor.h" - -namespace Rust { -namespace Resolver { - -class EarlyNameResolver : public AST::DefaultASTVisitor -{ -public: - EarlyNameResolver (); - - void go (AST::Crate &crate); - -private: - using AST::DefaultASTVisitor::visit; - - /** - * Execute a lambda within a scope. This is equivalent to calling - * `enter_scope` before your code and `exit_scope` after. This ensures - * no errors can be committed - */ - void scoped (NodeId scope_id, std::function fn) - { - auto old_scope = current_scope; - current_scope = scope_id; - resolver.get_macro_scope ().push (scope_id); - resolver.push_new_macro_rib (resolver.get_macro_scope ().peek ()); - - fn (); - - resolver.get_macro_scope ().pop (); - current_scope = old_scope; - } - - /** - * Accumulate all of the nested macros which escape their module through the - * use of the #[macro_use] attribute. - * - * This function recursively accumulates macros in all of the nested modules - * of an item container (an AST::Crate or an AST::Module) and returns this new - * list of items. You can then use the `take_items` and `set_items` functions - * on these containers to replace their list of items. - */ - std::vector> - accumulate_escaped_macros (AST::Module &module); - - /** - * The "scope" we are currently in. - * - * This involves lexical scopes: - * - * ```rust - * // current_scope = crate_id; - * macro_rules! foo { () => {} ) - * - * { - * // current_scope = current_block_id; - * macro_rules! foo { () => { something!(); } } - * } - * // current_scope = crate_id; - * ``` - * - * as well as any sort of scope-like structure that might impact import name - * resolution or macro name resolution: - * - * ```rust - * macro_rules! foo { - * () => { fn empty() {} } - * } - * - * - * trait Foo { - * fn foo() { - * fn inner_foo() { - * macro_rules! foo { () => {} ) - * - * foo!(); - * } - * - * foo!(); - * } - * - * foo!(); - * } - * - * foo!(); - * ``` - */ - NodeId current_scope; - - /* The crate's scope */ - NodeId crate_scope; - - Resolver &resolver; - Analysis::Mappings &mappings; - - /** - * Early name-resolve generic args, which can be macro invocations - */ - void resolve_generic_args (AST::GenericArgs &generic_args); - - /** - * Early name-resolve a qualified path type, which can contain macro - * invocations - */ - void resolve_qualified_path_type (AST::QualifiedPathType &path); - - virtual void visit (AST::Crate &crate); - virtual void visit (AST::DelimTokenTree &delim_tok_tree); - virtual void visit (AST::AttrInputMetaItemContainer &input); - virtual void visit (AST::IdentifierExpr &ident_expr); - virtual void visit (AST::LifetimeParam &lifetime_param); - virtual void visit (AST::ConstGenericParam &const_param); - virtual void visit (AST::PathInExpression &path); - virtual void visit (AST::TypePathSegmentGeneric &segment); - virtual void visit (AST::QualifiedPathInExpression &path); - virtual void visit (AST::QualifiedPathInType &path); - virtual void visit (AST::LiteralExpr &expr); - virtual void visit (AST::AttrInputLiteral &attr_input); - virtual void visit (AST::AttrInputMacro &attr_input); - virtual void visit (AST::MetaItemLitExpr &meta_item); - virtual void visit (AST::MetaItemPathLit &meta_item); - virtual void visit (AST::StructExprStruct &expr); - virtual void visit (AST::StructExprFieldIdentifier &field); - virtual void visit (AST::StructExprStructBase &expr); - virtual void visit (AST::BlockExpr &expr); - virtual void visit (AST::ContinueExpr &expr); - virtual void visit (AST::RangeFullExpr &expr); - virtual void visit (AST::ForLoopExpr &expr); - virtual void visit (AST::IfLetExpr &expr); - virtual void visit (AST::MatchExpr &expr); - virtual void visit (AST::LifetimeWhereClauseItem &item); - virtual void visit (AST::Module &module); - virtual void visit (AST::ExternCrate &crate); - virtual void visit (AST::UseTreeGlob &use_tree); - virtual void visit (AST::UseTreeList &use_tree); - virtual void visit (AST::UseTreeRebind &use_tree); - virtual void visit (AST::UseDeclaration &use_decl); - virtual void visit (AST::EnumItem &item); - virtual void visit (AST::Union &union_item); - virtual void visit (AST::TraitItemType &item); - virtual void visit (AST::Trait &trait); - virtual void visit (AST::InherentImpl &impl); - virtual void visit (AST::TraitImpl &impl); - virtual void visit (AST::ExternalTypeItem &item); - virtual void visit (AST::ExternBlock &block); - virtual void visit (AST::MacroMatchRepetition &match); - virtual void visit (AST::MacroMatcher &matcher); - virtual void visit (AST::MacroRulesDefinition &rules_def); - virtual void visit (AST::MacroInvocation ¯o_invoc); - virtual void visit (AST::MetaItemPath &meta_item); - virtual void visit (AST::MetaItemSeq &meta_item); - virtual void visit (AST::MetaNameValueStr &meta_item); - virtual void visit (AST::MetaListPaths &meta_item); - virtual void visit (AST::MetaListNameValueStr &meta_item); - virtual void visit (AST::RangePatternBoundLiteral &bound); - virtual void visit (AST::RangePatternBoundPath &bound); - virtual void visit (AST::RangePatternBoundQualPath &bound); - virtual void visit (AST::StructPatternFieldIdent &field); - virtual void visit (AST::StructPattern &pattern); - virtual void visit (AST::TupleStructPattern &pattern); - virtual void visit (AST::TupleType &type); - virtual void visit (AST::RawPointerType &type); - virtual void visit (AST::ReferenceType &type); - virtual void visit (AST::ArrayType &type); - virtual void visit (AST::SliceType &type); - virtual void visit (AST::InferredType &type); -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_EARLY_NAME_RESOLVER_H diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 1ed87b3d55b..4a29b20446c 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -583,13 +583,20 @@ ForeverStack::resolve_segments ( break; } - if (N == Namespace::Types) + auto rib_lookup = current_node->rib.get (seg.as_string ()); + if (rib_lookup && !rib_lookup->is_ambiguous ()) { - auto rib_lookup = current_node->rib.get (seg.as_string ()); - if (rib_lookup && !rib_lookup->is_ambiguous ()) + insert_segment_resolution (outer_seg, rib_lookup->get_node_id ()); + if (Analysis::Mappings::get () + .lookup_glob_container (rib_lookup->get_node_id ()) + .has_value ()) + { + current_node + = &dfs_node (root, rib_lookup->get_node_id ()).value (); + continue; + } + else { - insert_segment_resolution (outer_seg, - rib_lookup->get_node_id ()); return tl::nullopt; } } diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 1b560852418..1730609e354 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -135,18 +135,22 @@ Late::visit (AST::ForLoopExpr &expr) { visit_outer_attrs (expr); - ctx.bindings.enter (BindingSource::For); + visit (expr.get_iterator_expr ()); - visit (expr.get_pattern ()); + auto vis_method = [this, &expr] () { + ctx.bindings.enter (BindingSource::For); - ctx.bindings.exit (); + visit (expr.get_pattern ()); - visit (expr.get_iterator_expr ()); + ctx.bindings.exit (); - if (expr.has_loop_label ()) - visit (expr.get_loop_label ()); + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); - visit (expr.get_loop_block ()); + visit (expr.get_loop_block ()); + }; + + ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), vis_method); } void @@ -521,20 +525,22 @@ Late::visit_impl_type (AST::Type &type) block_big_self = false; } -void -Late::visit (AST::TypePath &type) +template +static void +resolve_type_path_like (NameResolutionContext &ctx, bool block_big_self, + P &type) { // should we add type path resolution in `ForeverStack` directly? Since it's // quite more complicated. // maybe we can overload `resolve_path` to only do // typepath-like path resolution? that sounds good - DefaultResolver::visit (type); - // prevent "impl Self {}" and similar if (type.get_segments ().size () == 1 - && !type.get_segments ().front ()->is_lang_item () - && type.get_segments ().front ()->is_big_self_seg () && block_big_self) + && !unwrap_segment_get_lang_item (type.get_segments ().front ()) + .has_value () + && unwrap_type_segment (type.get_segments ().front ()).is_big_self_seg () + && block_big_self) { rust_error_at (type.get_locus (), "% is not valid in the self type of an impl block"); @@ -547,17 +553,17 @@ Late::visit (AST::TypePath &type) if (!resolved.has_value ()) { - if (!ctx.lookup (type.get_segments ().front ()->get_node_id ())) + if (!ctx.lookup (unwrap_segment_node_id (type.get_segments ().front ()))) rust_error_at (type.get_locus (), ErrorCode::E0412, "could not resolve type path %qs", - type.make_debug_string ().c_str ()); + unwrap_segment_error_string (type).c_str ()); return; } if (resolved->is_ambiguous ()) { rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous", - type.make_debug_string ().c_str ()); + unwrap_segment_error_string (type).c_str ()); return; } @@ -573,6 +579,14 @@ Late::visit (AST::TypePath &type) Definition (resolved->get_node_id ())); } +void +Late::visit (AST::TypePath &type) +{ + DefaultResolver::visit (type); + + resolve_type_path_like (ctx, block_big_self, type); +} + void Late::visit (AST::Visibility &vis) { @@ -649,10 +663,7 @@ Late::visit (AST::StructExprStruct &s) visit_inner_attrs (s); DefaultResolver::visit (s.get_struct_name ()); - auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types); - - ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), - Definition (resolved->get_node_id ())); + resolve_type_path_like (ctx, block_big_self, s.get_struct_name ()); } void @@ -663,10 +674,7 @@ Late::visit (AST::StructExprStructBase &s) DefaultResolver::visit (s.get_struct_name ()); visit (s.get_struct_base ()); - auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types); - - ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), - Definition (resolved->get_node_id ())); + resolve_type_path_like (ctx, block_big_self, s.get_struct_name ()); } void @@ -680,10 +688,7 @@ Late::visit (AST::StructExprStructFields &s) for (auto &field : s.get_fields ()) visit (field); - auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types); - - ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), - Definition (resolved->get_node_id ())); + resolve_type_path_like (ctx, block_big_self, s.get_struct_name ()); } // needed because Late::visit (AST::GenericArg &) is non-virtual diff --git a/gcc/rust/resolve/rust-name-resolver.cc b/gcc/rust/resolve/rust-name-resolver.cc index dddaa079301..b6b3a0a5d9b 100644 --- a/gcc/rust/resolve/rust-name-resolver.cc +++ b/gcc/rust/resolve/rust-name-resolver.cc @@ -19,9 +19,6 @@ #include "rust-name-resolver.h" #include "rust-ast-full.h" -// for flag_name_resolution_2_0 -#include "options.h" - namespace Rust { namespace Resolver { @@ -275,412 +272,5 @@ Scope::decl_was_declared_here (NodeId def) const return found; } -Resolver::Resolver () - : mappings (Analysis::Mappings::get ()), tyctx (TypeCheckContext::get ()), - name_scope (Scope (mappings.get_current_crate ())), - type_scope (Scope (mappings.get_current_crate ())), - label_scope (Scope (mappings.get_current_crate ())), - macro_scope (Scope (mappings.get_current_crate ())), - global_type_node_id (UNKNOWN_NODEID), unit_ty_node_id (UNKNOWN_NODEID) -{ - generate_builtins (); -} - -Resolver * -Resolver::get () -{ - static Resolver *instance; - if (instance == nullptr) - instance = new Resolver (); - - return instance; -} - -void -Resolver::push_new_name_rib (Rib *r) -{ - rust_assert (name_ribs.find (r->get_node_id ()) == name_ribs.end ()); - name_ribs[r->get_node_id ()] = r; -} - -void -Resolver::push_new_type_rib (Rib *r) -{ - if (type_ribs.size () == 0) - global_type_node_id = r->get_node_id (); - - rust_assert (type_ribs.find (r->get_node_id ()) == type_ribs.end ()); - type_ribs[r->get_node_id ()] = r; -} - -void -Resolver::push_new_label_rib (Rib *r) -{ - rust_assert (label_ribs.find (r->get_node_id ()) == label_ribs.end ()); - label_ribs[r->get_node_id ()] = r; -} - -void -Resolver::push_new_macro_rib (Rib *r) -{ - rust_assert (label_ribs.find (r->get_node_id ()) == label_ribs.end ()); - macro_ribs[r->get_node_id ()] = r; -} - -bool -Resolver::find_name_rib (NodeId id, Rib **rib) -{ - auto it = name_ribs.find (id); - if (it == name_ribs.end ()) - return false; - - *rib = it->second; - return true; -} - -bool -Resolver::find_type_rib (NodeId id, Rib **rib) -{ - auto it = type_ribs.find (id); - if (it == type_ribs.end ()) - return false; - - *rib = it->second; - return true; -} - -bool -Resolver::find_macro_rib (NodeId id, Rib **rib) -{ - auto it = macro_ribs.find (id); - if (it == macro_ribs.end ()) - return false; - - *rib = it->second; - return true; -} - -void -Resolver::insert_builtin_types (Rib *r) -{ - auto builtins = get_builtin_types (); - for (auto &builtin : builtins) - { - CanonicalPath builtin_path - = CanonicalPath::new_seg (builtin->get_node_id (), - builtin->as_string ()); - r->insert_name (builtin_path, builtin->get_node_id (), BUILTINS_LOCATION, - false, Rib::ItemType::Type, - [] (const CanonicalPath &, NodeId, location_t) -> void { - }); - } -} - -std::vector & -Resolver::get_builtin_types () -{ - return builtins; -} - -void -Resolver::generate_builtins () -{ - auto u8 - = new TyTy::UintType (mappings.get_next_hir_id (), TyTy::UintType::U8); - auto u16 - = new TyTy::UintType (mappings.get_next_hir_id (), TyTy::UintType::U16); - auto u32 - = new TyTy::UintType (mappings.get_next_hir_id (), TyTy::UintType::U32); - auto u64 - = new TyTy::UintType (mappings.get_next_hir_id (), TyTy::UintType::U64); - auto u128 - = new TyTy::UintType (mappings.get_next_hir_id (), TyTy::UintType::U128); - auto i8 = new TyTy::IntType (mappings.get_next_hir_id (), TyTy::IntType::I8); - auto i16 - = new TyTy::IntType (mappings.get_next_hir_id (), TyTy::IntType::I16); - auto i32 - = new TyTy::IntType (mappings.get_next_hir_id (), TyTy::IntType::I32); - auto i64 - = new TyTy::IntType (mappings.get_next_hir_id (), TyTy::IntType::I64); - auto i128 - = new TyTy::IntType (mappings.get_next_hir_id (), TyTy::IntType::I128); - auto rbool = new TyTy::BoolType (mappings.get_next_hir_id ()); - auto f32 - = new TyTy::FloatType (mappings.get_next_hir_id (), TyTy::FloatType::F32); - auto f64 - = new TyTy::FloatType (mappings.get_next_hir_id (), TyTy::FloatType::F64); - auto usize = new TyTy::USizeType (mappings.get_next_hir_id ()); - auto isize = new TyTy::ISizeType (mappings.get_next_hir_id ()); - auto char_tyty = new TyTy::CharType (mappings.get_next_hir_id ()); - auto str = new TyTy::StrType (mappings.get_next_hir_id ()); - auto never = new TyTy::NeverType (mappings.get_next_hir_id ()); - - setup_builtin ("u8", u8); - setup_builtin ("u16", u16); - setup_builtin ("u32", u32); - setup_builtin ("u64", u64); - setup_builtin ("u128", u128); - setup_builtin ("i8", i8); - setup_builtin ("i16", i16); - setup_builtin ("i32", i32); - setup_builtin ("i64", i64); - setup_builtin ("i128", i128); - setup_builtin ("bool", rbool); - setup_builtin ("f32", f32); - setup_builtin ("f64", f64); - setup_builtin ("usize", usize); - setup_builtin ("isize", isize); - setup_builtin ("char", char_tyty); - setup_builtin ("str", str); - - // never type - NodeId never_node_id = setup_builtin ("!", never); - set_never_type_node_id (never_node_id); - - // unit type () - TyTy::TupleType *unit_tyty = TyTy::TupleType::get_unit_type (); - std::vector > elems; - AST::TupleType *unit_type - = new AST::TupleType (std::move (elems), BUILTINS_LOCATION); - builtins.push_back (unit_type); - tyctx->insert_builtin (unit_tyty->get_ref (), unit_type->get_node_id (), - unit_tyty); - set_unit_type_node_id (unit_type->get_node_id ()); -} - -NodeId -Resolver::setup_builtin (const std::string &name, TyTy::BaseType *tyty) -{ - AST::PathIdentSegment seg (name, BUILTINS_LOCATION); - auto typePath = ::std::unique_ptr ( - new AST::TypePathSegment (::std::move (seg), false, BUILTINS_LOCATION)); - ::std::vector< ::std::unique_ptr > segs; - segs.push_back (::std::move (typePath)); - auto builtin_type - = new AST::TypePath (::std::move (segs), BUILTINS_LOCATION, false); - builtins.push_back (builtin_type); - tyctx->insert_builtin (tyty->get_ref (), builtin_type->get_node_id (), tyty); - mappings.insert_node_to_hir (builtin_type->get_node_id (), tyty->get_ref ()); - mappings.insert_canonical_path ( - builtin_type->get_node_id (), - CanonicalPath::new_seg (builtin_type->get_node_id (), name)); - - return builtin_type->get_node_id (); -} - -void -Resolver::insert_resolved_name (NodeId refId, NodeId defId) -{ - rust_assert (!flag_name_resolution_2_0); - rust_assert (resolved_names.find (refId) == resolved_names.end ()); - - resolved_names[refId] = defId; - get_name_scope ().append_reference_for_def (refId, defId); - insert_captured_item (defId); -} - -bool -Resolver::lookup_resolved_name (NodeId refId, NodeId *defId) -{ - rust_assert (!flag_name_resolution_2_0); - auto it = resolved_names.find (refId); - if (it == resolved_names.end ()) - return false; - - *defId = it->second; - return true; -} - -void -Resolver::insert_resolved_type (NodeId refId, NodeId defId) -{ - rust_assert (!flag_name_resolution_2_0); - rust_assert (resolved_types.find (refId) == resolved_types.end ()); - - resolved_types[refId] = defId; - get_type_scope ().append_reference_for_def (refId, defId); -} - -bool -Resolver::lookup_resolved_type (NodeId refId, NodeId *defId) -{ - rust_assert (!flag_name_resolution_2_0); - auto it = resolved_types.find (refId); - if (it == resolved_types.end ()) - return false; - - *defId = it->second; - return true; -} - -void -Resolver::insert_resolved_label (NodeId refId, NodeId defId) -{ - rust_assert (!flag_name_resolution_2_0); - auto it = resolved_labels.find (refId); - rust_assert (it == resolved_labels.end ()); - - resolved_labels[refId] = defId; - get_label_scope ().append_reference_for_def (refId, defId); -} - -bool -Resolver::lookup_resolved_label (NodeId refId, NodeId *defId) -{ - rust_assert (!flag_name_resolution_2_0); - auto it = resolved_labels.find (refId); - if (it == resolved_labels.end ()) - return false; - - *defId = it->second; - return true; -} - -void -Resolver::insert_resolved_macro (NodeId refId, NodeId defId) -{ - rust_assert (!flag_name_resolution_2_0); - auto it = resolved_macros.find (refId); - rust_assert (it == resolved_macros.end ()); - - resolved_labels[refId] = defId; - get_label_scope ().append_reference_for_def (refId, defId); -} - -bool -Resolver::lookup_resolved_macro (NodeId refId, NodeId *defId) -{ - rust_assert (!flag_name_resolution_2_0); - auto it = resolved_macros.find (refId); - if (it == resolved_macros.end ()) - return false; - - *defId = it->second; - return true; -} - -void -Resolver::insert_resolved_misc (NodeId refId, NodeId defId) -{ - rust_assert (!flag_name_resolution_2_0); - auto it = misc_resolved_items.find (refId); - rust_assert (it == misc_resolved_items.end ()); - - misc_resolved_items[refId] = defId; -} - -bool -Resolver::lookup_resolved_misc (NodeId refId, NodeId *defId) -{ - rust_assert (!flag_name_resolution_2_0); - auto it = misc_resolved_items.find (refId); - if (it == misc_resolved_items.end ()) - return false; - - *defId = it->second; - return true; -} - -void -Resolver::push_closure_context (NodeId closure_expr_id) -{ - auto it = closures_capture_mappings.find (closure_expr_id); - rust_assert (it == closures_capture_mappings.end ()); - - closures_capture_mappings.insert ({closure_expr_id, {}}); - closure_context.push_back (closure_expr_id); -} - -void -Resolver::pop_closure_context () -{ - rust_assert (!closure_context.empty ()); - closure_context.pop_back (); -} - -void -Resolver::insert_captured_item (NodeId id) -{ - // nothing to do unless we are in a closure context - if (closure_context.empty ()) - return; - - // check that this is a VAR_DECL? - Scope &name_scope = get_name_scope (); - Rib::ItemType type = Rib::ItemType::Unknown; - bool found = name_scope.lookup_decl_type (id, &type); - if (!found) - return; - - // RIB Function { let a, let b } id = 1; - // RIB Closure { let c } id = 2; - // RIB IfStmt { } id = 3; - // RIB ... { ... } id = 4 - // - // if we have a resolved_node_id of 'a' and the current rib is '3' we know - // this is binding exists in a rib with id < the closure rib id, other wise - // its just a normal binding and we don't care - // - // Problem the node id's dont work like this because the inner most items are - // created first so this means the root will have a larger id and a simple - // less than or greater than check wont work for more complex scoping cases - // but we can use our current rib context to figure this out by checking if - // the rib id the decl we care about exists prior to the rib for the closure - // id - - const Rib *r = nullptr; - bool ok = name_scope.lookup_rib_for_decl (id, &r); - rust_assert (ok); - NodeId decl_rib_node_id = r->get_node_id (); - - // iterate the closure context and add in the mapping for all to handle the - // case of nested closures - for (auto &closure_expr_id : closure_context) - { - if (!decl_needs_capture (decl_rib_node_id, closure_expr_id, name_scope)) - continue; - - // is this a valid binding to take - bool is_var_decl_p = type == Rib::ItemType::Var; - if (!is_var_decl_p) - { - // FIXME is this an error case? - return; - } - - // append it to the context info - auto it = closures_capture_mappings.find (closure_expr_id); - rust_assert (it != closures_capture_mappings.end ()); - - it->second.insert (id); - } -} - -bool -Resolver::decl_needs_capture (NodeId decl_rib_node_id, - NodeId closure_rib_node_id, const Scope &scope) -{ - for (const auto &rib : scope.get_context ()) - { - bool rib_is_closure = rib->get_node_id () == closure_rib_node_id; - bool rib_is_decl = rib->get_node_id () == decl_rib_node_id; - if (rib_is_closure) - return false; - else if (rib_is_decl) - return true; - } - return false; -} - -const std::set & -Resolver::get_captures (NodeId id) const -{ - rust_assert (!flag_name_resolution_2_0); - - auto it = closures_capture_mappings.find (id); - rust_assert (it != closures_capture_mappings.end ()); - return it->second; -} - } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h index a3b34a9f160..c336d3d75e1 100644 --- a/gcc/rust/resolve/rust-name-resolver.h +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -118,181 +118,6 @@ class Scope std::vector stack; }; -class Resolver -{ -public: - static Resolver *get (); - ~Resolver () {} - - // these builtin types - void insert_builtin_types (Rib *r); - - // these will be required for type resolution passes to - // map back to tyty nodes - std::vector &get_builtin_types (); - - void push_new_name_rib (Rib *r); - void push_new_type_rib (Rib *r); - void push_new_label_rib (Rib *r); - void push_new_macro_rib (Rib *r); - - bool find_name_rib (NodeId id, Rib **rib); - bool find_type_rib (NodeId id, Rib **rib); - bool find_label_rib (NodeId id, Rib **rib); - bool find_macro_rib (NodeId id, Rib **rib); - - void insert_resolved_name (NodeId refId, NodeId defId); - bool lookup_resolved_name (NodeId refId, NodeId *defId); - - void insert_resolved_type (NodeId refId, NodeId defId); - bool lookup_resolved_type (NodeId refId, NodeId *defId); - - void insert_resolved_label (NodeId refId, NodeId defId); - bool lookup_resolved_label (NodeId refId, NodeId *defId); - - void insert_resolved_macro (NodeId refId, NodeId defId); - bool lookup_resolved_macro (NodeId refId, NodeId *defId); - - void insert_resolved_misc (NodeId refId, NodeId defId); - bool lookup_resolved_misc (NodeId refId, NodeId *defId); - - // proxy for scoping - Scope &get_name_scope () { return name_scope; } - Scope &get_type_scope () { return type_scope; } - Scope &get_label_scope () { return label_scope; } - Scope &get_macro_scope () { return macro_scope; } - - NodeId get_global_type_node_id () { return global_type_node_id; } - - void set_unit_type_node_id (NodeId id) { unit_ty_node_id = id; } - NodeId get_unit_type_node_id () { return unit_ty_node_id; } - - void set_never_type_node_id (NodeId id) { never_ty_node_id = id; } - NodeId get_never_type_node_id () { return never_ty_node_id; } - - void push_new_module_scope (NodeId module_id) - { - current_module_stack.push_back (module_id); - } - - void pop_module_scope () - { - rust_assert (!current_module_stack.empty ()); - current_module_stack.pop_back (); - } - - NodeId peek_current_module_scope () const - { - rust_assert (!current_module_stack.empty ()); - return current_module_stack.back (); - } - - NodeId peek_crate_module_scope () const - { - rust_assert (!current_module_stack.empty ()); - return current_module_stack.front (); - } - - NodeId peek_parent_module_scope () const - { - rust_assert (current_module_stack.size () > 1); - return current_module_stack.at (current_module_stack.size () - 2); - } - - void push_closure_context (NodeId closure_expr_id); - void pop_closure_context (); - void insert_captured_item (NodeId id); - const std::set &get_captures (NodeId id) const; - - std::string as_debug_string () const - { - std::stringstream ss; - - ss << "Names:\n"; - for (auto &n : name_ribs) - { - ss << "\tNodeID: " << n.first << " Rib: " << n.second->debug_str () - << "\n"; - } - ss << "Types:\n"; - for (auto &n : type_ribs) - { - ss << "\tNodeID: " << n.first << " Rib: " << n.second->debug_str () - << "\n"; - } - ss << "Macros:\n"; - - for (auto &n : macro_ribs) - { - ss << "\tNodeID: " << n.first << " Rib: " << n.second->debug_str () - << "\n"; - } - - ss << "Labels:\n"; - - for (auto &n : label_ribs) - { - ss << "\tNodeID: " << n.first << " Rib: " << n.second->debug_str () - << "\n"; - } - - return ss.str (); - } - -protected: - bool decl_needs_capture (NodeId decl_rib_node_id, NodeId closure_rib_node_id, - const Scope &scope); - -private: - Resolver (); - - void generate_builtins (); - NodeId setup_builtin (const std::string &name, TyTy::BaseType *tyty); - - Analysis::Mappings &mappings; - TypeCheckContext *tyctx; - - std::vector builtins; - - Scope name_scope; - Scope type_scope; - Scope label_scope; - Scope macro_scope; - - NodeId global_type_node_id; - NodeId unit_ty_node_id; - NodeId never_ty_node_id; - - // map a AST Node to a Rib - std::map name_ribs; - std::map type_ribs; - std::map label_ribs; - std::map macro_ribs; - - // Rust uses DefIds to namespace these under a crate_num - // but then it uses the def_collector to assign local_defids - // to each ast node as well. not sure if this is going to fit - // with gcc very well to compile a full crate in one go but we will - // see. - - // these are of the form ref->Def-NodeId - // we need two namespaces one for names and ones for types - std::map resolved_names; - std::map resolved_types; - std::map resolved_labels; - std::map resolved_macros; - - // misc - std::map misc_resolved_items; - - // keep track of the current module scope ids - std::vector current_module_stack; - - // captured variables mappings - std::vector closure_context; - std::map> closures_capture_mappings; -}; - } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index 0930f966e20..2e0ed268586 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -45,7 +45,12 @@ TopLevel::check_multiple_insertion_error ( const location_t &locus, const NodeId node_id) { if (result) - dirty = true; + { + static int n = 0; + if (!dirty && ++n == 38) + rust_error_at (locus, "38th dirty : %s", identifier.as_string ().c_str ()); + dirty = true; + } else if (result.error ().existing != node_id) { rich_location rich_loc (line_table, locus); diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc index 93ce041c252..1088845497e 100644 --- a/gcc/rust/rust-lang.cc +++ b/gcc/rust/rust-lang.cc @@ -34,7 +34,6 @@ #include "selftest.h" #include "rust-cfg-parser.h" #include "rust-privacy-ctx.h" -#include "rust-ast-resolve-item.h" #include "rust-lex.h" #include "optional.h" #include "rust-unicode.h" @@ -442,7 +441,6 @@ run_rust_tests () rust_cfg_parser_test (); rust_privacy_ctx_test (); rust_crate_name_validation_test (); - rust_simple_path_resolve_test (); } } // namespace selftest diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 17f9c06040d..6597007d342 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -29,7 +29,6 @@ #include "rust-lex.h" #include "rust-parse.h" #include "rust-macro-expand.h" -#include "rust-ast-resolve.h" #include "rust-ast-lower.h" #include "rust-hir-type-check.h" #include "rust-privacy-check.h" @@ -46,7 +45,6 @@ #include "rust-imports.h" #include "rust-extern-crate.h" #include "rust-attributes.h" -#include "rust-early-name-resolver.h" #include "rust-name-resolution-context.h" #include "rust-early-name-resolver-2.0.h" #include "rust-late-name-resolver-2.0.h" @@ -613,13 +611,13 @@ Session::compile_crate (const char *filename) if (last_step == CompileOptions::CompileStep::Expansion) return; - AST::CollectLangItems ().go (parsed_crate); - auto name_resolution_ctx = Resolver2_0::NameResolutionContext (); // expansion pipeline stage expansion (parsed_crate, name_resolution_ctx); + AST::CollectLangItems ().go (parsed_crate); + rust_debug ("\033[0;31mSUCCESSFULLY FINISHED EXPANSION \033[0m"); if (options.dump_option_enabled (CompileOptions::EXPANSION_DUMP)) { @@ -643,11 +641,11 @@ Session::compile_crate (const char *filename) if (last_step == CompileOptions::CompileStep::NameResolution) return; + if (saw_errors ()) + return; + // resolution pipeline stage - if (flag_name_resolution_2_0) - Resolver2_0::Late (name_resolution_ctx).go (parsed_crate); - else - Resolver::NameResolution::Resolve (parsed_crate); + Resolver2_0::Late (name_resolution_ctx).go (parsed_crate); if (options.dump_option_enabled (CompileOptions::RESOLUTION_DUMP)) dump_name_resolution (name_resolution_ctx); @@ -928,6 +926,8 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx) // if not, would at least have to configure recursion_limit ExpansionCfg cfg; + cfg.recursion_limit = 40; + auto fixed_point_reached = false; unsigned iterations = 0; @@ -941,24 +941,17 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx) { CfgStrip ().go (crate); // Errors might happen during cfg strip pass - bool visitor_dirty = false; - if (flag_name_resolution_2_0) - { - Resolver2_0::Early early (ctx); - early.go (crate); - macro_errors = early.get_macro_resolve_errors (); - visitor_dirty = early.is_dirty (); - } - else - Resolver::EarlyNameResolver ().go (crate); + Resolver2_0::Early early (ctx); + early.go (crate); + macro_errors = early.get_macro_resolve_errors (); if (saw_errors ()) break; ExpandVisitor (expander).go (crate); - fixed_point_reached = !expander.has_changed () && !visitor_dirty; + fixed_point_reached = !expander.has_changed () && !early.is_dirty (); expander.reset_changed_state (); iterations++; @@ -993,8 +986,7 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx) // HACK: we may need a final TopLevel pass // however, this should not count towards the recursion limit // and we don't need a full Early pass - if (flag_name_resolution_2_0) - Resolver2_0::TopLevel (ctx).go (crate); + Resolver2_0::TopLevel (ctx).go (crate); } // error reporting - check unused macros, get missing fragment specifiers @@ -1190,14 +1182,6 @@ Session::load_extern_crate (const std::string &crate_name, location_t locus) mappings.insert_bang_proc_macros (crate_num, bang_macros); mappings.insert_derive_proc_macros (crate_num, derive_macros); - // if flag_name_resolution_2_0 is enabled - // then we perform resolution later - if (!flag_name_resolution_2_0) - { - // name resolve it - Resolver::NameResolution::Resolve (parsed_crate); - } - // always restore the crate_num mappings.set_current_crate (saved_crate_num); diff --git a/gcc/rust/util/rust-attribute-values.h b/gcc/rust/util/rust-attribute-values.h index 09ef5664795..4377bc7f576 100644 --- a/gcc/rust/util/rust-attribute-values.h +++ b/gcc/rust/util/rust-attribute-values.h @@ -37,6 +37,7 @@ class Attributes static constexpr auto &MUST_USE = "must_use"; static constexpr auto &LANG = "lang"; static constexpr auto &LINK_SECTION = "link_section"; + static constexpr auto &LINK_NAME = "link_name"; static constexpr auto &NO_MANGLE = "no_mangle"; static constexpr auto &REPR = "repr"; static constexpr auto &RUSTC_BUILTIN_MACRO = "rustc_builtin_macro"; @@ -60,6 +61,7 @@ class Attributes static constexpr auto &RUSTC_PROMOTABLE = "rustc_promotable"; static constexpr auto &RUSTC_CONST_STABLE = "rustc_const_stable"; static constexpr auto &RUSTC_CONST_UNSTABLE = "rustc_const_unstable"; + static constexpr auto &RUSTC_ALLOW_CONST_FN_UNSTABLE = "rustc_allow_const_fn_unstable"; static constexpr auto &RUSTC_SPECIALIZATION_TRAIT = "rustc_specialization_trait"; @@ -88,7 +90,7 @@ class Attributes static constexpr auto &TEST = "test"; - static constexpr auto &SIMD_TEST = "simd_test"; + static constexpr auto &RUSTC_ARGS_REQUIRED_CONST = "rustc_args_required_const"; }; } // namespace Values } // namespace Rust diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc index 0c957fb2014..47c8d1b23f9 100644 --- a/gcc/rust/util/rust-attributes.cc +++ b/gcc/rust/util/rust-attributes.cc @@ -54,6 +54,7 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::MUST_USE, STATIC_ANALYSIS}, {Attrs::LANG, HIR_LOWERING}, {Attrs::LINK_SECTION, CODE_GENERATION}, + {Attrs::LINK_NAME, CODE_GENERATION}, {Attrs::NO_MANGLE, CODE_GENERATION}, {Attrs::REPR, CODE_GENERATION}, {Attrs::RUSTC_BUILTIN_MACRO, EXPANSION}, @@ -78,6 +79,7 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION}, {Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS}, {Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS}, + {Attrs::RUSTC_ALLOW_CONST_FN_UNSTABLE, STATIC_ANALYSIS}, {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION}, {Attrs::TRACK_CALLER, CODE_GENERATION}, {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK}, @@ -98,7 +100,10 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::RUSTFMT, EXTERNAL}, {Attrs::TEST, CODE_GENERATION}, - {Attrs::SIMD_TEST, CODE_GENERATION}}; + + // TODO: be careful about calling functions marked with this? + {Attrs::RUSTC_ARGS_REQUIRED_CONST, CODE_GENERATION}, +}; BuiltinAttributeMappings * BuiltinAttributeMappings::get () @@ -392,7 +397,7 @@ AttributeChecker::visit (AST::MetaItemLitExpr &) {} void -AttributeChecker::visit (AST::MetaItemPathLit &) +AttributeChecker::visit (AST::MetaItemPathExpr &) {} void diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h index 7c7a1fc3f6b..db8fe234778 100644 --- a/gcc/rust/util/rust-attributes.h +++ b/gcc/rust/util/rust-attributes.h @@ -130,7 +130,7 @@ class AttributeChecker : public AST::DefaultASTVisitor void visit (AST::AttrInputLiteral &attr_input) override; void visit (AST::AttrInputMacro &attr_input) override; void visit (AST::MetaItemLitExpr &meta_item) override; - void visit (AST::MetaItemPathLit &meta_item) override; + void visit (AST::MetaItemPathExpr &meta_item) override; void visit (AST::BorrowExpr &expr) override; void visit (AST::DereferenceExpr &expr) override; void visit (AST::ErrorPropagationExpr &expr) override; diff --git a/gcc/rust/util/rust-unwrap-segment.h b/gcc/rust/util/rust-unwrap-segment.h index af3a237ea28..e9d2381ca9a 100644 --- a/gcc/rust/util/rust-unwrap-segment.h +++ b/gcc/rust/util/rust-unwrap-segment.h @@ -115,4 +115,20 @@ unwrap_segment_get_lang_item (const std::unique_ptr &ptr) return unwrap_segment_get_lang_item (*ptr); } +/** + * Used to output a path in error messages + */ + +inline static std::string +unwrap_segment_error_string (const AST::TypePath &path) +{ + return path.make_debug_string (); +} + +inline static std::string +unwrap_segment_error_string (const AST::PathInExpression &path) +{ + return path.as_simple_path ().as_string (); +} + } // namespace Rust