Merge pull request 2879 from rcrisanti/fix/silence-deprecation-warnings-derive

This commit is contained in:
David Tolnay 2025-09-15 20:26:40 -07:00
commit 373b11dda7
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
9 changed files with 164 additions and 0 deletions

View File

@ -1,5 +1,6 @@
use crate::fragment::{Expr, Fragment, Match, Stmts};
use crate::internals::ast::{Container, Data, Field, Style, Variant};
use crate::internals::deprecated::allow_deprecated;
use crate::internals::name::Name;
use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
use crate::{bound, dummy, pretend, private, this};
@ -22,6 +23,8 @@ pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result<To
precondition(&ctxt, &cont);
ctxt.check()?;
let allow_deprecated = allow_deprecated(input)?;
let ident = &cont.ident;
let params = Parameters::new(&cont);
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(&params);
@ -33,6 +36,7 @@ pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result<To
let used = pretend::pretend_used(&cont, params.is_packed);
quote! {
#[automatically_derived]
#allow_deprecated
impl #de_impl_generics #ident #ty_generics #where_clause {
#vis fn deserialize<__D>(__deserializer: __D) -> _serde::#private::Result<#remote #ty_generics, __D::Error>
where
@ -48,6 +52,7 @@ pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result<To
quote! {
#[automatically_derived]
#allow_deprecated
impl #de_impl_generics _serde::Deserialize<#delife> for #ident #ty_generics #where_clause {
fn deserialize<__D>(__deserializer: __D) -> _serde::#private::Result<Self, __D::Error>
where

View File

@ -0,0 +1,58 @@
use proc_macro2::TokenStream;
use quote::quote;
pub fn allow_deprecated(input: &syn::DeriveInput) -> syn::Result<TokenStream> {
if should_allow_deprecated(input)? {
Ok(quote! { #[allow(deprecated)]})
} else {
Ok(TokenStream::default())
}
}
/// Determine if an `#[allow(deprecated)]` should be added to the derived impl.
///
/// This should happen if the derive input or a variant of the enum (if derive input is an enum)
/// has on of:
/// - `#[deprecated]`
/// - `#[allow(deprecated)]`
fn should_allow_deprecated(input: &syn::DeriveInput) -> syn::Result<bool> {
if contains_deprecated_attrs(&input.attrs)? {
return Ok(true);
}
if let syn::Data::Enum(data_enum) = &input.data {
for variant in &data_enum.variants {
if contains_deprecated_attrs(&variant.attrs)? {
return Ok(true);
}
}
}
Ok(false)
}
/// Check whether a set of attributes contains one of:
/// - `#[deprecated]`
/// - `#[allow(deprecated)]`
fn contains_deprecated_attrs(attrs: &[syn::Attribute]) -> syn::Result<bool> {
for attr in attrs {
if let syn::Meta::Path(path) = &attr.meta {
if path.is_ident("deprecated") {
return Ok(true);
}
}
if let syn::Meta::List(meta_list) = &attr.meta {
if meta_list.path.is_ident("allow") {
let mut deprecated_allowed = false;
meta_list.parse_nested_meta(|meta| {
if meta.path.is_ident("deprecated") {
deprecated_allowed = true;
}
Ok(())
})?;
if deprecated_allowed {
return Ok(true);
}
}
}
}
Ok(false)
}

View File

@ -1,5 +1,6 @@
pub mod ast;
pub mod attr;
pub mod deprecated;
pub mod name;
mod case;

View File

@ -1,5 +1,6 @@
use crate::fragment::{Fragment, Match, Stmts};
use crate::internals::ast::{Container, Data, Field, Style, Variant};
use crate::internals::deprecated::allow_deprecated;
use crate::internals::name::Name;
use crate::internals::{attr, replace_receiver, Ctxt, Derive};
use crate::{bound, dummy, pretend, private, this};
@ -18,6 +19,7 @@ pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<Toke
};
precondition(&ctxt, &cont);
ctxt.check()?;
let allow_deprecated = allow_deprecated(input)?;
let ident = &cont.ident;
let params = Parameters::new(&cont);
@ -29,6 +31,7 @@ pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<Toke
let used = pretend::pretend_used(&cont, params.is_packed);
quote! {
#[automatically_derived]
#allow_deprecated
impl #impl_generics #ident #ty_generics #where_clause {
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::#private::Result<__S::Ok, __S::Error>
where
@ -42,6 +45,7 @@ pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result<Toke
} else {
quote! {
#[automatically_derived]
#allow_deprecated
impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::#private::Result<__S::Ok, __S::Error>
where

View File

@ -0,0 +1,34 @@
#![deny(deprecated)]
#![allow(dead_code)]
use serde_derive::{Deserialize, Serialize};
/// deprecated enum
#[derive(Serialize, Deserialize)]
#[deprecated]
enum E1 {
A,
B,
}
/// deprecated struct
#[derive(Serialize, Deserialize)]
#[deprecated]
struct S1 {
a: bool,
}
/// deprecated enum variant
#[derive(Serialize, Deserialize)]
enum E2 {
A,
#[deprecated]
B,
}
/// deprecated struct field
#[derive(Serialize, Deserialize)]
struct S2 {
#[deprecated]
a: bool,
}

View File

@ -0,0 +1,20 @@
#![deny(deprecated)]
use serde::Deserializer;
use serde_derive::Deserialize;
#[derive(Deserialize)]
pub struct Struct {
#[serde(deserialize_with = "deprecated_with")]
pub field: i32,
}
#[deprecated]
fn deprecated_with<'de, D>(_deserializer: D) -> Result<i32, D::Error>
where
D: Deserializer<'de>,
{
unimplemented!()
}
fn main() {}

View File

@ -0,0 +1,11 @@
error: use of deprecated function `deprecated_with`
--> tests/ui/deprecated/deprecated_de_with.rs:8:32
|
8 | #[serde(deserialize_with = "deprecated_with")]
| ^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> tests/ui/deprecated/deprecated_de_with.rs:1:9
|
1 | #![deny(deprecated)]
| ^^^^^^^^^^

View File

@ -0,0 +1,20 @@
#![deny(deprecated)]
use serde::Serializer;
use serde_derive::Serialize;
#[derive(Serialize)]
pub struct Struct {
#[serde(serialize_with = "deprecated_with")]
pub field: i32,
}
#[deprecated]
fn deprecated_with<S>(_field: &i32, _serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
unimplemented!()
}
fn main() {}

View File

@ -0,0 +1,11 @@
error: use of deprecated function `deprecated_with`
--> tests/ui/deprecated/deprecated_ser_with.rs:8:30
|
8 | #[serde(serialize_with = "deprecated_with")]
| ^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> tests/ui/deprecated/deprecated_ser_with.rs:1:9
|
1 | #![deny(deprecated)]
| ^^^^^^^^^^