Reject display attribute on a field

This commit is contained in:
David Tolnay 2019-10-12 13:41:56 -07:00
parent 10d1f640da
commit aa123cfe0c
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
5 changed files with 40 additions and 4 deletions

View File

@ -8,12 +8,13 @@ use syn::{
};
pub struct Attrs<'a> {
pub display: Option<Display>,
pub display: Option<Display<'a>>,
pub source: Option<Source<'a>>,
}
#[derive(Clone)]
pub struct Display {
pub struct Display<'a> {
pub original: &'a Attribute,
pub fmt: LitStr,
pub args: TokenStream,
pub was_shorthand: bool,
@ -54,6 +55,7 @@ pub fn get(input: &[Attribute]) -> Result<Attrs> {
fn parse_display(attr: &Attribute) -> Result<Display> {
attr.parse_args_with(|input: ParseStream| {
let mut display = Display {
original: attr,
fmt: input.parse()?,
args: parse_token_expr(input, false)?,
was_shorthand: false,
@ -116,7 +118,7 @@ fn parse_source(attr: &Attribute) -> Result<Source> {
Ok(Source { original: attr })
}
impl ToTokens for Display {
impl ToTokens for Display<'_> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let fmt = &self.fmt;
let args = &self.args;

View File

@ -3,7 +3,7 @@ use proc_macro2::TokenStream;
use quote::quote_spanned;
use syn::{Ident, LitStr};
impl Display {
impl Display<'_> {
// Transform `"error {var}"` to `"error {}", var`.
pub fn expand_shorthand(&mut self) {
if !self.args.is_empty() {

View File

@ -17,6 +17,9 @@ impl Struct<'_> {
fn validate(&self) -> Result<()> {
check_no_source(&self.attrs)?;
find_duplicate_source(&self.fields)?;
for field in &self.fields {
field.validate()?;
}
Ok(())
}
}
@ -42,6 +45,21 @@ impl Variant<'_> {
fn validate(&self) -> Result<()> {
check_no_source(&self.attrs)?;
find_duplicate_source(&self.fields)?;
for field in &self.fields {
field.validate()?;
}
Ok(())
}
}
impl Field<'_> {
fn validate(&self) -> Result<()> {
if let Some(display) = &self.attrs.display {
return Err(Error::new_spanned(
display.original,
"not expected here; the #[error(...)] attribute belongs on top of a struct or an enum variant",
));
}
Ok(())
}
}

View File

@ -0,0 +1,11 @@
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
What {
#[error("...")]
io: std::io::Error,
},
}
fn main() {}

View File

@ -0,0 +1,5 @@
error: not expected here; the #[error(...)] attribute belongs on top of a struct or an enum variant
--> $DIR/unexpected-field-fmt.rs:6:9
|
6 | #[error("...")]
| ^^^^^^^^^^^^^^^