[gccrs COMMIT] gccrs: error on duplicate extern crate names
gerris.rs@gmail.com
gerris.rs@gmail.com
Tue Aug 11 12:11:52 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>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github: https://github.com/Rust-GCC/gccrs/commit/88c04c2dacbdbb6ef72ef627ed05cc2f7f725c54
The commit has been mentioned in the following issue(s):
- Rust-GCC/gccrs#4679: https://github.com/Rust-GCC/gccrs/issues/4679
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4728
.../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 117bb32fb..c7f35b628 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 897c54158..28c340b1c 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 10ee87e1b..58427b986 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 3212083b3..dfbec3c88 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 000000000..b47e53572
--- /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 000000000..da27b7f34
--- /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 000000000..8fec4d7c0
--- /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 000000000..da27b7f34
--- /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 000000000..034c2405d
--- /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 000000000..da27b7f34
--- /dev/null
+++ b/gcc/testsuite/rust/link/extern_crate_item_conflict_1.rs
@@ -0,0 +1,2 @@
+#![feature(no_core)]
+#![no_core]
base-commit: f3adcfed0203a2acf51e1e2a11dab0074cd9fbf3
--
2.54.0
More information about the Gcc-rust
mailing list