diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index ffe3137dd704..ea1644eabf69 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -149,6 +149,7 @@ GRS_OBJS = \
rust/rust-immutable-name-resolution-context.o \
rust/rust-early-name-resolver.o \
rust/rust-name-resolver.o \
+ rust/rust-resolve-builtins.o \
rust/rust-ast-resolve.o \
rust/rust-ast-resolve-base.o \
rust/rust-ast-resolve-item.o \
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 e39ca152c836..6effb7af42f1 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -24,6 +24,7 @@
#include "rust-late-name-resolver-2.0.h"
#include "rust-default-resolver.h"
#include "rust-name-resolution-context.h"
+#include "rust-resolve-builtins.h"
#include "rust-path.h"
#include "rust-system.h"
#include "rust-tyty.h"
@@ -38,84 +39,10 @@ Late::Late (NameResolutionContext &ctx)
: DefaultResolver (ctx), funny_error (false), block_big_self (false)
{}
-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 ()
-{
- // 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 ("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))},
- {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...
- };
-
- // There's a special Rib for putting prelude items, since prelude items need
- // to satisfy certain special rules.
- ctx.scoped (Rib::Kind::Prelude, 0, [this, &ty_ctx] (void) -> void {
- for (const auto &builtin : builtins)
- {
- 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 ();
- ty_ctx.insert_builtin (unit_type->get_ref (), next_node_id (), unit_type);
-}
-
void
Late::go (AST::Crate &crate)
{
- setup_builtin_types ();
+ Builtins::setup_type_ctx ();
visit (crate);
}
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
index 95540e340053..608ae38eb5c1 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -75,9 +75,6 @@ class Late : public DefaultResolver
private:
void resolve_label (AST::Lifetime &lifetime);
- /* Setup Rust's builtin types (u8, i32, !...) in the resolver */
- void setup_builtin_types ();
-
bool funny_error;
/* used to prevent "impl Self {}", "impl (Self, i32) {}", etc */
diff --git a/gcc/rust/resolve/rust-resolve-builtins.cc b/gcc/rust/resolve/rust-resolve-builtins.cc
new file mode 100644
index 000000000000..b16db9a3f63a
--- /dev/null
+++ b/gcc/rust/resolve/rust-resolve-builtins.cc
@@ -0,0 +1,125 @@
+// Copyright (C) 2025 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-resolve-builtins.h"
+#include "rust-name-resolution-context.h"
+#include "rust-tyty.h"
+#include "rust-hir-type-check.h"
+
+namespace Rust {
+namespace Resolver2_0 {
+namespace Builtins {
+
+// Use X-macros
+
+#define TYPE_UINT(n, enum_ident) TYPE1 (n, UintType, UintType::enum_ident)
+#define TYPE_INT(n, enum_ident) TYPE1 (n, IntType, IntType::enum_ident)
+
+#define BUILTIN_TYPES \
+ TYPE0 ("bool", BoolType) \
+ TYPE_UINT ("u8", U8) \
+ TYPE_UINT ("u16", U16) \
+ TYPE_UINT ("u32", U32) \
+ TYPE_UINT ("u64", U64) \
+ TYPE_UINT ("u128", U128) \
+ TYPE_INT ("i8", I8) \
+ TYPE_INT ("i16", I16) \
+ TYPE_INT ("i32", I32) \
+ TYPE_INT ("i64", I64) \
+ TYPE_INT ("i128", I128) \
+ TYPE1 ("f32", FloatType, FloatType::F32) \
+ TYPE1 ("f64", FloatType, FloatType::F64) \
+ TYPE0 ("usize", USizeType) \
+ TYPE0 ("isize", ISizeType) \
+ TYPE0 ("char", CharType) \
+ TYPE0 ("str", StrType) \
+ TYPE0 ("!", NeverType)
+
+// Define constants using X macros
+
+#define TYPE0(...) 1 +
+#define TYPE1(...) 1 +
+static constexpr size_t builtin_count = BUILTIN_TYPES 0;
+#undef TYPE0
+#undef TYPE1
+
+#define TYPE0(n, ...) n,
+#define TYPE1(n, ...) n,
+static constexpr const char *builtin_names[] = {BUILTIN_TYPES};
+#undef TYPE0
+#undef TYPE1
+
+static NodeId builtin_node_ids[builtin_count];
+
+void
+setup_lang_prelude (NameResolutionContext &ctx)
+{
+ auto &mappings = Analysis::Mappings::get ();
+
+ // insert into prelude rib
+ ctx.scoped (Rib::Kind::Prelude, 0, [&mappings, &ctx] (void) -> void {
+ for (size_t i = 0; i < builtin_count; i++)
+ {
+ NodeId node_id = mappings.get_next_node_id ();
+ rust_assert (ctx.types.insert (Identifier (builtin_names[i]), node_id));
+ builtin_node_ids[i] = node_id;
+ }
+ });
+}
+
+void
+setup_type_ctx ()
+{
+ auto &mappings = Analysis::Mappings::get ();
+ auto &ty_ctx = *Resolver::TypeCheckContext::get ();
+
+ HirId hir_ids[builtin_count];
+ for (size_t i = 0; i < builtin_count; i++)
+ hir_ids[i] = mappings.get_next_hir_id ();
+
+ TyTy::BaseType *types[builtin_count];
+ {
+ size_t i = 0;
+#define TYPE_BASE(stub) \
+ types[i] = new TyTy::stub; \
+ i++;
+#define TYPE0(n, ty) TYPE_BASE (ty (hir_ids[i]))
+#define TYPE1(n, ty, p1) TYPE_BASE (ty (hir_ids[i], TyTy::p1))
+ BUILTIN_TYPES
+#undef TYPE_BASE
+#undef TYPE0
+#undef TYPE1
+ }
+
+ for (size_t i = 0; i < builtin_count; i++)
+ {
+ NodeId node_id = builtin_node_ids[i];
+ HirId hir_id = hir_ids[i];
+ mappings.insert_node_to_hir (node_id, hir_id);
+ ty_ctx.insert_builtin (hir_id, node_id, types[i]);
+ }
+
+ // handle unit type separately
+ auto *unit_type = TyTy::TupleType::get_unit_type ();
+ ty_ctx.insert_builtin (unit_type->get_ref (), mappings.get_next_node_id (),
+ unit_type);
+}
+
+} // namespace Builtins
+} // namespace Resolver2_0
+} // namespace Rust
diff --git a/gcc/rust/resolve/rust-resolve-builtins.h b/gcc/rust/resolve/rust-resolve-builtins.h
new file mode 100644
index 000000000000..e7e1bd270b67
--- /dev/null
+++ b/gcc/rust/resolve/rust-resolve-builtins.h
@@ -0,0 +1,37 @@
+// Copyright (C) 2025 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_RESOLVE_BUILTINS_H
+#define RUST_RESOLVE_BUILTINS_H
+
+namespace Rust {
+namespace Resolver2_0 {
+
+// forward declare
+class NameResolutionContext;
+
+namespace Builtins {
+
+void setup_lang_prelude (NameResolutionContext &ctx);
+void setup_type_ctx ();
+
+} // namespace Builtins
+} // namespace Resolver2_0
+} // namespace Rust
+
+#endif // RUST_RESOLVE_BUILTINS_H
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 386aa65b966e..faadc3710a1a 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -48,6 +48,7 @@
#include "rust-name-resolution-context.h"
#include "rust-early-name-resolver-2.0.h"
#include "rust-late-name-resolver-2.0.h"
+#include "rust-resolve-builtins.h"
#include "rust-cfg-strip.h"
#include "rust-expand-visitor.h"
#include "rust-unicode.h"
@@ -934,6 +935,8 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx)
MacroExpander expander (crate, cfg, *this);
std::vector macro_errors;
+ Resolver2_0::Builtins::setup_lang_prelude (ctx);
+
while (!fixed_point_reached && iterations < cfg.recursion_limit)
{
CfgStrip (cfg).go (crate);
diff --git a/gcc/testsuite/rust/compile/primitive-import.rs b/gcc/testsuite/rust/compile/primitive-import.rs
new file mode 100644
index 000000000000..cc750af71988
--- /dev/null
+++ b/gcc/testsuite/rust/compile/primitive-import.rs
@@ -0,0 +1,7 @@
+mod primitive {
+ pub use i32;
+}
+
+pub fn foo() -> primitive::i32 {
+ 1
+}