From patchwork Thu Aug 1 14:57:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arthur Cohen X-Patchwork-Id: 1967818 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=embecosm.com header.i=@embecosm.com header.a=rsa-sha256 header.s=google header.b=aGoXP8gN; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WZXwn2d98z1yZv for ; Fri, 2 Aug 2024 01:30:49 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9518B3860757 for ; Thu, 1 Aug 2024 15:30:47 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-ed1-x532.google.com (mail-ed1-x532.google.com [IPv6:2a00:1450:4864:20::532]) by sourceware.org (Postfix) with ESMTPS id EFD35385E82F for ; Thu, 1 Aug 2024 14:59:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org EFD35385E82F Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org EFD35385E82F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::532 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722524427; cv=none; b=OL8MwXPqRaU+a2cx4Kc+bZDPNorKAIpd/XmUUbe4wKXfx9EHUjIlXY4GO/ZbmPPDOAzcAltRUjtlNHrASKCGG3U6ifdoadZcMnuO6VUBaTivxBrJqj/PZ0mCsU3XAkA/3xHVxpNxzENdtJGQrCFaflS3l7+5a6QbK0PHL4gYS+w= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1722524427; c=relaxed/simple; bh=3kkE0W2G+8Utln3YAG0EWqqLfM3SLXeOL4oItEyp5tM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Nxc76ARE2bm8LEQxrdAzO6lVB7SWP5pweY/nsDsbHNLigtkTS1c6Wn5umrrqS2cjaNUyfx5Lts1Ach0FRhV817H7OrbZop7q4LV58f1F1p33SEJOhdKHQIny6Nh8IVELzSdkiTgUkIhIGh8bZPEyHYfyf4k5lLpIVa72LmoE5yw= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-ed1-x532.google.com with SMTP id 4fb4d7f45d1cf-5a156557026so9574417a12.2 for ; Thu, 01 Aug 2024 07:59:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; t=1722524379; x=1723129179; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=S/aumA54HzMFD7ScCEGM5JnXteofB7T013zin7XHnzg=; b=aGoXP8gNmHj8XS7yrC3GVwX7vbXt5C1FB6Q3nTzZDUrGRVbunQvqwgsTuBBOsUtPQI ZNAxZmnMQe4MLnrgkIqPA0/AJZGbRKUaPWOt+FGPJITW3sERwaXsDUQ9RF17DaMZTR5s tWQU8nDF7b0SZgjV03BQc0wxaY2DEScvU/KH/NoFHamZH0d23YriLHaz6UJBYFBFp078 ulvVK1LhmarO7+IyNQEOjo8yTcEzdWw5oj3039ThOB9t/KywqT87jWP6CO2L21lNUIVm 8CRdcmqSb85StGHANlvAhBhKHVPSYVVNVSEDWQIMuzhst7Dq4bn76XbIY+TiWOtLE3os fj4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722524379; x=1723129179; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=S/aumA54HzMFD7ScCEGM5JnXteofB7T013zin7XHnzg=; b=eCRXBvMJa4iha1P4bGtO+hQZKXxr9IvpjG8dFw0mbMQZGZ5a3y2UlpNw0DGo8JmjMe SHpzJv/7HIn7lQ3JCeubaEqYBHou0uMycUyHEbWotpFmNAzQs3vanmymY4X4DufhmW2X h/OTQoCKNy3IaMTkBHh+Smw/BycMu4KtAorXMCehaAPmXHErrFgEHAfHz1YLX7XNq7qt hEMO6BGxZy8bS8WWxE9md1DMBTd3jby9R3950yqatrYzbHpxZesSNM+id6OJyaNLfN2j yP1UodvFcsJQjXUQzYaS9EaopzKmYjUXxe+dooy1LjKYrlGA79ZyhsiVllQTm//+qY67 M4yA== X-Gm-Message-State: AOJu0YzxgC9XJvn8ocTpI5+WMyRXzhu/xGTlI+0nTDbj2sg7bJ2WKe2a TMBrDKIBAarKf1Bs1R9LrB4iLV/5HsvP0F3rs9CL+NgS197FtoFpZYyQbYsE/G8oh9nJuq5SX63 zeChh X-Google-Smtp-Source: AGHT+IEdDoOlUlY2O78EnsVlMNbL3esriq6/KnIhMlPgwb5aHwRKPnOgbCuPjkfGOyeaq0qHr3p4fQ== X-Received: by 2002:a05:6402:2d5:b0:5af:7b5a:81a0 with SMTP id 4fb4d7f45d1cf-5b7f37ed775mr433553a12.6.1722524379319; Thu, 01 Aug 2024 07:59:39 -0700 (PDT) Received: from platypus.lan ([2a04:cec2:9:dc84:3622:6733:ff49:ee91]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5ac63590592sm10252456a12.25.2024.08.01.07.59.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Aug 2024 07:59:38 -0700 (PDT) From: Arthur Cohen To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org, Pierre-Emmanuel Patry Subject: [PATCH 074/125] gccrs: Add name resolution for on globbing use decl Date: Thu, 1 Aug 2024 16:57:10 +0200 Message-ID: <20240801145809.366388-76-arthur.cohen@embecosm.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240801145809.366388-2-arthur.cohen@embecosm.com> References: <20240801145809.366388-2-arthur.cohen@embecosm.com> MIME-Version: 1.0 X-Spam-Status: No, score=-14.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org From: Pierre-Emmanuel Patry This is the first part of the code required to enable globbing on use declarations. gcc/rust/ChangeLog: * resolve/rust-toplevel-name-resolver-2.0.cc (GlobbingVisitor::visit): Insert names into their namespace. (TopLevel::visit): Insert ast module. (TopLevel::handle_use_dec): Resolve use declaration. (TopLevel::handle_use_glob): Use globbing visitor. (flatten_list): Use globbing path vector. (flatten_glob): Likewise. (flatten): Likewise. (prefix_subpaths): Add a function to prefix subpath. * resolve/rust-toplevel-name-resolver-2.0.h (class GlobbingVisitor): Add globbing visitor. * util/rust-hir-map.cc (Mappings::insert_ast_module): Add function to insert module in module hashmap. (Mappings::lookup_ast_module): Add function to retrieve ast module. * util/rust-hir-map.h: Add module map and getter/setter prototypes. Signed-off-by: Pierre-Emmanuel Patry --- .../rust-toplevel-name-resolver-2.0.cc | 179 +++++++++++++++--- .../resolve/rust-toplevel-name-resolver-2.0.h | 23 +++ gcc/rust/util/rust-hir-map.cc | 19 ++ gcc/rust/util/rust-hir-map.h | 3 + 4 files changed, 199 insertions(+), 25 deletions(-) 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 5e6f5e9bd78..3122d41412f 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -25,6 +25,87 @@ namespace Rust { namespace Resolver2_0 { +void +GlobbingVisitor::visit (AST::Module &module) +{ + if (module.get_visibility ().is_public ()) + ctx.insert (module.get_name (), module.get_node_id (), Namespace::Types); +} + +void +GlobbingVisitor::visit (AST::MacroRulesDefinition ¯o) +{ + if (macro.get_visibility ().is_public ()) + ctx.insert (macro.get_rule_name (), macro.get_node_id (), + Namespace::Macros); +} + +void +GlobbingVisitor::visit (AST::Function &function) +{ + if (function.get_visibility ().is_public ()) + ctx.insert (function.get_function_name (), function.get_node_id (), + Namespace::Values); +} + +void +GlobbingVisitor::visit (AST::StaticItem &static_item) +{ + if (static_item.get_visibility ().is_public ()) + ctx.insert (static_item.get_identifier (), static_item.get_node_id (), + Namespace::Values); +} + +void +GlobbingVisitor::visit (AST::StructStruct &struct_item) +{ + if (struct_item.get_visibility ().is_public ()) + ctx.insert (struct_item.get_identifier (), struct_item.get_node_id (), + Namespace::Values); +} + +void +GlobbingVisitor::visit (AST::TupleStruct &tuple_struct) +{ + if (tuple_struct.get_visibility ().is_public ()) + ctx.insert (tuple_struct.get_identifier (), tuple_struct.get_node_id (), + Namespace::Values); +} + +void +GlobbingVisitor::visit (AST::Enum &enum_item) +{ + if (enum_item.get_visibility ().is_public ()) + ctx.insert (enum_item.get_identifier (), enum_item.get_node_id (), + Namespace::Values); +} + +void +GlobbingVisitor::visit (AST::Union &union_item) +{ + if (union_item.get_visibility ().is_public ()) + ctx.insert (union_item.get_identifier (), union_item.get_node_id (), + Namespace::Values); +} + +void +GlobbingVisitor::visit (AST::ConstantItem &const_item) +{ + if (const_item.get_visibility ().is_public ()) + ctx.insert (const_item.get_identifier (), const_item.get_node_id (), + Namespace::Values); +} + +void +GlobbingVisitor::visit (AST::ExternCrate &crate) +{} + +void +GlobbingVisitor::visit (AST::UseDeclaration &use) +{ + // Handle cycles ? +} + TopLevel::TopLevel (NameResolutionContext &resolver) : DefaultResolver (resolver) {} @@ -81,6 +162,10 @@ TopLevel::visit (AST::Module &module) ctx.scoped (Rib::Kind::Module, module.get_node_id (), sub_visitor, module.get_name ()); + + if (Analysis::Mappings::get ()->lookup_ast_module (module.get_node_id ()) + == tl::nullopt) + Analysis::Mappings::get ()->insert_ast_module (&module); } template @@ -302,13 +387,26 @@ TopLevel::visit (AST::ConstantItem &const_item) } bool -TopLevel::handle_use_dec (AST::SimplePath path) +TopLevel::handle_use_glob (AST::SimplePath glob) { - // TODO: Glob imports can get shadowed by regular imports and regular items. - // So we need to store them in a specific way in the ForeverStack - which can - // also probably be used by labels and macros etc. Like store it as a - // `Shadowable(NodeId)` instead of just a `NodeId` + auto resolved = ctx.types.resolve_path (glob.get_segments ()); + if (!resolved.has_value ()) + return false; + + auto result = Analysis::Mappings::get ()->lookup_ast_module (*resolved); + + if (!result.has_value ()) + return false; + + GlobbingVisitor gvisitor (ctx); + gvisitor.visit (*result.value ()); + + return true; +} +bool +TopLevel::handle_use_dec (AST::SimplePath path) +{ auto locus = path.get_final_segment ().get_locus (); auto declared_name = path.get_final_segment ().as_string (); @@ -377,14 +475,17 @@ static void flatten_rebind (const AST::UseTreeRebind &glob, std::vector &paths); static void -flatten_list (const AST::UseTreeList &glob, - std::vector &paths); +flatten_list (const AST::UseTreeList &glob, std::vector &paths, + std::vector &glob_paths, + NameResolutionContext &ctx); static void flatten_glob (const AST::UseTreeGlob &glob, - std::vector &paths); + std::vector &glob_paths, + NameResolutionContext &ctx); static void -flatten (const AST::UseTree *tree, std::vector &paths) +flatten (const AST::UseTree *tree, std::vector &paths, + std::vector &glob_paths, NameResolutionContext &ctx) { switch (tree->get_kind ()) { @@ -395,13 +496,12 @@ flatten (const AST::UseTree *tree, std::vector &paths) } case AST::UseTree::List: { auto list = static_cast (tree); - flatten_list (*list, paths); + flatten_list (*list, paths, glob_paths, ctx); break; } case AST::UseTree::Glob: { - rust_sorry_at (tree->get_locus (), "cannot resolve glob imports yet"); auto glob = static_cast (tree); - flatten_glob (*glob, paths); + flatten_glob (*glob, glob_paths, ctx); break; } break; @@ -432,8 +532,28 @@ flatten_rebind (const AST::UseTreeRebind &rebind, } } +/** Prefix a list of subpath + * @param prefix A prefix for all subpath + * @param subs List of subpath to prefix + * @param size List where results should be stored + */ +static void +prefix_subpaths (AST::SimplePath prefix, std::vector subs, + std::vector &results) +{ + for (auto &sub : subs) + { + auto new_path = prefix; + std::copy (sub.get_segments ().begin (), sub.get_segments ().end (), + std::back_inserter (new_path.get_segments ())); + results.emplace_back (new_path); + } +} + static void -flatten_list (const AST::UseTreeList &list, std::vector &paths) +flatten_list (const AST::UseTreeList &list, std::vector &paths, + std::vector &glob_paths, + NameResolutionContext &ctx) { auto prefix = AST::SimplePath::create_empty (); if (list.has_path ()) @@ -442,43 +562,52 @@ flatten_list (const AST::UseTreeList &list, std::vector &paths) for (const auto &tree : list.get_trees ()) { auto sub_paths = std::vector (); - flatten (tree.get (), sub_paths); - - for (auto &sub_path : sub_paths) - { - auto new_path = prefix; - std::copy (sub_path.get_segments ().begin (), - sub_path.get_segments ().end (), - std::back_inserter (new_path.get_segments ())); + auto sub_globs = std::vector (); + flatten (tree.get (), sub_paths, sub_globs, ctx); - paths.emplace_back (new_path); - } + prefix_subpaths (prefix, sub_paths, paths); + prefix_subpaths (prefix, sub_globs, glob_paths); } } static void -flatten_glob (const AST::UseTreeGlob &glob, std::vector &paths) +flatten_glob (const AST::UseTreeGlob &glob, std::vector &paths, + NameResolutionContext &ctx) { if (glob.has_path ()) paths.emplace_back (glob.get_path ()); + + // (PE): Get path rib + auto rib = ctx.values.resolve_path (glob.get_path ().get_segments ()) + .and_then ([&] (NodeId id) { return ctx.values.to_rib (id); }); + if (rib.has_value ()) + { + auto value = rib.value ().get_values (); + } } void TopLevel::visit (AST::UseDeclaration &use) { auto paths = std::vector (); + auto glob_path = std::vector (); // FIXME: How do we handle `use foo::{self}` imports? Some beforehand cleanup? // How do we handle module imports in general? Should they get added to all // namespaces? const auto &tree = use.get_tree (); - flatten (tree.get (), paths); + flatten (tree.get (), paths, glob_path, this->ctx); for (auto &path : paths) if (!handle_use_dec (path)) rust_error_at (path.get_final_segment ().get_locus (), ErrorCode::E0433, "unresolved import %qs", path.as_string ().c_str ()); + + for (auto &glob : glob_path) + if (!handle_use_glob (glob)) + rust_error_at (glob.get_final_segment ().get_locus (), ErrorCode::E0433, + "unresolved import %qs", glob.as_string ().c_str ()); } } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h index 0a766bab259..31535a9b22e 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h @@ -26,6 +26,28 @@ namespace Rust { namespace Resolver2_0 { +class GlobbingVisitor : public AST::DefaultASTVisitor +{ + using AST::DefaultASTVisitor::visit; + +public: + GlobbingVisitor (NameResolutionContext &ctx) : ctx (ctx) {} + + void visit (AST::Module &module) override; + void visit (AST::MacroRulesDefinition ¯o) override; + void visit (AST::Function &function) override; + void visit (AST::StaticItem &static_item) override; + void visit (AST::StructStruct &struct_item) override; + void visit (AST::TupleStruct &tuple_struct) override; + void visit (AST::Enum &enum_item) override; + void visit (AST::Union &union_item) override; + void visit (AST::ConstantItem &const_item) override; + void visit (AST::ExternCrate &crate) override; + void visit (AST::UseDeclaration &use) override; + +private: + NameResolutionContext &ctx; +}; /** * The `TopLevel` visitor takes care of collecting all the definitions in a * crate, and inserting them into the proper namespaces. These definitions can @@ -85,6 +107,7 @@ private: // UseTreeList for example // FIXME: Should that return `found`? bool handle_use_dec (AST::SimplePath path); + bool handle_use_glob (AST::SimplePath glob); void visit (AST::UseDeclaration &use) override; }; diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index c62c11189ae..05b26d64069 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -17,9 +17,11 @@ // . #include "rust-hir-map.h" +#include "optional.h" #include "rust-ast-full.h" #include "rust-diagnostics.h" #include "rust-hir-full.h" +#include "rust-item.h" #include "rust-macro-builtins.h" #include "rust-mapping-common.h" #include "rust-attribute-values.h" @@ -1158,6 +1160,23 @@ Mappings::lookup_module_children (NodeId module) return it->second; } +void +Mappings::insert_ast_module (AST::Module *module) +{ + rust_assert (modules.find (module->get_node_id ()) == modules.end ()); + modules[module->get_node_id ()] = module; +} + +tl::optional +Mappings::lookup_ast_module (NodeId id) +{ + auto it = modules.find (id); + if (it == modules.end ()) + return tl::nullopt; + + return {it->second}; +} + void Mappings::insert_module_child_item (NodeId module, Resolver::CanonicalPath child) diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 927c01251db..92af0673f95 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -328,6 +328,8 @@ public: void insert_visibility (NodeId id, Privacy::ModuleVisibility visibility); bool lookup_visibility (NodeId id, Privacy::ModuleVisibility &def); + void insert_ast_module (AST::Module *); + tl::optional lookup_ast_module (NodeId id); void insert_module_child (NodeId module, NodeId child); tl::optional &> lookup_module_children (NodeId module); @@ -427,6 +429,7 @@ private: std::map> module_child_map; std::map> module_child_items; std::map child_to_parent_module_map; + std::map modules; // AST mappings std::map ast_item_mappings;