Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gcc/rust/Make-lang.in
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
4 changes: 4 additions & 0 deletions gcc/rust/checks/errors/feature/rust-feature-defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions gcc/rust/checks/errors/feature/rust-feature-gate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
76 changes: 76 additions & 0 deletions gcc/rust/expand/rust-derive-coerce-pointee.cc
Original file line number Diff line number Diff line change
@@ -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
44 changes: 44 additions & 0 deletions gcc/rust/expand/rust-derive-coerce-pointee.h
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions gcc/rust/expand/rust-derive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 ();
};
Expand Down
1 change: 1 addition & 0 deletions gcc/rust/expand/rust-macro-builtins.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions gcc/rust/expand/rust-macro-builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ enum class BuiltinMacro
Ord,
PartialOrd,
Hash,
CoercePointee,
};

tl::optional<BuiltinMacro>
Expand Down
6 changes: 6 additions & 0 deletions gcc/rust/resolve/rust-early-name-resolver-2.0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 ())
{
Expand Down
5 changes: 5 additions & 0 deletions gcc/rust/rust-session-manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
16 changes: 16 additions & 0 deletions gcc/testsuite/rust/compile/derive-coerce-pointee1.rs
Original file line number Diff line number Diff line change
@@ -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,
}
14 changes: 14 additions & 0 deletions gcc/testsuite/rust/compile/derive-coerce-pointee2.rs
Original file line number Diff line number Diff line change
@@ -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);
14 changes: 14 additions & 0 deletions gcc/testsuite/rust/compile/derive-coerce-pointee3.rs
Original file line number Diff line number Diff line change
@@ -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);
Loading