diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 552de0153d6..79ea9524b55 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -108,6 +108,7 @@ GRS_OBJS = \
rust/rust-derive-eq.o \
rust/rust-derive-ord.o \
rust/rust-derive-hash.o \
+ rust/rust-derive-coerce-pointee.o \
rust/rust-proc-macro.o \
rust/rust-macro-invoc-lexer.o \
rust/rust-macro-substitute-ctx.o \
diff --git a/gcc/rust/checks/errors/feature/rust-feature-defs.h b/gcc/rust/checks/errors/feature/rust-feature-defs.h
index b541bbd2350..b91a041c665 100644
--- a/gcc/rust/checks/errors/feature/rust-feature-defs.h
+++ b/gcc/rust/checks/errors/feature/rust-feature-defs.h
@@ -521,6 +521,10 @@ FEATURE_ACTIVE ("destructuring_assignment", DESTRUCTURING_ASSIGNMENT, "1.49.0",
ISSUE_SOME (71126), EDITION_NONE)
FEATURE_ACTIVE ("cfg_panic", CFG_PANIC, "1.49.0", ISSUE_SOME (77443),
EDITION_NONE)
+FEATURE_ACTIVE ("derive_coerce_pointee", DERIVE_COERCE_POINTEE,
+ "1.84.0" /* Not sure about the version number for this one */,
+ /* We also need a compatibility check to enable this */
+ ISSUE_SOME (123430), EDITION_NONE)
FEATURE_REMOVED ("import_shadowing", IMPORT_SHADOWING, "1.0.0", ISSUE_NONE,
REASON_NONE)
FEATURE_REMOVED ("managed_boxes", MANAGED_BOXES, "1.0.0", ISSUE_NONE,
diff --git a/gcc/rust/checks/errors/feature/rust-feature-gate.cc b/gcc/rust/checks/errors/feature/rust-feature-gate.cc
index 4cb4583f713..6b481fafa17 100644
--- a/gcc/rust/checks/errors/feature/rust-feature-gate.cc
+++ b/gcc/rust/checks/errors/feature/rust-feature-gate.cc
@@ -262,6 +262,8 @@ FeatureGate::visit (AST::ExternalTypeItem &item)
// `AST::ExternalTypeItem`.
gate (Feature::Name::EXTERN_TYPES, item.get_locus (),
"extern types are experimental");
+
+ AST::DefaultASTVisitor::visit (item);
}
void
diff --git a/gcc/rust/expand/rust-derive-coerce-pointee.cc b/gcc/rust/expand/rust-derive-coerce-pointee.cc
new file mode 100644
index 00000000000..51bb7d3e4ea
--- /dev/null
+++ b/gcc/rust/expand/rust-derive-coerce-pointee.cc
@@ -0,0 +1,76 @@
+// Copyright (C) 2026 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-derive-coerce-pointee.h"
+#include "rust-session-manager.h"
+#include "rust-feature.h"
+#include "rust-feature-store.h"
+
+namespace Rust {
+namespace AST {
+
+DeriveCoercePointee::DeriveCoercePointee (location_t loc,
+ Builder::Source item_source)
+ : DeriveVisitor (loc, item_source)
+{}
+
+std::unique_ptr
+DeriveCoercePointee::go (Item &item)
+{
+ Features::EarlyFeatureGateStore::get ().add (
+ Feature::Name::DERIVE_COERCE_POINTEE,
+ Error (loc, "use of unstable library feature %"));
+
+ // NOTE: This is technically a library feature, so I don't think this is
+ // how it should be gated. But as far as I can tell at the moment we have
+ // no mechanisms for handling these, and furthermore this will go through
+ // our compatibility layer.
+ //
+ // What this means is that the `CoercePointee` macro will *not* be defined
+ // in the `core` that we will be using to compile the kernel at first.
+ //
+ // The basic example for `CoercePointee` is something like this:
+ //
+ // ```rust
+ // use std::marker::CoercePointee;
+ //
+ // #[derive(CoercePointee)]
+ // struct Flip(*const Flop);
+ // ```
+ //
+ // but the marker will not be present in the `core` we will be using at
+ // first, so we will need to fake its existence with
+ // -frust-compat-version, and then the compiler can assume that it is a
+ // built-in derive. At least that's my expectation.
+
+ if (!Session::get_instance ().should_support_coerce_pointee ())
+ {
+ rust_error_at (loc, "derive(CoercePointee) requires a compatibility mode "
+ "greater or equal to 1.84");
+ return {};
+ }
+
+ rust_warning_at (
+ loc, 0,
+ "derive(CoercePointee) is currently unimplemented and has no effect");
+
+ return {};
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-derive-coerce-pointee.h b/gcc/rust/expand/rust-derive-coerce-pointee.h
new file mode 100644
index 00000000000..b6f5c2b464f
--- /dev/null
+++ b/gcc/rust/expand/rust-derive-coerce-pointee.h
@@ -0,0 +1,44 @@
+// Copyright (C) 2026 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_DERIVE_COERCE_POINTEE_H
+#define RUST_DERIVE_COERCE_POINTEE_H
+
+#include "rust-derive.h"
+
+namespace Rust {
+namespace AST {
+
+class DeriveCoercePointee : DeriveVisitor
+{
+public:
+ DeriveCoercePointee (location_t loc, Builder::Source item_source);
+
+ std::unique_ptr- go (Item &item);
+
+private:
+ virtual void visit_struct (StructStruct &item) override {}
+ virtual void visit_tuple (TupleStruct &item) override {}
+ virtual void visit_enum (Enum &item) override {}
+ virtual void visit_union (Union &item) override {}
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DERIVE_COERCE_POINTEE_H
diff --git a/gcc/rust/expand/rust-derive.cc b/gcc/rust/expand/rust-derive.cc
index f45acaa8c24..7e60eff9470 100644
--- a/gcc/rust/expand/rust-derive.cc
+++ b/gcc/rust/expand/rust-derive.cc
@@ -18,6 +18,7 @@
#include "rust-derive.h"
#include "rust-derive-clone.h"
+#include "rust-derive-coerce-pointee.h"
#include "rust-derive-copy.h"
#include "rust-derive-debug.h"
#include "rust-derive-default.h"
@@ -83,6 +84,8 @@ DeriveVisitor::derive (Item &item, const Attribute &attr,
? "RustcEncodable"
: "RustcDecodable");
return {};
+ case BuiltinMacro::CoercePointee:
+ return vec (DeriveCoercePointee (loc, item_source).go (item));
default:
rust_unreachable ();
};
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index d96b23f9992..998477c5253 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -83,6 +83,7 @@ const BiMap MacroBuiltin::builtins = {{
{"Ord", BuiltinMacro::Ord},
{"PartialOrd", BuiltinMacro::PartialOrd},
{"Hash", BuiltinMacro::Hash},
+ {"CoercePointee", BuiltinMacro::CoercePointee},
}};
AST::MacroTranscriberFunc
diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h
index b0c2db57f05..c433ab1a372 100644
--- a/gcc/rust/expand/rust-macro-builtins.h
+++ b/gcc/rust/expand/rust-macro-builtins.h
@@ -76,6 +76,7 @@ enum class BuiltinMacro
Ord,
PartialOrd,
Hash,
+ CoercePointee,
};
tl::optional
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 8b3220d49f3..4860163beb6 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -392,6 +392,12 @@ Early::visit_derive_attribute (AST::Attribute &attr,
auto traits = attr.get_traits_to_derive ();
for (auto &trait : traits)
{
+ // Special case CoercePointee if we're in a proper compatibility mode.
+ // Count it as a builtin derive macro and keep going.
+ if (trait.get ().as_string () == "CoercePointee"
+ && Session::get_instance ().should_support_coerce_pointee ())
+ continue;
+
auto ns_def = ctx.resolve_path (trait.get (), Namespace::Macros);
if (!ns_def.has_value ())
{
diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h
index 6a0acda7c1a..0f4ba7257a1 100644
--- a/gcc/rust/rust-session-manager.h
+++ b/gcc/rust/rust-session-manager.h
@@ -519,6 +519,11 @@ struct Session
return get_compat_version () >= 90;
}
+ bool should_support_coerce_pointee () const
+ {
+ return get_compat_version () >= 84;
+ }
+
private:
Session () : mappings (Analysis::Mappings::get ()) {}
void compile_crate (const char *filename);
diff --git a/gcc/testsuite/rust/compile/derive-coerce-pointee1.rs b/gcc/testsuite/rust/compile/derive-coerce-pointee1.rs
new file mode 100644
index 00000000000..ebc9cde10be
--- /dev/null
+++ b/gcc/testsuite/rust/compile/derive-coerce-pointee1.rs
@@ -0,0 +1,16 @@
+// { dg-additional-options "-frust-compat-version=1.84" }
+
+// check that we error out when the compat mode is right but the feature is missing
+
+#![feature(no_core)]
+#![feature(lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[derive(CoercePointee)] // { dg-warning "no effect" }
+ // { dg-error "use of unstable library feature" "" { target *-*-* } .-1 }
+struct Floop {
+ a: *const T,
+}
diff --git a/gcc/testsuite/rust/compile/derive-coerce-pointee2.rs b/gcc/testsuite/rust/compile/derive-coerce-pointee2.rs
new file mode 100644
index 00000000000..8c84a7fb336
--- /dev/null
+++ b/gcc/testsuite/rust/compile/derive-coerce-pointee2.rs
@@ -0,0 +1,14 @@
+#![feature(no_core)]
+#![feature(lang_items)]
+#![feature(derive_coerce_pointee)]
+#![no_core]
+
+// check that we error out when the feature is right but the compat mode is missing (opposite of derive-coerce-pointee1.rs)
+
+#[lang = "sized"]
+trait Sized {}
+
+#[derive(CoercePointee)]
+// { dg-error "derive.CoercePointee. requires a compatibility mode" "" { target *-*-* } .-1 }
+// { dg-error "could not resolve trait .CoercePointee." "" { target *-*-* } .-2 }
+pub struct Floop(*const T);
diff --git a/gcc/testsuite/rust/compile/derive-coerce-pointee3.rs b/gcc/testsuite/rust/compile/derive-coerce-pointee3.rs
new file mode 100644
index 00000000000..8ca8a1bae58
--- /dev/null
+++ b/gcc/testsuite/rust/compile/derive-coerce-pointee3.rs
@@ -0,0 +1,14 @@
+// { dg-additional-options "-frust-compat-version=1.84" }
+
+// this time everything is enabled - check we fake name resolve properly and we have access to the derive
+
+#![feature(no_core)]
+#![feature(lang_items)]
+#![feature(derive_coerce_pointee)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[derive(CoercePointee)] // { dg-warning "no effect" }
+pub struct Floop(*const T);