https://gcc.gnu.org/g:5dc8451b867d996d1685cb96f3d1ea7c57c4bcbd
commit r17-4104-g5dc8451b867d996d1685cb96f3d1ea7c57c4bcbd Author: Utkarsh Bahuguna <[email protected]> Date: Tue Aug 11 15:38:32 2026 +0530 gccrs: error on duplicate extern crate names Extern crate declarations did not insert their bound name into any namespace. Because nothing was inserted, the existing duplicate-name check could never fire for extern crates. As a result, both extern crate foo; extern crate foo; and extern crate foo; mod foo {} compiled silently. Insert the bound name, using the alias when one is present, into the type namespace. Record extern crate node ids in Mappings so the check can determine what kind of declaration each side represents. Select E0259 when both sides are extern crates and E0260 when only one side is an extern crate. E0428 remains unchanged for every other item kind. Record the extern crate node in Mappings before calling insert_or_error_out because check_multiple_insertion_error runs inside that call and needs to know whether the new node is an extern crate. This differs from visit (AST::Module&), which records the node after the insertion call. Fixes Rust-GCC/gccrs#4679 gcc/rust/ChangeLog: * util/rust-hir-map.h (Mappings::insert_extern_crate_id) (Mappings::is_extern_crate): New declaration. (Mappings::extern_crate_ids): New member. * util/rust-hir-map.cc (Mappings::insert_extern_crate_id) (Mappings::is_extern_crate): New function. * resolve/rust-toplevel-name-resolver-2.0.h (TopLevel::visit (ExternCrate)): New declaration. * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::check_multiple_insertion_error): Select E0259, E0260 or E0428 based on the colliding declarations. (TopLevel::visit (ExternCrate)): New function definition. gcc/testsuite/ChangeLog: * rust/link/extern_crate_alias_0.rs: New test. * rust/link/extern_crate_alias_1.rs: New test. * rust/link/extern_crate_dup_0.rs: New test. * rust/link/extern_crate_dup_1.rs: New test. * rust/link/extern_crate_item_conflict_0.rs: New test. * rust/link/extern_crate_item_conflict_1.rs: New test. Signed-off-by: Utkarsh Bahuguna <[email protected]> Diff: --- .../resolve/rust-toplevel-name-resolver-2.0.cc | 25 ++++++++++++++++++++-- gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h | 1 + gcc/rust/util/rust-hir-map.cc | 12 +++++++++++ gcc/rust/util/rust-hir-map.h | 4 ++++ gcc/testsuite/rust/link/extern_crate_alias_0.rs | 9 ++++++++ gcc/testsuite/rust/link/extern_crate_alias_1.rs | 2 ++ gcc/testsuite/rust/link/extern_crate_dup_0.rs | 5 +++++ gcc/testsuite/rust/link/extern_crate_dup_1.rs | 2 ++ .../rust/link/extern_crate_item_conflict_0.rs | 5 +++++ .../rust/link/extern_crate_item_conflict_1.rs | 2 ++ 10 files changed, 65 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 117bb32fb0f5..c7f35b62859e 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -50,8 +50,18 @@ TopLevel::check_multiple_insertion_error ( { rich_location rich_loc (line_table, locus); rich_loc.add_range (node_locations[result.error ().existing]); - - rust_error_at (rich_loc, ErrorCode::E0428, "%qs defined multiple times", + auto &mappings = Analysis::Mappings::get (); + ErrorCode code; + if (mappings.is_extern_crate (node_id) + && mappings.is_extern_crate (result.error ().existing)) + code = ErrorCode::E0259; + else if (mappings.is_extern_crate (node_id) + || mappings.is_extern_crate (result.error ().existing)) + code = ErrorCode::E0260; + else + code = ErrorCode::E0428; + + rust_error_at (rich_loc, code, "%qs defined multiple times", identifier.as_string ().c_str ()); } } @@ -127,6 +137,17 @@ TopLevel::visit (AST::Trait &trait) DefaultResolver::visit (trait); } +void +TopLevel::visit (AST::ExternCrate &crate) +{ + auto &name = crate.has_as_clause () ? crate.get_as_clause () + : crate.get_referenced_crate (); + Analysis::Mappings::get ().insert_extern_crate_id (crate.get_node_id ()); + insert_or_error_out (name, crate, Namespace::Types); + + DefaultResolver::visit (crate); +} + void TopLevel::maybe_insert_big_self (AST::Impl &impl) { 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 897c54158e58..28c340b1cc03 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h @@ -167,6 +167,7 @@ private: void visit (AST::Module &module) override; void visit (AST::Trait &trait) override; + void visit (AST::ExternCrate &crate) override; void maybe_insert_big_self (AST::Impl &impl) override; void visit (AST::TraitItemType &trait_item) override; void visit (AST::MacroRulesDefinition ¯o) override; diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 10ee87e1bc8c..58427b98631d 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -1180,6 +1180,18 @@ Mappings::is_module (NodeId id) return module_ids.find (id) != module_ids.end (); } +void +Mappings::insert_extern_crate_id (NodeId id) +{ + extern_crate_ids.insert (id); +} + +bool +Mappings::is_extern_crate (NodeId id) +{ + return extern_crate_ids.find (id) != extern_crate_ids.end (); +} + tl::optional<AST::GlobContainer *> Mappings::lookup_glob_container (NodeId id) { diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 3212083b3769..dfbec3c88a70 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -328,6 +328,9 @@ public: void insert_module_id (NodeId); bool is_module (NodeId id); + void insert_extern_crate_id (NodeId); + bool is_extern_crate (NodeId id); + void insert_module_child (NodeId module, NodeId child); tl::optional<std::vector<NodeId> &> lookup_module_children (NodeId module); @@ -453,6 +456,7 @@ private: std::map<NodeId, AST::GlobContainer *> glob_containers; std::set<NodeId> module_ids; + std::set<NodeId> extern_crate_ids; // AST mappings std::map<NodeId, AST::Item *> ast_item_mappings; diff --git a/gcc/testsuite/rust/link/extern_crate_alias_0.rs b/gcc/testsuite/rust/link/extern_crate_alias_0.rs new file mode 100644 index 000000000000..b47e53572bda --- /dev/null +++ b/gcc/testsuite/rust/link/extern_crate_alias_0.rs @@ -0,0 +1,9 @@ +// TODO: this should compile cleanly. It currently ICEs because the same crate +// gets lowered twice, see Rust-GCC/gccrs#4724. +// { dg-ice "" } + +#![feature(no_core)] +#![no_core] + +extern crate extern_crate_alias_1; +extern crate extern_crate_alias_1 as other; diff --git a/gcc/testsuite/rust/link/extern_crate_alias_1.rs b/gcc/testsuite/rust/link/extern_crate_alias_1.rs new file mode 100644 index 000000000000..da27b7f3463d --- /dev/null +++ b/gcc/testsuite/rust/link/extern_crate_alias_1.rs @@ -0,0 +1,2 @@ +#![feature(no_core)] +#![no_core] diff --git a/gcc/testsuite/rust/link/extern_crate_dup_0.rs b/gcc/testsuite/rust/link/extern_crate_dup_0.rs new file mode 100644 index 000000000000..8fec4d7c0254 --- /dev/null +++ b/gcc/testsuite/rust/link/extern_crate_dup_0.rs @@ -0,0 +1,5 @@ +#![feature(no_core)] +#![no_core] + +extern crate extern_crate_dup_1; +extern crate extern_crate_dup_1; // { dg-error ".extern_crate_dup_1. defined multiple times" } diff --git a/gcc/testsuite/rust/link/extern_crate_dup_1.rs b/gcc/testsuite/rust/link/extern_crate_dup_1.rs new file mode 100644 index 000000000000..da27b7f3463d --- /dev/null +++ b/gcc/testsuite/rust/link/extern_crate_dup_1.rs @@ -0,0 +1,2 @@ +#![feature(no_core)] +#![no_core] diff --git a/gcc/testsuite/rust/link/extern_crate_item_conflict_0.rs b/gcc/testsuite/rust/link/extern_crate_item_conflict_0.rs new file mode 100644 index 000000000000..034c2405d61a --- /dev/null +++ b/gcc/testsuite/rust/link/extern_crate_item_conflict_0.rs @@ -0,0 +1,5 @@ +#![feature(no_core)] +#![no_core] + +extern crate extern_crate_item_conflict_1; +mod extern_crate_item_conflict_1 {} // { dg-error ".extern_crate_item_conflict_1. defined multiple times" } diff --git a/gcc/testsuite/rust/link/extern_crate_item_conflict_1.rs b/gcc/testsuite/rust/link/extern_crate_item_conflict_1.rs new file mode 100644 index 000000000000..da27b7f3463d --- /dev/null +++ b/gcc/testsuite/rust/link/extern_crate_item_conflict_1.rs @@ -0,0 +1,2 @@ +#![feature(no_core)] +#![no_core]
