summaryrefslogtreecommitdiff
path: root/subprojects/thiserror/impl/src
diff options
context:
space:
mode:
authorJohn Turner <jturner.usa@gmail.com>2025-12-21 04:20:53 +0000
committerJohn Turner <jturner.usa@gmail.com>2025-12-22 08:05:20 +0000
commit96708614ba46c42f87b23f2a957c510499d8811e (patch)
tree372dcf90f1a6fdf1b90f5d006ce7a32717f47166 /subprojects/thiserror/impl/src
parent0ec856797256b5d9807929e1b32c03756eb43124 (diff)
downloadgentoo-utils-feature/port-to-meson-cargo.tar.gz
Use the new unstable meson cargo support. This simplifies the meson.build script and allows to use crates such as clap that require picking up features from Cargo.toml. This also allows us to not embed thiserror in subprojects, and instead use a wrap file with a custom meson.build and some patches to make it compile without running its build.rs script.
Diffstat (limited to 'subprojects/thiserror/impl/src')
-rw-r--r--subprojects/thiserror/impl/src/ast.rs185
-rw-r--r--subprojects/thiserror/impl/src/attr.rs358
-rw-r--r--subprojects/thiserror/impl/src/expand.rs584
-rw-r--r--subprojects/thiserror/impl/src/fallback.rs33
-rw-r--r--subprojects/thiserror/impl/src/fmt.rs323
-rw-r--r--subprojects/thiserror/impl/src/generics.rs83
-rw-r--r--subprojects/thiserror/impl/src/lib.rs52
-rw-r--r--subprojects/thiserror/impl/src/prop.rs148
-rw-r--r--subprojects/thiserror/impl/src/scan_expr.rs264
-rw-r--r--subprojects/thiserror/impl/src/unraw.rs142
-rw-r--r--subprojects/thiserror/impl/src/valid.rs248
11 files changed, 0 insertions, 2420 deletions
diff --git a/subprojects/thiserror/impl/src/ast.rs b/subprojects/thiserror/impl/src/ast.rs
deleted file mode 100644
index 77f9583..0000000
--- a/subprojects/thiserror/impl/src/ast.rs
+++ /dev/null
@@ -1,185 +0,0 @@
-use crate::attr::{self, Attrs};
-use crate::generics::ParamsInScope;
-use crate::unraw::{IdentUnraw, MemberUnraw};
-use proc_macro2::Span;
-use std::fmt::{self, Display};
-use syn::{
- Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Result, Type,
-};
-
-pub enum Input<'a> {
- Struct(Struct<'a>),
- Enum(Enum<'a>),
-}
-
-pub struct Struct<'a> {
- pub attrs: Attrs<'a>,
- pub ident: Ident,
- pub generics: &'a Generics,
- pub fields: Vec<Field<'a>>,
-}
-
-pub struct Enum<'a> {
- pub attrs: Attrs<'a>,
- pub ident: Ident,
- pub generics: &'a Generics,
- pub variants: Vec<Variant<'a>>,
-}
-
-pub struct Variant<'a> {
- pub original: &'a syn::Variant,
- pub attrs: Attrs<'a>,
- pub ident: Ident,
- pub fields: Vec<Field<'a>>,
-}
-
-pub struct Field<'a> {
- pub original: &'a syn::Field,
- pub attrs: Attrs<'a>,
- pub member: MemberUnraw,
- pub ty: &'a Type,
- pub contains_generic: bool,
-}
-
-#[derive(Copy, Clone)]
-pub enum ContainerKind {
- Struct,
- TupleStruct,
- UnitStruct,
- StructVariant,
- TupleVariant,
- UnitVariant,
-}
-
-impl<'a> Input<'a> {
- pub fn from_syn(node: &'a DeriveInput) -> Result<Self> {
- match &node.data {
- Data::Struct(data) => Struct::from_syn(node, data).map(Input::Struct),
- Data::Enum(data) => Enum::from_syn(node, data).map(Input::Enum),
- Data::Union(_) => Err(Error::new_spanned(
- node,
- "union as errors are not supported",
- )),
- }
- }
-}
-
-impl<'a> Struct<'a> {
- fn from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result<Self> {
- let mut attrs = attr::get(&node.attrs)?;
- let scope = ParamsInScope::new(&node.generics);
- let fields = Field::multiple_from_syn(&data.fields, &scope)?;
- if let Some(display) = &mut attrs.display {
- let container = ContainerKind::from_struct(data);
- display.expand_shorthand(&fields, container)?;
- }
- Ok(Struct {
- attrs,
- ident: node.ident.clone(),
- generics: &node.generics,
- fields,
- })
- }
-}
-
-impl<'a> Enum<'a> {
- fn from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result<Self> {
- let attrs = attr::get(&node.attrs)?;
- let scope = ParamsInScope::new(&node.generics);
- let variants = data
- .variants
- .iter()
- .map(|node| {
- let mut variant = Variant::from_syn(node, &scope)?;
- if variant.attrs.display.is_none()
- && variant.attrs.transparent.is_none()
- && variant.attrs.fmt.is_none()
- {
- variant.attrs.display.clone_from(&attrs.display);
- variant.attrs.transparent = attrs.transparent;
- variant.attrs.fmt.clone_from(&attrs.fmt);
- }
- if let Some(display) = &mut variant.attrs.display {
- let container = ContainerKind::from_variant(node);
- display.expand_shorthand(&variant.fields, container)?;
- }
- Ok(variant)
- })
- .collect::<Result<_>>()?;
- Ok(Enum {
- attrs,
- ident: node.ident.clone(),
- generics: &node.generics,
- variants,
- })
- }
-}
-
-impl<'a> Variant<'a> {
- fn from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>) -> Result<Self> {
- let attrs = attr::get(&node.attrs)?;
- Ok(Variant {
- original: node,
- attrs,
- ident: node.ident.clone(),
- fields: Field::multiple_from_syn(&node.fields, scope)?,
- })
- }
-}
-
-impl<'a> Field<'a> {
- fn multiple_from_syn(fields: &'a Fields, scope: &ParamsInScope<'a>) -> Result<Vec<Self>> {
- fields
- .iter()
- .enumerate()
- .map(|(i, field)| Field::from_syn(i, field, scope))
- .collect()
- }
-
- fn from_syn(i: usize, node: &'a syn::Field, scope: &ParamsInScope<'a>) -> Result<Self> {
- Ok(Field {
- original: node,
- attrs: attr::get(&node.attrs)?,
- member: match &node.ident {
- Some(name) => MemberUnraw::Named(IdentUnraw::new(name.clone())),
- None => MemberUnraw::Unnamed(Index {
- index: i as u32,
- span: Span::call_site(),
- }),
- },
- ty: &node.ty,
- contains_generic: scope.intersects(&node.ty),
- })
- }
-}
-
-impl ContainerKind {
- fn from_struct(node: &DataStruct) -> Self {
- match node.fields {
- Fields::Named(_) => ContainerKind::Struct,
- Fields::Unnamed(_) => ContainerKind::TupleStruct,
- Fields::Unit => ContainerKind::UnitStruct,
- }
- }
-
- fn from_variant(node: &syn::Variant) -> Self {
- match node.fields {
- Fields::Named(_) => ContainerKind::StructVariant,
- Fields::Unnamed(_) => ContainerKind::TupleVariant,
- Fields::Unit => ContainerKind::UnitVariant,
- }
- }
-}
-
-impl Display for ContainerKind {
- fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter.write_str(match self {
- ContainerKind::Struct => "struct",
- ContainerKind::TupleStruct => "tuple struct",
- ContainerKind::UnitStruct => "unit struct",
- ContainerKind::StructVariant => "struct variant",
- ContainerKind::TupleVariant => "tuple variant",
- ContainerKind::UnitVariant => "unit variant",
- })
- }
-}
diff --git a/subprojects/thiserror/impl/src/attr.rs b/subprojects/thiserror/impl/src/attr.rs
deleted file mode 100644
index 7ad83e0..0000000
--- a/subprojects/thiserror/impl/src/attr.rs
+++ /dev/null
@@ -1,358 +0,0 @@
-use proc_macro2::{Delimiter, Group, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
-use quote::{format_ident, quote, quote_spanned, ToTokens};
-use std::collections::BTreeSet as Set;
-use syn::parse::discouraged::Speculative;
-use syn::parse::{End, ParseStream};
-use syn::{
- braced, bracketed, parenthesized, token, Attribute, Error, ExprPath, Ident, Index, LitFloat,
- LitInt, LitStr, Meta, Result, Token,
-};
-
-pub struct Attrs<'a> {
- pub display: Option<Display<'a>>,
- pub source: Option<Source<'a>>,
- pub backtrace: Option<&'a Attribute>,
- pub from: Option<From<'a>>,
- pub transparent: Option<Transparent<'a>>,
- pub fmt: Option<Fmt<'a>>,
-}
-
-#[derive(Clone)]
-pub struct Display<'a> {
- pub original: &'a Attribute,
- pub fmt: LitStr,
- pub args: TokenStream,
- pub requires_fmt_machinery: bool,
- pub has_bonus_display: bool,
- pub infinite_recursive: bool,
- pub implied_bounds: Set<(usize, Trait)>,
- pub bindings: Vec<(Ident, TokenStream)>,
-}
-
-#[derive(Copy, Clone)]
-pub struct Source<'a> {
- pub original: &'a Attribute,
- pub span: Span,
-}
-
-#[derive(Copy, Clone)]
-pub struct From<'a> {
- pub original: &'a Attribute,
- pub span: Span,
-}
-
-#[derive(Copy, Clone)]
-pub struct Transparent<'a> {
- pub original: &'a Attribute,
- pub span: Span,
-}
-
-#[derive(Clone)]
-pub struct Fmt<'a> {
- pub original: &'a Attribute,
- pub path: ExprPath,
-}
-
-#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
-pub enum Trait {
- Debug,
- Display,
- Octal,
- LowerHex,
- UpperHex,
- Pointer,
- Binary,
- LowerExp,
- UpperExp,
-}
-
-pub fn get(input: &[Attribute]) -> Result<Attrs> {
- let mut attrs = Attrs {
- display: None,
- source: None,
- backtrace: None,
- from: None,
- transparent: None,
- fmt: None,
- };
-
- for attr in input {
- if attr.path().is_ident("error") {
- parse_error_attribute(&mut attrs, attr)?;
- } else if attr.path().is_ident("source") {
- attr.meta.require_path_only()?;
- if attrs.source.is_some() {
- return Err(Error::new_spanned(attr, "duplicate #[source] attribute"));
- }
- let span = (attr.pound_token.span)
- .join(attr.bracket_token.span.join())
- .unwrap_or(attr.path().get_ident().unwrap().span());
- attrs.source = Some(Source {
- original: attr,
- span,
- });
- } else if attr.path().is_ident("backtrace") {
- attr.meta.require_path_only()?;
- if attrs.backtrace.is_some() {
- return Err(Error::new_spanned(attr, "duplicate #[backtrace] attribute"));
- }
- attrs.backtrace = Some(attr);
- } else if attr.path().is_ident("from") {
- match attr.meta {
- Meta::Path(_) => {}
- Meta::List(_) | Meta::NameValue(_) => {
- // Assume this is meant for derive_more crate or something.
- continue;
- }
- }
- if attrs.from.is_some() {
- return Err(Error::new_spanned(attr, "duplicate #[from] attribute"));
- }
- let span = (attr.pound_token.span)
- .join(attr.bracket_token.span.join())
- .unwrap_or(attr.path().get_ident().unwrap().span());
- attrs.from = Some(From {
- original: attr,
- span,
- });
- }
- }
-
- Ok(attrs)
-}
-
-fn parse_error_attribute<'a>(attrs: &mut Attrs<'a>, attr: &'a Attribute) -> Result<()> {
- mod kw {
- syn::custom_keyword!(transparent);
- syn::custom_keyword!(fmt);
- }
-
- attr.parse_args_with(|input: ParseStream| {
- let lookahead = input.lookahead1();
- let fmt = if lookahead.peek(LitStr) {
- input.parse::<LitStr>()?
- } else if lookahead.peek(kw::transparent) {
- let kw: kw::transparent = input.parse()?;
- if attrs.transparent.is_some() {
- return Err(Error::new_spanned(
- attr,
- "duplicate #[error(transparent)] attribute",
- ));
- }
- attrs.transparent = Some(Transparent {
- original: attr,
- span: kw.span,
- });
- return Ok(());
- } else if lookahead.peek(kw::fmt) {
- input.parse::<kw::fmt>()?;
- input.parse::<Token![=]>()?;
- let path: ExprPath = input.parse()?;
- if attrs.fmt.is_some() {
- return Err(Error::new_spanned(
- attr,
- "duplicate #[error(fmt = ...)] attribute",
- ));
- }
- attrs.fmt = Some(Fmt {
- original: attr,
- path,
- });
- return Ok(());
- } else {
- return Err(lookahead.error());
- };
-
- let args = if input.is_empty() || input.peek(Token![,]) && input.peek2(End) {
- input.parse::<Option<Token![,]>>()?;
- TokenStream::new()
- } else {
- parse_token_expr(input, false)?
- };
-
- let requires_fmt_machinery = !args.is_empty();
-
- let display = Display {
- original: attr,
- fmt,
- args,
- requires_fmt_machinery,
- has_bonus_display: false,
- infinite_recursive: false,
- implied_bounds: Set::new(),
- bindings: Vec::new(),
- };
- if attrs.display.is_some() {
- return Err(Error::new_spanned(
- attr,
- "only one #[error(...)] attribute is allowed",
- ));
- }
- attrs.display = Some(display);
- Ok(())
- })
-}
-
-fn parse_token_expr(input: ParseStream, mut begin_expr: bool) -> Result<TokenStream> {
- let mut tokens = Vec::new();
- while !input.is_empty() {
- if input.peek(token::Group) {
- let group: TokenTree = input.parse()?;
- tokens.push(group);
- begin_expr = false;
- continue;
- }
-
- if begin_expr && input.peek(Token![.]) {
- if input.peek2(Ident) {
- input.parse::<Token![.]>()?;
- begin_expr = false;
- continue;
- } else if input.peek2(LitInt) {
- input.parse::<Token![.]>()?;
- let int: Index = input.parse()?;
- tokens.push({
- let ident = format_ident!("_{}", int.index, span = int.span);
- TokenTree::Ident(ident)
- });
- begin_expr = false;
- continue;
- } else if input.peek2(LitFloat) {
- let ahead = input.fork();
- ahead.parse::<Token![.]>()?;
- let float: LitFloat = ahead.parse()?;
- let repr = float.to_string();
- let mut indices = repr.split('.').map(syn::parse_str::<Index>);
- if let (Some(Ok(first)), Some(Ok(second)), None) =
- (indices.next(), indices.next(), indices.next())
- {
- input.advance_to(&ahead);
- tokens.push({
- let ident = format_ident!("_{}", first, span = float.span());
- TokenTree::Ident(ident)
- });
- tokens.push({
- let mut punct = Punct::new('.', Spacing::Alone);
- punct.set_span(float.span());
- TokenTree::Punct(punct)
- });
- tokens.push({
- let mut literal = Literal::u32_unsuffixed(second.index);
- literal.set_span(float.span());
- TokenTree::Literal(literal)
- });
- begin_expr = false;
- continue;
- }
- }
- }
-
- begin_expr = input.peek(Token![break])
- || input.peek(Token![continue])
- || input.peek(Token![if])
- || input.peek(Token![in])
- || input.peek(Token![match])
- || input.peek(Token![mut])
- || input.peek(Token![return])
- || input.peek(Token![while])
- || input.peek(Token![+])
- || input.peek(Token![&])
- || input.peek(Token![!])
- || input.peek(Token![^])
- || input.peek(Token![,])
- || input.peek(Token![/])
- || input.peek(Token![=])
- || input.peek(Token![>])
- || input.peek(Token![<])
- || input.peek(Token![|])
- || input.peek(Token![%])
- || input.peek(Token![;])
- || input.peek(Token![*])
- || input.peek(Token![-]);
-
- let token: TokenTree = if input.peek(token::Paren) {
- let content;
- let delimiter = parenthesized!(content in input);
- let nested = parse_token_expr(&content, true)?;
- let mut group = Group::new(Delimiter::Parenthesis, nested);
- group.set_span(delimiter.span.join());
- TokenTree::Group(group)
- } else if input.peek(token::Brace) {
- let content;
- let delimiter = braced!(content in input);
- let nested = parse_token_expr(&content, true)?;
- let mut group = Group::new(Delimiter::Brace, nested);
- group.set_span(delimiter.span.join());
- TokenTree::Group(group)
- } else if input.peek(token::Bracket) {
- let content;
- let delimiter = bracketed!(content in input);
- let nested = parse_token_expr(&content, true)?;
- let mut group = Group::new(Delimiter::Bracket, nested);
- group.set_span(delimiter.span.join());
- TokenTree::Group(group)
- } else {
- input.parse()?
- };
- tokens.push(token);
- }
- Ok(TokenStream::from_iter(tokens))
-}
-
-impl ToTokens for Display<'_> {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- if self.infinite_recursive {
- let span = self.fmt.span();
- tokens.extend(quote_spanned! {span=>
- #[warn(unconditional_recursion)]
- fn _fmt() { _fmt() }
- });
- }
-
- let fmt = &self.fmt;
- let args = &self.args;
-
- // Currently `write!(f, "text")` produces less efficient code than
- // `f.write_str("text")`. We recognize the case when the format string
- // has no braces and no interpolated values, and generate simpler code.
- let write = if self.requires_fmt_machinery {
- quote! {
- ::core::write!(__formatter, #fmt #args)
- }
- } else {
- quote! {
- __formatter.write_str(#fmt)
- }
- };
-
- tokens.extend(if self.bindings.is_empty() {
- write
- } else {
- let locals = self.bindings.iter().map(|(local, _value)| local);
- let values = self.bindings.iter().map(|(_local, value)| value);
- quote! {
- match (#(#values,)*) {
- (#(#locals,)*) => #write
- }
- }
- });
- }
-}
-
-impl ToTokens for Trait {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- let trait_name = match self {
- Trait::Debug => "Debug",
- Trait::Display => "Display",
- Trait::Octal => "Octal",
- Trait::LowerHex => "LowerHex",
- Trait::UpperHex => "UpperHex",
- Trait::Pointer => "Pointer",
- Trait::Binary => "Binary",
- Trait::LowerExp => "LowerExp",
- Trait::UpperExp => "UpperExp",
- };
- let ident = Ident::new(trait_name, Span::call_site());
- tokens.extend(quote!(::core::fmt::#ident));
- }
-}
diff --git a/subprojects/thiserror/impl/src/expand.rs b/subprojects/thiserror/impl/src/expand.rs
deleted file mode 100644
index 97466dd..0000000
--- a/subprojects/thiserror/impl/src/expand.rs
+++ /dev/null
@@ -1,584 +0,0 @@
-use crate::ast::{Enum, Field, Input, Struct};
-use crate::attr::Trait;
-use crate::fallback;
-use crate::generics::InferredBounds;
-use crate::private;
-use crate::unraw::MemberUnraw;
-use proc_macro2::{Ident, Span, TokenStream};
-use quote::{format_ident, quote, quote_spanned, ToTokens};
-use std::collections::BTreeSet as Set;
-use syn::{DeriveInput, GenericArgument, PathArguments, Result, Token, Type};
-
-pub fn derive(input: &DeriveInput) -> TokenStream {
- match try_expand(input) {
- Ok(expanded) => expanded,
- // If there are invalid attributes in the input, expand to an Error impl
- // anyway to minimize spurious secondary errors in other code that uses
- // this type as an Error.
- Err(error) => fallback::expand(input, error),
- }
-}
-
-fn try_expand(input: &DeriveInput) -> Result<TokenStream> {
- let input = Input::from_syn(input)?;
- input.validate()?;
- Ok(match input {
- Input::Struct(input) => impl_struct(input),
- Input::Enum(input) => impl_enum(input),
- })
-}
-
-fn impl_struct(input: Struct) -> TokenStream {
- let ty = call_site_ident(&input.ident);
- let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
- let mut error_inferred_bounds = InferredBounds::new();
-
- let source_body = if let Some(transparent_attr) = &input.attrs.transparent {
- let only_field = &input.fields[0];
- if only_field.contains_generic {
- error_inferred_bounds.insert(only_field.ty, quote!(::thiserror::#private::Error));
- }
- let member = &only_field.member;
- Some(quote_spanned! {transparent_attr.span=>
- ::thiserror::#private::Error::source(self.#member.as_dyn_error())
- })
- } else if let Some(source_field) = input.source_field() {
- let source = &source_field.member;
- if source_field.contains_generic {
- let ty = unoptional_type(source_field.ty);
- error_inferred_bounds.insert(ty, quote!(::thiserror::#private::Error + 'static));
- }
- let asref = if type_is_option(source_field.ty) {
- Some(quote_spanned!(source.span()=> .as_ref()?))
- } else {
- None
- };
- let dyn_error = quote_spanned! {source_field.source_span()=>
- self.#source #asref.as_dyn_error()
- };
- Some(quote! {
- ::core::option::Option::Some(#dyn_error)
- })
- } else {
- None
- };
- let source_method = source_body.map(|body| {
- quote! {
- fn source(&self) -> ::core::option::Option<&(dyn ::thiserror::#private::Error + 'static)> {
- use ::thiserror::#private::AsDynError as _;
- #body
- }
- }
- });
-
- let provide_method = input.backtrace_field().map(|backtrace_field| {
- let request = quote!(request);
- let backtrace = &backtrace_field.member;
- let body = if let Some(source_field) = input.source_field() {
- let source = &source_field.member;
- let source_provide = if type_is_option(source_field.ty) {
- quote_spanned! {source.span()=>
- if let ::core::option::Option::Some(source) = &self.#source {
- source.thiserror_provide(#request);
- }
- }
- } else {
- quote_spanned! {source.span()=>
- self.#source.thiserror_provide(#request);
- }
- };
- let self_provide = if source == backtrace {
- None
- } else if type_is_option(backtrace_field.ty) {
- Some(quote! {
- if let ::core::option::Option::Some(backtrace) = &self.#backtrace {
- #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace);
- }
- })
- } else {
- Some(quote! {
- #request.provide_ref::<::thiserror::#private::Backtrace>(&self.#backtrace);
- })
- };
- quote! {
- use ::thiserror::#private::ThiserrorProvide as _;
- #source_provide
- #self_provide
- }
- } else if type_is_option(backtrace_field.ty) {
- quote! {
- if let ::core::option::Option::Some(backtrace) = &self.#backtrace {
- #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace);
- }
- }
- } else {
- quote! {
- #request.provide_ref::<::thiserror::#private::Backtrace>(&self.#backtrace);
- }
- };
- quote! {
- fn provide<'_request>(&'_request self, #request: &mut ::core::error::Request<'_request>) {
- #body
- }
- }
- });
-
- let mut display_implied_bounds = Set::new();
- let display_body = if input.attrs.transparent.is_some() {
- let only_field = &input.fields[0].member;
- display_implied_bounds.insert((0, Trait::Display));
- Some(quote! {
- ::core::fmt::Display::fmt(&self.#only_field, __formatter)
- })
- } else if let Some(display) = &input.attrs.display {
- display_implied_bounds.clone_from(&display.implied_bounds);
- let use_as_display = use_as_display(display.has_bonus_display);
- let pat = fields_pat(&input.fields);
- Some(quote! {
- #use_as_display
- #[allow(unused_variables, deprecated)]
- let Self #pat = self;
- #display
- })
- } else {
- None
- };
- let display_impl = display_body.map(|body| {
- let mut display_inferred_bounds = InferredBounds::new();
- for (field, bound) in display_implied_bounds {
- let field = &input.fields[field];
- if field.contains_generic {
- display_inferred_bounds.insert(field.ty, bound);
- }
- }
- let display_where_clause = display_inferred_bounds.augment_where_clause(input.generics);
- quote! {
- #[allow(unused_qualifications)]
- #[automatically_derived]
- impl #impl_generics ::core::fmt::Display for #ty #ty_generics #display_where_clause {
- #[allow(clippy::used_underscore_binding)]
- fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- #body
- }
- }
- }
- });
-
- let from_impl = input.from_field().map(|from_field| {
- let span = from_field.attrs.from.unwrap().span;
- let backtrace_field = input.distinct_backtrace_field();
- let from = unoptional_type(from_field.ty);
- let source_var = Ident::new("source", span);
- let body = from_initializer(from_field, backtrace_field, &source_var);
- let from_function = quote! {
- fn from(#source_var: #from) -> Self {
- #ty #body
- }
- };
- let from_impl = quote_spanned! {span=>
- #[automatically_derived]
- impl #impl_generics ::core::convert::From<#from> for #ty #ty_generics #where_clause {
- #from_function
- }
- };
- Some(quote! {
- #[allow(
- deprecated,
- unused_qualifications,
- clippy::elidable_lifetime_names,
- clippy::needless_lifetimes,
- )]
- #from_impl
- })
- });
-
- if input.generics.type_params().next().is_some() {
- let self_token = <Token![Self]>::default();
- error_inferred_bounds.insert(self_token, Trait::Debug);
- error_inferred_bounds.insert(self_token, Trait::Display);
- }
- let error_where_clause = error_inferred_bounds.augment_where_clause(input.generics);
-
- quote! {
- #[allow(unused_qualifications)]
- #[automatically_derived]
- impl #impl_generics ::thiserror::#private::Error for #ty #ty_generics #error_where_clause {
- #source_method
- #provide_method
- }
- #display_impl
- #from_impl
- }
-}
-
-fn impl_enum(input: Enum) -> TokenStream {
- let ty = call_site_ident(&input.ident);
- let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
- let mut error_inferred_bounds = InferredBounds::new();
-
- let source_method = if input.has_source() {
- let arms = input.variants.iter().map(|variant| {
- let ident = &variant.ident;
- if let Some(transparent_attr) = &variant.attrs.transparent {
- let only_field = &variant.fields[0];
- if only_field.contains_generic {
- error_inferred_bounds.insert(only_field.ty, quote!(::thiserror::#private::Error));
- }
- let member = &only_field.member;
- let source = quote_spanned! {transparent_attr.span=>
- ::thiserror::#private::Error::source(transparent.as_dyn_error())
- };
- quote! {
- #ty::#ident {#member: transparent} => #source,
- }
- } else if let Some(source_field) = variant.source_field() {
- let source = &source_field.member;
- if source_field.contains_generic {
- let ty = unoptional_type(source_field.ty);
- error_inferred_bounds.insert(ty, quote!(::thiserror::#private::Error + 'static));
- }
- let asref = if type_is_option(source_field.ty) {
- Some(quote_spanned!(source.span()=> .as_ref()?))
- } else {
- None
- };
- let varsource = quote!(source);
- let dyn_error = quote_spanned! {source_field.source_span()=>
- #varsource #asref.as_dyn_error()
- };
- quote! {
- #ty::#ident {#source: #varsource, ..} => ::core::option::Option::Some(#dyn_error),
- }
- } else {
- quote! {
- #ty::#ident {..} => ::core::option::Option::None,
- }
- }
- });
- Some(quote! {
- fn source(&self) -> ::core::option::Option<&(dyn ::thiserror::#private::Error + 'static)> {
- use ::thiserror::#private::AsDynError as _;
- #[allow(deprecated)]
- match self {
- #(#arms)*
- }
- }
- })
- } else {
- None
- };
-
- let provide_method = if input.has_backtrace() {
- let request = quote!(request);
- let arms = input.variants.iter().map(|variant| {
- let ident = &variant.ident;
- match (variant.backtrace_field(), variant.source_field()) {
- (Some(backtrace_field), Some(source_field))
- if backtrace_field.attrs.backtrace.is_none() =>
- {
- let backtrace = &backtrace_field.member;
- let source = &source_field.member;
- let varsource = quote!(source);
- let source_provide = if type_is_option(source_field.ty) {
- quote_spanned! {source.span()=>
- if let ::core::option::Option::Some(source) = #varsource {
- source.thiserror_provide(#request);
- }
- }
- } else {
- quote_spanned! {source.span()=>
- #varsource.thiserror_provide(#request);
- }
- };
- let self_provide = if type_is_option(backtrace_field.ty) {
- quote! {
- if let ::core::option::Option::Some(backtrace) = backtrace {
- #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace);
- }
- }
- } else {
- quote! {
- #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace);
- }
- };
- quote! {
- #ty::#ident {
- #backtrace: backtrace,
- #source: #varsource,
- ..
- } => {
- use ::thiserror::#private::ThiserrorProvide as _;
- #source_provide
- #self_provide
- }
- }
- }
- (Some(backtrace_field), Some(source_field))
- if backtrace_field.member == source_field.member =>
- {
- let backtrace = &backtrace_field.member;
- let varsource = quote!(source);
- let source_provide = if type_is_option(source_field.ty) {
- quote_spanned! {backtrace.span()=>
- if let ::core::option::Option::Some(source) = #varsource {
- source.thiserror_provide(#request);
- }
- }
- } else {
- quote_spanned! {backtrace.span()=>
- #varsource.thiserror_provide(#request);
- }
- };
- quote! {
- #ty::#ident {#backtrace: #varsource, ..} => {
- use ::thiserror::#private::ThiserrorProvide as _;
- #source_provide
- }
- }
- }
- (Some(backtrace_field), _) => {
- let backtrace = &backtrace_field.member;
- let body = if type_is_option(backtrace_field.ty) {
- quote! {
- if let ::core::option::Option::Some(backtrace) = backtrace {
- #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace);
- }
- }
- } else {
- quote! {
- #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace);
- }
- };
- quote! {
- #ty::#ident {#backtrace: backtrace, ..} => {
- #body
- }
- }
- }
- (None, _) => quote! {
- #ty::#ident {..} => {}
- },
- }
- });
- Some(quote! {
- fn provide<'_request>(&'_request self, #request: &mut ::core::error::Request<'_request>) {
- #[allow(deprecated)]
- match self {
- #(#arms)*
- }
- }
- })
- } else {
- None
- };
-
- let display_impl = if input.has_display() {
- let mut display_inferred_bounds = InferredBounds::new();
- let has_bonus_display = input.variants.iter().any(|v| {
- v.attrs
- .display
- .as_ref()
- .map_or(false, |display| display.has_bonus_display)
- });
- let use_as_display = use_as_display(has_bonus_display);
- let void_deref = if input.variants.is_empty() {
- Some(quote!(*))
- } else {
- None
- };
- let arms = input.variants.iter().map(|variant| {
- let mut display_implied_bounds = Set::new();
- let display = if let Some(display) = &variant.attrs.display {
- display_implied_bounds.clone_from(&display.implied_bounds);
- display.to_token_stream()
- } else if let Some(fmt) = &variant.attrs.fmt {
- let fmt_path = &fmt.path;
- let vars = variant.fields.iter().map(|field| match &field.member {
- MemberUnraw::Named(ident) => ident.to_local(),
- MemberUnraw::Unnamed(index) => format_ident!("_{}", index),
- });
- quote!(#fmt_path(#(#vars,)* __formatter))
- } else {
- let only_field = match &variant.fields[0].member {
- 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))
- };
- for (field, bound) in display_implied_bounds {
- let field = &variant.fields[field];
- if field.contains_generic {
- display_inferred_bounds.insert(field.ty, bound);
- }
- }
- let ident = &variant.ident;
- let pat = fields_pat(&variant.fields);
- quote! {
- #ty::#ident #pat => #display
- }
- });
- let arms = arms.collect::<Vec<_>>();
- let display_where_clause = display_inferred_bounds.augment_where_clause(input.generics);
- Some(quote! {
- #[allow(unused_qualifications)]
- #[automatically_derived]
- impl #impl_generics ::core::fmt::Display for #ty #ty_generics #display_where_clause {
- fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- #use_as_display
- #[allow(unused_variables, deprecated, clippy::used_underscore_binding)]
- match #void_deref self {
- #(#arms,)*
- }
- }
- }
- })
- } else {
- None
- };
-
- let from_impls = input.variants.iter().filter_map(|variant| {
- let from_field = variant.from_field()?;
- let span = from_field.attrs.from.unwrap().span;
- let backtrace_field = variant.distinct_backtrace_field();
- let variant = &variant.ident;
- let from = unoptional_type(from_field.ty);
- let source_var = Ident::new("source", span);
- let body = from_initializer(from_field, backtrace_field, &source_var);
- let from_function = quote! {
- fn from(#source_var: #from) -> Self {
- #ty::#variant #body
- }
- };
- let from_impl = quote_spanned! {span=>
- #[automatically_derived]
- impl #impl_generics ::core::convert::From<#from> for #ty #ty_generics #where_clause {
- #from_function
- }
- };
- Some(quote! {
- #[allow(
- deprecated,
- unused_qualifications,
- clippy::elidable_lifetime_names,
- clippy::needless_lifetimes,
- )]
- #from_impl
- })
- });
-
- if input.generics.type_params().next().is_some() {
- let self_token = <Token![Self]>::default();
- error_inferred_bounds.insert(self_token, Trait::Debug);
- error_inferred_bounds.insert(self_token, Trait::Display);
- }
- let error_where_clause = error_inferred_bounds.augment_where_clause(input.generics);
-
- quote! {
- #[allow(unused_qualifications)]
- #[automatically_derived]
- impl #impl_generics ::thiserror::#private::Error for #ty #ty_generics #error_where_clause {
- #source_method
- #provide_method
- }
- #display_impl
- #(#from_impls)*
- }
-}
-
-// Create an ident with which we can expand `impl Trait for #ident {}` on a
-// deprecated type without triggering deprecation warning on the generated impl.
-pub(crate) fn call_site_ident(ident: &Ident) -> Ident {
- let mut ident = ident.clone();
- ident.set_span(ident.span().resolved_at(Span::call_site()));
- ident
-}
-
-fn fields_pat(fields: &[Field]) -> TokenStream {
- let mut members = fields.iter().map(|field| &field.member).peekable();
- match members.peek() {
- Some(MemberUnraw::Named(_)) => quote!({ #(#members),* }),
- Some(MemberUnraw::Unnamed(_)) => {
- let vars = members.map(|member| match member {
- MemberUnraw::Unnamed(index) => format_ident!("_{}", index),
- MemberUnraw::Named(_) => unreachable!(),
- });
- quote!((#(#vars),*))
- }
- None => quote!({}),
- }
-}
-
-fn use_as_display(needs_as_display: bool) -> Option<TokenStream> {
- if needs_as_display {
- Some(quote! {
- use ::thiserror::#private::AsDisplay as _;
- })
- } else {
- None
- }
-}
-
-fn from_initializer(
- from_field: &Field,
- backtrace_field: Option<&Field>,
- source_var: &Ident,
-) -> TokenStream {
- let from_member = &from_field.member;
- let some_source = if type_is_option(from_field.ty) {
- quote!(::core::option::Option::Some(#source_var))
- } else {
- quote!(#source_var)
- };
- let backtrace = backtrace_field.map(|backtrace_field| {
- let backtrace_member = &backtrace_field.member;
- if type_is_option(backtrace_field.ty) {
- quote! {
- #backtrace_member: ::core::option::Option::Some(::thiserror::#private::Backtrace::capture()),
- }
- } else {
- quote! {
- #backtrace_member: ::core::convert::From::from(::thiserror::#private::Backtrace::capture()),
- }
- }
- });
- quote!({
- #from_member: #some_source,
- #backtrace
- })
-}
-
-fn type_is_option(ty: &Type) -> bool {
- type_parameter_of_option(ty).is_some()
-}
-
-fn unoptional_type(ty: &Type) -> TokenStream {
- let unoptional = type_parameter_of_option(ty).unwrap_or(ty);
- quote!(#unoptional)
-}
-
-fn type_parameter_of_option(ty: &Type) -> Option<&Type> {
- let path = match ty {
- Type::Path(ty) => &ty.path,
- _ => return None,
- };
-
- let last = path.segments.last().unwrap();
- if last.ident != "Option" {
- return None;
- }
-
- let bracketed = match &last.arguments {
- PathArguments::AngleBracketed(bracketed) => bracketed,
- _ => return None,
- };
-
- if bracketed.args.len() != 1 {
- return None;
- }
-
- match &bracketed.args[0] {
- GenericArgument::Type(arg) => Some(arg),
- _ => None,
- }
-}
diff --git a/subprojects/thiserror/impl/src/fallback.rs b/subprojects/thiserror/impl/src/fallback.rs
deleted file mode 100644
index 9914aa5..0000000
--- a/subprojects/thiserror/impl/src/fallback.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-use crate::expand::call_site_ident;
-use crate::private;
-use proc_macro2::TokenStream;
-use quote::quote;
-use syn::DeriveInput;
-
-pub(crate) fn expand(input: &DeriveInput, error: syn::Error) -> TokenStream {
- let ty = call_site_ident(&input.ident);
- let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
-
- let error = error.to_compile_error();
-
- quote! {
- #error
-
- #[allow(unused_qualifications)]
- #[automatically_derived]
- impl #impl_generics ::thiserror::#private::Error for #ty #ty_generics #where_clause
- where
- // Work around trivial bounds being unstable.
- // https://github.com/rust-lang/rust/issues/48214
- for<'workaround> #ty #ty_generics: ::core::fmt::Debug,
- {}
-
- #[allow(unused_qualifications)]
- #[automatically_derived]
- impl #impl_generics ::core::fmt::Display for #ty #ty_generics #where_clause {
- fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::unreachable!()
- }
- }
- }
-}
diff --git a/subprojects/thiserror/impl/src/fmt.rs b/subprojects/thiserror/impl/src/fmt.rs
deleted file mode 100644
index 2988ca3..0000000
--- a/subprojects/thiserror/impl/src/fmt.rs
+++ /dev/null
@@ -1,323 +0,0 @@
-use crate::ast::{ContainerKind, Field};
-use crate::attr::{Display, Trait};
-use crate::private;
-use crate::scan_expr::scan_expr;
-use crate::unraw::{IdentUnraw, MemberUnraw};
-use proc_macro2::{Delimiter, TokenStream, TokenTree};
-use quote::{format_ident, quote, quote_spanned, ToTokens as _};
-use std::collections::{BTreeSet, HashMap};
-use std::iter;
-use syn::ext::IdentExt;
-use syn::parse::discouraged::Speculative;
-use syn::parse::{Error, ParseStream, Parser, Result};
-use syn::{Expr, Ident, Index, LitStr, Token};
-
-impl Display<'_> {
- pub fn expand_shorthand(&mut self, fields: &[Field], container: ContainerKind) -> Result<()> {
- let raw_args = self.args.clone();
- let FmtArguments {
- named: user_named_args,
- first_unnamed,
- } = explicit_named_args.parse2(raw_args).unwrap();
-
- let mut member_index = HashMap::new();
- let mut extra_positional_arguments_allowed = true;
- for (i, field) in fields.iter().enumerate() {
- member_index.insert(&field.member, i);
- extra_positional_arguments_allowed &= matches!(&field.member, MemberUnraw::Named(_));
- }
-
- let span = self.fmt.span();
- let fmt = self.fmt.value();
- let mut read = fmt.as_str();
- let mut out = String::new();
- let mut has_bonus_display = false;
- let mut infinite_recursive = false;
- let mut implied_bounds = BTreeSet::new();
- let mut bindings = Vec::new();
- let mut macro_named_args = BTreeSet::new();
-
- self.requires_fmt_machinery = self.requires_fmt_machinery || fmt.contains('}');
-
- while let Some(brace) = read.find('{') {
- self.requires_fmt_machinery = true;
- out += &read[..brace + 1];
- read = &read[brace + 1..];
- if read.starts_with('{') {
- out.push('{');
- read = &read[1..];
- continue;
- }
- let next = match read.chars().next() {
- Some(next) => next,
- None => return Ok(()),
- };
- let member = match next {
- '0'..='9' => {
- let int = take_int(&mut read);
- if !extra_positional_arguments_allowed {
- if let Some(first_unnamed) = &first_unnamed {
- let msg = format!("ambiguous reference to positional arguments by number in a {container}; change this to a named argument");
- return Err(Error::new_spanned(first_unnamed, msg));
- }
- }
- match int.parse::<u32>() {
- Ok(index) => MemberUnraw::Unnamed(Index { index, span }),
- Err(_) => return Ok(()),
- }
- }
- 'a'..='z' | 'A'..='Z' | '_' => {
- if read.starts_with("r#") {
- continue;
- }
- let repr = take_ident(&mut read);
- if repr == "_" {
- // Invalid. Let rustc produce the diagnostic.
- out += repr;
- continue;
- }
- let ident = IdentUnraw::new(Ident::new(repr, span));
- if user_named_args.contains(&ident) {
- // Refers to a named argument written by the user, not to field.
- out += repr;
- continue;
- }
- MemberUnraw::Named(ident)
- }
- _ => continue,
- };
- let end_spec = match read.find('}') {
- Some(end_spec) => end_spec,
- None => return Ok(()),
- };
- let mut bonus_display = false;
- let bound = match read[..end_spec].chars().next_back() {
- Some('?') => Trait::Debug,
- Some('o') => Trait::Octal,
- Some('x') => Trait::LowerHex,
- Some('X') => Trait::UpperHex,
- Some('p') => Trait::Pointer,
- Some('b') => Trait::Binary,
- Some('e') => Trait::LowerExp,
- Some('E') => Trait::UpperExp,
- Some(_) => Trait::Display,
- None => {
- bonus_display = true;
- has_bonus_display = true;
- Trait::Display
- }
- };
- infinite_recursive |= member == *"self" && bound == Trait::Display;
- let field = match member_index.get(&member) {
- Some(&field) => field,
- None => {
- out += &member.to_string();
- continue;
- }
- };
- implied_bounds.insert((field, bound));
- let formatvar_prefix = if bonus_display {
- "__display"
- } else if bound == Trait::Pointer {
- "__pointer"
- } else {
- "__field"
- };
- let mut formatvar = IdentUnraw::new(match &member {
- MemberUnraw::Unnamed(index) => format_ident!("{}{}", formatvar_prefix, index),
- MemberUnraw::Named(ident) => {
- format_ident!("{}_{}", formatvar_prefix, ident.to_string())
- }
- });
- while user_named_args.contains(&formatvar) {
- formatvar = IdentUnraw::new(format_ident!("_{}", formatvar.to_string()));
- }
- formatvar.set_span(span);
- out += &formatvar.to_string();
- if !macro_named_args.insert(formatvar.clone()) {
- // Already added to bindings by a previous use.
- continue;
- }
- let mut binding_value = match &member {
- MemberUnraw::Unnamed(index) => format_ident!("_{}", index),
- MemberUnraw::Named(ident) => ident.to_local(),
- };
- binding_value.set_span(span.resolved_at(fields[field].member.span()));
- let wrapped_binding_value = if bonus_display {
- quote_spanned!(span=> #binding_value.as_display())
- } else if bound == Trait::Pointer {
- quote!(::thiserror::#private::Var(#binding_value))
- } else {
- binding_value.into_token_stream()
- };
- bindings.push((formatvar.to_local(), wrapped_binding_value));
- }
-
- out += read;
- self.fmt = LitStr::new(&out, self.fmt.span());
- self.has_bonus_display = has_bonus_display;
- self.infinite_recursive = infinite_recursive;
- self.implied_bounds = implied_bounds;
- self.bindings = bindings;
- Ok(())
- }
-}
-
-struct FmtArguments {
- named: BTreeSet<IdentUnraw>,
- first_unnamed: Option<TokenStream>,
-}
-
-#[allow(clippy::unnecessary_wraps)]
-fn explicit_named_args(input: ParseStream) -> Result<FmtArguments> {
- let ahead = input.fork();
- if let Ok(set) = try_explicit_named_args(&ahead) {
- input.advance_to(&ahead);
- return Ok(set);
- }
-
- let ahead = input.fork();
- if let Ok(set) = fallback_explicit_named_args(&ahead) {
- input.advance_to(&ahead);
- return Ok(set);
- }
-
- input.parse::<TokenStream>().unwrap();
- Ok(FmtArguments {
- named: BTreeSet::new(),
- first_unnamed: None,
- })
-}
-
-fn try_explicit_named_args(input: ParseStream) -> Result<FmtArguments> {
- let mut syn_full = None;
- let mut args = FmtArguments {
- named: BTreeSet::new(),
- first_unnamed: None,
- };
-
- while !input.is_empty() {
- input.parse::<Token![,]>()?;
- if input.is_empty() {
- break;
- }
-
- let mut begin_unnamed = None;
- if input.peek(Ident::peek_any) && input.peek2(Token![=]) && !input.peek2(Token![==]) {
- let ident: IdentUnraw = input.parse()?;
- input.parse::<Token![=]>()?;
- args.named.insert(ident);
- } else {
- begin_unnamed = Some(input.fork());
- }
-
- let ahead = input.fork();
- if *syn_full.get_or_insert_with(is_syn_full) && ahead.parse::<Expr>().is_ok() {
- input.advance_to(&ahead);
- } else {
- scan_expr(input)?;
- }
-
- if let Some(begin_unnamed) = begin_unnamed {
- if args.first_unnamed.is_none() {
- args.first_unnamed = Some(between(&begin_unnamed, input));
- }
- }
- }
-
- Ok(args)
-}
-
-fn fallback_explicit_named_args(input: ParseStream) -> Result<FmtArguments> {
- let mut args = FmtArguments {
- named: BTreeSet::new(),
- first_unnamed: None,
- };
-
- while !input.is_empty() {
- if input.peek(Token![,])
- && input.peek2(Ident::peek_any)
- && input.peek3(Token![=])
- && !input.peek3(Token![==])
- {
- input.parse::<Token![,]>()?;
- let ident: IdentUnraw = input.parse()?;
- input.parse::<Token![=]>()?;
- args.named.insert(ident);
- } else {
- input.parse::<TokenTree>()?;
- }
- }
-
- Ok(args)
-}
-
-fn is_syn_full() -> bool {
- // Expr::Block contains syn::Block which contains Vec<syn::Stmt>. In the
- // current version of Syn, syn::Stmt is exhaustive and could only plausibly
- // represent `trait Trait {}` in Stmt::Item which contains syn::Item. Most
- // of the point of syn's non-"full" mode is to avoid compiling Item and the
- // entire expansive syntax tree it comprises. So the following expression
- // being parsed to Expr::Block is a reliable indication that "full" is
- // enabled.
- let test = quote!({
- trait Trait {}
- });
- match syn::parse2(test) {
- Ok(Expr::Verbatim(_)) | Err(_) => false,
- Ok(Expr::Block(_)) => true,
- Ok(_) => unreachable!(),
- }
-}
-
-fn take_int<'a>(read: &mut &'a str) -> &'a str {
- let mut int_len = 0;
- for ch in read.chars() {
- match ch {
- '0'..='9' => int_len += 1,
- _ => break,
- }
- }
- let (int, rest) = read.split_at(int_len);
- *read = rest;
- int
-}
-
-fn take_ident<'a>(read: &mut &'a str) -> &'a str {
- let mut ident_len = 0;
- for ch in read.chars() {
- match ch {
- 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident_len += 1,
- _ => break,
- }
- }
- let (ident, rest) = read.split_at(ident_len);
- *read = rest;
- ident
-}
-
-fn between<'a>(begin: ParseStream<'a>, end: ParseStream<'a>) -> TokenStream {
- let end = end.cursor();
- let mut cursor = begin.cursor();
- let mut tokens = TokenStream::new();
-
- while cursor < end {
- let (tt, next) = cursor.token_tree().unwrap();
-
- if end < next {
- if let Some((inside, _span, _after)) = cursor.group(Delimiter::None) {
- cursor = inside;
- continue;
- }
- if tokens.is_empty() {
- tokens.extend(iter::once(tt));
- }
- break;
- }
-
- tokens.extend(iter::once(tt));
- cursor = next;
- }
-
- tokens
-}
diff --git a/subprojects/thiserror/impl/src/generics.rs b/subprojects/thiserror/impl/src/generics.rs
deleted file mode 100644
index 26fe0a9..0000000
--- a/subprojects/thiserror/impl/src/generics.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-use proc_macro2::TokenStream;
-use quote::ToTokens;
-use std::collections::btree_map::Entry;
-use std::collections::{BTreeMap as Map, BTreeSet as Set};
-use syn::punctuated::Punctuated;
-use syn::{parse_quote, GenericArgument, Generics, Ident, PathArguments, Token, Type, WhereClause};
-
-pub struct ParamsInScope<'a> {
- names: Set<&'a Ident>,
-}
-
-impl<'a> ParamsInScope<'a> {
- pub fn new(generics: &'a Generics) -> Self {
- ParamsInScope {
- names: generics.type_params().map(|param| &param.ident).collect(),
- }
- }
-
- pub fn intersects(&self, ty: &Type) -> bool {
- let mut found = false;
- crawl(self, ty, &mut found);
- found
- }
-}
-
-fn crawl(in_scope: &ParamsInScope, ty: &Type, found: &mut bool) {
- if let Type::Path(ty) = ty {
- if let Some(qself) = &ty.qself {
- crawl(in_scope, &qself.ty, found);
- } else {
- let front = ty.path.segments.first().unwrap();
- if front.arguments.is_none() && in_scope.names.contains(&front.ident) {
- *found = true;
- }
- }
- for segment in &ty.path.segments {
- if let PathArguments::AngleBracketed(arguments) = &segment.arguments {
- for arg in &arguments.args {
- if let GenericArgument::Type(ty) = arg {
- crawl(in_scope, ty, found);
- }
- }
- }
- }
- }
-}
-
-pub struct InferredBounds {
- bounds: Map<String, (Set<String>, Punctuated<TokenStream, Token![+]>)>,
- order: Vec<TokenStream>,
-}
-
-impl InferredBounds {
- pub fn new() -> Self {
- InferredBounds {
- bounds: Map::new(),
- order: Vec::new(),
- }
- }
-
- pub fn insert(&mut self, ty: impl ToTokens, bound: impl ToTokens) {
- let ty = ty.to_token_stream();
- let bound = bound.to_token_stream();
- let entry = self.bounds.entry(ty.to_string());
- if let Entry::Vacant(_) = entry {
- self.order.push(ty);
- }
- let (set, tokens) = entry.or_default();
- if set.insert(bound.to_string()) {
- tokens.push(bound);
- }
- }
-
- pub fn augment_where_clause(&self, generics: &Generics) -> WhereClause {
- let mut generics = generics.clone();
- let where_clause = generics.make_where_clause();
- for ty in &self.order {
- let (_set, bounds) = &self.bounds[&ty.to_string()];
- where_clause.predicates.push(parse_quote!(#ty: #bounds));
- }
- generics.where_clause.unwrap()
- }
-}
diff --git a/subprojects/thiserror/impl/src/lib.rs b/subprojects/thiserror/impl/src/lib.rs
deleted file mode 100644
index 2ff054b..0000000
--- a/subprojects/thiserror/impl/src/lib.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-#![allow(
- clippy::blocks_in_conditions,
- clippy::cast_lossless,
- clippy::cast_possible_truncation,
- clippy::enum_glob_use,
- clippy::expl_impl_clone_on_copy, // https://github.com/rust-lang/rust-clippy/issues/15842
- clippy::manual_find,
- clippy::manual_let_else,
- clippy::manual_map,
- clippy::map_unwrap_or,
- clippy::module_name_repetitions,
- clippy::needless_pass_by_value,
- clippy::range_plus_one,
- clippy::single_match_else,
- clippy::struct_field_names,
- clippy::too_many_lines,
- clippy::wrong_self_convention
-)]
-#![allow(unknown_lints, mismatched_lifetime_syntaxes)]
-
-extern crate proc_macro;
-
-mod ast;
-mod attr;
-mod expand;
-mod fallback;
-mod fmt;
-mod generics;
-mod prop;
-mod scan_expr;
-mod unraw;
-mod valid;
-
-use proc_macro::TokenStream;
-use proc_macro2::{Ident, Span};
-use quote::{ToTokens, TokenStreamExt as _};
-use syn::{DeriveInput, parse_macro_input};
-
-#[proc_macro_derive(Error, attributes(backtrace, error, from, source))]
-pub fn derive_error(input: TokenStream) -> TokenStream {
- let input = parse_macro_input!(input as DeriveInput);
- expand::derive(&input).into()
-}
-
-#[allow(non_camel_case_types)]
-struct private;
-
-impl ToTokens for private {
- fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
- tokens.append(Ident::new(concat!("__private"), Span::call_site()));
- }
-}
diff --git a/subprojects/thiserror/impl/src/prop.rs b/subprojects/thiserror/impl/src/prop.rs
deleted file mode 100644
index 0a101fc..0000000
--- a/subprojects/thiserror/impl/src/prop.rs
+++ /dev/null
@@ -1,148 +0,0 @@
-use crate::ast::{Enum, Field, Struct, Variant};
-use crate::unraw::MemberUnraw;
-use proc_macro2::Span;
-use syn::Type;
-
-impl Struct<'_> {
- pub(crate) fn from_field(&self) -> Option<&Field> {
- from_field(&self.fields)
- }
-
- pub(crate) fn source_field(&self) -> Option<&Field> {
- source_field(&self.fields)
- }
-
- pub(crate) fn backtrace_field(&self) -> Option<&Field> {
- backtrace_field(&self.fields)
- }
-
- pub(crate) fn distinct_backtrace_field(&self) -> Option<&Field> {
- let backtrace_field = self.backtrace_field()?;
- distinct_backtrace_field(backtrace_field, self.from_field())
- }
-}
-
-impl Enum<'_> {
- pub(crate) fn has_source(&self) -> bool {
- self.variants
- .iter()
- .any(|variant| variant.source_field().is_some() || variant.attrs.transparent.is_some())
- }
-
- pub(crate) fn has_backtrace(&self) -> bool {
- self.variants
- .iter()
- .any(|variant| variant.backtrace_field().is_some())
- }
-
- pub(crate) fn has_display(&self) -> bool {
- self.attrs.display.is_some()
- || self.attrs.transparent.is_some()
- || self.attrs.fmt.is_some()
- || self
- .variants
- .iter()
- .any(|variant| variant.attrs.display.is_some() || variant.attrs.fmt.is_some())
- || self
- .variants
- .iter()
- .all(|variant| variant.attrs.transparent.is_some())
- }
-}
-
-impl Variant<'_> {
- pub(crate) fn from_field(&self) -> Option<&Field> {
- from_field(&self.fields)
- }
-
- pub(crate) fn source_field(&self) -> Option<&Field> {
- source_field(&self.fields)
- }
-
- pub(crate) fn backtrace_field(&self) -> Option<&Field> {
- backtrace_field(&self.fields)
- }
-
- pub(crate) fn distinct_backtrace_field(&self) -> Option<&Field> {
- let backtrace_field = self.backtrace_field()?;
- distinct_backtrace_field(backtrace_field, self.from_field())
- }
-}
-
-impl Field<'_> {
- pub(crate) fn is_backtrace(&self) -> bool {
- type_is_backtrace(self.ty)
- }
-
- pub(crate) fn source_span(&self) -> Span {
- if let Some(source_attr) = &self.attrs.source {
- source_attr.span
- } else if let Some(from_attr) = &self.attrs.from {
- from_attr.span
- } else {
- self.member.span()
- }
- }
-}
-
-fn from_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> {
- for field in fields {
- if field.attrs.from.is_some() {
- return Some(field);
- }
- }
- None
-}
-
-fn source_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> {
- for field in fields {
- if field.attrs.from.is_some() || field.attrs.source.is_some() {
- return Some(field);
- }
- }
- for field in fields {
- match &field.member {
- MemberUnraw::Named(ident) if ident == "source" => return Some(field),
- _ => {}
- }
- }
- None
-}
-
-fn backtrace_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> {
- for field in fields {
- if field.attrs.backtrace.is_some() {
- return Some(field);
- }
- }
- for field in fields {
- if field.is_backtrace() {
- return Some(field);
- }
- }
- None
-}
-
-// The #[backtrace] field, if it is not the same as the #[from] field.
-fn distinct_backtrace_field<'a, 'b>(
- backtrace_field: &'a Field<'b>,
- from_field: Option<&Field>,
-) -> Option<&'a Field<'b>> {
- if from_field.map_or(false, |from_field| {
- from_field.member == backtrace_field.member
- }) {
- None
- } else {
- Some(backtrace_field)
- }
-}
-
-fn type_is_backtrace(ty: &Type) -> bool {
- let path = match ty {
- Type::Path(ty) => &ty.path,
- _ => return false,
- };
-
- let last = path.segments.last().unwrap();
- last.ident == "Backtrace" && last.arguments.is_empty()
-}
diff --git a/subprojects/thiserror/impl/src/scan_expr.rs b/subprojects/thiserror/impl/src/scan_expr.rs
deleted file mode 100644
index 155b5b6..0000000
--- a/subprojects/thiserror/impl/src/scan_expr.rs
+++ /dev/null
@@ -1,264 +0,0 @@
-use self::{Action::*, Input::*};
-use proc_macro2::{Delimiter, Ident, Spacing, TokenTree};
-use syn::parse::{ParseStream, Result};
-use syn::{AngleBracketedGenericArguments, BinOp, Expr, ExprPath, Lifetime, Lit, Token, Type};
-
-enum Input {
- Keyword(&'static str),
- Punct(&'static str),
- ConsumeAny,
- ConsumeBinOp,
- ConsumeBrace,
- ConsumeDelimiter,
- ConsumeIdent,
- ConsumeLifetime,
- ConsumeLiteral,
- ConsumeNestedBrace,
- ExpectPath,
- ExpectTurbofish,
- ExpectType,
- CanBeginExpr,
- Otherwise,
- Empty,
-}
-
-enum Action {
- SetState(&'static [(Input, Action)]),
- IncDepth,
- DecDepth,
- Finish,
-}
-
-static INIT: [(Input, Action); 28] = [
- (ConsumeDelimiter, SetState(&POSTFIX)),
- (Keyword("async"), SetState(&ASYNC)),
- (Keyword("break"), SetState(&BREAK_LABEL)),
- (Keyword("const"), SetState(&CONST)),
- (Keyword("continue"), SetState(&CONTINUE)),
- (Keyword("for"), SetState(&FOR)),
- (Keyword("if"), IncDepth),
- (Keyword("let"), SetState(&PATTERN)),
- (Keyword("loop"), SetState(&BLOCK)),
- (Keyword("match"), IncDepth),
- (Keyword("move"), SetState(&CLOSURE)),
- (Keyword("return"), SetState(&RETURN)),
- (Keyword("static"), SetState(&CLOSURE)),
- (Keyword("unsafe"), SetState(&BLOCK)),
- (Keyword("while"), IncDepth),
- (Keyword("yield"), SetState(&RETURN)),
- (Keyword("_"), SetState(&POSTFIX)),
- (Punct("!"), SetState(&INIT)),
- (Punct("#"), SetState(&[(ConsumeDelimiter, SetState(&INIT))])),
- (Punct("&"), SetState(&REFERENCE)),
- (Punct("*"), SetState(&INIT)),
- (Punct("-"), SetState(&INIT)),
- (Punct("..="), SetState(&INIT)),
- (Punct(".."), SetState(&RANGE)),
- (Punct("|"), SetState(&CLOSURE_ARGS)),
- (ConsumeLifetime, SetState(&[(Punct(":"), SetState(&INIT))])),
- (ConsumeLiteral, SetState(&POSTFIX)),
- (ExpectPath, SetState(&PATH)),
-];
-
-static POSTFIX: [(Input, Action); 10] = [
- (Keyword("as"), SetState(&[(ExpectType, SetState(&POSTFIX))])),
- (Punct("..="), SetState(&INIT)),
- (Punct(".."), SetState(&RANGE)),
- (Punct("."), SetState(&DOT)),
- (Punct("?"), SetState(&POSTFIX)),
- (ConsumeBinOp, SetState(&INIT)),
- (Punct("="), SetState(&INIT)),
- (ConsumeNestedBrace, SetState(&IF_THEN)),
- (ConsumeDelimiter, SetState(&POSTFIX)),
- (Empty, Finish),
-];
-
-static ASYNC: [(Input, Action); 3] = [
- (Keyword("move"), SetState(&ASYNC)),
- (Punct("|"), SetState(&CLOSURE_ARGS)),
- (ConsumeBrace, SetState(&POSTFIX)),
-];
-
-static BLOCK: [(Input, Action); 1] = [(ConsumeBrace, SetState(&POSTFIX))];
-
-static BREAK_LABEL: [(Input, Action); 2] = [
- (ConsumeLifetime, SetState(&BREAK_VALUE)),
- (Otherwise, SetState(&BREAK_VALUE)),
-];
-
-static BREAK_VALUE: [(Input, Action); 3] = [
- (ConsumeNestedBrace, SetState(&IF_THEN)),
- (CanBeginExpr, SetState(&INIT)),
- (Otherwise, SetState(&POSTFIX)),
-];
-
-static CLOSURE: [(Input, Action); 6] = [
- (Keyword("async"), SetState(&CLOSURE)),
- (Keyword("move"), SetState(&CLOSURE)),
- (Punct(","), SetState(&CLOSURE)),
- (Punct(">"), SetState(&CLOSURE)),
- (Punct("|"), SetState(&CLOSURE_ARGS)),
- (ConsumeLifetime, SetState(&CLOSURE)),
-];
-
-static CLOSURE_ARGS: [(Input, Action); 2] = [
- (Punct("|"), SetState(&CLOSURE_RET)),
- (ConsumeAny, SetState(&CLOSURE_ARGS)),
-];
-
-static CLOSURE_RET: [(Input, Action); 2] = [
- (Punct("->"), SetState(&[(ExpectType, SetState(&BLOCK))])),
- (Otherwise, SetState(&INIT)),
-];
-
-static CONST: [(Input, Action); 2] = [
- (Punct("|"), SetState(&CLOSURE_ARGS)),
- (ConsumeBrace, SetState(&POSTFIX)),
-];
-
-static CONTINUE: [(Input, Action); 2] = [
- (ConsumeLifetime, SetState(&POSTFIX)),
- (Otherwise, SetState(&POSTFIX)),
-];
-
-static DOT: [(Input, Action); 3] = [
- (Keyword("await"), SetState(&POSTFIX)),
- (ConsumeIdent, SetState(&METHOD)),
- (ConsumeLiteral, SetState(&POSTFIX)),
-];
-
-static FOR: [(Input, Action); 2] = [
- (Punct("<"), SetState(&CLOSURE)),
- (Otherwise, SetState(&PATTERN)),
-];
-
-static IF_ELSE: [(Input, Action); 2] = [(Keyword("if"), SetState(&INIT)), (ConsumeBrace, DecDepth)];
-static IF_THEN: [(Input, Action); 2] =
- [(Keyword("else"), SetState(&IF_ELSE)), (Otherwise, DecDepth)];
-
-static METHOD: [(Input, Action); 1] = [(ExpectTurbofish, SetState(&POSTFIX))];
-
-static PATH: [(Input, Action); 4] = [
- (Punct("!="), SetState(&INIT)),
- (Punct("!"), SetState(&INIT)),
- (ConsumeNestedBrace, SetState(&IF_THEN)),
- (Otherwise, SetState(&POSTFIX)),
-];
-
-static PATTERN: [(Input, Action); 15] = [
- (ConsumeDelimiter, SetState(&PATTERN)),
- (Keyword("box"), SetState(&PATTERN)),
- (Keyword("in"), IncDepth),
- (Keyword("mut"), SetState(&PATTERN)),
- (Keyword("ref"), SetState(&PATTERN)),
- (Keyword("_"), SetState(&PATTERN)),
- (Punct("!"), SetState(&PATTERN)),
- (Punct("&"), SetState(&PATTERN)),
- (Punct("..="), SetState(&PATTERN)),
- (Punct(".."), SetState(&PATTERN)),
- (Punct("="), SetState(&INIT)),
- (Punct("@"), SetState(&PATTERN)),
- (Punct("|"), SetState(&PATTERN)),
- (ConsumeLiteral, SetState(&PATTERN)),
- (ExpectPath, SetState(&PATTERN)),
-];
-
-static RANGE: [(Input, Action); 6] = [
- (Punct("..="), SetState(&INIT)),
- (Punct(".."), SetState(&RANGE)),
- (Punct("."), SetState(&DOT)),
- (ConsumeNestedBrace, SetState(&IF_THEN)),
- (Empty, Finish),
- (Otherwise, SetState(&INIT)),
-];
-
-static RAW: [(Input, Action); 3] = [
- (Keyword("const"), SetState(&INIT)),
- (Keyword("mut"), SetState(&INIT)),
- (Otherwise, SetState(&POSTFIX)),
-];
-
-static REFERENCE: [(Input, Action); 3] = [
- (Keyword("mut"), SetState(&INIT)),
- (Keyword("raw"), SetState(&RAW)),
- (Otherwise, SetState(&INIT)),
-];
-
-static RETURN: [(Input, Action); 2] = [
- (CanBeginExpr, SetState(&INIT)),
- (Otherwise, SetState(&POSTFIX)),
-];
-
-pub(crate) fn scan_expr(input: ParseStream) -> Result<()> {
- let mut state = INIT.as_slice();
- let mut depth = 0usize;
- 'table: loop {
- for rule in state {
- if match rule.0 {
- Input::Keyword(expected) => input.step(|cursor| match cursor.ident() {
- Some((ident, rest)) if ident == expected => Ok((true, rest)),
- _ => Ok((false, *cursor)),
- })?,
- Input::Punct(expected) => input.step(|cursor| {
- let begin = *cursor;
- let mut cursor = begin;
- for (i, ch) in expected.chars().enumerate() {
- match cursor.punct() {
- Some((punct, _)) if punct.as_char() != ch => break,
- Some((_, rest)) if i == expected.len() - 1 => {
- return Ok((true, rest));
- }
- Some((punct, rest)) if punct.spacing() == Spacing::Joint => {
- cursor = rest;
- }
- _ => break,
- }
- }
- Ok((false, begin))
- })?,
- Input::ConsumeAny => input.parse::<Option<TokenTree>>()?.is_some(),
- Input::ConsumeBinOp => input.parse::<BinOp>().is_ok(),
- Input::ConsumeBrace | Input::ConsumeNestedBrace => {
- (matches!(rule.0, Input::ConsumeBrace) || depth > 0)
- && input.step(|cursor| match cursor.group(Delimiter::Brace) {
- Some((_inside, _span, rest)) => Ok((true, rest)),
- None => Ok((false, *cursor)),
- })?
- }
- Input::ConsumeDelimiter => input.step(|cursor| match cursor.any_group() {
- Some((_inside, _delimiter, _span, rest)) => Ok((true, rest)),
- None => Ok((false, *cursor)),
- })?,
- Input::ConsumeIdent => input.parse::<Option<Ident>>()?.is_some(),
- Input::ConsumeLifetime => input.parse::<Option<Lifetime>>()?.is_some(),
- Input::ConsumeLiteral => input.parse::<Option<Lit>>()?.is_some(),
- Input::ExpectPath => {
- input.parse::<ExprPath>()?;
- true
- }
- Input::ExpectTurbofish => {
- if input.peek(Token![::]) {
- input.parse::<AngleBracketedGenericArguments>()?;
- }
- true
- }
- Input::ExpectType => {
- Type::without_plus(input)?;
- true
- }
- Input::CanBeginExpr => Expr::peek(input),
- Input::Otherwise => true,
- Input::Empty => input.is_empty() || input.peek(Token![,]),
- } {
- state = match rule.1 {
- Action::SetState(next) => next,
- Action::IncDepth => (depth += 1, &INIT).1,
- Action::DecDepth => (depth -= 1, &POSTFIX).1,
- Action::Finish => return if depth == 0 { Ok(()) } else { break },
- };
- continue 'table;
- }
- }
- return Err(input.error("unsupported expression"));
- }
-}
diff --git a/subprojects/thiserror/impl/src/unraw.rs b/subprojects/thiserror/impl/src/unraw.rs
deleted file mode 100644
index 73b9970..0000000
--- a/subprojects/thiserror/impl/src/unraw.rs
+++ /dev/null
@@ -1,142 +0,0 @@
-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 struct IdentUnraw(Ident);
-
-impl IdentUnraw {
- pub fn new(ident: Ident) -> Self {
- IdentUnraw(ident)
- }
-
- pub fn to_local(&self) -> Ident {
- let unraw = self.0.unraw();
- let repr = unraw.to_string();
- if syn::parse_str::<Ident>(&repr).is_err() {
- if let "_" | "super" | "self" | "Self" | "crate" = repr.as_str() {
- // Some identifiers are never allowed to appear as raw, like r#self and r#_.
- } else {
- return Ident::new_raw(&repr, Span::call_site());
- }
- }
- unraw
- }
-
- pub fn set_span(&mut self, span: Span) {
- self.0.set_span(span);
- }
-}
-
-impl Display for IdentUnraw {
- fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- Display::fmt(&self.0.unraw(), formatter)
- }
-}
-
-impl Eq for IdentUnraw {}
-
-impl PartialEq for IdentUnraw {
- fn eq(&self, other: &Self) -> bool {
- PartialEq::eq(&self.0.unraw(), &other.0.unraw())
- }
-}
-
-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())
- }
-}
-
-impl PartialOrd for IdentUnraw {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- Some(Self::cmp(self, other))
- }
-}
-
-impl Parse for IdentUnraw {
- fn parse(input: ParseStream) -> Result<Self> {
- input.call(Ident::parse_any).map(IdentUnraw::new)
- }
-}
-
-impl ToTokens for IdentUnraw {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- self.0.unraw().to_tokens(tokens);
- }
-}
-
-#[derive(Clone)]
-pub enum MemberUnraw {
- Named(IdentUnraw),
- Unnamed(Index),
-}
-
-impl MemberUnraw {
- pub fn span(&self) -> Span {
- match self {
- MemberUnraw::Named(ident) => ident.0.span(),
- MemberUnraw::Unnamed(index) => index.span,
- }
- }
-}
-
-impl Display for MemberUnraw {
- fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- match self {
- MemberUnraw::Named(this) => Display::fmt(this, formatter),
- MemberUnraw::Unnamed(this) => Display::fmt(&this.index, formatter),
- }
- }
-}
-
-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 PartialEq<str> for MemberUnraw {
- fn eq(&self, other: &str) -> bool {
- match self {
- MemberUnraw::Named(this) => this == other,
- MemberUnraw::Unnamed(_) => 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),
- }
- }
-}
diff --git a/subprojects/thiserror/impl/src/valid.rs b/subprojects/thiserror/impl/src/valid.rs
deleted file mode 100644
index 21bd885..0000000
--- a/subprojects/thiserror/impl/src/valid.rs
+++ /dev/null
@@ -1,248 +0,0 @@
-use crate::ast::{Enum, Field, Input, Struct, Variant};
-use crate::attr::Attrs;
-use syn::{Error, GenericArgument, PathArguments, Result, Type};
-
-impl Input<'_> {
- pub(crate) fn validate(&self) -> Result<()> {
- match self {
- Input::Struct(input) => input.validate(),
- Input::Enum(input) => input.validate(),
- }
- }
-}
-
-impl Struct<'_> {
- fn validate(&self) -> Result<()> {
- check_non_field_attrs(&self.attrs)?;
- if let Some(transparent) = self.attrs.transparent {
- if self.fields.len() != 1 {
- return Err(Error::new_spanned(
- transparent.original,
- "#[error(transparent)] requires exactly one field",
- ));
- }
- if let Some(source) = self.fields.iter().find_map(|f| f.attrs.source) {
- return Err(Error::new_spanned(
- source.original,
- "transparent error struct can't contain #[source]",
- ));
- }
- }
- if let Some(fmt) = &self.attrs.fmt {
- return Err(Error::new_spanned(
- fmt.original,
- "#[error(fmt = ...)] is only supported in enums; for a struct, handwrite your own Display impl",
- ));
- }
- check_field_attrs(&self.fields)?;
- for field in &self.fields {
- field.validate()?;
- }
- Ok(())
- }
-}
-
-impl Enum<'_> {
- fn validate(&self) -> Result<()> {
- check_non_field_attrs(&self.attrs)?;
- let has_display = self.has_display();
- for variant in &self.variants {
- variant.validate()?;
- if has_display
- && variant.attrs.display.is_none()
- && variant.attrs.transparent.is_none()
- && variant.attrs.fmt.is_none()
- {
- return Err(Error::new_spanned(
- variant.original,
- "missing #[error(\"...\")] display attribute",
- ));
- }
- }
- Ok(())
- }
-}
-
-impl Variant<'_> {
- fn validate(&self) -> Result<()> {
- check_non_field_attrs(&self.attrs)?;
- if self.attrs.transparent.is_some() {
- if self.fields.len() != 1 {
- return Err(Error::new_spanned(
- self.original,
- "#[error(transparent)] requires exactly one field",
- ));
- }
- if let Some(source) = self.fields.iter().find_map(|f| f.attrs.source) {
- return Err(Error::new_spanned(
- source.original,
- "transparent variant can't contain #[source]",
- ));
- }
- }
- check_field_attrs(&self.fields)?;
- for field in &self.fields {
- field.validate()?;
- }
- Ok(())
- }
-}
-
-impl Field<'_> {
- fn validate(&self) -> Result<()> {
- if let Some(unexpected_display_attr) = if let Some(display) = &self.attrs.display {
- Some(display.original)
- } else if let Some(fmt) = &self.attrs.fmt {
- Some(fmt.original)
- } else {
- None
- } {
- return Err(Error::new_spanned(
- unexpected_display_attr,
- "not expected here; the #[error(...)] attribute belongs on top of a struct or an enum variant",
- ));
- }
- Ok(())
- }
-}
-
-fn check_non_field_attrs(attrs: &Attrs) -> Result<()> {
- if let Some(from) = &attrs.from {
- return Err(Error::new_spanned(
- from.original,
- "not expected here; the #[from] attribute belongs on a specific field",
- ));
- }
- if let Some(source) = &attrs.source {
- return Err(Error::new_spanned(
- source.original,
- "not expected here; the #[source] attribute belongs on a specific field",
- ));
- }
- if let Some(backtrace) = &attrs.backtrace {
- return Err(Error::new_spanned(
- backtrace,
- "not expected here; the #[backtrace] attribute belongs on a specific field",
- ));
- }
- if attrs.transparent.is_some() {
- if let Some(display) = &attrs.display {
- return Err(Error::new_spanned(
- display.original,
- "cannot have both #[error(transparent)] and a display attribute",
- ));
- }
- if let Some(fmt) = &attrs.fmt {
- return Err(Error::new_spanned(
- fmt.original,
- "cannot have both #[error(transparent)] and #[error(fmt = ...)]",
- ));
- }
- } else if let (Some(display), Some(_)) = (&attrs.display, &attrs.fmt) {
- return Err(Error::new_spanned(
- display.original,
- "cannot have both #[error(fmt = ...)] and a format arguments attribute",
- ));
- }
-
- Ok(())
-}
-
-fn check_field_attrs(fields: &[Field]) -> Result<()> {
- let mut from_field = None;
- let mut source_field = None;
- let mut backtrace_field = None;
- let mut has_backtrace = false;
- for field in fields {
- if let Some(from) = field.attrs.from {
- if from_field.is_some() {
- return Err(Error::new_spanned(
- from.original,
- "duplicate #[from] attribute",
- ));
- }
- from_field = Some(field);
- }
- if let Some(source) = field.attrs.source {
- if source_field.is_some() {
- return Err(Error::new_spanned(
- source.original,
- "duplicate #[source] attribute",
- ));
- }
- source_field = Some(field);
- }
- if let Some(backtrace) = field.attrs.backtrace {
- if backtrace_field.is_some() {
- return Err(Error::new_spanned(
- backtrace,
- "duplicate #[backtrace] attribute",
- ));
- }
- backtrace_field = Some(field);
- has_backtrace = true;
- }
- if let Some(transparent) = field.attrs.transparent {
- return Err(Error::new_spanned(
- transparent.original,
- "#[error(transparent)] needs to go outside the enum or struct, not on an individual field",
- ));
- }
- has_backtrace |= field.is_backtrace();
- }
- if let (Some(from_field), Some(source_field)) = (from_field, source_field) {
- if from_field.member != source_field.member {
- return Err(Error::new_spanned(
- from_field.attrs.from.unwrap().original,
- "#[from] is only supported on the source field, not any other field",
- ));
- }
- }
- if let Some(from_field) = from_field {
- let max_expected_fields = match backtrace_field {
- Some(backtrace_field) => 1 + (from_field.member != backtrace_field.member) as usize,
- None => 1 + has_backtrace as usize,
- };
- if fields.len() > max_expected_fields {
- return Err(Error::new_spanned(
- from_field.attrs.from.unwrap().original,
- "deriving From requires no fields other than source and backtrace",
- ));
- }
- }
- if let Some(source_field) = source_field.or(from_field) {
- if contains_non_static_lifetime(source_field.ty) {
- return Err(Error::new_spanned(
- &source_field.original.ty,
- "non-static lifetimes are not allowed in the source of an error, because std::error::Error requires the source is dyn Error + 'static",
- ));
- }
- }
- Ok(())
-}
-
-fn contains_non_static_lifetime(ty: &Type) -> bool {
- match ty {
- Type::Path(ty) => {
- let bracketed = match &ty.path.segments.last().unwrap().arguments {
- PathArguments::AngleBracketed(bracketed) => bracketed,
- _ => return false,
- };
- for arg in &bracketed.args {
- match arg {
- GenericArgument::Type(ty) if contains_non_static_lifetime(ty) => return true,
- GenericArgument::Lifetime(lifetime) if lifetime.ident != "static" => {
- return true
- }
- _ => {}
- }
- }
- false
- }
- Type::Reference(ty) => ty
- .lifetime
- .as_ref()
- .map_or(false, |lifetime| lifetime.ident != "static"),
- _ => false, // maybe implement later if there are common other cases
- }
-}