// 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-default-resolver.h" #include "rust-ast-full.h" #include "rust-ast-visitor.h" #include "rust-item.h" namespace Rust { namespace Resolver2_0 { void DefaultResolver::visit (AST::Crate &crate) { auto inner_fn = [this, &crate] () { AST::DefaultASTVisitor::visit (crate); }; auto &mappings = Analysis::Mappings::get (); auto crate_num = mappings.lookup_crate_num (crate.get_node_id ()); rust_assert (crate_num.has_value ()); auto crate_name = mappings.get_crate_name (*crate_num); rust_assert (crate_name.has_value ()); ctx.canonical_ctx.scope_crate (crate.get_node_id (), *crate_name, inner_fn); } void DefaultResolver::visit (AST::BlockExpr &expr) { // extracting the lambda from the `scoped` call otherwise the code looks like // a hot turd thanks to our .clang-format auto inner_fn = [this, &expr] () { AST::DefaultASTVisitor::visit (expr); }; ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), inner_fn); } void DefaultResolver::visit (AST::Module &module) { auto item_fn_1 = [this, &module] () { AST::DefaultASTVisitor::visit (module); }; auto item_fn_2 = [this, &module, &item_fn_1] () { ctx.canonical_ctx.scope (module.get_node_id (), module.get_name (), std::move (item_fn_1)); }; ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn_2, module.get_name ()); } void DefaultResolver::visit (AST::Function &function) { auto def_fn_1 = [this, &function] () { AST::DefaultASTVisitor::visit (function); }; auto def_fn_2 = [this, &function, &def_fn_1] () { ctx.canonical_ctx.scope (function.get_node_id (), function.get_function_name (), std::move (def_fn_1)); }; ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn_2, function.get_function_name ()); } void DefaultResolver::visit (AST::ForLoopExpr &expr) { ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), [this, &expr] () { AST::DefaultASTVisitor::visit (expr); }); } void DefaultResolver::visit_if_let_patterns (AST::IfLetExpr &expr) { for (auto &pattern : expr.get_patterns ()) visit (pattern); } void DefaultResolver::visit (AST::IfLetExpr &expr) { auto inner_vis = [this, &expr] () { visit_if_let_patterns (expr); visit (expr.get_if_block ()); }; visit_outer_attrs (expr); visit (expr.get_value_expr ()); ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), inner_vis); } void DefaultResolver::visit (AST::IfLetExprConseqElse &expr) { DefaultResolver::visit (static_cast (expr)); visit (expr.get_else_block ()); } void DefaultResolver::visit (AST::Trait &trait) { visit_outer_attrs (trait); visit (trait.get_visibility ()); visit_inner_attrs (trait); auto inner_fn_1 = [this, &trait] () { for (auto &item : trait.get_trait_items ()) visit (item); }; auto inner_fn_2 = [this, &trait, &inner_fn_1] () { visit (trait.get_implicit_self ()); for (auto &generic : trait.get_generic_params ()) visit (generic); if (trait.has_where_clause ()) visit (trait.get_where_clause ()); for (auto &bound : trait.get_type_param_bounds ()) visit (bound); ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn_1); }; auto inner_fn_3 = [this, &trait, &inner_fn_2] () { ctx.canonical_ctx.scope (trait.get_node_id (), trait.get_identifier (), std::move (inner_fn_2)); }; ctx.scoped (Rib::Kind::Generics, trait.get_node_id (), inner_fn_3, trait.get_identifier () /* FIXME: Is that valid?*/); } void DefaultResolver::visit (AST::InherentImpl &impl) { visit_outer_attrs (impl); visit (impl.get_visibility ()); visit_inner_attrs (impl); auto inner_fn_1 = [this, &impl] () { for (auto &item : impl.get_impl_items ()) visit (item); }; auto inner_fn_2 = [this, &impl, &inner_fn_1] () { maybe_insert_big_self (impl); for (auto &generic : impl.get_generic_params ()) visit (generic); if (impl.has_where_clause ()) visit (impl.get_where_clause ()); visit_impl_type (impl.get_type ()); ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1); }; auto inner_fn_3 = [this, &impl, &inner_fn_2] () { ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2)); }; ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3); } void DefaultResolver::visit (AST::TraitImpl &impl) { visit_outer_attrs (impl); visit (impl.get_visibility ()); visit_inner_attrs (impl); auto inner_fn_1 = [this, &impl] () { for (auto &item : impl.get_impl_items ()) visit (item); }; auto inner_fn_2 = [this, &impl, &inner_fn_1] () { maybe_insert_big_self (impl); for (auto &generic : impl.get_generic_params ()) visit (generic); if (impl.has_where_clause ()) visit (impl.get_where_clause ()); visit_impl_type (impl.get_type ()); visit (impl.get_trait_path ()); ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1); }; auto inner_fn_3 = [this, &impl, &inner_fn_2] () { ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2)); }; ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3); } void DefaultResolver::visit (AST::StructStruct &type) { auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; auto inner_fn_2 = [this, &type, &inner_fn_1] () { ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (), std::move (inner_fn_1)); }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), inner_fn_2, type.get_struct_name ()); } void DefaultResolver::visit (AST::TupleStruct &type) { auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; auto inner_fn_2 = [this, &type, &inner_fn_1] () { ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (), std::move (inner_fn_1)); }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), inner_fn_2, type.get_struct_name ()); } void DefaultResolver::visit (AST::EnumItem &item) { auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), inner_fn); } void DefaultResolver::visit (AST::EnumItemTuple &item) { auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), inner_fn); } void DefaultResolver::visit (AST::EnumItemStruct &item) { auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), inner_fn); } void DefaultResolver::visit (AST::EnumItemDiscriminant &item) { auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), inner_fn); } void DefaultResolver::visit (AST::Enum &type) { auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; auto inner_fn_2 = [this, &type, &inner_fn_1] () { ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (), std::move (inner_fn_1)); }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), inner_fn_2, type.get_identifier ()); } void DefaultResolver::visit (AST::Union &type) { auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; auto inner_fn_2 = [this, &type, &inner_fn_1] () { ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (), std::move (inner_fn_1)); }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), inner_fn_2, type.get_identifier ()); } void DefaultResolver::visit (AST::TypeAlias &type) { auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; auto inner_fn_2 = [this, &type, &inner_fn_1] () { ctx.canonical_ctx.scope (type.get_node_id (), type.get_new_type_name (), std::move (inner_fn_1)); }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), inner_fn_2, type.get_new_type_name ()); } void DefaultResolver::visit_closure_params (AST::ClosureExpr &expr) { for (auto ¶m : expr.get_params ()) visit (param); } void DefaultResolver::visit (AST::ClosureExpr &expr) { auto expr_fn = [this, &expr] () { visit_closure_params (expr); visit (expr.get_definition_expr ()); }; visit_outer_attrs (expr); ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), expr_fn); } void DefaultResolver::visit (AST::ClosureExprInner &expr) { if (expr.is_marked_for_strip ()) return; visit (static_cast (expr)); } void DefaultResolver::visit (AST::ClosureExprInnerTyped &expr) { if (expr.is_marked_for_strip ()) return; visit (static_cast (expr)); visit (expr.get_return_type ()); } void DefaultResolver::visit (AST::MatchExpr &expr) { if (expr.is_marked_for_strip ()) return; AST::DefaultASTVisitor::visit (expr); } void DefaultResolver::visit (AST::ConstantItem &item) { auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; auto expr_vis_2 = [this, &item, &expr_vis_1] () { ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), std::move (expr_vis_1)); }; // FIXME: Why do we need a Rib here? ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2); } void DefaultResolver::visit (AST::StaticItem &item) { auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; auto expr_vis_2 = [this, &item, &expr_vis_1] () { ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), std::move (expr_vis_1)); }; // FIXME: Why do we need a Rib here? ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2); } void DefaultResolver::visit (AST::TypeParam ¶m) { auto expr_vis = [this, ¶m] () { AST::DefaultASTVisitor::visit (param); }; ctx.scoped (Rib::Kind::ForwardTypeParamBan, param.get_node_id (), expr_vis); } void DefaultResolver::visit_extern_crate (AST::ExternCrate &extern_crate, AST::Crate &crate, CrateNum num) { visit (crate); } void DefaultResolver::visit (AST::ExternCrate &crate) { auto &mappings = Analysis::Mappings::get (); auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ()); if (!num_opt) { rust_error_at (crate.get_locus (), "unknown crate %qs", crate.get_referenced_crate ().c_str ()); return; } CrateNum num = *num_opt; AST::Crate &referenced_crate = mappings.get_ast_crate (num); auto sub_visitor_1 = [&, this] () { visit_extern_crate (crate, referenced_crate, num); }; auto sub_visitor_2 = [&] () { ctx.canonical_ctx.scope_crate (referenced_crate.get_node_id (), crate.get_referenced_crate (), std::move (sub_visitor_1)); }; if (crate.has_as_clause ()) ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (), sub_visitor_2, crate.get_as_clause ()); else ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (), sub_visitor_2, crate.get_referenced_crate ()); } } // namespace Resolver2_0 } // namespace Rust