mirror of
https://github.com/dtolnay/thiserror.git
synced 2025-04-06 22:37:38 +03:00
Use IdentUnraw consistently when comparing Member
This commit is contained in:
parent
3d23842d35
commit
9116fdb8ea
8 changed files with 84 additions and 46 deletions
|
@ -1,9 +1,9 @@
|
|||
use crate::attr::{self, Attrs};
|
||||
use crate::generics::ParamsInScope;
|
||||
use crate::unraw::{IdentUnraw, MemberUnraw};
|
||||
use proc_macro2::Span;
|
||||
use syn::{
|
||||
Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Member, Result,
|
||||
Type,
|
||||
Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Result, Type,
|
||||
};
|
||||
|
||||
pub enum Input<'a> {
|
||||
|
@ -35,7 +35,7 @@ pub struct Variant<'a> {
|
|||
pub struct Field<'a> {
|
||||
pub original: &'a syn::Field,
|
||||
pub attrs: Attrs<'a>,
|
||||
pub member: Member,
|
||||
pub member: MemberUnraw,
|
||||
pub ty: &'a Type,
|
||||
pub contains_generic: bool,
|
||||
}
|
||||
|
@ -136,12 +136,13 @@ impl<'a> Field<'a> {
|
|||
Ok(Field {
|
||||
original: node,
|
||||
attrs: attr::get(&node.attrs)?,
|
||||
member: node.ident.clone().map(Member::Named).unwrap_or_else(|| {
|
||||
Member::Unnamed(Index {
|
||||
member: match &node.ident {
|
||||
Some(name) => MemberUnraw::Named(IdentUnraw::new(name.clone())),
|
||||
None => MemberUnraw::Unnamed(Index {
|
||||
index: i as u32,
|
||||
span,
|
||||
})
|
||||
}),
|
||||
}),
|
||||
},
|
||||
ty: &node.ty,
|
||||
contains_generic: scope.intersects(&node.ty),
|
||||
})
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::ast::{Enum, Field, Input, Struct};
|
||||
use crate::attr::Trait;
|
||||
use crate::generics::InferredBounds;
|
||||
use crate::span::MemberSpan;
|
||||
use crate::unraw::MemberUnraw;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote, quote_spanned, ToTokens};
|
||||
use std::collections::BTreeSet as Set;
|
||||
use syn::{DeriveInput, GenericArgument, Member, PathArguments, Result, Token, Type};
|
||||
use syn::{DeriveInput, GenericArgument, PathArguments, Result, Token, Type};
|
||||
|
||||
pub fn derive(input: &DeriveInput) -> TokenStream {
|
||||
match try_expand(input) {
|
||||
|
@ -409,8 +409,8 @@ fn impl_enum(input: Enum) -> TokenStream {
|
|||
}
|
||||
None => {
|
||||
let only_field = match &variant.fields[0].member {
|
||||
Member::Named(ident) => ident.clone(),
|
||||
Member::Unnamed(index) => format_ident!("_{}", index),
|
||||
MemberUnraw::Named(ident) => ident.to_local(),
|
||||
MemberUnraw::Unnamed(index) => format_ident!("_{}", index),
|
||||
};
|
||||
display_implied_bounds.insert((0, Trait::Display));
|
||||
quote!(::core::fmt::Display::fmt(#only_field, __formatter))
|
||||
|
@ -487,11 +487,11 @@ fn impl_enum(input: Enum) -> TokenStream {
|
|||
fn fields_pat(fields: &[Field]) -> TokenStream {
|
||||
let mut members = fields.iter().map(|field| &field.member).peekable();
|
||||
match members.peek() {
|
||||
Some(Member::Named(_)) => quote!({ #(#members),* }),
|
||||
Some(Member::Unnamed(_)) => {
|
||||
Some(MemberUnraw::Named(_)) => quote!({ #(#members),* }),
|
||||
Some(MemberUnraw::Unnamed(_)) => {
|
||||
let vars = members.map(|member| match member {
|
||||
Member::Unnamed(member) => format_ident!("_{}", member),
|
||||
Member::Named(_) => unreachable!(),
|
||||
MemberUnraw::Unnamed(member) => format_ident!("_{}", member),
|
||||
MemberUnraw::Named(_) => unreachable!(),
|
||||
});
|
||||
quote!((#(#vars),*))
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use crate::ast::Field;
|
||||
use crate::attr::{Display, Trait};
|
||||
use crate::scan_expr::scan_expr;
|
||||
use crate::unraw::IdentUnraw;
|
||||
use crate::unraw::{IdentUnraw, MemberUnraw};
|
||||
use proc_macro2::{TokenStream, TokenTree};
|
||||
use quote::{format_ident, quote, quote_spanned};
|
||||
use std::collections::{BTreeSet as Set, HashMap as Map};
|
||||
use syn::ext::IdentExt;
|
||||
use syn::parse::discouraged::Speculative;
|
||||
use syn::parse::{ParseStream, Parser};
|
||||
use syn::{Expr, Ident, Index, LitStr, Member, Result, Token};
|
||||
use syn::{Expr, Ident, Index, LitStr, Result, Token};
|
||||
|
||||
impl Display<'_> {
|
||||
// Transform `"error {var}"` to `"error {}", var`.
|
||||
|
@ -54,7 +54,7 @@ impl Display<'_> {
|
|||
'0'..='9' => {
|
||||
let int = take_int(&mut read);
|
||||
let member = match int.parse::<u32>() {
|
||||
Ok(index) => Member::Unnamed(Index { index, span }),
|
||||
Ok(index) => MemberUnraw::Unnamed(Index { index, span }),
|
||||
Err(_) => return,
|
||||
};
|
||||
if !member_index.contains_key(&member) {
|
||||
|
@ -65,7 +65,7 @@ impl Display<'_> {
|
|||
}
|
||||
'a'..='z' | 'A'..='Z' | '_' => {
|
||||
let ident = Ident::new(take_ident(&mut read), span);
|
||||
Member::Named(ident)
|
||||
MemberUnraw::Named(IdentUnraw::new(ident))
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
|
@ -87,10 +87,10 @@ impl Display<'_> {
|
|||
};
|
||||
implied_bounds.insert((field, bound));
|
||||
}
|
||||
let formatvar = IdentUnraw::new(match &member {
|
||||
Member::Unnamed(index) => format_ident!("_{}", index),
|
||||
Member::Named(ident) => ident.clone(),
|
||||
});
|
||||
let formatvar = match &member {
|
||||
MemberUnraw::Unnamed(index) => IdentUnraw::new(format_ident!("_{}", index)),
|
||||
MemberUnraw::Named(ident) => ident.clone(),
|
||||
};
|
||||
out += &formatvar.to_string();
|
||||
if !named_args.insert(formatvar.clone()) {
|
||||
// Already specified in the format argument list.
|
||||
|
|
|
@ -25,7 +25,6 @@ mod fmt;
|
|||
mod generics;
|
||||
mod prop;
|
||||
mod scan_expr;
|
||||
mod span;
|
||||
mod unraw;
|
||||
mod valid;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::ast::{Enum, Field, Struct, Variant};
|
||||
use crate::span::MemberSpan;
|
||||
use crate::unraw::MemberUnraw;
|
||||
use proc_macro2::Span;
|
||||
use syn::{Member, Type};
|
||||
use syn::Type;
|
||||
|
||||
impl Struct<'_> {
|
||||
pub(crate) fn from_field(&self) -> Option<&Field> {
|
||||
|
@ -101,7 +101,7 @@ fn source_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> {
|
|||
}
|
||||
for field in fields {
|
||||
match &field.member {
|
||||
Member::Named(ident) if ident == "source" => return Some(field),
|
||||
MemberUnraw::Named(ident) if ident == "source" => return Some(field),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
use proc_macro2::Span;
|
||||
use syn::Member;
|
||||
|
||||
pub trait MemberSpan {
|
||||
fn member_span(&self) -> Span;
|
||||
}
|
||||
|
||||
impl MemberSpan for Member {
|
||||
fn member_span(&self) -> Span {
|
||||
match self {
|
||||
Member::Named(ident) => ident.span(),
|
||||
Member::Unnamed(index) => index.span,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,12 +2,14 @@ use proc_macro2::{Ident, Span, TokenStream};
|
|||
use quote::ToTokens;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Display};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use syn::ext::IdentExt as _;
|
||||
use syn::parse::{Parse, ParseStream, Result};
|
||||
use syn::Index;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[repr(transparent)]
|
||||
pub(crate) struct IdentUnraw(Ident);
|
||||
pub struct IdentUnraw(Ident);
|
||||
|
||||
impl IdentUnraw {
|
||||
pub fn new(ident: Ident) -> Self {
|
||||
|
@ -42,6 +44,12 @@ impl PartialEq for IdentUnraw {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for IdentUnraw {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
self.0 == other
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for IdentUnraw {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
Ord::cmp(&self.0.unraw(), &other.0.unraw())
|
||||
|
@ -65,3 +73,47 @@ impl ToTokens for IdentUnraw {
|
|||
self.0.unraw().to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MemberUnraw {
|
||||
Named(IdentUnraw),
|
||||
Unnamed(Index),
|
||||
}
|
||||
|
||||
impl MemberUnraw {
|
||||
pub fn member_span(&self) -> Span {
|
||||
match self {
|
||||
MemberUnraw::Named(ident) => ident.0.span(),
|
||||
MemberUnraw::Unnamed(index) => index.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for MemberUnraw {}
|
||||
|
||||
impl PartialEq for MemberUnraw {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(MemberUnraw::Named(this), MemberUnraw::Named(other)) => this == other,
|
||||
(MemberUnraw::Unnamed(this), MemberUnraw::Unnamed(other)) => this == other,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for MemberUnraw {
|
||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||
match self {
|
||||
MemberUnraw::Named(ident) => ident.0.unraw().hash(hasher),
|
||||
MemberUnraw::Unnamed(index) => index.hash(hasher),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for MemberUnraw {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
match self {
|
||||
MemberUnraw::Named(ident) => ident.to_local().to_tokens(tokens),
|
||||
MemberUnraw::Unnamed(index) => index.to_tokens(tokens),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use crate::ast::{Enum, Field, Input, Struct, Variant};
|
||||
use crate::attr::Attrs;
|
||||
use crate::unraw::MemberUnraw;
|
||||
use quote::ToTokens;
|
||||
use std::collections::BTreeSet as Set;
|
||||
use syn::{Error, GenericArgument, Member, PathArguments, Result, Type};
|
||||
use syn::{Error, GenericArgument, PathArguments, Result, Type};
|
||||
|
||||
impl Input<'_> {
|
||||
pub(crate) fn validate(&self) -> Result<()> {
|
||||
|
@ -204,8 +205,8 @@ fn check_field_attrs(fields: &[Field]) -> Result<()> {
|
|||
|
||||
fn same_member(one: &Field, two: &Field) -> bool {
|
||||
match (&one.member, &two.member) {
|
||||
(Member::Named(one), Member::Named(two)) => one == two,
|
||||
(Member::Unnamed(one), Member::Unnamed(two)) => one.index == two.index,
|
||||
(MemberUnraw::Named(one), MemberUnraw::Named(two)) => one == two,
|
||||
(MemberUnraw::Unnamed(one), MemberUnraw::Unnamed(two)) => one.index == two.index,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue