diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index d1cb95507d91c..7e873347c82b0 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -6,7 +6,6 @@ use rustc_abi::Align; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods}; use rustc_data_structures::fx::FxIndexMap; use rustc_index::IndexVec; -use rustc_macros::TryFromU32; use rustc_middle::ty::TyCtxt; use rustc_session::RemapFileNameExt; use rustc_session::config::RemapPathScopeComponents; @@ -16,7 +15,7 @@ use tracing::debug; use crate::common::CodegenCx; use crate::coverageinfo::llvm_cov; use crate::coverageinfo::mapgen::covfun::prepare_covfun_record; -use crate::llvm; +use crate::{TryFromU32, llvm}; mod covfun; mod spans; diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 2405a25c7020b..807049f08d367 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -14,6 +14,7 @@ #![feature(if_let_guard)] #![feature(impl_trait_in_assoc_type)] #![feature(iter_intersperse)] +#![feature(macro_derive)] #![feature(rustdoc_internals)] #![feature(slice_as_array)] #![feature(try_blocks)] @@ -65,6 +66,7 @@ mod errors; mod intrinsic; mod llvm; mod llvm_util; +mod macros; mod mono_item; mod type_; mod type_of; @@ -74,6 +76,8 @@ mod value; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } +pub(crate) use macros::TryFromU32; + #[derive(Clone)] pub struct LlvmCodegenBackend(()); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index ccbc999dad1f0..c4b5cf413a725 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -19,7 +19,6 @@ use std::ptr; use bitflags::bitflags; use libc::{c_char, c_int, c_uchar, c_uint, c_ulonglong, c_void, size_t}; -use rustc_macros::TryFromU32; use super::RustString; use super::debuginfo::{ @@ -27,8 +26,8 @@ use super::debuginfo::{ DIGlobalVariableExpression, DILocation, DISPFlags, DIScope, DISubprogram, DITemplateTypeParameter, DIType, DebugEmissionKind, DebugNameTableKind, }; -use crate::llvm; use crate::llvm::MetadataKindId; +use crate::{TryFromU32, llvm}; /// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`, /// which has a different ABI from Rust or C++ `bool`. diff --git a/compiler/rustc_codegen_llvm/src/macros.rs b/compiler/rustc_codegen_llvm/src/macros.rs new file mode 100644 index 0000000000000..fddc428ca273b --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/macros.rs @@ -0,0 +1,22 @@ +macro_rules! TryFromU32 { + derive() ( + $(#[$meta:meta])* + $vis:vis enum $Type:ident { + $( + $(#[$varmeta:meta])* + $Variant:ident $(= $discr:expr)? + ),* $(,)? + } + ) => { + impl ::core::convert::TryFrom for $Type { + type Error = u32; + #[allow(deprecated)] // Don't warn about deprecated variants. + fn try_from(value: u32) -> ::core::result::Result<$Type, Self::Error> { + $( if value == const { $Type::$Variant as u32 } { return Ok($Type::$Variant) } )* + Err(value) + } + } + } +} + +pub(crate) use TryFromU32; diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 803b3621c887e..a6f53d92e1006 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -18,7 +18,6 @@ mod print_attribute; mod query; mod serialize; mod symbols; -mod try_from; mod type_foldable; mod type_visitable; mod visitable; @@ -176,14 +175,6 @@ decl_derive!( applicability)] => diagnostics::subdiagnostic_derive ); -decl_derive! { - [TryFromU32] => - /// Derives `TryFrom` for the annotated `enum`, which must have no fields. - /// Each variant maps to the value it would produce under an `as u32` cast. - /// - /// The error type is `u32`. - try_from::try_from_u32 -} decl_derive! { [PrintAttribute] => /// Derives `PrintAttribute` for `AttributeKind`. diff --git a/compiler/rustc_macros/src/try_from.rs b/compiler/rustc_macros/src/try_from.rs deleted file mode 100644 index 9338c1c2b3361..0000000000000 --- a/compiler/rustc_macros/src/try_from.rs +++ /dev/null @@ -1,55 +0,0 @@ -use proc_macro2::TokenStream; -use quote::{quote, quote_spanned}; -use syn::Data; -use syn::spanned::Spanned; -use synstructure::Structure; - -pub(crate) fn try_from_u32(s: Structure<'_>) -> TokenStream { - let span_error = |span, message: &str| { - quote_spanned! { span => const _: () = ::core::compile_error!(#message); } - }; - - // Must be applied to an enum type. - if let Some(span) = match &s.ast().data { - Data::Enum(_) => None, - Data::Struct(s) => Some(s.struct_token.span()), - Data::Union(u) => Some(u.union_token.span()), - } { - return span_error(span, "type is not an enum (TryFromU32)"); - } - - // The enum's variants must not have fields. - let variant_field_errors = s - .variants() - .iter() - .filter_map(|v| v.ast().fields.iter().map(|f| f.span()).next()) - .map(|span| span_error(span, "enum variant cannot have fields (TryFromU32)")) - .collect::(); - if !variant_field_errors.is_empty() { - return variant_field_errors; - } - - let ctor = s - .variants() - .iter() - .map(|v| v.construct(|_, _| -> TokenStream { unreachable!() })) - .collect::>(); - // FIXME(edition_2024): Fix the `keyword_idents_2024` lint to not trigger here? - #[allow(keyword_idents_2024)] - s.gen_impl(quote! { - // The surrounding code might have shadowed these identifiers. - use ::core::convert::TryFrom; - use ::core::primitive::u32; - use ::core::result::Result::{self, Ok, Err}; - - gen impl TryFrom for @Self { - type Error = u32; - - #[allow(deprecated)] // Don't warn about deprecated variants. - fn try_from(value: u32) -> Result { - #( if value == const { #ctor as u32 } { return Ok(#ctor) } )* - Err(value) - } - } - }) -} diff --git a/tests/ui-fulldeps/try-from-u32/errors.rs b/tests/ui-fulldeps/try-from-u32/errors.rs deleted file mode 100644 index a25069c0a53cb..0000000000000 --- a/tests/ui-fulldeps/try-from-u32/errors.rs +++ /dev/null @@ -1,24 +0,0 @@ -#![feature(rustc_private)] -//@ edition: 2021 - -// Checks the error messages produced by `#[derive(TryFromU32)]`. - -extern crate rustc_macros; - -use rustc_macros::TryFromU32; - -#[derive(TryFromU32)] -struct MyStruct {} //~ ERROR type is not an enum - -#[derive(TryFromU32)] -enum NonTrivial { - A, - B(), - C {}, - D(bool), //~ ERROR enum variant cannot have fields - E(bool, bool), //~ ERROR enum variant cannot have fields - F { x: bool }, //~ ERROR enum variant cannot have fields - G { x: bool, y: bool }, //~ ERROR enum variant cannot have fields -} - -fn main() {} diff --git a/tests/ui-fulldeps/try-from-u32/errors.stderr b/tests/ui-fulldeps/try-from-u32/errors.stderr deleted file mode 100644 index d20567061d7bb..0000000000000 --- a/tests/ui-fulldeps/try-from-u32/errors.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error: type is not an enum (TryFromU32) - --> $DIR/errors.rs:11:1 - | -LL | struct MyStruct {} - | ^^^^^^ - -error: enum variant cannot have fields (TryFromU32) - --> $DIR/errors.rs:18:7 - | -LL | D(bool), - | ^^^^ - -error: enum variant cannot have fields (TryFromU32) - --> $DIR/errors.rs:19:7 - | -LL | E(bool, bool), - | ^^^^ - -error: enum variant cannot have fields (TryFromU32) - --> $DIR/errors.rs:20:9 - | -LL | F { x: bool }, - | ^ - -error: enum variant cannot have fields (TryFromU32) - --> $DIR/errors.rs:21:9 - | -LL | G { x: bool, y: bool }, - | ^ - -error: aborting due to 5 previous errors - diff --git a/tests/ui-fulldeps/try-from-u32/hygiene.rs b/tests/ui-fulldeps/try-from-u32/hygiene.rs deleted file mode 100644 index e0655a64a64db..0000000000000 --- a/tests/ui-fulldeps/try-from-u32/hygiene.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![feature(rustc_private)] -//@ edition: 2021 -//@ check-pass - -// Checks that the derive macro still works even if the surrounding code has -// shadowed the relevant library types. - -extern crate rustc_macros; - -mod submod { - use rustc_macros::TryFromU32; - - struct Result; - trait TryFrom {} - #[allow(non_camel_case_types)] - struct u32; - struct Ok; - struct Err; - mod core {} - mod std {} - - #[derive(TryFromU32)] - pub(crate) enum MyEnum { - Zero, - One, - } -} - -fn main() { - use submod::MyEnum; - let _: Result = MyEnum::try_from(1u32); -} diff --git a/tests/ui-fulldeps/try-from-u32/values.rs b/tests/ui-fulldeps/try-from-u32/values.rs deleted file mode 100644 index 180a8f2beb75b..0000000000000 --- a/tests/ui-fulldeps/try-from-u32/values.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![feature(assert_matches)] -#![feature(rustc_private)] -//@ edition: 2021 -//@ run-pass - -// Checks the values accepted by the `TryFrom` impl produced by `#[derive(TryFromU32)]`. - -extern crate rustc_macros; - -use core::assert_matches::assert_matches; -use rustc_macros::TryFromU32; - -#[derive(TryFromU32, Debug, PartialEq)] -#[repr(u32)] -enum Repr { - Zero, - One(), - Seven = 7, -} - -#[derive(TryFromU32, Debug)] -enum NoRepr { - Zero, - One, -} - -fn main() { - assert_eq!(Repr::try_from(0u32), Ok(Repr::Zero)); - assert_eq!(Repr::try_from(1u32), Ok(Repr::One())); - assert_eq!(Repr::try_from(2u32), Err(2)); - assert_eq!(Repr::try_from(7u32), Ok(Repr::Seven)); - - assert_matches!(NoRepr::try_from(0u32), Ok(NoRepr::Zero)); - assert_matches!(NoRepr::try_from(1u32), Ok(NoRepr::One)); - assert_matches!(NoRepr::try_from(2u32), Err(2)); -}