Merge pull request #2847 from dtolnay/newtypewith

Hygiene for macro-generated newtype struct deserialization with `with` attr
This commit is contained in:
David Tolnay 2024-10-22 11:14:18 -07:00 committed by GitHub
commit ef0ed22593
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 3 deletions

View File

@ -875,13 +875,14 @@ fn deserialize_newtype_struct(
) -> TokenStream {
let delife = params.borrowed.de_lifetime();
let field_ty = field.ty;
let deserializer_var = quote!(__e);
let value = match field.attrs.deserialize_with() {
None => {
let span = field.original.span();
let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize);
quote! {
#func(__e)?
#func(#deserializer_var)?
}
}
Some(path) => {
@ -890,7 +891,7 @@ fn deserialize_newtype_struct(
// on the #[serde(with = "...")]
// ^^^^^
quote_spanned! {path.span()=>
#path(__e)?
#path(#deserializer_var)?
}
}
};
@ -906,7 +907,7 @@ fn deserialize_newtype_struct(
quote! {
#[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result<Self::Value, __E::Error>
fn visit_newtype_struct<__E>(self, #deserializer_var: __E) -> _serde::__private::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<#delife>,
{

View File

@ -0,0 +1,27 @@
#![allow(clippy::trivially_copy_pass_by_ref)]
use serde_derive::Deserialize;
macro_rules! declare_in_macro {
($with:literal) => {
#[derive(Deserialize)]
pub struct S(
#[serde(with = $with)]
#[allow(dead_code)]
i32,
);
};
}
declare_in_macro!("with");
mod with {
use serde::Deserializer;
pub fn deserialize<'de, D>(_: D) -> Result<i32, D::Error>
where
D: Deserializer<'de>,
{
unimplemented!()
}
}