diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 6de0a20b6a0a..fe82ab42ec87 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -227,8 +227,9 @@ GRS_OBJS = \
rust/rust-dir-owner.o \
rust/rust-unicode.o \
rust/rust-punycode.o \
- rust/rust-lang-item.o \
rust/rust-expand-format-args.o \
+ rust/rust-lang-item.o \
+ rust/rust-collect-lang-items.o \
$(END)
# removed object files from here
diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc
new file mode 100644
index 000000000000..97ea6a543cb8
--- /dev/null
+++ b/gcc/rust/ast/rust-collect-lang-items.cc
@@ -0,0 +1,96 @@
+// Copyright (C) 2024 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-collect-lang-items.h"
+#include "optional.h"
+#include "rust-ast-collector.h"
+#include "rust-ast.h"
+#include "rust-attribute-values.h"
+#include "rust-attributes.h"
+#include "rust-hir-map.h"
+
+namespace Rust {
+namespace AST {
+
+// FIXME: Before merging: De-duplicate with function in rust-ast-lower-base.cc
+bool
+is_known_attribute (const std::string &attribute_path)
+{
+ const auto &lookup
+ = Analysis::BuiltinAttributeMappings::get ()->lookup_builtin (
+ attribute_path);
+
+ return !lookup.is_error ();
+}
+
+template
+tl::optional
+get_lang_item_attr (const T &maybe_lang_item)
+{
+ for (const auto &attr : maybe_lang_item.get_outer_attrs ())
+ {
+ const auto &str_path = attr.get_path ().as_string ();
+ if (!is_known_attribute (str_path))
+ {
+ rust_error_at (attr.get_locus (), "unknown attribute");
+ continue;
+ }
+
+ bool is_lang_item = str_path == Values::Attributes::LANG
+ && attr.has_attr_input ()
+ && attr.get_attr_input ().get_attr_input_type ()
+ == AST::AttrInput::AttrInputType::LITERAL;
+
+ if (is_lang_item)
+ {
+ auto &literal = static_cast (attr.get_attr_input ());
+ const auto &lang_item_type_str = literal.get_literal ().as_string ();
+
+ return LangItem::Parse (lang_item_type_str);
+ }
+ }
+
+ return tl::nullopt;
+}
+
+template
+void
+CollectLangItems::maybe_add_lang_item (const T &item)
+{
+ if (auto lang_item = get_lang_item_attr (item))
+ mappings.insert_lang_item_node (lang_item.value (), item.get_node_id ());
+}
+
+void
+CollectLangItems::visit (AST::Trait &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit(item);
+}
+
+void
+CollectLangItems::visit (AST::TraitItemType &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit(item);
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-collect-lang-items.h b/gcc/rust/ast/rust-collect-lang-items.h
new file mode 100644
index 000000000000..552648f04eda
--- /dev/null
+++ b/gcc/rust/ast/rust-collect-lang-items.h
@@ -0,0 +1,58 @@
+// Copyright (C) 2024 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_COLLECT_LANG_ITEMS_H
+#define RUST_COLLECT_LANG_ITEMS_H
+
+#include "rust-ast-visitor.h"
+#include "rust-ast.h"
+#include "rust-hir-map.h"
+#include "rust-item.h"
+
+namespace Rust {
+namespace AST {
+
+// This class collects lang items ahead of lowering, as they are now needed for
+// some parts of name resolution
+class CollectLangItems : public DefaultASTVisitor
+{
+public:
+ CollectLangItems () : mappings (Analysis::Mappings::get ()){};
+
+ void go (AST::Crate &crate) { DefaultASTVisitor::visit (crate); }
+
+ Analysis::Mappings &mappings;
+
+ // We must implement visitors for all constructs that could be lang items.
+ // Lang items can be traits, but also enums, and even enum variants.
+ //
+ // https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs
+
+ using DefaultASTVisitor::visit;
+
+ void visit (AST::Trait &item) override;
+ void visit (AST::TraitItemType &item) override;
+
+private:
+ template void maybe_add_lang_item (const T &item);
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_COLLECT_LANG_ITEMS_H
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 1cf58e814f69..561ba95d14e5 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -17,6 +17,7 @@
// .
#include "rust-session-manager.h"
+#include "rust-collect-lang-items.h"
#include "rust-diagnostics.h"
#include "rust-hir-pattern-analysis.h"
#include "rust-immutable-name-resolution-context.h"
@@ -600,6 +601,8 @@ Session::compile_crate (const char *filename)
if (last_step == CompileOptions::CompileStep::Expansion)
return;
+ AST::CollectLangItems ().go (parsed_crate);
+
auto name_resolution_ctx = Resolver2_0::NameResolutionContext ();
// expansion pipeline stage