From a26d60902e1833514c9386583213abd114c915ac Mon Sep 17 00:00:00 2001 From: Brezak Date: Tue, 20 Aug 2024 20:53:49 +0200 Subject: [PATCH] Check that `#[pointee]` is applied only to generic arguments --- compiler/rustc_builtin_macros/messages.ftl | 2 ++ .../src/deriving/smart_ptr.rs | 25 +++++++++++++++++++ compiler/rustc_builtin_macros/src/errors.rs | 7 ++++++ .../ui/deriving/deriving-smart-pointer-neg.rs | 8 ++++++ .../deriving-smart-pointer-neg.stderr | 8 +++++- 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 9695df9c87e8a..8bd07027da46f 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -235,6 +235,8 @@ builtin_macros_non_exhaustive_default = default variant must be exhaustive .label = declared `#[non_exhaustive]` here .help = consider a manual implementation of `Default` +builtin_macros_non_generic_pointee = the `#[pointee]` attribute may only be used on generic parameters + builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants .help = consider a manual implementation of `Default` diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs index bc41d33a609e3..ecf232bac5ce8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs +++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs @@ -13,6 +13,8 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, Symbol}; use thin_vec::{thin_vec, ThinVec}; +use crate::errors; + macro_rules! path { ($span:expr, $($part:ident)::*) => { vec![$(Ident::new(sym::$part, $span),)*] } } @@ -25,6 +27,8 @@ pub(crate) fn expand_deriving_smart_ptr( push: &mut dyn FnMut(Annotatable), _is_const: bool, ) { + item.visit_with(&mut DetectNonGenericPointeeAttr { cx }); + let (name_ident, generics) = if let Annotatable::Item(aitem) = item && let ItemKind::Struct(struct_data, g) = &aitem.kind { @@ -396,3 +400,24 @@ impl<'a> ast::mut_visit::MutVisitor for TypeSubstitution<'a> { } } } + +struct DetectNonGenericPointeeAttr<'a, 'b> { + cx: &'a ExtCtxt<'b>, +} + +impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonGenericPointeeAttr<'a, 'b> { + fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) -> Self::Result { + if attr.has_name(sym::pointee) { + self.cx.dcx().emit_err(errors::NonGenericPointee { span: attr.span }); + } + } + + fn visit_generic_param(&mut self, param: &'a rustc_ast::GenericParam) -> Self::Result { + match param.kind { + GenericParamKind::Type { .. } => return, + GenericParamKind::Lifetime | GenericParamKind::Const { .. } => { + rustc_ast::visit::walk_generic_param(self, param) + } + } + } +} diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 4fffffb91c8b4..625aa4f2b75de 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -937,3 +937,10 @@ pub(crate) struct NakedFunctionTestingAttribute { #[label] pub testing_span: Span, } + +#[derive(Diagnostic)] +#[diag(builtin_macros_non_generic_pointee)] +pub(crate) struct NonGenericPointee { + #[primary_span] + pub span: Span, +} diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.rs b/tests/ui/deriving/deriving-smart-pointer-neg.rs index f02fb56130fa7..e7b45b2fd4b6c 100644 --- a/tests/ui/deriving/deriving-smart-pointer-neg.rs +++ b/tests/ui/deriving/deriving-smart-pointer-neg.rs @@ -53,6 +53,14 @@ struct NoMaybeSized<'a, #[pointee] T> { ptr: &'a T, } +#[derive(SmartPointer)] +#[repr(transparent)] +struct PointeeOnField<'a, #[pointee] T: ?Sized> { + #[pointee] + //~^ ERROR: the `#[pointee]` attribute may only be used on generic parameters + ptr: &'a T +} + // However, reordering attributes should work nevertheless. #[repr(transparent)] #[derive(SmartPointer)] diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.stderr b/tests/ui/deriving/deriving-smart-pointer-neg.stderr index e7c2afc8b00c7..e84b2ee9a6c05 100644 --- a/tests/ui/deriving/deriving-smart-pointer-neg.stderr +++ b/tests/ui/deriving/deriving-smart-pointer-neg.stderr @@ -58,6 +58,12 @@ error: `derive(SmartPointer)` requires T to be marked `?Sized` LL | struct NoMaybeSized<'a, #[pointee] T> { | ^ +error: the `#[pointee]` attribute may only be used on generic parameters + --> $DIR/deriving-smart-pointer-neg.rs:59:5 + | +LL | #[pointee] + | ^^^^^^^^^^ + error[E0392]: lifetime parameter `'a` is never used --> $DIR/deriving-smart-pointer-neg.rs:15:16 | @@ -90,6 +96,6 @@ LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0392`.