[COMMITTED 17/43] gccrs: error on duplicate extern crate names
arthur.cohen@opensrcsec.com
arthur.cohen@opensrcsec.com
Thu Sep 10 08:19:30 GMT 2026
From: Utkarsh Bahuguna <utkarshbahuguna10@gmail.com>
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 <utkarshbahuguna10@gmail.com>
---
.../rust-toplevel-name-resolver-2.0.cc | 25 +++++++++++++++++--
.../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 +++
.../rust/link/extern_crate_alias_0.rs | 9 +++++++
.../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(-)
create mode 100644 gcc/testsuite/rust/link/extern_crate_alias_0.rs
create mode 100644 gcc/testsuite/rust/link/extern_crate_alias_1.rs
create mode 100644 gcc/testsuite/rust/link/extern_crate_dup_0.rs
create mode 100644 gcc/testsuite/rust/link/extern_crate_dup_1.rs
create mode 100644 gcc/testsuite/rust/link/extern_crate_item_conflict_0.rs
create mode 100644 gcc/testsuite/rust/link/extern_crate_item_conflict_1.rs
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 117bb32fb0f..c7f35b62859 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 897c54158e5..28c340b1cc0 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 10ee87e1bc8..58427b98631 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 3212083b376..dfbec3c88a7 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 00000000000..b47e53572bd
--- /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 00000000000..da27b7f3463
--- /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 00000000000..8fec4d7c025
--- /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 00000000000..da27b7f3463
--- /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 00000000000..034c2405d61
--- /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 00000000000..da27b7f3463
--- /dev/null
+++ b/gcc/testsuite/rust/link/extern_crate_item_conflict_1.rs
@@ -0,0 +1,2 @@
+#![feature(no_core)]
+#![no_core]
--
2.50.1
More information about the Gcc-rust
mailing list