From: Arthur Cohen <[email protected]>

Gate derive(CoercePointee) behind `#![feature(derive_coerce_pointee)` and start 
adding the
infrastructure required to support it. Warn that it doesn't do anything yet.

gcc/rust/ChangeLog:

        * checks/errors/feature/rust-feature-defs.h (FEATURE_ACTIVE): New 
feature.
        * expand/rust-derive.cc (DeriveVisitor::derive): Add base handling for 
CoercePointee derive.
        * expand/rust-macro-builtins.cc: Add CoercePointee as a built-in derive
        * expand/rust-macro-builtins.h (enum class): Likewise.
        * resolve/rust-early-name-resolver-2.0.cc 
(Early::visit_derive_attribute): Special case
        derive(CoercePointee).
        * rust-session-manager.h (should_support_coerce_pointee): New method.
        * expand/rust-derive-coerce-pointee.cc: New file.
        * expand/rust-derive-coerce-pointee.h: New file.
        * Make-lang.in: Compile it.

gcc/testsuite/ChangeLog:

        * rust/compile/derive-coerce-pointee1.rs: New test.
        * rust/compile/derive-coerce-pointee2.rs: New test.
        * rust/compile/derive-coerce-pointee3.rs: New test.
---
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/0fed9b4dbafe137b2a52ef84be8f20fffb3512ca

The commit has NOT been mentioned in any issue.

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4841

 gcc/rust/Make-lang.in                         |  1 +
 .../checks/errors/feature/rust-feature-defs.h |  4 +
 gcc/rust/expand/rust-derive-coerce-pointee.cc | 76 +++++++++++++++++++
 gcc/rust/expand/rust-derive-coerce-pointee.h  | 44 +++++++++++
 gcc/rust/expand/rust-derive.cc                |  3 +
 gcc/rust/expand/rust-macro-builtins.cc        |  1 +
 gcc/rust/expand/rust-macro-builtins.h         |  1 +
 .../resolve/rust-early-name-resolver-2.0.cc   |  6 ++
 gcc/rust/rust-session-manager.h               |  5 ++
 .../rust/compile/derive-coerce-pointee1.rs    | 16 ++++
 .../rust/compile/derive-coerce-pointee2.rs    | 14 ++++
 .../rust/compile/derive-coerce-pointee3.rs    | 14 ++++
 12 files changed, 185 insertions(+)
 create mode 100644 gcc/rust/expand/rust-derive-coerce-pointee.cc
 create mode 100644 gcc/rust/expand/rust-derive-coerce-pointee.h
 create mode 100644 gcc/testsuite/rust/compile/derive-coerce-pointee1.rs
 create mode 100644 gcc/testsuite/rust/compile/derive-coerce-pointee2.rs
 create mode 100644 gcc/testsuite/rust/compile/derive-coerce-pointee3.rs

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 552de0153..79ea9524b 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 b541bbd23..b91a041c6 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/expand/rust-derive-coerce-pointee.cc 
b/gcc/rust/expand/rust-derive-coerce-pointee.cc
new file mode 100644
index 000000000..51bb7d3e4
--- /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
+// <http://www.gnu.org/licenses/>.
+
+#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<AST::Item>
+DeriveCoercePointee::go (Item &item)
+{
+  Features::EarlyFeatureGateStore::get ().add (
+    Feature::Name::DERIVE_COERCE_POINTEE,
+    Error (loc, "use of unstable library feature %<derive_coerce_pointee%>"));
+
+  // 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<Flop>(*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 000000000..b6f5c2b46
--- /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
+// <http://www.gnu.org/licenses/>.
+
+#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<Item> 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 f45acaa8c..7e60eff94 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 d96b23f99..998477c52 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -83,6 +83,7 @@ const BiMap<std::string, BuiltinMacro> 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 b0c2db57f..c433ab1a3 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<BuiltinMacro>
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 8b3220d49..4860163be 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 6a0acda7c..0f4ba7257 100644
--- a/gcc/rust/rust-session-manager.h
+++ b/gcc/rust/rust-session-manager.h
@@ -519,6 +519,11 @@ public:
     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 000000000..ebc9cde10
--- /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<T> {
+    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 000000000..8c84a7fb3
--- /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<T>(*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 000000000..8ca8a1bae
--- /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<T>(*const T);
-- 
2.55.0

Reply via email to