fix(tvix/nix-compat-derive): Better errors for default

This adds a span to default handling so that any error message
gives a more precise location as a hint for why the error occurred
instead of just pointing to the type.

Change-Id: I7bf6cf38e0284f9726d670ea50a94a6b1edd8a94
Reviewed-on: https://cl.tvl.fyi/c/depot/+/12728
Reviewed-by: Vladimir Kryachko <v.kryachko@gmail.com>
Reviewed-by: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Autosubmit: Brian Olsen <me@griff.name>
This commit is contained in:
Brian Olsen 2024-11-03 20:37:08 +01:00 committed by clbot
parent cae3afc758
commit 6582fa69f1
2 changed files with 13 additions and 7 deletions

View file

@ -111,7 +111,9 @@ fn nix_deserialize_struct(style: Style, fields: &[Field<'_>]) -> TokenStream {
}; };
if let Some(version) = f.attrs.version.as_ref() { if let Some(version) = f.attrs.version.as_ref() {
let default = match &f.attrs.default { let default = match &f.attrs.default {
Default::Default => quote_spanned!(ty.span()=>::std::default::Default::default), Default::Default(span) => {
quote_spanned!(span.span()=>::std::default::Default::default)
}
Default::Path(path) => path.to_token_stream(), Default::Path(path) => path.to_token_stream(),
_ => panic!("No default for versioned field"), _ => panic!("No default for versioned field"),
}; };
@ -172,7 +174,9 @@ fn nix_deserialize_variant(variant: &Variant<'_>) -> TokenStream {
}; };
if let Some(version) = f.attrs.version.as_ref() { if let Some(version) = f.attrs.version.as_ref() {
let default = match &f.attrs.default { let default = match &f.attrs.default {
Default::Default => quote_spanned!(ty.span()=>::std::default::Default::default), Default::Default(span) => {
quote_spanned!(span.span()=>::std::default::Default::default)
}
Default::Path(path) => path.to_token_stream(), Default::Path(path) => path.to_token_stream(),
_ => panic!("No default for versioned field"), _ => panic!("No default for versioned field"),
}; };

View file

@ -10,7 +10,7 @@ use super::Context;
pub enum Default { pub enum Default {
None, None,
#[allow(clippy::enum_variant_names)] #[allow(clippy::enum_variant_names)]
Default, Default(syn::Path),
Path(ExprPath), Path(ExprPath),
} }
@ -29,6 +29,7 @@ pub struct Field {
impl Field { impl Field {
pub fn from_ast(ctx: &Context, attrs: &Vec<Attribute>) -> Field { pub fn from_ast(ctx: &Context, attrs: &Vec<Attribute>) -> Field {
let mut version = None; let mut version = None;
let mut version_path = None;
let mut default = Default::None; let mut default = Default::None;
for attr in attrs { for attr in attrs {
if attr.path() != NIX { if attr.path() != NIX {
@ -37,13 +38,14 @@ impl Field {
if let Err(err) = attr.parse_nested_meta(|meta| { if let Err(err) = attr.parse_nested_meta(|meta| {
if meta.path == VERSION { if meta.path == VERSION {
version = parse_lit(ctx, &meta, VERSION)?; version = parse_lit(ctx, &meta, VERSION)?;
version_path = Some(meta.path);
} else if meta.path == DEFAULT { } else if meta.path == DEFAULT {
if meta.input.peek(Token![=]) { if meta.input.peek(Token![=]) {
if let Some(path) = parse_lit(ctx, &meta, DEFAULT)? { if let Some(path) = parse_lit(ctx, &meta, DEFAULT)? {
default = Default::Path(path); default = Default::Path(path);
} }
} else { } else {
default = Default::Default; default = Default::Default(meta.path);
} }
} else { } else {
let path = meta.path.to_token_stream().to_string(); let path = meta.path.to_token_stream().to_string();
@ -56,7 +58,7 @@ impl Field {
} }
} }
if version.is_some() && default.is_none() { if version.is_some() && default.is_none() {
default = Default::Default; default = Default::Default(version_path.unwrap());
} }
Field { default, version } Field { default, version }
@ -199,7 +201,7 @@ mod test {
assert_eq!( assert_eq!(
field, field,
Field { Field {
default: Default::Default, default: Default::Default(parse_quote!(version)),
version: Some(parse_quote!(..34)), version: Some(parse_quote!(..34)),
} }
); );
@ -214,7 +216,7 @@ mod test {
assert_eq!( assert_eq!(
field, field,
Field { Field {
default: Default::Default, default: Default::Default(parse_quote!(default)),
version: None, version: None,
} }
); );