From c8d552c6c3ae13c849953d94ea807dd62aeca406 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 3 Sep 2026 17:36:20 +0200 Subject: [PATCH 1/2] feature-gate: Default-visit extern types for completeness gcc/rust/ChangeLog: * checks/errors/feature/rust-feature-gate.cc (FeatureGate::visit): Add missing call to default visitor for ExternType items. --- gcc/rust/checks/errors/feature/rust-feature-gate.cc | 2 ++ 1 file changed, 2 insertions(+) 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 From cc0597d8330ac1e91bda3bed7c5468b6ca215b93 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 3 Sep 2026 19:24:53 +0200 Subject: [PATCH 2/2] 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. --- 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 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/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);