https://gcc.gnu.org/g:c58af0e264218111e122231c82eee6cf747e171e
commit r17-5169-gc58af0e264218111e122231c82eee6cf747e171e Author: Arthur Cohen <[email protected]> Date: Thu Sep 3 19:24:53 2026 +0200 gccrs: derive: Gate CoercePointee and add framework for implementing it. 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. Diff: --- gcc/rust/Make-lang.in | 1 + gcc/rust/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 + gcc/rust/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(+) diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index acecc31416a9..0acd0896ac3c 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 b541bbd23500..b91a041c6656 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 000000000000..51bb7d3e4eae --- /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 000000000000..b6f5c2b464f2 --- /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 f45acaa8c245..7e60eff94704 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 d96b23f99924..998477c52536 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 b0c2db57f058..c433ab1a3725 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 8b3220d49f37..4860163beb64 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 6a0acda7c1a2..0f4ba7257a1a 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 000000000000..ebc9cde10be1 --- /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 000000000000..8c84a7fb3360 --- /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 000000000000..8ca8a1bae584 --- /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);
