From 8c6d4da671a77f797701da718f9e25ddefb25f74 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 24 Aug 2023 17:49:42 +0200 Subject: [PATCH 01/26] immutable nrctx: new --- gcc/rust/Make-lang.in | 1 + .../rust-immutable-name-resolution-context.cc | 56 +++++++++++++++++++ .../rust-immutable-name-resolution-context.h | 55 ++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 gcc/rust/resolve/rust-immutable-name-resolution-context.cc create mode 100644 gcc/rust/resolve/rust-immutable-name-resolution-context.h diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 9f91c5b686fd..35169d15e045 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -117,6 +117,7 @@ GRS_OBJS = \ rust/rust-toplevel-name-resolver-2.0.o \ rust/rust-early-name-resolver-2.0.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 \ diff --git a/gcc/rust/resolve/rust-immutable-name-resolution-context.cc b/gcc/rust/resolve/rust-immutable-name-resolution-context.cc new file mode 100644 index 000000000000..3894e27cd202 --- /dev/null +++ b/gcc/rust/resolve/rust-immutable-name-resolution-context.cc @@ -0,0 +1,56 @@ +// Copyright (C) 2020-2023 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-immutable-name-resolution-context.h" + +namespace Rust { +namespace Resolver2_0 { + +static ImmutableNameResolutionContext *instance = nullptr; + +const ImmutableNameResolutionContext & +ImmutableNameResolutionContext::init (const NameResolutionContext &ctx) +{ + rust_assert (!instance); + + instance = new ImmutableNameResolutionContext (ctx); + + return *instance; +} + +const ImmutableNameResolutionContext & +ImmutableNameResolutionContext::get () +{ + rust_assert (instance); + + return *instance; +} + +const NameResolutionContext & +ImmutableNameResolutionContext::resolver () const +{ + return ctx; +} + +ImmutableNameResolutionContext::ImmutableNameResolutionContext ( + const NameResolutionContext &ctx) + : ctx (ctx) +{} + +} // namespace Resolver2_0 +} // namespace Rust diff --git a/gcc/rust/resolve/rust-immutable-name-resolution-context.h b/gcc/rust/resolve/rust-immutable-name-resolution-context.h new file mode 100644 index 000000000000..9f9e7764cd2a --- /dev/null +++ b/gcc/rust/resolve/rust-immutable-name-resolution-context.h @@ -0,0 +1,55 @@ +// Copyright (C) 2020-2023 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_IMMUTABLE_NRCTX_H +#define RUST_IMMUTABLE_NRCTX_H + +#include "rust-name-resolution-context.h" + +namespace Rust { +namespace Resolver2_0 { + +/** + * Once the name resolution pass is complete, the typechecker can access it + * + * FIXME: More documentation + */ +class ImmutableNameResolutionContext +{ +public: + /** FIXME: Documentation */ + static const ImmutableNameResolutionContext & + init (const NameResolutionContext &ctx); + + /** FIXME: Documentation */ + static const ImmutableNameResolutionContext &get (); + + const NameResolutionContext &resolver () const; + +private: + ImmutableNameResolutionContext (const NameResolutionContext &ctx); + ImmutableNameResolutionContext (const ImmutableNameResolutionContext &other) + = default; + + const NameResolutionContext &ctx; +}; + +} // namespace Resolver2_0 +} // namespace Rust + +#endif //! RUST_IMMUTABLE_NRCTX_H From ab87d0125e661f827fc37ca451bd4f39f3d3012c Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 4 Aug 2023 11:11:13 +0200 Subject: [PATCH 02/26] sesh: [wip][from here tests don't work] Add late name resolution 2.0 --- gcc/rust/rust-session-manager.cc | 14 +++++++++----- gcc/rust/rust-session-manager.h | 3 ++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 33aa13364807..028aed968cf6 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -42,6 +42,7 @@ #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" #include "rust-cfg-strip.h" #include "rust-expand-visitor.h" #include "rust-unicode.h" @@ -590,8 +591,10 @@ Session::compile_crate (const char *filename) if (last_step == CompileOptions::CompileStep::Expansion) return; + auto name_resolution_ctx = Resolver2_0::NameResolutionContext (); // expansion pipeline stage - expansion (parsed_crate); + + expansion (parsed_crate, name_resolution_ctx); rust_debug ("\033[0;31mSUCCESSFULLY FINISHED EXPANSION \033[0m"); if (options.dump_option_enabled (CompileOptions::EXPANSION_DUMP)) { @@ -616,7 +619,10 @@ Session::compile_crate (const char *filename) return; // resolution pipeline stage - Resolver::NameResolution::Resolve (parsed_crate); + if (flag_name_resolution_2_0) + Resolver2_0::Late (name_resolution_ctx).go (parsed_crate); + else + Resolver::NameResolution::Resolve (parsed_crate); if (options.dump_option_enabled (CompileOptions::RESOLUTION_DUMP)) { @@ -878,7 +884,7 @@ Session::injection (AST::Crate &crate) } void -Session::expansion (AST::Crate &crate) +Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx) { rust_debug ("started expansion"); @@ -905,8 +911,6 @@ Session::expansion (AST::Crate &crate) if (saw_errors ()) break; - auto ctx = Resolver2_0::NameResolutionContext (); - if (flag_name_resolution_2_0) { Resolver2_0::Early early (ctx); diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index 0240c0180080..7ab4b94ad0b6 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -24,6 +24,7 @@ #include "rust-backend.h" #include "rust-hir-map.h" #include "safe-ctype.h" +#include "rust-name-resolution-context.h" #include "config.h" #include "rust-system.h" @@ -413,7 +414,7 @@ struct Session /* Expansion pipeline stage. TODO maybe move to another object? Expands all * macros, maybe build test harness in future, AST validation, maybe create * macro crate (if not rustdoc).*/ - void expansion (AST::Crate &crate); + void expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx); // handle cfg_option bool handle_cfg_option (std::string &data); From 12e8a39bcecaeb3b3d2369e99ed108320debc0f1 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 14 Nov 2023 18:59:34 +0100 Subject: [PATCH 03/26] tests: [wip] [fmeup] delete failing tests for now --- .../rust/compile/name_resolution10.rs | 19 ------------- .../rust/compile/name_resolution6.rs | 28 ------------------- .../rust/compile/name_resolution8.rs | 26 ----------------- .../rust/compile/nested_macro_definition.rs | 16 ----------- 4 files changed, 89 deletions(-) delete mode 100644 gcc/testsuite/rust/compile/name_resolution10.rs delete mode 100644 gcc/testsuite/rust/compile/name_resolution6.rs delete mode 100644 gcc/testsuite/rust/compile/name_resolution8.rs delete mode 100644 gcc/testsuite/rust/compile/nested_macro_definition.rs diff --git a/gcc/testsuite/rust/compile/name_resolution10.rs b/gcc/testsuite/rust/compile/name_resolution10.rs deleted file mode 100644 index 33643bd1a147..000000000000 --- a/gcc/testsuite/rust/compile/name_resolution10.rs +++ /dev/null @@ -1,19 +0,0 @@ -// { dg-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } - -#![feature(decl_macro)] - -pub mod foo { - pub mod bar { - pub mod baz { - // macros 2.0 get inserted in Ribs like items - pub macro boof() {} - } - } -} - -#[macro_export] -fn main() { - foo::bar::baz::boof!(); - crate::foo::bar::baz::boof!(); - self::foo::bar::baz::boof!(); -} diff --git a/gcc/testsuite/rust/compile/name_resolution6.rs b/gcc/testsuite/rust/compile/name_resolution6.rs deleted file mode 100644 index e4087e6281ca..000000000000 --- a/gcc/testsuite/rust/compile/name_resolution6.rs +++ /dev/null @@ -1,28 +0,0 @@ -// { dg-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } - -pub mod foo { - pub mod bar { - pub mod baz { - pub mod qux { - #[macro_export] - macro_rules! foo { - (one) => {}; - } - - pub fn foo() {} - } - } - - fn f() { - fn inner() { - macro_rules! foo { - (two) => {}; - } - - foo!(two); // ok, textual scope - crate::foo!(one); // ok, path res - super::super::foo!(one); // ok, path res - } - } - } -} diff --git a/gcc/testsuite/rust/compile/name_resolution8.rs b/gcc/testsuite/rust/compile/name_resolution8.rs deleted file mode 100644 index 6fb517033824..000000000000 --- a/gcc/testsuite/rust/compile/name_resolution8.rs +++ /dev/null @@ -1,26 +0,0 @@ -// { dg-options "-frust-name-resolution-2.0" } - -// check that macros by example get exported to the crate's root with #[macro_export] -pub mod foo { - pub mod bar { - pub mod baz { - pub mod qux { - #[macro_export] - macro_rules! foo { - (one) => {}; - } - } - } - } -} - -crate::foo!(one); // ok -foo!(one); // ok - -mod a { - mod b { - mod c { - super::super::super::foo!(one); // ok - } - } -} diff --git a/gcc/testsuite/rust/compile/nested_macro_definition.rs b/gcc/testsuite/rust/compile/nested_macro_definition.rs deleted file mode 100644 index c0b72506accd..000000000000 --- a/gcc/testsuite/rust/compile/nested_macro_definition.rs +++ /dev/null @@ -1,16 +0,0 @@ -// { dg-options "-frust-name-resolution-2.0" } - -macro_rules! toto { - () => { - macro_rules! tata { - () => { - let _i = 0; - }; - } - }; -} - -pub fn main() { - toto!(); - tata!(); -} From 22115dff6bf66113e83d1fd6a2d3466e29722696 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 23 Aug 2023 15:14:46 +0200 Subject: [PATCH 04/26] session-manager: [fix me] Start dumping name resolution pass --- gcc/rust/rust-session-manager.cc | 26 +++++++++++++++++++++++--- gcc/rust/rust-session-manager.h | 1 + 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 028aed968cf6..0eef466d92c6 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -68,6 +68,10 @@ const char *kASTDumpFile = "gccrs.ast.dump"; const char *kASTPrettyDumpFile = "gccrs.ast-pretty.dump"; const char *kASTPrettyDumpFileExpanded = "gccrs.ast-pretty-expanded.dump"; const char *kASTExpandedDumpFile = "gccrs.ast-expanded.dump"; +const char *kASTmacroResolutionDumpFile = "gccrs.ast-macro-resolution.dump"; +const char *kASTlabelResolutionDumpFile = "gccrs.ast-label-resolution.dump"; +const char *kASTtypeResolutionDumpFile = "gccrs.ast-type-resolution.dump"; +const char *kASTvalueResolutionDumpFile = "gccrs.ast-value-resolution.dump"; const char *kHIRDumpFile = "gccrs.hir.dump"; const char *kHIRPrettyDumpFile = "gccrs.hir-pretty.dump"; const char *kHIRTypeResolutionDumpFile = "gccrs.type-resolution.dump"; @@ -85,6 +89,7 @@ Session::get_instance () static std::string infer_crate_name (const std::string &filename) + { if (filename == "-") return kDefaultCrateName; @@ -625,9 +630,7 @@ Session::compile_crate (const char *filename) Resolver::NameResolution::Resolve (parsed_crate); if (options.dump_option_enabled (CompileOptions::RESOLUTION_DUMP)) - { - // TODO: what do I dump here? resolved names? AST with resolved names? - } + dump_name_resolution (name_resolution_ctx); if (saw_errors ()) return; @@ -979,6 +982,23 @@ Session::dump_ast_pretty (AST::Crate &crate, bool expanded) const out.close (); } +void +Session::dump_name_resolution (Resolver2_0::NameResolutionContext &ctx) const +{ + std::array, 4> content_and_streams = {{ + {ctx.types.as_debug_string (), std::ofstream (kASTtypeResolutionDumpFile)}, + {ctx.macros.as_debug_string (), + std::ofstream (kASTmacroResolutionDumpFile)}, + {ctx.labels.as_debug_string (), + std::ofstream (kASTlabelResolutionDumpFile)}, + {ctx.values.as_debug_string (), + std::ofstream (kASTvalueResolutionDumpFile)}, + }}; + + for (auto &to_dump : content_and_streams) + to_dump.second << to_dump.first; +} + void Session::dump_hir (HIR::Crate &crate) const { diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index 7ab4b94ad0b6..858e3352fe2e 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -396,6 +396,7 @@ struct Session void dump_lex (Parser &parser) const; void dump_ast_pretty (AST::Crate &crate, bool expanded = false) const; + void dump_name_resolution (Resolver2_0::NameResolutionContext &ctx) const; void dump_hir (HIR::Crate &crate) const; void dump_hir_pretty (HIR::Crate &crate) const; From af8c0bd93e661428e5d591fc0cbc3f92b5fcf818 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 24 Aug 2023 17:50:45 +0200 Subject: [PATCH 05/26] session manager: Init Immutable name resolver --- gcc/rust/rust-session-manager.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 0eef466d92c6..f52565cf2356 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -18,6 +18,7 @@ #include "rust-session-manager.h" #include "rust-diagnostics.h" +#include "rust-immutable-name-resolution-context.h" #include "rust-unsafe-checker.h" #include "rust-lex.h" #include "rust-parse.h" @@ -658,6 +659,9 @@ Session::compile_crate (const char *filename) if (last_step == CompileOptions::CompileStep::TypeCheck) return; + // name resolution is done, we now freeze the name resolver for type checking + Resolver2_0::ImmutableNameResolutionContext::init (name_resolution_ctx); + // type resolve Resolver::TypeResolution::Resolve (hir); From 7da69cbe43c47a028160a0a963553c89e9dd3dc0 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 24 Aug 2023 17:51:11 +0200 Subject: [PATCH 06/26] nrctx: add resolved lookup --- gcc/rust/resolve/rust-name-resolution-context.cc | 13 +++++++++++++ gcc/rust/resolve/rust-name-resolution-context.h | 3 +++ 2 files changed, 16 insertions(+) diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc index f71ef91505bd..dcbd175299ee 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-name-resolution-context.cc @@ -17,6 +17,8 @@ // . #include "rust-name-resolution-context.h" +#include "optional.h" +#include "rust-mapping-common.h" namespace Rust { namespace Resolver2_0 { @@ -52,6 +54,17 @@ NameResolutionContext::map_usage (NodeId usage, NodeId definition) rust_assert (inserted); } +tl::optional +NameResolutionContext::lookup (NodeId usage) +{ + auto it = resolved_nodes.find (usage); + + if (it == resolved_nodes.end ()) + return tl::nullopt; + + return it->second; +} + void NameResolutionContext::scoped (Rib rib, NodeId id, std::function lambda, diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index 7a1924581abd..201df5321995 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -19,6 +19,7 @@ #ifndef RUST_NAME_RESOLVER_2_0_H #define RUST_NAME_RESOLVER_2_0_H +#include "optional.h" #include "rust-forever-stack.h" #include "rust-hir-map.h" @@ -180,7 +181,9 @@ class NameResolutionContext Analysis::Mappings &mappings; // TODO: Rename + // TODO: Use newtype pattern for Usage and Definition void map_usage (NodeId usage, NodeId definition); + tl::optional lookup (NodeId usage); private: /* Map of "usage" nodes which have been resolved to a "definition" node */ From 5a19a7c6b380d0b4bed7d36cc816e42dea9ff1ed Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 24 Aug 2023 17:51:21 +0200 Subject: [PATCH 07/26] typecheck: [tests fail from here] [needs f'ed up commits] Fetch ImmutableNRCtx --- .../typecheck/rust-hir-type-check-item.cc | 30 ++++++++++++------- .../typecheck/rust-hir-type-check-type.cc | 22 ++++++++++++-- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 87313af9a587..f0f73948efce 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -17,12 +17,16 @@ // . #include "rust-hir-type-check-item.h" +#include "rust-canonical-path.h" +#include "rust-diagnostics.h" #include "rust-hir-type-check-enumitem.h" #include "rust-hir-type-check-implitem.h" #include "rust-hir-type-check-type.h" #include "rust-hir-type-check-expr.h" #include "rust-hir-type-check-pattern.h" #include "rust-hir-trait-resolve.h" +#include "rust-identifier.h" +#include "rust-immutable-name-resolution-context.h" #include "rust-substitution-mapper.h" #include "rust-type-util.h" @@ -171,12 +175,13 @@ TypeCheckItem::visit (HIR::TupleStruct &struct_decl) idx++; } - // get the path - const CanonicalPath *canonical_path = nullptr; - bool ok = mappings->lookup_canonical_path ( - struct_decl.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); - RustIdent ident{*canonical_path, struct_decl.get_locus ()}; + // const CanonicalPath *canonical_path = nullptr; + // bool ok = mappings->lookup_canonical_path ( + // struct_decl.get_mappings ().get_nodeid (), &canonical_path); + // rust_assert (ok); + // RustIdent ident{*canonical_path, struct_decl.get_locus ()}; + + RustIdent ident (CanonicalPath::create_empty (), struct_decl.get_locus ()); // its a single variant ADT std::vector variants; @@ -229,11 +234,14 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl) } // get the path - const CanonicalPath *canonical_path = nullptr; - bool ok = mappings->lookup_canonical_path ( - struct_decl.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); - RustIdent ident{*canonical_path, struct_decl.get_locus ()}; + // const CanonicalPath *canonical_path = nullptr; + // bool ok = mappings->lookup_canonical_path ( + // struct_decl.get_mappings ().get_nodeid (), &canonical_path); + // rust_assert (ok); + + // RustIdent ident{*canonical_path, struct_decl.get_locus ()}; + + RustIdent ident (CanonicalPath::create_empty (), struct_decl.get_locus ()); // its a single variant ADT std::vector variants; diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 9fa64e10e8a2..c0828ee16845 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -17,10 +17,13 @@ // . #include "rust-hir-type-check-type.h" +#include "options.h" #include "rust-hir-trait-resolve.h" #include "rust-hir-type-check-expr.h" #include "rust-hir-path-probe.h" #include "rust-hir-type-bounds.h" +#include "rust-immutable-name-resolution-context.h" +#include "rust-mapping-common.h" #include "rust-substitution-mapper.h" #include "rust-type-util.h" @@ -327,11 +330,26 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, bool is_root = *offset == 0; NodeId ast_node_id = seg->get_mappings ().get_nodeid (); + auto name_resolver2_0 + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + // then lookup the reference_node_id NodeId ref_node_id = UNKNOWN_NODEID; - if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + + // FIXME: HACK: ARTHUR: Disgusting + if (flag_name_resolution_2_0) + { + // I think that whole ResolveRootPath can just be resolved by the name + // resolution pass, correct? + auto candidate = name_resolver2_0.lookup (ast_node_id); + + // FIXME: We then need to do reverse lookup, correct? + ref_node_id = candidate ? *candidate : UNKNOWN_NODEID; + } + else { - resolver->lookup_resolved_type (ast_node_id, &ref_node_id); + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + resolver->lookup_resolved_type (ast_node_id, &ref_node_id); } // ref_node_id is the NodeId that the segments refers to. From 62f13712791d74f88eb952c088bb9413819e201f Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 25 Aug 2023 14:28:54 +0200 Subject: [PATCH 08/26] typecheck: Start using nr2.0 properly --- .../typecheck/rust-hir-type-check-item.cc | 34 +++++++++++++++---- .../typecheck/rust-hir-type-check-type.cc | 26 +++++++------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index f0f73948efce..4723fa2b7025 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -26,6 +26,7 @@ #include "rust-hir-type-check-pattern.h" #include "rust-hir-trait-resolve.h" #include "rust-identifier.h" +#include "rust-session-manager.h" #include "rust-immutable-name-resolution-context.h" #include "rust-substitution-mapper.h" #include "rust-type-util.h" @@ -478,13 +479,34 @@ TypeCheckItem::visit (HIR::Function &function) TypeCheckPattern::Resolve (param.get_param_name ().get (), param_tyty); } - const CanonicalPath *canonical_path = nullptr; - bool ok - = mappings->lookup_canonical_path (function.get_mappings ().get_nodeid (), - &canonical_path); - rust_assert (ok); + rust_warning_at (function.get_locus (), 0, + "Arthur didn't clean up his stupid code: %s:%d", __FILE__, + __LINE__); + + auto path = CanonicalPath::create_empty (); + + // FIXME: HACK: ARTHUR: Disgusting + if (flag_name_resolution_2_0) + { + auto nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto canonical_path = nr_ctx.values.to_canonical_path ( + function.get_mappings ().get_nodeid ()); + + path = canonical_path.value (); + } + else + { + const CanonicalPath *canonical_path = nullptr; + bool ok = mappings->lookup_canonical_path ( + function.get_mappings ().get_nodeid (), &canonical_path); + rust_assert (ok); + + path = *canonical_path; + } + + RustIdent ident{path, function.get_locus ()}; - RustIdent ident{*canonical_path, function.get_locus ()}; auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (), function.get_mappings ().get_defid (), function.get_function_name ().as_string (), diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index c0828ee16845..b1cd7610428d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -126,6 +126,8 @@ TypeCheckType::visit (HIR::TupleType &tuple) void TypeCheckType::visit (HIR::TypePath &path) { + rust_debug ("{ARTHUR}: Path visited: %s", path.as_string ().c_str ()); + // this can happen so we need to look up the root then resolve the // remaining segments if possible size_t offset = 0; @@ -336,21 +338,17 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, // then lookup the reference_node_id NodeId ref_node_id = UNKNOWN_NODEID; - // FIXME: HACK: ARTHUR: Disgusting + // FIXME: HACK: ARTHUR: Remove this if (flag_name_resolution_2_0) - { - // I think that whole ResolveRootPath can just be resolved by the name - // resolution pass, correct? - auto candidate = name_resolver2_0.lookup (ast_node_id); - - // FIXME: We then need to do reverse lookup, correct? - ref_node_id = candidate ? *candidate : UNKNOWN_NODEID; - } - else - { - if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - resolver->lookup_resolved_type (ast_node_id, &ref_node_id); - } + // assign the ref_node_id if we've found something + name_resolver2_0.lookup (path.get_mappings ().get_nodeid ()) + .map ([&ref_node_id, &path] (NodeId resolved) { + rust_warning_at (path.get_locus (), 0, + "{ARTHUR}: found reference: %d", resolved); + ref_node_id = resolved; + }); + else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + resolver->lookup_resolved_type (ast_node_id, &ref_node_id); // ref_node_id is the NodeId that the segments refers to. if (ref_node_id == UNKNOWN_NODEID) From 29b7c5d5984705a293353044eb88fc9cf2d94ff9 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 25 Aug 2023 14:33:36 +0200 Subject: [PATCH 09/26] backend: Use new name resolver where necessary [needs f'ed up commits] --- gcc/rust/backend/rust-compile-base.cc | 1 + gcc/rust/backend/rust-compile-context.h | 1 + gcc/rust/backend/rust-compile-expr.cc | 22 ++++++++++--- gcc/rust/backend/rust-compile-item.cc | 33 +++++++++++++++---- .../typecheck/rust-hir-type-check-item.cc | 4 --- 5 files changed, 46 insertions(+), 15 deletions(-) diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index 77fcb91520d7..35e78ea7bb69 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -31,6 +31,7 @@ #include "rust-type-util.h" #include "rust-compile-implitem.h" #include "rust-attribute-values.h" +#include "rust-immutable-name-resolution-context.h" #include "fold-const.h" #include "stringpool.h" diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index acfb360c3499..941391d9f51f 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -27,6 +27,7 @@ #include "rust-hir-full.h" #include "rust-mangle.h" #include "rust-tree.h" +#include "rust-immutable-name-resolution-context.h" namespace Rust { namespace Compile { diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index c511cf1074f9..702f87561764 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -2313,11 +2313,23 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr, if (is_block_expr) { auto body_mappings = function_body->get_mappings (); - Resolver::Rib *rib = nullptr; - bool ok - = ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), - &rib); - rust_assert (ok); + if (flag_name_resolution_2_0) + { + auto nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + auto candidate = nr_ctx.values.to_rib (body_mappings.get_nodeid ()); + + rust_assert (candidate.has_value ()); + } + else + { + Resolver::Rib *rib = nullptr; + bool ok + = ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), + &rib); + rust_assert (ok); + } } tree enclosing_scope = NULL_TREE; diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc index 967d154e463b..deea825c3343 100644 --- a/gcc/rust/backend/rust-compile-item.cc +++ b/gcc/rust/backend/rust-compile-item.cc @@ -19,6 +19,7 @@ #include "rust-compile-item.h" #include "rust-compile-implitem.h" #include "rust-compile-extern.h" +#include "rust-immutable-name-resolution-context.h" namespace Rust { namespace Compile { @@ -149,12 +150,32 @@ CompileItem::visit (HIR::Function &function) } } - const Resolver::CanonicalPath *canonical_path = nullptr; - bool ok = ctx->get_mappings ()->lookup_canonical_path ( - function.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); + Resolver::CanonicalPath canonical_path + = Resolver::CanonicalPath::create_empty (); + + if (flag_name_resolution_2_0) + { + // FIXME: What we need to do here is build the CanonicalPath from the name + // resolver 2.0. this isn't super difficult, we just need to get to it + auto nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + auto path = nr_ctx.values.to_canonical_path ( + function.get_mappings ().get_nodeid ()); + + canonical_path = path.value (); + } + else + { + const Resolver::CanonicalPath *path = nullptr; + bool ok = ctx->get_mappings ()->lookup_canonical_path ( + function.get_mappings ().get_nodeid (), &path); + rust_assert (ok); + + canonical_path = *path; + } - const std::string asm_name = ctx->mangle_item (fntype, *canonical_path); + const std::string asm_name = ctx->mangle_item (fntype, canonical_path); // items can be forward compiled which means we may not need to invoke this // code. We might also have already compiled this generic function as well. @@ -181,7 +202,7 @@ CompileItem::visit (HIR::Function &function) function.get_function_params (), function.get_qualifiers (), function.get_visibility (), function.get_outer_attrs (), function.get_locus (), - function.get_definition ().get (), canonical_path, + function.get_definition ().get (), &canonical_path, fntype); reference = address_expression (fndecl, ref_locus); diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 4723fa2b7025..e186476a2ea2 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -479,10 +479,6 @@ TypeCheckItem::visit (HIR::Function &function) TypeCheckPattern::Resolve (param.get_param_name ().get (), param_tyty); } - rust_warning_at (function.get_locus (), 0, - "Arthur didn't clean up his stupid code: %s:%d", __FILE__, - __LINE__); - auto path = CanonicalPath::create_empty (); // FIXME: HACK: ARTHUR: Disgusting From f49671c56abf5f599b4b3e1c9af6a4e2e999e1a2 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 14 Sep 2023 17:38:06 +0200 Subject: [PATCH 10/26] nr2.0: Start using newtype pattern for Usage and Declaration --- .../resolve/rust-late-name-resolver-2.0.cc | 4 +-- .../resolve/rust-name-resolution-context.cc | 6 ++--- .../resolve/rust-name-resolution-context.h | 27 +++++++++++++++++-- 3 files changed, 30 insertions(+), 7 deletions(-) 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 5f70f5755824..a7d094b5fb72 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -132,7 +132,7 @@ Late::visit (AST::IdentifierExpr &expr) resolved = value; // TODO: else emit error? - ctx.map_usage (expr.get_node_id (), *resolved); + ctx.map_usage (Usage (expr.get_node_id ()), Definition (*resolved)); // in the old resolver, resolutions are kept in the resolver, not the mappings // :/ how do we deal with that? @@ -163,7 +163,7 @@ Late::visit (AST::TypePath &type) auto resolved = ctx.types.get (type.get_segments ().back ()->as_string ()); - ctx.map_usage (type.get_node_id (), *resolved); + ctx.map_usage (Usage (type.get_node_id ()), Definition (*resolved)); } } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc index dcbd175299ee..2d16a70a1a0c 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-name-resolution-context.cc @@ -46,7 +46,7 @@ NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns) } void -NameResolutionContext::map_usage (NodeId usage, NodeId definition) +NameResolutionContext::map_usage (Usage usage, Definition definition) { auto inserted = resolved_nodes.emplace (usage, definition).second; @@ -57,12 +57,12 @@ NameResolutionContext::map_usage (NodeId usage, NodeId definition) tl::optional NameResolutionContext::lookup (NodeId usage) { - auto it = resolved_nodes.find (usage); + auto it = resolved_nodes.find (Usage (usage)); if (it == resolved_nodes.end ()) return tl::nullopt; - return it->second; + return it->second.id; } void diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index 201df5321995..c8b2f37ecd09 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -133,6 +133,28 @@ change? correct */ +// FIXME: Documentation +class Usage +{ +public: + explicit Usage (NodeId id) : id (id) {} + + // TODO: move to name-resolution-ctx.cc + // storing it as a key in a map + bool operator< (const Usage other) const { return other.id < id; } + + NodeId id; +}; + +// FIXME: Documentation +class Definition +{ +public: + explicit Definition (NodeId id) : id (id) {} + + NodeId id; +}; + // Now our resolver, which keeps track of all the `ForeverStack`s we could want class NameResolutionContext { @@ -182,12 +204,13 @@ class NameResolutionContext // TODO: Rename // TODO: Use newtype pattern for Usage and Definition - void map_usage (NodeId usage, NodeId definition); + void map_usage (Usage usage, Definition definition); + tl::optional lookup (NodeId usage); private: /* Map of "usage" nodes which have been resolved to a "definition" node */ - std::map resolved_nodes; + std::map resolved_nodes; }; } // namespace Resolver2_0 From c04726a4b382e30e617d160643a08c0dc2861215 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 28 Aug 2023 16:40:12 +0200 Subject: [PATCH 11/26] late: Setup builtin types properly, change Rib API --- gcc/rust/resolve/rust-forever-stack.hxx | 22 +++-- .../resolve/rust-late-name-resolver-2.0.cc | 84 +++++++++++++------ gcc/rust/resolve/rust-rib.cc | 38 +++++++-- gcc/rust/resolve/rust-rib.h | 30 +++++-- 4 files changed, 126 insertions(+), 48 deletions(-) diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 867144adf926..d4c01ef0817b 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -100,9 +100,9 @@ ForeverStack::pop () } static tl::expected -insert_inner (Rib &rib, std::string name, NodeId node, bool can_shadow) +insert_inner (Rib &rib, std::string name, Rib::Definition definition) { - return rib.insert (name, node, can_shadow); + return rib.insert (name, definition); } template @@ -115,7 +115,8 @@ ForeverStack::insert (Identifier name, NodeId node) // pass, we might end up in a situation where it is okay to re-add new names. // Do we just ignore that here? Do we keep track of if the Rib is new or not? // should our cursor have info on the current node like "is it newly pushed"? - return insert_inner (innermost_rib, name.as_string (), node, false); + return insert_inner (innermost_rib, name.as_string (), + Rib::Definition::NonShadowable (node)); } template @@ -126,7 +127,8 @@ ForeverStack::insert_at_root (Identifier name, NodeId node) // inserting in the root of the crate is never a shadowing operation, even for // macros - return insert_inner (root_rib, name.as_string (), node, false); + return insert_inner (root_rib, name.as_string (), + Rib::Definition::NonShadowable (node)); } // Specialization for Macros and Labels - where we are allowed to shadow @@ -135,14 +137,16 @@ template <> inline tl::expected ForeverStack::insert (Identifier name, NodeId node) { - return insert_inner (peek (), name.as_string (), node, true); + return insert_inner (peek (), name.as_string (), + Rib::Definition::Shadowable (node)); } template <> inline tl::expected ForeverStack::insert (Identifier name, NodeId node) { - return insert_inner (peek (), name.as_string (), node, true); + return insert_inner (peek (), name.as_string (), + Rib::Definition::Shadowable (node)); } template @@ -455,10 +459,10 @@ template tl::optional::Node &, std::string>> ForeverStack::dfs (ForeverStack::Node &starting_point, NodeId to_find) { - auto &values = starting_point.rib.get_values (); + auto values = starting_point.rib.get_values (); for (auto &kv : values) - if (kv.second == to_find) + if (kv.second.id == to_find) return {{starting_point, kv.first}}; for (auto &child : starting_point.children) @@ -568,7 +572,7 @@ ForeverStack::stream_rib (std::stringstream &stream, const Rib &rib, stream << next << "rib: {\n"; for (const auto &kv : rib.get_values ()) - stream << next_next << kv.first << ": " << kv.second << "\n"; + stream << next_next << kv.first << ": " << kv.second.id << "\n"; stream << next << "},\n"; } 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 a7d094b5fb72..353d3debb777 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -18,8 +18,10 @@ #include "optional.h" #include "rust-ast-full.h" +#include "rust-hir-map.h" #include "rust-late-name-resolver-2.0.h" #include "rust-default-resolver.h" +#include "rust-name-resolution-context.h" #include "rust-path.h" #include "rust-tyty.h" #include "rust-hir-type-check.h" @@ -29,41 +31,75 @@ namespace Resolver2_0 { Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {} +static NodeId +next_node_id () +{ + return Analysis::Mappings::get ()->get_next_node_id (); +}; + +static HirId +next_hir_id () +{ + return Analysis::Mappings::get ()->get_next_hir_id (); +}; + void Late::setup_builtin_types () { - auto next_id = [this] () { return ctx.mappings.get_next_hir_id (); }; - - static const std::pair builtins[] = { - {"u8", new TyTy::UintType (next_id (), TyTy::UintType::U8)}, - {"u16", new TyTy::UintType (next_id (), TyTy::UintType::U16)}, - {"u32", new TyTy::UintType (next_id (), TyTy::UintType::U32)}, - {"u64", new TyTy::UintType (next_id (), TyTy::UintType::U64)}, - {"u128", new TyTy::UintType (next_id (), TyTy::UintType::U128)}, - {"i8", new TyTy::IntType (next_id (), TyTy::IntType::I8)}, - {"i16", new TyTy::IntType (next_id (), TyTy::IntType::I16)}, - {"i32", new TyTy::IntType (next_id (), TyTy::IntType::I32)}, - {"i64", new TyTy::IntType (next_id (), TyTy::IntType::I64)}, - {"i128", new TyTy::IntType (next_id (), TyTy::IntType::I128)}, - {"f32", new TyTy::FloatType (next_id (), TyTy::FloatType::F32)}, - {"f64", new TyTy::FloatType (next_id (), TyTy::FloatType::F64)}, - {"usize", new TyTy::USizeType (next_id ())}, - {"isize", new TyTy::ISizeType (next_id ())}, - // missing char, str, never, () - // does name resolution play a part for this? or is it all at typechecking? - // yeah it seems to be name resolution as well, which makes sense + // access the global type context to setup the TyTys + auto &ty_ctx = *Resolver::TypeCheckContext::get (); + + // Late builtin type struct helper + struct LType + { + std::string name; + NodeId node_id; + NodeId hir_id; + TyTy::BaseType *type; + + explicit LType (std::string name, TyTy::BaseType *type) + : name (name), node_id (next_node_id ()), hir_id (type->get_ref ()), + type (type) + {} + }; + + static const LType builtins[] = { + {LType ("u8", new TyTy::UintType (next_hir_id (), TyTy::UintType::U8))}, + {LType ("u16", new TyTy::UintType (next_hir_id (), TyTy::UintType::U16))}, + {LType ("u32", new TyTy::UintType (next_hir_id (), TyTy::UintType::U32))}, + {LType ("u64", new TyTy::UintType (next_hir_id (), TyTy::UintType::U64))}, + {LType ("u128", new TyTy::UintType (next_hir_id (), TyTy::UintType::U128))}, + {LType ("i8", new TyTy::IntType (next_hir_id (), TyTy::IntType::I8))}, + {LType ("i16", new TyTy::IntType (next_hir_id (), TyTy::IntType::I16))}, + {LType ("i32", new TyTy::IntType (next_hir_id (), TyTy::IntType::I32))}, + {LType ("i64", new TyTy::IntType (next_hir_id (), TyTy::IntType::I64))}, + {LType ("i128", new TyTy::IntType (next_hir_id (), TyTy::IntType::I128))}, + {LType ("f32", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F32))}, + {LType ("f64", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F64))}, + {LType ("usize", new TyTy::USizeType (next_hir_id ()))}, + {LType ("isize", new TyTy::ISizeType (next_hir_id ()))}, + {LType ("char", new TyTy::CharType (next_hir_id ()))}, + {LType ("str", new TyTy::StrType (next_hir_id ()))}, + {LType ("!", new TyTy::NeverType (next_hir_id ()))}, + + // the unit type `()` does not play a part in name-resolution - so we only + // insert it in the type context... }; for (const auto &builtin : builtins) { // we should be able to use `insert_at_root` or `insert` here, since we're // at the root :) hopefully! - auto ok - = ctx.types.insert (builtin.first, builtin.second->get_ref () - /* FIXME: Invalid! This returns an *HirId* */); - + auto ok = ctx.types.insert (builtin.name, builtin.node_id); rust_assert (ok); + + ctx.mappings.insert_node_to_hir (builtin.node_id, builtin.hir_id); + ty_ctx.insert_builtin (builtin.hir_id, builtin.node_id, builtin.type); } + + // ...here! + auto *unit_type = TyTy::TupleType::get_unit_type (next_hir_id ()); + ty_ctx.insert_builtin (unit_type->get_ref (), next_node_id (), unit_type); } void diff --git a/gcc/rust/resolve/rust-rib.cc b/gcc/rust/resolve/rust-rib.cc index 21fbe2ca530e..4ff8c8da1e3b 100644 --- a/gcc/rust/resolve/rust-rib.cc +++ b/gcc/rust/resolve/rust-rib.cc @@ -17,10 +17,27 @@ // . #include "rust-rib.h" +#include "rust-name-resolution-context.h" namespace Rust { namespace Resolver2_0 { +Rib::Definition::Definition (NodeId id, bool shadowable) + : id (id), shadowable (shadowable) +{} + +Rib::Definition +Rib::Definition::Shadowable (NodeId id) +{ + return Definition (id, true); +} + +Rib::Definition +Rib::Definition::NonShadowable (NodeId id) +{ + return Definition (id, false); +} + DuplicateNameError::DuplicateNameError (std::string name, NodeId existing) : name (name), existing (existing) {} @@ -31,20 +48,23 @@ Rib::Rib (Kind kind, std::string identifier, NodeId id) : Rib (kind, {{identifier, id}}) {} -Rib::Rib (Kind kind, std::unordered_map values) - : kind (kind), values (std::move (values)) -{} +Rib::Rib (Kind kind, std::unordered_map to_insert) + : kind (kind) +{ + for (auto &value : to_insert) + values.insert ({value.first, Definition::NonShadowable (value.second)}); +} tl::expected -Rib::insert (std::string name, NodeId id, bool can_shadow) +Rib::insert (std::string name, Definition def) { - auto res = values.insert ({name, id}); - auto inserted_id = res.first->second; + auto res = values.insert ({name, def}); + auto inserted_id = res.first->second.id; auto existed = !res.second; // if we couldn't insert, the element already exists - exit with an error, // unless shadowing is allowed - if (existed && !can_shadow) + if (existed && !def.shadowable) return tl::make_unexpected (DuplicateNameError (name, inserted_id)); // return the NodeId @@ -59,10 +79,10 @@ Rib::get (const std::string &name) if (it == values.end ()) return {}; - return it->second; + return it->second.id; } -const std::unordered_map & +const std::unordered_map & Rib::get_values () const { return values; diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h index 4ffd00a5d6c3..e74af436c30a 100644 --- a/gcc/rust/resolve/rust-rib.h +++ b/gcc/rust/resolve/rust-rib.h @@ -103,6 +103,24 @@ struct DuplicateNameError class Rib { public: + // TODO: Rename the class? to what? Binding? Declaration? + // This is useful for items which are in namespaces where shadowing is not + // allowed, but which are still shadowable! for example, when you do a glob + // import, if a later import has the same name as an item imported in the glob + // import, that glob imported item will need to get shadowed + class Definition + { + public: + static Definition NonShadowable (NodeId id); + static Definition Shadowable (NodeId id); + + NodeId id; + bool shadowable; + + private: + Definition (NodeId id, bool shadowable); + }; + enum class Kind { Normal, @@ -131,15 +149,14 @@ class Rib * Insert a new node in the rib * * @param name The name associated with the AST node - * @param id Its NodeId - * @param can_shadow If the newly inserted value can shadow an existing one + * @param def The `Definition` to insert * * @return `DuplicateNameError` if the node is already present in the rib. The * `DuplicateNameError` class contains the NodeId of the existing * node. Returns the new NodeId on success. */ - tl::expected insert (std::string name, NodeId id, - bool can_shadow = false); + tl::expected insert (std::string name, + Definition def); /** * Access an inserted NodeId. @@ -149,10 +166,11 @@ class Rib tl::optional get (const std::string &name); /* View all the values stored in the rib */ - const std::unordered_map &get_values () const; + const std::unordered_map &get_values () const; private: - std::unordered_map values; + // TODO: Switch this to (NodeId, shadowable = false); + std::unordered_map values; }; } // namespace Resolver2_0 From 67f1b28a4832a80b089c5ddeeada7dc4e66f74e6 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 29 Aug 2023 11:19:49 +0200 Subject: [PATCH 12/26] typecheck path: wip --- .../typecheck/rust-hir-type-check-path.cc | 20 +++++++++++++++---- .../typecheck/rust-hir-type-check-type.cc | 4 ++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index 2b5d3860ec32..8ee768ba6826 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -24,6 +24,8 @@ #include "rust-hir-path-probe.h" #include "rust-type-util.h" #include "rust-hir-type-bounds.h" +#include "rust-session-manager.h" +#include "rust-immutable-name-resolution-context.h" namespace Rust { namespace Resolver { @@ -193,12 +195,22 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset, bool is_root = *offset == 0; NodeId ast_node_id = seg.get_mappings ().get_nodeid (); + auto nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + // then lookup the reference_node_id NodeId ref_node_id = UNKNOWN_NODEID; - if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - { - resolver->lookup_resolved_type (ast_node_id, &ref_node_id); - } + + if (flag_name_resolution_2_0) + // assign the ref_node_id if we've found something + nr_ctx.lookup (expr.get_mappings ().get_nodeid ()) + .map ([&ref_node_id, &expr] (NodeId resolved) { + rust_warning_at (expr.get_locus (), 0, + "{ARTHUR}: found reference: %d", resolved); + ref_node_id = resolved; + }); + else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + resolver->lookup_resolved_type (ast_node_id, &ref_node_id); // ref_node_id is the NodeId that the segments refers to. if (ref_node_id == UNKNOWN_NODEID) diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index b1cd7610428d..60a20c30cbf5 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -332,7 +332,7 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, bool is_root = *offset == 0; NodeId ast_node_id = seg->get_mappings ().get_nodeid (); - auto name_resolver2_0 + auto nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); // then lookup the reference_node_id @@ -341,7 +341,7 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, // FIXME: HACK: ARTHUR: Remove this if (flag_name_resolution_2_0) // assign the ref_node_id if we've found something - name_resolver2_0.lookup (path.get_mappings ().get_nodeid ()) + nr_ctx.lookup (path.get_mappings ().get_nodeid ()) .map ([&ref_node_id, &path] (NodeId resolved) { rust_warning_at (path.get_locus (), 0, "{ARTHUR}: found reference: %d", resolved); From df77f794ab9ff599b3f7cb436100bc800357d433 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 29 Aug 2023 17:24:35 +0200 Subject: [PATCH 13/26] toplevel: Add note about resolving glob imports --- gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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 46113a8a46b3..84dd7d601dca 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -466,6 +466,18 @@ flatten_glob (const AST::UseTreeGlob &glob, std::vector &paths) { if (glob.has_path ()) paths.emplace_back (glob.get_path ()); + + // so what is the plan for glob imports + // 1. figure out the rib which contains all the exports, in each namespace + // 2. for that namespace, go through all the nodes + // 3. filter out the exported ones (is that correct?) + // 4. export them in the current rib, BUT make them shadowable + + // 1. needs us to be able to find a Rib based on a SimplePath - can we already + // do that with resolve path? + // 2. ok + // 3. how do we get the visibiliy information for each node? in the mappings? + // 4. ok } void From 230a0377ca1ea956775d750fc539e2708e54608c Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 29 Aug 2023 17:43:07 +0200 Subject: [PATCH 14/26] default: Visit external functions properly --- gcc/rust/resolve/rust-default-resolver.cc | 16 ++++- .../typecheck/rust-hir-type-check-item.cc | 58 ++++++++++++++----- .../typecheck/rust-hir-type-check-path.cc | 6 +- .../typecheck/rust-hir-type-check-type.cc | 2 +- 4 files changed, 61 insertions(+), 21 deletions(-) diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index ab4d5e8b70dc..75a268155eb0 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -80,6 +80,8 @@ DefaultResolver::visit (AST::Function &function) if (function.has_body ()) function.get_definition ().value ()->accept_vis (*this); + + // TODO: Don't we need to visit the return type here as well? }; ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn); @@ -427,8 +429,18 @@ DefaultResolver::visit (AST::ExternalStaticItem &) {} void -DefaultResolver::visit (AST::ExternalFunctionItem &) -{} +DefaultResolver::visit (AST::ExternalFunctionItem &function) +{ + auto def_fn = [this, &function] () { + for (auto ¶m : function.get_function_params ()) + { + // TODO: So extern function params are not patterns? + param.get_type ()->accept_vis (*this); + } + }; + + ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn); +} void DefaultResolver::visit (AST::MacroMatchRepetition &) diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index e186476a2ea2..d3faa1ccc723 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -176,13 +176,31 @@ TypeCheckItem::visit (HIR::TupleStruct &struct_decl) idx++; } - // const CanonicalPath *canonical_path = nullptr; - // bool ok = mappings->lookup_canonical_path ( - // struct_decl.get_mappings ().get_nodeid (), &canonical_path); - // rust_assert (ok); - // RustIdent ident{*canonical_path, struct_decl.get_locus ()}; + // get the path + + auto path = CanonicalPath::create_empty (); + + // FIXME: HACK: ARTHUR: Disgusting + if (flag_name_resolution_2_0) + { + auto nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto canonical_path = nr_ctx.values.to_canonical_path ( + struct_decl.get_mappings ().get_nodeid ()); + + path = canonical_path.value (); + } + else + { + const CanonicalPath *canonical_path = nullptr; + bool ok = mappings->lookup_canonical_path ( + struct_decl.get_mappings ().get_nodeid (), &canonical_path); + rust_assert (ok); + + path = *canonical_path; + } - RustIdent ident (CanonicalPath::create_empty (), struct_decl.get_locus ()); + RustIdent ident{path, struct_decl.get_locus ()}; // its a single variant ADT std::vector variants; @@ -234,15 +252,29 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl) context->insert_type (field.get_mappings (), ty_field->get_field_type ()); } - // get the path - // const CanonicalPath *canonical_path = nullptr; - // bool ok = mappings->lookup_canonical_path ( - // struct_decl.get_mappings ().get_nodeid (), &canonical_path); - // rust_assert (ok); + auto path = CanonicalPath::create_empty (); + + // FIXME: HACK: ARTHUR: Disgusting + if (flag_name_resolution_2_0) + { + auto nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto canonical_path = nr_ctx.values.to_canonical_path ( + struct_decl.get_mappings ().get_nodeid ()); - // RustIdent ident{*canonical_path, struct_decl.get_locus ()}; + path = canonical_path.value (); + } + else + { + const CanonicalPath *canonical_path = nullptr; + bool ok = mappings->lookup_canonical_path ( + struct_decl.get_mappings ().get_nodeid (), &canonical_path); + rust_assert (ok); + + path = *canonical_path; + } - RustIdent ident (CanonicalPath::create_empty (), struct_decl.get_locus ()); + RustIdent ident{path, struct_decl.get_locus ()}; // its a single variant ADT std::vector variants; diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index 8ee768ba6826..660d7de73df1 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -204,11 +204,7 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset, if (flag_name_resolution_2_0) // assign the ref_node_id if we've found something nr_ctx.lookup (expr.get_mappings ().get_nodeid ()) - .map ([&ref_node_id, &expr] (NodeId resolved) { - rust_warning_at (expr.get_locus (), 0, - "{ARTHUR}: found reference: %d", resolved); - ref_node_id = resolved; - }); + .map ([&ref_node_id] (NodeId resolved) { ref_node_id = resolved; }); else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) resolver->lookup_resolved_type (ast_node_id, &ref_node_id); diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 60a20c30cbf5..1b1f6b6afe10 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -356,7 +356,7 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, if (is_root) { rust_error_at (seg->get_locus (), - "unknown reference for resolved name: %<%s%>", + "unknown reference for resolved name: %qs", seg->get_ident_segment ().as_string ().c_str ()); return new TyTy::ErrorType (path.get_mappings ().get_hirid ()); } From 1719fb3e515ae60e432f85656a573f15bfebd4c9 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 23 Aug 2023 17:19:28 +0200 Subject: [PATCH 15/26] add more name res test casaes --- .../rust/compile/name_resolution14.rs | 13 ++++++++++++ .../rust/compile/name_resolution15.rs | 19 ++++++++++++++++++ .../rust/compile/name_resolution16.rs | 17 ++++++++++++++++ .../rust/compile/name_resolution17.rs | 8 ++++++++ .../rust/compile/name_resolution18.rs | 13 ++++++++++++ .../rust/compile/name_resolution19.rs | 20 +++++++++++++++++++ .../rust/compile/name_resolution20.rs | 9 +++++++++ .../rust/compile/name_resolution21.rs | 10 ++++++++++ 8 files changed, 109 insertions(+) create mode 100644 gcc/testsuite/rust/compile/name_resolution14.rs create mode 100644 gcc/testsuite/rust/compile/name_resolution15.rs create mode 100644 gcc/testsuite/rust/compile/name_resolution16.rs create mode 100644 gcc/testsuite/rust/compile/name_resolution17.rs create mode 100644 gcc/testsuite/rust/compile/name_resolution18.rs create mode 100644 gcc/testsuite/rust/compile/name_resolution19.rs create mode 100644 gcc/testsuite/rust/compile/name_resolution20.rs create mode 100644 gcc/testsuite/rust/compile/name_resolution21.rs diff --git a/gcc/testsuite/rust/compile/name_resolution14.rs b/gcc/testsuite/rust/compile/name_resolution14.rs new file mode 100644 index 000000000000..dba58a745e8b --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution14.rs @@ -0,0 +1,13 @@ +pub mod foo { + pub macro bar() {} +} + +use foo::biz; // { dg-error "unresolved import .foo::biz." } + +use foo::{bar, baz, biz}; +// { dg-error "unresolved import .foo::baz." "" { target *-*-* } .-1 } +// { dg-error "unresolved import .foo::biz." "" { target *-*-* } .-2 } + +fn main() { + bar!(); +} diff --git a/gcc/testsuite/rust/compile/name_resolution15.rs b/gcc/testsuite/rust/compile/name_resolution15.rs new file mode 100644 index 000000000000..06f02d68047d --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution15.rs @@ -0,0 +1,19 @@ +#![feature(decl_macro)] + +pub mod foo { + pub struct Foo { + pub a: i32, + } + pub fn Foo() {} + pub macro Foo() {{}} +} + +pub use foo::Foo; + +use self::Foo as Fo; + +fn main() { + let a = Fo(); + let b = Fo { a: 15 }; + let c = Fo!(); +} diff --git a/gcc/testsuite/rust/compile/name_resolution16.rs b/gcc/testsuite/rust/compile/name_resolution16.rs new file mode 100644 index 000000000000..19d90d01ea59 --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution16.rs @@ -0,0 +1,17 @@ +#![feature(decl_macro)] + +pub mod foo { + pub struct Foo { + pub a: i32, + } + pub fn Foo() {} + pub macro Foo() {{}} +} + +pub use foo::Foo; + +fn main() { + let a = Foo(); + let b = Foo { a: 15 }; + let c = Foo!(); +} diff --git a/gcc/testsuite/rust/compile/name_resolution17.rs b/gcc/testsuite/rust/compile/name_resolution17.rs new file mode 100644 index 000000000000..84ad380fd956 --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution17.rs @@ -0,0 +1,8 @@ +struct Foo; +fn Foo() {} // { dg-error ".Foo. defined multiple times" } + +struct Marker; +struct Bar { + a: Marker, +} +fn Bar() {} // ok, since `Bar` is not a value here diff --git a/gcc/testsuite/rust/compile/name_resolution18.rs b/gcc/testsuite/rust/compile/name_resolution18.rs new file mode 100644 index 000000000000..17a335280278 --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution18.rs @@ -0,0 +1,13 @@ +struct Marker; + +struct Foo { + a: Marker, +} + +pub mod foo { + struct Foo { + b: Marker, + } +} + +use foo::Foo; // { dg-error ".Foo. defined multiple times" } diff --git a/gcc/testsuite/rust/compile/name_resolution19.rs b/gcc/testsuite/rust/compile/name_resolution19.rs new file mode 100644 index 000000000000..9a2c84375c7a --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution19.rs @@ -0,0 +1,20 @@ +struct Marker; + +fn foo(a: Marker, b: Marker) -> Marker { + let a = b; + + a +} + +fn bar() { + let a = 15; + + fn inner() { + // inner functions cannot capture dynamic environment + let b = a; // { dg-error "cannot find value .a. in this scope" } + } +} + +fn main() { + let m = foo(Marker, Marker); +} diff --git a/gcc/testsuite/rust/compile/name_resolution20.rs b/gcc/testsuite/rust/compile/name_resolution20.rs new file mode 100644 index 000000000000..f131bb41c170 --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution20.rs @@ -0,0 +1,9 @@ +pub mod foo { + pub macro bar() {} +} + +use foo::bar; + +fn main() { + bar!(); +} diff --git a/gcc/testsuite/rust/compile/name_resolution21.rs b/gcc/testsuite/rust/compile/name_resolution21.rs new file mode 100644 index 000000000000..2dc68d866949 --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution21.rs @@ -0,0 +1,10 @@ +pub mod foo { + pub macro bar() {} +} + +use foo::bar; +use foo::bar; // { dg-error ".bar. defined multiple times" } + +fn main() { + bar!(); +} From ee4ac05dfd507bd58f353a8468bd5bef5604a2ef Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 14 Sep 2023 17:39:37 +0200 Subject: [PATCH 16/26] Fix duplicate detection The resolver did report duplicate symbols when being run multiple times even if the node id was the same. This commit adds an additional condition, the error will only be reported if the existing node id is different from the current node id. gcc/rust/ChangeLog: * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::insert_or_error_out): Add new constraint to duplicate errors. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 5 +---- 1 file changed, 1 insertion(+), 4 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 84dd7d601dca..b2291a0295f3 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -47,11 +47,8 @@ TopLevel::insert_or_error_out (const Identifier &identifier, auto result = ctx.insert (identifier, node_id, ns); - if (!result) + if (!result && result.error ().existing != node_id) { - // can we do something like check if the node id is the same? if it is the - // same, it's not an error, just the resolver running multiple times? - rich_location rich_loc (line_table, locus); rich_loc.add_range (node_locations[result.error ().existing]); From 723cc17542db18a10aebd4bbbe806cf066c6d95e Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Fri, 15 Sep 2023 13:09:28 +0200 Subject: [PATCH 17/26] Change to new resolution 2.0 Change the test's name resolution algorithm to 2.0. gcc/testsuite/ChangeLog: * rust/compile/name_resolution12.rs: Add name resolution 2.0 flag. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/name_resolution20.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/testsuite/rust/compile/name_resolution20.rs b/gcc/testsuite/rust/compile/name_resolution20.rs index f131bb41c170..e6c2dd5ea8f9 100644 --- a/gcc/testsuite/rust/compile/name_resolution20.rs +++ b/gcc/testsuite/rust/compile/name_resolution20.rs @@ -1,3 +1,5 @@ +// { dg-options "-frust-name-resolution-2.0" } + pub mod foo { pub macro bar() {} } From 5ba2a905c27063fae171f7eee34ce3071e17b9b1 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Fri, 15 Sep 2023 13:12:38 +0200 Subject: [PATCH 18/26] Change to name resolution 2.0 Change test name resolution algorithm to 2.0. gcc/testsuite/ChangeLog: * rust/compile/name_resolution13.rs: Add compile flag to use the new name resolution 2.0 algorithm. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/name_resolution13.rs | 8 ++++++++ gcc/testsuite/rust/compile/name_resolution21.rs | 2 ++ 2 files changed, 10 insertions(+) diff --git a/gcc/testsuite/rust/compile/name_resolution13.rs b/gcc/testsuite/rust/compile/name_resolution13.rs index 52a152bf51a5..5fbf47174e24 100644 --- a/gcc/testsuite/rust/compile/name_resolution13.rs +++ b/gcc/testsuite/rust/compile/name_resolution13.rs @@ -1,4 +1,12 @@ +<<<<<<< HEAD // { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } +======= +// { dg-options "-frust-name-resolution-2.0" } + +pub mod foo { + pub macro bar() {} +} +>>>>>>> 9cd774074db (Change to name resolution 2.0) fn foo() { let b = 10; diff --git a/gcc/testsuite/rust/compile/name_resolution21.rs b/gcc/testsuite/rust/compile/name_resolution21.rs index 2dc68d866949..3d0af2b37b76 100644 --- a/gcc/testsuite/rust/compile/name_resolution21.rs +++ b/gcc/testsuite/rust/compile/name_resolution21.rs @@ -1,3 +1,5 @@ +// { dg-additional-options "-frust-name-resolution-2.0" } + pub mod foo { pub macro bar() {} } From 4783b1f7f39b94575853fe3edf0599c64fed6a88 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Fri, 15 Sep 2023 13:14:56 +0200 Subject: [PATCH 19/26] Emit error on identical use declarations The compiler did not emit any warning when a same target was declared from different sources. gcc/rust/ChangeLog: * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::handle_use_dec): Use the new dict to track down already resolved use declarations. * resolve/rust-toplevel-name-resolver-2.0.h: Add new dict to store previous use declarations. Signed-off-by: Pierre-Emmanuel Patry --- .../rust-toplevel-name-resolver-2.0.cc | 76 ++++++++++--------- .../resolve/rust-toplevel-name-resolver-2.0.h | 1 + 2 files changed, 43 insertions(+), 34 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 b2291a0295f3..7b4976debec2 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -329,40 +329,48 @@ TopLevel::handle_use_dec (AST::SimplePath path) auto found = false; - auto resolve_and_insert = [this, &found, &declared_name, - locus] (Namespace ns, - const AST::SimplePath &path) { - tl::optional resolved = tl::nullopt; - - // FIXME: resolve_path needs to return an `expected` so - // that we can improve it with hints or location or w/ever. and maybe - // only emit it the first time. - switch (ns) - { - case Namespace::Values: - resolved = ctx.values.resolve_path (path.get_segments ()); - break; - case Namespace::Types: - resolved = ctx.types.resolve_path (path.get_segments ()); - break; - case Namespace::Macros: - resolved = ctx.macros.resolve_path (path.get_segments ()); - break; - case Namespace::Labels: - // TODO: Is that okay? - rust_unreachable (); - } - - // FIXME: Ugly - (void) resolved.map ([this, &found, &declared_name, locus, ns] (NodeId id) { - found = true; - - // what do we do with the id? - insert_or_error_out (declared_name, locus, id, ns); - - return id; - }); - }; + auto resolve_and_insert + = [this, &found, &declared_name, locus] (Namespace ns, + const AST::SimplePath &path) { + tl::optional resolved = tl::nullopt; + + // FIXME: resolve_path needs to return an `expected` so + // that we can improve it with hints or location or w/ever. and maybe + // only emit it the first time. + switch (ns) + { + case Namespace::Values: + resolved = ctx.values.resolve_path (path.get_segments ()); + break; + case Namespace::Types: + resolved = ctx.types.resolve_path (path.get_segments ()); + break; + case Namespace::Macros: + resolved = ctx.macros.resolve_path (path.get_segments ()); + break; + case Namespace::Labels: + // TODO: Is that okay? + rust_unreachable (); + } + + // FIXME: Ugly + (void) resolved.map ( + [this, &found, &declared_name, locus, ns, path] (NodeId id) { + found = true; + + // what do we do with the id? + insert_or_error_out (declared_name, locus, id, ns); + auto result = node_forwarding.find (id); + if (result != node_forwarding.cend () + && result->second != path.get_node_id ()) + rust_error_at (path.get_locus (), "%<%s%> defined multiple times", + declared_name.c_str ()); + else // No previous thing has inserted this into our scope + node_forwarding.insert ({id, path.get_node_id ()}); + + return id; + }); + }; // do this for all namespaces (even Labels?) 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 996899b0848f..9354959a41d8 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h @@ -59,6 +59,7 @@ class TopLevel : public DefaultResolver // FIXME: Do we move these to our mappings? std::unordered_map node_locations; + std::unordered_map node_forwarding; void visit (AST::Module &module) override; void visit (AST::MacroRulesDefinition ¯o) override; From fbfca2158df09d3aa55b81ccc55832b9e87e6bf4 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Fri, 15 Sep 2023 15:33:00 +0200 Subject: [PATCH 20/26] Change unresolved import error text The original error text did not match the test nor rustc's behavior. gcc/rust/ChangeLog: * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Update error text to match rustc's one. gcc/testsuite/ChangeLog: * rust/compile/name_resolution14.rs: Update the test with error code. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 3 +-- gcc/testsuite/rust/compile/name_resolution14.rs | 6 +++--- 2 files changed, 4 insertions(+), 5 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 7b4976debec2..558d027a8cd5 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -500,8 +500,7 @@ TopLevel::visit (AST::UseDeclaration &use) for (auto &path : paths) if (!handle_use_dec (path)) rust_error_at (path.get_final_segment ().get_locus (), ErrorCode::E0433, - "could not resolve import %qs", - path.as_string ().c_str ()); + "unresolved import %qs", path.as_string ().c_str ()); } } // namespace Resolver2_0 diff --git a/gcc/testsuite/rust/compile/name_resolution14.rs b/gcc/testsuite/rust/compile/name_resolution14.rs index dba58a745e8b..44c43aa2c0fd 100644 --- a/gcc/testsuite/rust/compile/name_resolution14.rs +++ b/gcc/testsuite/rust/compile/name_resolution14.rs @@ -2,11 +2,11 @@ pub mod foo { pub macro bar() {} } -use foo::biz; // { dg-error "unresolved import .foo::biz." } +use foo::biz; // { dg-error "unresolved import .foo::biz. .E0433." } use foo::{bar, baz, biz}; -// { dg-error "unresolved import .foo::baz." "" { target *-*-* } .-1 } -// { dg-error "unresolved import .foo::biz." "" { target *-*-* } .-2 } +// { dg-error "unresolved import .foo::baz. .E0433." "" { target *-*-* } .-1 } +// { dg-error "unresolved import .foo::biz. .E0433." "" { target *-*-* } .-2 } fn main() { bar!(); From cae4a703aef4bdd16d2209f9c64c5aef389b0ffd Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Fri, 15 Sep 2023 15:57:34 +0200 Subject: [PATCH 21/26] Change name resolution version in test Change the name resoltion algorithm to 2.0 in this test. gcc/testsuite/ChangeLog: * rust/compile/name_resolution14.rs: Add flag to activate name resolution 2.0. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/name_resolution14.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/testsuite/rust/compile/name_resolution14.rs b/gcc/testsuite/rust/compile/name_resolution14.rs index 44c43aa2c0fd..eaef6a52f160 100644 --- a/gcc/testsuite/rust/compile/name_resolution14.rs +++ b/gcc/testsuite/rust/compile/name_resolution14.rs @@ -1,3 +1,5 @@ +// { dg-options "-frust-name-resolution-2.0" } + pub mod foo { pub macro bar() {} } From d60af27297b5c8e2de206d43cf01e1ee7c8479a3 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Fri, 15 Sep 2023 16:09:47 +0200 Subject: [PATCH 22/26] Change name resolution algorithm in one test Change name resolution algorithm in name resolution test 18 to the new name resolution 2.0. gcc/testsuite/ChangeLog: * rust/compile/name_resolution17.rs: Add flag to use new name resolution algorithm. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/name_resolution17.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/testsuite/rust/compile/name_resolution17.rs b/gcc/testsuite/rust/compile/name_resolution17.rs index 84ad380fd956..485947647a95 100644 --- a/gcc/testsuite/rust/compile/name_resolution17.rs +++ b/gcc/testsuite/rust/compile/name_resolution17.rs @@ -1,3 +1,5 @@ +// { dg-options "-frust-name-resolution-2.0" } + struct Foo; fn Foo() {} // { dg-error ".Foo. defined multiple times" } From 825b224196a06676c98ffdbacf0ec5ce90a000d6 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Fri, 15 Sep 2023 16:12:55 +0200 Subject: [PATCH 23/26] Change name resolution algorithm in test Change the name resolution algorithm to name resolution 2.0 in one name resolution test. gcc/testsuite/ChangeLog: * rust/compile/name_resolution18.rs: Add flag to enable name resolution algorithm. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/name_resolution18.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/testsuite/rust/compile/name_resolution18.rs b/gcc/testsuite/rust/compile/name_resolution18.rs index 17a335280278..5940149d3bbf 100644 --- a/gcc/testsuite/rust/compile/name_resolution18.rs +++ b/gcc/testsuite/rust/compile/name_resolution18.rs @@ -1,3 +1,5 @@ +// { dg-options "-frust-name-resolution-2.0" } + struct Marker; struct Foo { From 966932cec90152f7457bd71bcfcc6b1a47356bb2 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 18 Sep 2023 15:34:24 +0200 Subject: [PATCH 24/26] Prevent error emission on resolver reentry The resolver was emitting an error when meeting the same symbol twice. What is important here is the origin of the resolved symbol, we should emit an error when the name is similar but the symbol isn't be not when the resolver is simply meeting the exact same symbol. gcc/rust/ChangeLog: * resolve/rust-toplevel-name-resolver-2.0.cc (insert_macros): Add constraint over the ast node id. (TopLevel::visit): Likewise. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 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 558d027a8cd5..fe13c2886898 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -91,7 +91,7 @@ insert_macros (std::vector ¯os, NameResolutionContext &ctx) { auto res = ctx.macros.insert (macro.get_name (), macro.get_node_id ()); - if (!res) + if (!res && res.error ().existing != macro.get_node_id ()) { rust_error_at (UNKNOWN_LOCATION, ErrorCode::E0428, "macro %qs defined multiple times", @@ -167,7 +167,7 @@ TopLevel::visit (AST::MacroRulesDefinition ¯o) { auto res = ctx.macros.insert_at_root (macro.get_rule_name (), macro.get_node_id ()); - if (!res) + if (!res && res.error ().existing != macro.get_node_id ()) { // TODO: Factor this rich_location rich_loc (line_table, macro.get_locus ()); From 15afef4e9c3e9b9133123db6ef896db432762190 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 9 Nov 2023 00:39:46 +0100 Subject: [PATCH 25/26] late: Add bool builtin type --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 1 + 1 file changed, 1 insertion(+) 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 353d3debb777..cb15fc6f8d4b 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -64,6 +64,7 @@ Late::setup_builtin_types () }; static const LType builtins[] = { + {LType ("bool", new TyTy::BoolType (next_hir_id ()))}, {LType ("u8", new TyTy::UintType (next_hir_id (), TyTy::UintType::U8))}, {LType ("u16", new TyTy::UintType (next_hir_id (), TyTy::UintType::U16))}, {LType ("u32", new TyTy::UintType (next_hir_id (), TyTy::UintType::U32))}, From 022d75c46a35b6faea86b241226684c9ef7dbdf9 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 14 Nov 2023 19:35:48 +0100 Subject: [PATCH 26/26] tests: Re-add macro nr2.0 test cases --- .../rust/compile/name_resolution10.rs | 19 +++++++++++++ .../rust/compile/name_resolution6.rs | 28 +++++++++++++++++++ .../rust/compile/name_resolution8.rs | 26 +++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 gcc/testsuite/rust/compile/name_resolution10.rs create mode 100644 gcc/testsuite/rust/compile/name_resolution6.rs create mode 100644 gcc/testsuite/rust/compile/name_resolution8.rs diff --git a/gcc/testsuite/rust/compile/name_resolution10.rs b/gcc/testsuite/rust/compile/name_resolution10.rs new file mode 100644 index 000000000000..33643bd1a147 --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution10.rs @@ -0,0 +1,19 @@ +// { dg-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } + +#![feature(decl_macro)] + +pub mod foo { + pub mod bar { + pub mod baz { + // macros 2.0 get inserted in Ribs like items + pub macro boof() {} + } + } +} + +#[macro_export] +fn main() { + foo::bar::baz::boof!(); + crate::foo::bar::baz::boof!(); + self::foo::bar::baz::boof!(); +} diff --git a/gcc/testsuite/rust/compile/name_resolution6.rs b/gcc/testsuite/rust/compile/name_resolution6.rs new file mode 100644 index 000000000000..e4087e6281ca --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution6.rs @@ -0,0 +1,28 @@ +// { dg-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } + +pub mod foo { + pub mod bar { + pub mod baz { + pub mod qux { + #[macro_export] + macro_rules! foo { + (one) => {}; + } + + pub fn foo() {} + } + } + + fn f() { + fn inner() { + macro_rules! foo { + (two) => {}; + } + + foo!(two); // ok, textual scope + crate::foo!(one); // ok, path res + super::super::foo!(one); // ok, path res + } + } + } +} diff --git a/gcc/testsuite/rust/compile/name_resolution8.rs b/gcc/testsuite/rust/compile/name_resolution8.rs new file mode 100644 index 000000000000..6fb517033824 --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution8.rs @@ -0,0 +1,26 @@ +// { dg-options "-frust-name-resolution-2.0" } + +// check that macros by example get exported to the crate's root with #[macro_export] +pub mod foo { + pub mod bar { + pub mod baz { + pub mod qux { + #[macro_export] + macro_rules! foo { + (one) => {}; + } + } + } + } +} + +crate::foo!(one); // ok +foo!(one); // ok + +mod a { + mod b { + mod c { + super::super::super::foo!(one); // ok + } + } +}