Eagerly parse variant-level borrow attribute instead of deferring entire Meta
This commit is contained in:
parent
696f6f56db
commit
e106feb5ec
@ -797,7 +797,12 @@ pub struct Variant {
|
|||||||
other: bool,
|
other: bool,
|
||||||
serialize_with: Option<syn::ExprPath>,
|
serialize_with: Option<syn::ExprPath>,
|
||||||
deserialize_with: Option<syn::ExprPath>,
|
deserialize_with: Option<syn::ExprPath>,
|
||||||
borrow: Option<syn::Meta>,
|
borrow: Option<BorrowAttribute>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BorrowAttribute {
|
||||||
|
path: syn::Path,
|
||||||
|
lifetimes: Option<BTreeSet<syn::Lifetime>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Variant {
|
impl Variant {
|
||||||
@ -950,10 +955,35 @@ impl Variant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defer `#[serde(borrow)]` and `#[serde(borrow = "'a + 'b")]`
|
// Parse `#[serde(borrow)]`
|
||||||
Meta(m) if m.path() == BORROW => match &variant.fields {
|
Meta(Path(word)) if word == BORROW => match &variant.fields {
|
||||||
syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
|
syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
|
||||||
borrow.set(m.path(), m.clone());
|
borrow.set(
|
||||||
|
word,
|
||||||
|
BorrowAttribute {
|
||||||
|
path: word.clone(),
|
||||||
|
lifetimes: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let msg = "#[serde(borrow)] may only be used on newtype variants";
|
||||||
|
cx.error_spanned_by(variant, msg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Parse `#[serde(borrow = "'a + 'b")]`
|
||||||
|
Meta(NameValue(m)) if m.path == BORROW => match &variant.fields {
|
||||||
|
syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
|
||||||
|
if let Ok(lifetimes) = parse_lit_into_lifetimes(cx, BORROW, &m.lit) {
|
||||||
|
borrow.set(
|
||||||
|
&m.path,
|
||||||
|
BorrowAttribute {
|
||||||
|
path: m.path.clone(),
|
||||||
|
lifetimes: Some(lifetimes),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let msg = "#[serde(borrow)] may only be used on newtype variants";
|
let msg = "#[serde(borrow)] may only be used on newtype variants";
|
||||||
@ -1110,17 +1140,29 @@ impl Field {
|
|||||||
None => index.to_string(),
|
None => index.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let variant_borrow = attrs
|
if let Some(borrow_attribute) = attrs.and_then(|variant| variant.borrow.as_ref()) {
|
||||||
.and_then(|variant| variant.borrow.as_ref())
|
if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) {
|
||||||
.map(|borrow| Meta(borrow.clone()));
|
if let Some(lifetimes) = &borrow_attribute.lifetimes {
|
||||||
|
for lifetime in lifetimes {
|
||||||
|
if !borrowable.contains(lifetime) {
|
||||||
|
let msg =
|
||||||
|
format!("field `{}` does not have lifetime {}", ident, lifetime);
|
||||||
|
cx.error_spanned_by(field, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
borrowed_lifetimes.set(&borrow_attribute.path, lifetimes.clone());
|
||||||
|
} else {
|
||||||
|
borrowed_lifetimes.set(&borrow_attribute.path, borrowable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for meta_item in variant_borrow.into_iter().chain(
|
for meta_item in field
|
||||||
field
|
.attrs
|
||||||
.attrs
|
.iter()
|
||||||
.iter()
|
.flat_map(|attr| get_serde_meta_items(cx, attr))
|
||||||
.flat_map(|attr| get_serde_meta_items(cx, attr))
|
.flatten()
|
||||||
.flatten(),
|
{
|
||||||
) {
|
|
||||||
match &meta_item {
|
match &meta_item {
|
||||||
// Parse `#[serde(rename = "foo")]`
|
// Parse `#[serde(rename = "foo")]`
|
||||||
Meta(NameValue(m)) if m.path == RENAME => {
|
Meta(NameValue(m)) if m.path == RENAME => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user