From 0ba7d01e8ea67ae0f84ab50043f75adbe2903b5e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 7 Dec 2024 08:42:53 -0800 Subject: [PATCH 1/3] Add tests of deprecated error types error: use of deprecated struct `test_deprecated::DeprecatedStruct` --> tests/test_lints.rs:44:16 | 44 | pub struct DeprecatedStruct; | ^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> tests/test_lints.rs:39:13 | 39 | #![deny(deprecated)] | ^^^^^^^^^^ error: use of deprecated struct `test_deprecated::DeprecatedStruct` --> tests/test_lints.rs:44:16 | 44 | pub struct DeprecatedStruct; | ^^^^^^^^^^^^^^^^ error: use of deprecated enum `test_deprecated::DeprecatedEnum` --> tests/test_lints.rs:55:14 | 55 | pub enum DeprecatedEnum { | ^^^^^^^^^^^^^^ --- tests/test_lints.rs | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/tests/test_lints.rs b/tests/test_lints.rs index 6c39fba..b46a391 100644 --- a/tests/test_lints.rs +++ b/tests/test_lints.rs @@ -39,12 +39,37 @@ fn test_deprecated() { #![deny(deprecated)] #[derive(Error, Debug)] - pub enum MyError { + #[deprecated] + #[error("...")] + pub struct DeprecatedStruct; + + #[derive(Error, Debug)] + #[error("{message} {}", .message)] + pub struct DeprecatedStructField { + #[deprecated] + message: String, + } + + #[derive(Error, Debug)] + #[deprecated] + pub enum DeprecatedEnum { + #[error("...")] + Variant, + } + + #[derive(Error, Debug)] + pub enum DeprecatedVariant { #[deprecated] #[error("...")] - Deprecated, + Variant, } #[allow(deprecated)] - let _ = MyError::Deprecated; + let _: DeprecatedStruct; + #[allow(deprecated)] + let _: DeprecatedStructField; + #[allow(deprecated)] + let _ = DeprecatedEnum::Variant; + #[allow(deprecated)] + let _ = DeprecatedVariant::Variant; } From 714229d8214e77df019254afbbca18f1c921737e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 6 Dec 2024 11:00:27 -0800 Subject: [PATCH 2/3] Work around deprecation warning on generated impl for deprecated type --- impl/src/expand.rs | 16 ++++++++++++---- tests/ui/missing-display.stderr | 7 ++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/impl/src/expand.rs b/impl/src/expand.rs index 23e77b6..d657da7 100644 --- a/impl/src/expand.rs +++ b/impl/src/expand.rs @@ -2,7 +2,7 @@ use crate::ast::{Enum, Field, Input, Struct}; use crate::attr::Trait; use crate::generics::InferredBounds; use crate::unraw::MemberUnraw; -use proc_macro2::{Ident, TokenStream}; +use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned, ToTokens}; use std::collections::BTreeSet as Set; use syn::{DeriveInput, GenericArgument, PathArguments, Result, Token, Type}; @@ -27,7 +27,7 @@ fn try_expand(input: &DeriveInput) -> Result { } fn fallback(input: &DeriveInput, error: syn::Error) -> TokenStream { - let ty = &input.ident; + let ty = call_site_ident(&input.ident); let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let error = error.to_compile_error(); @@ -55,7 +55,7 @@ fn fallback(input: &DeriveInput, error: syn::Error) -> TokenStream { } fn impl_struct(input: Struct) -> TokenStream { - let ty = &input.ident; + let ty = call_site_ident(&input.ident); let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let mut error_inferred_bounds = InferredBounds::new(); @@ -228,7 +228,7 @@ fn impl_struct(input: Struct) -> TokenStream { } fn impl_enum(input: Enum) -> TokenStream { - let ty = &input.ident; + let ty = call_site_ident(&input.ident); let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let mut error_inferred_bounds = InferredBounds::new(); @@ -492,6 +492,14 @@ fn impl_enum(input: Enum) -> TokenStream { } } +// Create an ident with which we can expand `impl Trait for #ident {}` on a +// deprecated type without triggering deprecation warning on the generated impl. +fn call_site_ident(ident: &Ident) -> Ident { + let mut ident = ident.clone(); + ident.set_span(Span::call_site()); + ident +} + fn fields_pat(fields: &[Field]) -> TokenStream { let mut members = fields.iter().map(|field| &field.member).peekable(); match members.peek() { diff --git a/tests/ui/missing-display.stderr b/tests/ui/missing-display.stderr index 48c9ded..7b55ad3 100644 --- a/tests/ui/missing-display.stderr +++ b/tests/ui/missing-display.stderr @@ -1,8 +1,8 @@ error[E0277]: `MyError` doesn't implement `std::fmt::Display` - --> tests/ui/missing-display.rs:4:10 + --> tests/ui/missing-display.rs:3:10 | -4 | pub enum MyError { - | ^^^^^^^ `MyError` cannot be formatted with the default formatter +3 | #[derive(Error, Debug)] + | ^^^^^ `MyError` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `MyError` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead @@ -11,3 +11,4 @@ note: required by a bound in `std::error::Error` | | pub trait Error: Debug + Display { | ^^^^^^^ required by this bound in `Error` + = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info) From 07e7d990facdfdbd559df323dae1f5deb1ba9ab6 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 7 Dec 2024 08:56:02 -0800 Subject: [PATCH 3/3] Add "in this derive macro expansion" to missing Display errors --- impl/src/expand.rs | 2 +- tests/ui/missing-display.stderr | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/impl/src/expand.rs b/impl/src/expand.rs index d657da7..52782e3 100644 --- a/impl/src/expand.rs +++ b/impl/src/expand.rs @@ -496,7 +496,7 @@ fn impl_enum(input: Enum) -> TokenStream { // deprecated type without triggering deprecation warning on the generated impl. fn call_site_ident(ident: &Ident) -> Ident { let mut ident = ident.clone(); - ident.set_span(Span::call_site()); + ident.set_span(ident.span().resolved_at(Span::call_site())); ident } diff --git a/tests/ui/missing-display.stderr b/tests/ui/missing-display.stderr index 7b55ad3..f7a044b 100644 --- a/tests/ui/missing-display.stderr +++ b/tests/ui/missing-display.stderr @@ -1,8 +1,10 @@ error[E0277]: `MyError` doesn't implement `std::fmt::Display` - --> tests/ui/missing-display.rs:3:10 + --> tests/ui/missing-display.rs:4:10 | 3 | #[derive(Error, Debug)] - | ^^^^^ `MyError` cannot be formatted with the default formatter + | ----- in this derive macro expansion +4 | pub enum MyError { + | ^^^^^^^ `MyError` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `MyError` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead