Merge pull request #394 from dtolnay/deprecated

Prevent deprecation warning on generated impl for deprecated type
This commit is contained in:
David Tolnay 2024-12-07 09:00:30 -08:00 committed by GitHub
commit 6712f8cca6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 43 additions and 7 deletions

View file

@ -2,7 +2,7 @@ use crate::ast::{Enum, Field, Input, Struct};
use crate::attr::Trait; use crate::attr::Trait;
use crate::generics::InferredBounds; use crate::generics::InferredBounds;
use crate::unraw::MemberUnraw; use crate::unraw::MemberUnraw;
use proc_macro2::{Ident, TokenStream}; use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote, quote_spanned, ToTokens}; use quote::{format_ident, quote, quote_spanned, ToTokens};
use std::collections::BTreeSet as Set; use std::collections::BTreeSet as Set;
use syn::{DeriveInput, GenericArgument, PathArguments, Result, Token, Type}; use syn::{DeriveInput, GenericArgument, PathArguments, Result, Token, Type};
@ -27,7 +27,7 @@ fn try_expand(input: &DeriveInput) -> Result<TokenStream> {
} }
fn fallback(input: &DeriveInput, error: syn::Error) -> TokenStream { 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 (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let error = error.to_compile_error(); let error = error.to_compile_error();
@ -55,7 +55,7 @@ fn fallback(input: &DeriveInput, error: syn::Error) -> TokenStream {
} }
fn impl_struct(input: Struct) -> 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 (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let mut error_inferred_bounds = InferredBounds::new(); let mut error_inferred_bounds = InferredBounds::new();
@ -228,7 +228,7 @@ fn impl_struct(input: Struct) -> TokenStream {
} }
fn impl_enum(input: Enum) -> 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 (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let mut error_inferred_bounds = InferredBounds::new(); 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(ident.span().resolved_at(Span::call_site()));
ident
}
fn fields_pat(fields: &[Field]) -> TokenStream { fn fields_pat(fields: &[Field]) -> TokenStream {
let mut members = fields.iter().map(|field| &field.member).peekable(); let mut members = fields.iter().map(|field| &field.member).peekable();
match members.peek() { match members.peek() {

View file

@ -39,12 +39,37 @@ fn test_deprecated() {
#![deny(deprecated)] #![deny(deprecated)]
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum MyError {
#[deprecated] #[deprecated]
#[error("...")] #[error("...")]
Deprecated, 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("...")]
Variant,
} }
#[allow(deprecated)] #[allow(deprecated)]
let _ = MyError::Deprecated; let _: DeprecatedStruct;
#[allow(deprecated)]
let _: DeprecatedStructField;
#[allow(deprecated)]
let _ = DeprecatedEnum::Variant;
#[allow(deprecated)]
let _ = DeprecatedVariant::Variant;
} }

View file

@ -1,6 +1,8 @@
error[E0277]: `MyError` doesn't implement `std::fmt::Display` error[E0277]: `MyError` doesn't implement `std::fmt::Display`
--> tests/ui/missing-display.rs:4:10 --> tests/ui/missing-display.rs:4:10
| |
3 | #[derive(Error, Debug)]
| ----- in this derive macro expansion
4 | pub enum MyError { 4 | pub enum MyError {
| ^^^^^^^ `MyError` cannot be formatted with the default formatter | ^^^^^^^ `MyError` cannot be formatted with the default formatter
| |
@ -11,3 +13,4 @@ note: required by a bound in `std::error::Error`
| |
| pub trait Error: Debug + Display { | pub trait Error: Debug + Display {
| ^^^^^^^ required by this bound in `Error` | ^^^^^^^ 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)