abi_stable_derive/stable_abi/
attribute_parsing.rs

1use as_derive_utils::{
2    datastructure::{DataStructure, DataVariant, Field, FieldMap, TypeParamMap},
3    parse_utils::{ret_err_on, ret_err_on_peek, ParseBufferExt},
4    return_spanned_err, return_syn_err, spanned_err, syn_err,
5    utils::SynErrorExt,
6};
7
8use syn::{
9    parse::ParseBuffer, punctuated::Punctuated, token::Comma, Attribute, Expr, ExprLit, Ident, Lit,
10    Token, Type, TypeParamBound, WherePredicate,
11};
12
13use std::{collections::HashSet, mem};
14
15use core_extensions::{matches, IteratorExt};
16
17use proc_macro2::Span;
18
19use crate::*;
20
21use crate::{
22    attribute_parsing::contains_doc_hidden,
23    impl_interfacetype::{parse_impl_interfacetype, ImplInterfaceType},
24    parse_utils::{parse_str_as_ident, ParseBounds, ParsePunctuated},
25    utils::{LinearResult, SynResultExt},
26};
27
28use super::{
29    nonexhaustive::{
30        EnumInterface, ExprOrType, NonExhaustive, UncheckedNEVariant, UncheckedNonExhaustive,
31        UncheckedVariantConstructor,
32    },
33    prefix_types::{
34        AccessorOrMaybe, FirstSuffixField, OnMissingField, PrefixKind, PrefixKindCtor,
35        PrefixKindField,
36    },
37    reflection::{FieldAccessor, ModReflMode},
38    repr_attrs::{
39        DiscriminantRepr, Repr, ReprAttr, UncheckedReprAttr, UncheckedReprKind, REPR_ERROR_MSG,
40    },
41};
42
43mod kw {
44    syn::custom_keyword! {accessible_if}
45    syn::custom_keyword! {accessor_bound}
46    syn::custom_keyword! {assert_nonexhaustive}
47    syn::custom_keyword! {align}
48    syn::custom_keyword! {bounds}
49    syn::custom_keyword! {bound}
50    syn::custom_keyword! {Clone}
51    syn::custom_keyword! {C}
52    syn::custom_keyword! {Debug}
53    syn::custom_keyword! {debug_print}
54    syn::custom_keyword! {default}
55    syn::custom_keyword! {Deref}
56    syn::custom_keyword! {Deserialize}
57    syn::custom_keyword! {Display}
58    syn::custom_keyword! {Eq}
59    syn::custom_keyword! {Error}
60    syn::custom_keyword! {extra_checks}
61    syn::custom_keyword! {Hash}
62    syn::custom_keyword! {ident}
63    syn::custom_keyword! {interface}
64    syn::custom_keyword! {impl_InterfaceType}
65    syn::custom_keyword! {impl_prefix_stable_abi}
66    syn::custom_keyword! {kind}
67    syn::custom_keyword! {last_prefix_field}
68    syn::custom_keyword! {missing_field}
69    syn::custom_keyword! {module_reflection}
70    syn::custom_keyword! {Module}
71    syn::custom_keyword! {not_stableabi}
72    syn::custom_keyword! {Opaque}
73    syn::custom_keyword! {option}
74    syn::custom_keyword! {Ord}
75    syn::custom_keyword! {packed}
76    syn::custom_keyword! {panic}
77    syn::custom_keyword! {PartialEq}
78    syn::custom_keyword! {PartialOrd}
79    syn::custom_keyword! {phantom_const_param}
80    syn::custom_keyword! {phantom_field}
81    syn::custom_keyword! {phantom_type_param}
82    syn::custom_keyword! {prefix_bounds}
83    syn::custom_keyword! {prefix_bound}
84    syn::custom_keyword! {prefix_fields}
85    syn::custom_keyword! {prefix_ref}
86    syn::custom_keyword! {prefix_ref_docs}
87    syn::custom_keyword! {Prefix}
88    syn::custom_keyword! {pub_getter}
89    syn::custom_keyword! {refl}
90    syn::custom_keyword! {rename}
91    syn::custom_keyword! {size}
92    syn::custom_keyword! {Send}
93    syn::custom_keyword! {Serialize}
94    syn::custom_keyword! {Sync}
95    syn::custom_keyword! {tag}
96    syn::custom_keyword! {transparent}
97    syn::custom_keyword! {traits}
98    syn::custom_keyword! {unrecognized}
99    syn::custom_keyword! {unsafe_allow_type_macros}
100    syn::custom_keyword! {unsafe_change_type}
101    syn::custom_keyword! {unsafe_opaque_fields}
102    syn::custom_keyword! {unsafe_opaque_field}
103    syn::custom_keyword! {unsafe_sabi_opaque_fields}
104    syn::custom_keyword! {unsafe_sabi_opaque_field}
105    syn::custom_keyword! {unsafe_unconstrained}
106    syn::custom_keyword! {value}
107    syn::custom_keyword! {Value}
108    syn::custom_keyword! {with_boxed_constructor}
109    syn::custom_keyword! {with_constructor}
110    syn::custom_keyword! {with_field_indices}
111    syn::custom_keyword! {WithNonExhaustive}
112    syn::custom_keyword! {with}
113}
114
115pub(crate) struct StableAbiOptions<'a> {
116    pub(crate) debug_print: bool,
117    pub(crate) kind: StabilityKind<'a>,
118    pub(crate) repr: ReprAttr,
119
120    pub(crate) type_param_bounds: TypeParamMap<'a, ASTypeParamBound>,
121
122    pub(crate) extra_bounds: Vec<WherePredicate>,
123
124    pub(crate) tags: Option<syn::Expr>,
125    pub(crate) extra_checks: Option<syn::Expr>,
126
127    pub(crate) layout_ctor: FieldMap<LayoutConstructor>,
128
129    pub(crate) override_field_accessor: FieldMap<Option<FieldAccessor<'a>>>,
130
131    pub(crate) renamed_fields: FieldMap<Option<&'a Ident>>,
132    pub(crate) changed_types: FieldMap<Option<&'a Type>>,
133
134    pub(crate) doc_hidden_attr: Option<&'a TokenStream2>,
135
136    pub(crate) mod_refl_mode: ModReflMode<usize>,
137
138    pub(crate) impl_interfacetype: Option<ImplInterfaceType>,
139
140    pub(crate) phantom_fields: Vec<(&'a Ident, &'a Type)>,
141    pub(crate) phantom_type_params: Vec<&'a Type>,
142    pub(crate) phantom_const_params: Vec<&'a syn::Expr>,
143
144    pub(crate) const_idents: ConstIdents,
145
146    pub(crate) allow_type_macros: bool,
147    pub(crate) with_field_indices: bool,
148}
149
150//////////////////////
151
152/// Identifiers of generated top-level constants.
153pub struct ConstIdents {
154    /// The identifier of a constant where the string in MonoSharedVars will be stored.
155    pub(crate) strings: Ident,
156}
157
158//////////////////////
159
160#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
161pub(crate) enum ASTypeParamBound {
162    NoBound,
163    GetStaticEquivalent,
164    StableAbi,
165}
166
167impl Default for ASTypeParamBound {
168    fn default() -> Self {
169        ASTypeParamBound::StableAbi
170    }
171}
172
173//////////////////////
174
175#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
176pub(crate) enum LayoutConstructor {
177    Regular,
178    Opaque,
179    SabiOpaque,
180}
181
182impl LayoutConstructor {
183    pub(crate) fn is_opaque(self) -> bool {
184        matches!(self, LayoutConstructor::Opaque { .. })
185    }
186}
187
188impl From<ASTypeParamBound> for LayoutConstructor {
189    fn from(bound: ASTypeParamBound) -> Self {
190        match bound {
191            ASTypeParamBound::NoBound => LayoutConstructor::Opaque,
192            ASTypeParamBound::GetStaticEquivalent => LayoutConstructor::Opaque,
193            ASTypeParamBound::StableAbi => LayoutConstructor::Regular,
194        }
195    }
196}
197
198impl Default for LayoutConstructor {
199    fn default() -> Self {
200        LayoutConstructor::Regular
201    }
202}
203
204//////////////////////
205
206pub(crate) enum StabilityKind<'a> {
207    Value { impl_prefix_stable_abi: bool },
208    Prefix(PrefixKind<'a>),
209    NonExhaustive(NonExhaustive<'a>),
210}
211
212impl<'a> StabilityKind<'a> {
213    pub(crate) fn field_accessor(
214        &self,
215        mod_refl_mode: ModReflMode<usize>,
216        field: &Field<'a>,
217    ) -> FieldAccessor<'a> {
218        let is_public = field.is_public() && mod_refl_mode != ModReflMode::Opaque;
219        match (is_public, self) {
220            (false, _) => FieldAccessor::Opaque,
221            (true, StabilityKind::Value { .. }) | (true, StabilityKind::NonExhaustive { .. }) => {
222                FieldAccessor::Direct
223            }
224            (true, StabilityKind::Prefix(prefix)) => prefix.field_accessor(field),
225        }
226    }
227}
228
229impl<'a> StableAbiOptions<'a> {
230    fn new(
231        ds: &'a DataStructure<'a>,
232        mut this: StableAbiAttrs<'a>,
233        arenas: &'a Arenas,
234    ) -> Result<Self, syn::Error> {
235        let mut phantom_fields = Vec::<(&'a Ident, &'a Type)>::new();
236
237        let repr = ReprAttr::new(this.repr)?;
238
239        let mut errors = LinearResult::ok(());
240
241        let kind = match this.kind {
242            _ if repr.is_repr_transparent() => {
243                // let field=&ds.variants[0].fields[0];
244
245                // let accessor_bound=syn::parse_str::<WherePredicate>(
246                //     &format!("({}):__StableAbi",(&field.mutated_ty).into_token_stream())
247                // ).expect(concat!(file!(),"-",line!()));
248                // this.extra_bounds.push(accessor_bound);
249
250                StabilityKind::Value {
251                    impl_prefix_stable_abi: false,
252                }
253            }
254            UncheckedStabilityKind::Value {
255                impl_prefix_stable_abi,
256            } => StabilityKind::Value {
257                impl_prefix_stable_abi,
258            },
259            UncheckedStabilityKind::Prefix(prefix) => PrefixKindCtor::<'a> {
260                arenas,
261                struct_name: ds.name,
262                first_suffix_field: this.first_suffix_field,
263                prefix_ref: prefix.prefix_ref,
264                prefix_fields: prefix.prefix_fields,
265                replacing_prefix_ref_docs: prefix.replacing_prefix_ref_docs,
266                fields: mem::replace(&mut this.prefix_kind_fields, FieldMap::empty()).map(
267                    |fi, pk_field| {
268                        AccessorOrMaybe::new(
269                            fi,
270                            this.first_suffix_field,
271                            pk_field,
272                            this.default_on_missing_fields.unwrap_or_default(),
273                        )
274                    },
275                ),
276                prefix_bounds: this.prefix_bounds,
277                accessor_bounds: this.accessor_bounds,
278            }
279            .make()
280            .piped(StabilityKind::Prefix),
281            UncheckedStabilityKind::NonExhaustive(nonexhaustive) => {
282                let ne_variants = this.ne_variants;
283                nonexhaustive
284                    .piped(|x| NonExhaustive::new(x, ne_variants, ds, arenas))?
285                    .piped(StabilityKind::NonExhaustive)
286            }
287        };
288
289        match (repr.variant, ds.data_variant) {
290            (Repr::Transparent, DataVariant::Struct) => {}
291            (Repr::Transparent, _) => {
292                errors.push_err(syn_err!(
293                    *repr.span,
294                    "\nAbiStable does not suport non-struct #[repr(transparent)] types.\n"
295                ));
296            }
297            (Repr::Int { .. }, DataVariant::Enum) => {}
298            (Repr::Int { .. }, _) => {
299                errors.push_err(syn_err!(
300                    *repr.span,
301                    "AbiStable does not suport non-enum #[repr(<some_integer_type>)] types."
302                ));
303            }
304            (Repr::C { .. }, _) => {}
305        }
306
307        let mod_refl_mode = match this.mod_refl_mode {
308            Some(ModReflMode::Module) => ModReflMode::Module,
309            Some(ModReflMode::Opaque) => ModReflMode::Opaque,
310            Some(ModReflMode::DelegateDeref(())) => {
311                let index = phantom_fields.len();
312                let field_ty =
313                    syn::parse_str::<Type>("<Self as __sabi_re::GetPointerKind >::PtrTarget")
314                        .expect("BUG")
315                        .piped(|x| arenas.alloc(x));
316
317                let dt = arenas.alloc(parse_str_as_ident("deref_target"));
318                phantom_fields.push((dt, field_ty));
319
320                [
321                    "Self: __sabi_re::GetPointerKind",
322                    "<Self as __sabi_re::GetPointerKind>::Target: __StableAbi",
323                ]
324                .iter()
325                .map(|x| syn::parse_str::<WherePredicate>(x).expect("BUG"))
326                .extending(&mut this.extra_bounds);
327
328                ModReflMode::DelegateDeref(index)
329            }
330            None if ds.has_public_fields() => ModReflMode::Module,
331            None => ModReflMode::Opaque,
332        };
333
334        phantom_fields.extend(this.extra_phantom_fields);
335        phantom_fields.extend(this.phantom_type_params.iter().cloned().enumerate().map(
336            |(i, ty)| {
337                let x = format!("_phantom_ty_param_{}", i);
338                let name = arenas.alloc(parse_str_as_ident(&x));
339                (name, ty)
340            },
341        ));
342
343        let doc_hidden_attr = if this.is_hidden {
344            Some(arenas.alloc(quote!(#[doc(hidden)])))
345        } else {
346            None
347        };
348
349        let const_idents = ConstIdents {
350            strings: parse_str_as_ident(&format!("_SHARED_VARS_STRINGS_{}", ds.name)),
351        };
352
353        errors.into_result()?;
354
355        Ok(StableAbiOptions {
356            debug_print: this.debug_print,
357            kind,
358            repr,
359            extra_bounds: this.extra_bounds,
360            type_param_bounds: this.type_param_bounds,
361            layout_ctor: this.layout_ctor,
362            renamed_fields: this.renamed_fields,
363            changed_types: this.changed_types,
364            override_field_accessor: this.override_field_accessor,
365            tags: this.tags,
366            extra_checks: this.extra_checks,
367            impl_interfacetype: this.impl_interfacetype,
368            phantom_fields,
369            phantom_type_params: this.phantom_type_params,
370            phantom_const_params: this.phantom_const_params,
371            allow_type_macros: this.allow_type_macros,
372            with_field_indices: this.with_field_indices,
373            const_idents,
374            mod_refl_mode,
375            doc_hidden_attr,
376        })
377    }
378}
379
380////////////////////////////////////////////////////////////////////////////////
381////////////////////////////////////////////////////////////////////////////////
382
383#[derive(Default)]
384struct StableAbiAttrs<'a> {
385    debug_print: bool,
386    kind: UncheckedStabilityKind<'a>,
387    repr: UncheckedReprAttr,
388
389    extra_bounds: Vec<WherePredicate>,
390
391    tags: Option<syn::Expr>,
392    extra_checks: Option<syn::Expr>,
393
394    first_suffix_field: FirstSuffixField,
395    default_on_missing_fields: Option<OnMissingField<'a>>,
396    prefix_kind_fields: FieldMap<PrefixKindField<'a>>,
397
398    prefix_bounds: Vec<WherePredicate>,
399
400    type_param_bounds: TypeParamMap<'a, ASTypeParamBound>,
401
402    layout_ctor: FieldMap<LayoutConstructor>,
403
404    ne_variants: Vec<UncheckedNEVariant>,
405
406    override_field_accessor: FieldMap<Option<FieldAccessor<'a>>>,
407
408    renamed_fields: FieldMap<Option<&'a Ident>>,
409    changed_types: FieldMap<Option<&'a Type>>,
410
411    accessor_bounds: FieldMap<Vec<TypeParamBound>>,
412
413    extra_phantom_fields: Vec<(&'a Ident, &'a Type)>,
414    phantom_type_params: Vec<&'a Type>,
415    phantom_const_params: Vec<&'a syn::Expr>,
416
417    impl_interfacetype: Option<ImplInterfaceType>,
418
419    mod_refl_mode: Option<ModReflMode<()>>,
420
421    allow_type_macros: bool,
422    with_field_indices: bool,
423    is_hidden: bool,
424
425    errors: LinearResult<()>,
426}
427
428#[derive(Clone)]
429enum UncheckedStabilityKind<'a> {
430    Value { impl_prefix_stable_abi: bool },
431    Prefix(UncheckedPrefixKind<'a>),
432    NonExhaustive(UncheckedNonExhaustive<'a>),
433}
434
435#[derive(Copy, Clone)]
436struct UncheckedPrefixKind<'a> {
437    prefix_ref: Option<&'a Ident>,
438    prefix_fields: Option<&'a Ident>,
439    replacing_prefix_ref_docs: &'a [syn::Expr],
440}
441
442impl<'a> Default for UncheckedStabilityKind<'a> {
443    fn default() -> Self {
444        UncheckedStabilityKind::Value {
445            impl_prefix_stable_abi: false,
446        }
447    }
448}
449
450#[derive(Copy, Clone)]
451enum ParseContext<'a> {
452    TypeAttr,
453    Variant {
454        variant_index: usize,
455    },
456    Field {
457        field_index: usize,
458        field: &'a Field<'a>,
459    },
460}
461
462/// Parses the attributes for the `StableAbi` derive macro.
463pub(crate) fn parse_attrs_for_stable_abi<'a, I>(
464    attrs: I,
465    ds: &'a DataStructure<'a>,
466    arenas: &'a Arenas,
467) -> Result<StableAbiOptions<'a>, syn::Error>
468where
469    I: IntoIterator<Item = &'a Attribute>,
470{
471    let mut this = StableAbiAttrs::default();
472
473    this.layout_ctor = FieldMap::defaulted(ds);
474    this.prefix_kind_fields = FieldMap::defaulted(ds);
475    this.renamed_fields = FieldMap::defaulted(ds);
476    this.override_field_accessor = FieldMap::defaulted(ds);
477    this.accessor_bounds = FieldMap::defaulted(ds);
478    this.changed_types = FieldMap::defaulted(ds);
479    this.ne_variants.resize(
480        ds.variants.len(),
481        UncheckedNEVariant {
482            constructor: None,
483            is_hidden: false,
484        },
485    );
486
487    this.type_param_bounds = TypeParamMap::defaulted(ds);
488
489    parse_inner(&mut this, attrs, ParseContext::TypeAttr, arenas);
490
491    for (variant_index, variant) in ds.variants.iter().enumerate() {
492        parse_inner(
493            &mut this,
494            variant.attrs,
495            ParseContext::Variant { variant_index },
496            arenas,
497        );
498        for (field_index, field) in variant.fields.iter().enumerate() {
499            parse_inner(
500                &mut this,
501                field.attrs,
502                ParseContext::Field { field, field_index },
503                arenas,
504            );
505        }
506    }
507
508    this.errors.take()?;
509
510    StableAbiOptions::new(ds, this, arenas)
511}
512
513/// Parses an individual attribute
514fn parse_inner<'a, I>(
515    this: &mut StableAbiAttrs<'a>,
516    attrs: I,
517    pctx: ParseContext<'a>,
518    arenas: &'a Arenas,
519) where
520    I: IntoIterator<Item = &'a Attribute>,
521{
522    for attr in attrs {
523        if attr.path.is_ident("sabi") {
524            attr.parse_args_with(|input: &'_ ParseBuffer<'_>| {
525                input.for_each_separated(Token!(,), |input| {
526                    parse_sabi_attr(this, pctx, input, arenas)
527                })
528            })
529        } else if attr.path.is_ident("doc") {
530            (|| -> syn::Result<()> {
531                let is_hidden =
532                    syn::parse::Parser::parse2(contains_doc_hidden, attr.tokens.clone())?;
533
534                match pctx {
535                    ParseContext::TypeAttr { .. } => {
536                        this.is_hidden = is_hidden;
537                    }
538                    ParseContext::Variant { variant_index, .. } => {
539                        this.ne_variants[variant_index].is_hidden = is_hidden;
540                    }
541                    ParseContext::Field { .. } => {}
542                }
543
544                Ok(())
545            })()
546        } else if attr.path.is_ident("repr") {
547            fn parse_int_arg(input: &'_ ParseBuffer<'_>) -> Result<u32, syn::Error> {
548                input.parse_paren_buffer()?.parse_int::<u32>()
549            }
550
551            attr.parse_args_with(|input: &'_ ParseBuffer<'_>| {
552                input.for_each_separated(Token!(,), |input| {
553                    let span = input.span();
554                    if input.check_parse(kw::C)? {
555                        this.repr.set_repr_kind(UncheckedReprKind::C, span)
556                    } else if input.check_parse(kw::transparent)? {
557                        this.repr
558                            .set_repr_kind(UncheckedReprKind::Transparent, span)
559                    } else if input.check_parse(kw::align)? {
560                        this.repr.set_aligned(parse_int_arg(input)?)
561                    } else if input.check_parse(kw::packed)? {
562                        if input.peek(syn::token::Paren) {
563                            this.repr.set_packed(Some(parse_int_arg(input)?))
564                        } else {
565                            this.repr.set_packed(None)
566                        }
567                    } else if let Some(dr) = DiscriminantRepr::from_parser(input) {
568                        this.repr.set_discriminant_repr(dr, span)
569                    } else {
570                        Err(syn_err!(
571                            span,
572                            "repr attribute not currently recognized by this macro.{}",
573                            REPR_ERROR_MSG
574                        ))
575                    }?;
576
577                    Ok(())
578                })
579            })
580        } else {
581            Ok(())
582        }
583        .combine_into_err(&mut this.errors);
584    }
585}
586
587/// Parses the contents of a `#[sabi( .. )]` attribute.
588fn parse_sabi_attr<'a>(
589    this: &mut StableAbiAttrs<'a>,
590    pctx: ParseContext<'a>,
591    input: &'_ ParseBuffer<'_>,
592    arenas: &'a Arenas,
593) -> Result<(), syn::Error> {
594    fn make_err(input: &ParseBuffer) -> syn::Error {
595        input.error("unrecognized attribute")
596    }
597
598    if let ParseContext::TypeAttr = pctx {
599        fn parse_pred(input: &ParseBuffer) -> Result<WherePredicate, syn::Error> {
600            let input = input.parse_paren_buffer()?;
601
602            ret_err_on_peek! {input, syn::Lit, "where predicate", "literal"}
603
604            input
605                .parse::<WherePredicate>()
606                .map_err(|e| e.prepend_msg("while parsing where predicate: "))
607        }
608
609        fn parse_preds(
610            input: &ParseBuffer<'_>,
611        ) -> Result<Punctuated<WherePredicate, Comma>, syn::Error> {
612            let input = input.parse_paren_buffer()?;
613
614            ret_err_on_peek! {input, syn::Lit, "where predicates", "literal"}
615
616            match input.parse::<ParsePunctuated<WherePredicate, Comma>>() {
617                Ok(x) => Ok(x.list),
618                Err(e) => Err(e.prepend_msg("while parsing where predicates: ")),
619            }
620        }
621
622        if input.check_parse(kw::bound)? {
623            this.extra_bounds.push(parse_pred(input)?);
624        } else if input.check_parse(kw::prefix_bound)? {
625            this.prefix_bounds.push(parse_pred(input)?);
626        } else if input.check_parse(kw::bounds)? {
627            this.extra_bounds.extend(parse_preds(input)?);
628        } else if input.check_parse(kw::prefix_bounds)? {
629            this.prefix_bounds.extend(parse_preds(input)?);
630        } else if input.check_parse(kw::phantom_field)? {
631            input.parse_paren_with(|input| {
632                let fname = arenas.alloc(input.parse::<Ident>()?);
633                let _ = input.parse::<Token!(:)>()?;
634                let ty = arenas.alloc(input.parse_type()?);
635                this.extra_phantom_fields.push((fname, ty));
636                Ok(())
637            })?;
638        } else if input.check_parse(kw::phantom_type_param)? {
639            input.parse::<Token!(=)>()?;
640            let ty = arenas.alloc(input.parse_type()?);
641            this.phantom_type_params.push(ty);
642        } else if input.check_parse(kw::phantom_const_param)? {
643            input.parse::<Token!(=)>()?;
644            let constant = arenas.alloc(input.parse_expr()?);
645            ret_err_on! {
646                matches!(constant, syn::Expr::Lit(ExprLit{lit: Lit::Str{..}, ..})),
647                syn::spanned::Spanned::span(constant),
648                "`impl StableAbi + Eq + Debug` expression",
649                "string literal",
650            }
651            this.phantom_const_params.push(constant);
652        } else if let Some(tag_token) = input.peek_parse(kw::tag)? {
653            input.parse::<Token!(=)>()?;
654
655            ret_err_on_peek! {
656                input,
657                syn::Lit,
658                "`abi_stable::type_layout::Tag` expression",
659                "literal",
660            }
661
662            let bound = input.parse_expr()?;
663            if this.tags.is_some() {
664                return_syn_err!(
665                    tag_token.span,
666                    "\
667                    Cannot specify multiple tags,\
668                    you must choose whether you want array or set semantics \
669                    when adding more tags.\n\
670                    \n\
671                    For multiple elements you can do:\n\
672                    \n\
673                    - `tag![[ tag0,tag1 ]]` or `Tag::arr(&[ tag0,tag1 ])` :\n\
674                        \tThis will require that the tags match exactly between \
675                        interface and implementation.\n\
676                    \n\
677                    - `tag!{{ tag0,tag1 }}` or `Tag::set(&[ tag0,tag1 ])` :\n\
678                        \tThis will require that the tags in the interface are \
679                        a subset of the implementation.\n\
680                    ",
681                );
682            }
683            this.tags = Some(bound);
684        } else if let Some(ec_token) = input.peek_parse(kw::extra_checks)? {
685            input.parse::<Token!(=)>()?;
686
687            ret_err_on_peek! {input, syn::Lit, "`impl ExtraChecks` expression", "literal"}
688
689            let bound = input.parse_expr()?;
690            if this.extra_checks.is_some() {
691                return_syn_err!(
692                    ec_token.span,
693                    "cannot use the `#[sabi(extra_checks=\"\")]` \
694                     attribute multiple times,\
695                    "
696                );
697            }
698
699            this.extra_checks = Some(bound);
700        } else if input.check_parse(kw::missing_field)? {
701            let on_missing = &mut this.default_on_missing_fields;
702            if on_missing.is_some() {
703                return Err(
704                    input.error("Cannot use this attribute multiple times on the same type")
705                );
706            }
707            *on_missing = Some(input.parse_paren_with(|i| parse_missing_field(i, arenas))?);
708        } else if input.check_parse(kw::kind)? {
709            input.parse_paren_with(|input| {
710                if input.check_parse(kw::Value)? {
711                    this.kind = UncheckedStabilityKind::Value {
712                        impl_prefix_stable_abi: false,
713                    };
714                } else if input.check_parse(kw::Prefix)? {
715                    if input.peek(syn::token::Paren) {
716                        let prefix = input
717                            .parse_paren_with(|input| parse_prefix_type_list(input, arenas))?;
718                        this.kind = UncheckedStabilityKind::Prefix(prefix);
719                    } else {
720                        let prefix = parse_prefix_type_list(input, arenas)?;
721                        this.kind = UncheckedStabilityKind::Prefix(prefix);
722                    }
723                } else if input.check_parse(kw::WithNonExhaustive)? {
724                    let nonexhaustive =
725                        input.parse_paren_with(|input| parse_non_exhaustive_list(input, arenas))?;
726                    this.kind = UncheckedStabilityKind::NonExhaustive(nonexhaustive);
727                } else {
728                    return Err(input.error("invalid #[kind(..)] attribute"));
729                }
730                Ok(())
731            })?;
732        } else if input.check_parse(kw::debug_print)? {
733            this.debug_print = true;
734        } else if input.check_parse(kw::module_reflection)? {
735            input
736                .parse_paren_buffer()?
737                .for_each_separated(Token!(,), |input| {
738                    if this.mod_refl_mode.is_some() {
739                        return Err(input.error("Cannot use this attribute multiple times"));
740                    }
741
742                    if input.check_parse(kw::Module)? {
743                        this.mod_refl_mode = Some(ModReflMode::Module);
744                    } else if input.check_parse(kw::Opaque)? {
745                        this.mod_refl_mode = Some(ModReflMode::Opaque);
746                    } else if input.check_parse(kw::Deref)? {
747                        this.mod_refl_mode = Some(ModReflMode::DelegateDeref(()));
748                    } else {
749                        return Err(input.error("invalid #[module_reflection(..)] attribute."));
750                    }
751
752                    Ok(())
753                })?;
754        } else if input.check_parse(kw::not_stableabi)? {
755            input
756                .parse_paren_buffer()?
757                .for_each_separated(Token!(,), |input| {
758                    let type_param = input.parse::<Ident>().map_err(|_| {
759                        input.error(
760                            "\
761                        invalid #[not_stableabi(..)] attribute\
762                        (it must be the identifier of a type parameter).\
763                    ",
764                        )
765                    })?;
766
767                    *this.type_param_bounds.get_mut(&type_param)? =
768                        ASTypeParamBound::GetStaticEquivalent;
769
770                    Ok(())
771                })?;
772        } else if input.check_parse(kw::unsafe_unconstrained)? {
773            input
774                .parse_paren_buffer()?
775                .for_each_separated(Token!(,), |input| {
776                    let type_param = input.parse::<Ident>().map_err(|_| {
777                        input.error(
778                            "\
779                        invalid #[unsafe_unconstrained(..)] attribute\
780                        (it must be the identifier of a type parameter).\
781                    ",
782                        )
783                    })?;
784
785                    *this.type_param_bounds.get_mut(&type_param)? = ASTypeParamBound::NoBound;
786
787                    Ok(())
788                })?;
789        } else if let Some(attr_ident) = input.peek_parse(kw::impl_InterfaceType)? {
790            if this.impl_interfacetype.is_some() {
791                return_spanned_err!(attr_ident, "Cannot use this attribute multiple times")
792            }
793            let content = input.parse_paren_buffer()?;
794            this.impl_interfacetype = Some(parse_impl_interfacetype(&content)?);
795        } else if input.check_parse(kw::with_constructor)? {
796            this.ne_variants
797                .iter_mut()
798                .for_each(|x| x.constructor = Some(UncheckedVariantConstructor::Regular));
799        } else if input.check_parse(kw::with_boxed_constructor)? {
800            this.ne_variants
801                .iter_mut()
802                .for_each(|x| x.constructor = Some(UncheckedVariantConstructor::Boxed));
803        } else if input.check_parse(kw::unsafe_opaque_fields)? {
804            this.layout_ctor
805                .iter_mut()
806                .for_each(|(_, x)| *x = LayoutConstructor::Opaque);
807        } else if input.check_parse(kw::unsafe_sabi_opaque_fields)? {
808            this.layout_ctor
809                .iter_mut()
810                .for_each(|(_, x)| *x = LayoutConstructor::SabiOpaque);
811        } else if input.check_parse(kw::unsafe_allow_type_macros)? {
812            this.allow_type_macros = true;
813        } else if input.check_parse(kw::with_field_indices)? {
814            this.with_field_indices = true;
815        } else if input.check_parse(kw::impl_prefix_stable_abi)? {
816            this.kind = UncheckedStabilityKind::Value {
817                impl_prefix_stable_abi: true,
818            };
819        } else {
820            return Err(make_err(input));
821        }
822    } else if let ParseContext::Variant { variant_index } = pctx {
823        if input.check_parse(kw::with_constructor)? {
824            this.ne_variants[variant_index].constructor =
825                Some(UncheckedVariantConstructor::Regular);
826        } else if input.check_parse(kw::with_boxed_constructor)? {
827            this.ne_variants[variant_index].constructor = Some(UncheckedVariantConstructor::Boxed);
828        } else {
829            return Err(make_err(input));
830        }
831    } else if let ParseContext::Field { field, field_index } = pctx {
832        if input.check_parse(kw::unsafe_opaque_field)? {
833            this.layout_ctor[field] = LayoutConstructor::Opaque;
834        } else if input.check_parse(kw::unsafe_sabi_opaque_field)? {
835            this.layout_ctor[field] = LayoutConstructor::SabiOpaque;
836        } else if input.check_parse(kw::last_prefix_field)? {
837            let field_pos = field_index + 1;
838            this.first_suffix_field = FirstSuffixField { field_pos };
839        } else if input.check_parse(kw::rename)? {
840            input.parse::<Token!(=)>()?;
841            let renamed = input.parse::<Ident>()?.piped(|x| arenas.alloc(x));
842            this.renamed_fields.insert(field, Some(renamed));
843        } else if input.check_parse(kw::unsafe_change_type)? {
844            input.parse::<Token!(=)>()?;
845            let changed_type = input.parse_type()?.piped(|x| arenas.alloc(x));
846            this.changed_types.insert(field, Some(changed_type));
847        } else if input.check_parse(kw::accessible_if)? {
848            input.parse::<Token!(=)>()?;
849
850            let expr = input.parse_expr()?;
851
852            if let Expr::Lit(ExprLit { lit, .. }) = &expr {
853                ret_err_on! {
854                    !matches!(lit, Lit::Bool{..}),
855                    syn::spanned::Spanned::span(&expr),
856                    "`bool` expression",
857                    "non-bool literal",
858                }
859            }
860
861            let expr = arenas.alloc(expr);
862            this.prefix_kind_fields[field].accessible_if = Some(expr);
863        } else if input.check_parse(kw::accessor_bound)? {
864            input.parse::<Token!(=)>()?;
865            let bound = input.parse::<ParseBounds>()?.list;
866            this.accessor_bounds[field].extend(bound);
867        } else if input.check_parse(kw::bound)? {
868            input.parse::<Token!(=)>()?;
869            let bounds = input.parse::<ParseBounds>()?.list;
870            let preds = where_predicate_from(field.ty.clone(), bounds);
871            this.extra_bounds.push(preds);
872        } else if input.check_parse(kw::missing_field)? {
873            let on_missing_field =
874                input.parse_paren_with(|input| parse_missing_field(input, arenas))?;
875            let on_missing = &mut this.prefix_kind_fields[field].on_missing;
876            if on_missing.is_some() {
877                return Err(
878                    input.error("Cannot use this attribute multiple times on the same field")
879                );
880            }
881            *on_missing = Some(on_missing_field);
882        } else if input.check_parse(kw::refl)? {
883            input.parse_paren_with(|input| parse_refl_field(this, field, input, arenas))?;
884        } else {
885            return Err(make_err(input));
886        }
887    }
888    Ok(())
889}
890
891/// Parses the `#[sabi(refl = ...)` attribute.
892fn parse_refl_field<'a>(
893    this: &mut StableAbiAttrs<'a>,
894    field: &'a Field<'a>,
895    input: &ParseBuffer,
896    arenas: &'a Arenas,
897) -> Result<(), syn::Error> {
898    input.for_each_separated(Token!(,), |input| {
899        if input.check_parse(kw::pub_getter)? {
900            input.parse::<Token!(=)>()?;
901            let function = arenas.alloc(input.parse::<Ident>()?);
902            this.override_field_accessor[field] = Some(FieldAccessor::Method {
903                name: Some(function),
904            });
905        } else {
906            return Err(input.error("invalid #[sabi(refl(..))] attribute"));
907        }
908        Ok(())
909    })
910}
911
912/// Parses the contents of #[sabi(missing_field( ... ))]
913fn parse_missing_field<'a>(
914    input: &ParseBuffer,
915    arenas: &'a Arenas,
916) -> Result<OnMissingField<'a>, syn::Error> {
917    const ATTRIBUTE_MSG: &str = "
918
919Valid Attributes:
920
921    `#[sabi(missing_field(panic))]`
922    This panics if the field doesn't exist.
923
924    `#[sabi(missing_field(option))]`
925    This returns Some(field_value) if the field exists,None if the field doesn't exist.
926    This is the default.
927
928    `#[sabi(missing_field(with=\"somefunction\"))]`
929    This returns `somefunction()` if the field doesn't exist.
930    
931    `#[sabi(missing_field(value=\"some_expression\"))]`
932    This returns `(some_expression)` if the field doesn't exist.
933    
934    `#[sabi(missing_field(default))]`
935    This returns `Default::default` if the field doesn't exist.
936
937";
938    if input.check_parse(kw::option)? {
939        Ok(OnMissingField::ReturnOption)
940    } else if input.check_parse(kw::panic)? {
941        Ok(OnMissingField::Panic)
942    } else if input.check_parse(kw::default)? {
943        Ok(OnMissingField::Default_)
944    } else if input.check_parse(kw::with)? {
945        input.parse::<Token!(=)>()?;
946        let function = input.parse::<syn::Path>()?.piped(|i| arenas.alloc(i));
947        Ok(OnMissingField::With { function })
948    } else if input.check_parse(kw::value)? {
949        input.parse::<Token!(=)>()?;
950        let value = input.parse_expr()?.piped(|i| arenas.alloc(i));
951        Ok(OnMissingField::Value { value })
952    } else if input.is_empty() {
953        Err(syn_err!(
954            input.span(),
955            "Error:Expected one attribute inside `missing_field(..)`\n{}",
956            ATTRIBUTE_MSG
957        ))
958    } else {
959        Err(syn_err!(
960            input.span(),
961            "Invalid attribute.\n{}",
962            ATTRIBUTE_MSG,
963        ))
964    }
965}
966
967/// Parses the contents of #[sabi(kind(Prefix( ... )))]
968fn parse_prefix_type_list<'a>(
969    input: &ParseBuffer,
970    arenas: &'a Arenas,
971) -> Result<UncheckedPrefixKind<'a>, syn::Error> {
972    let mut prefix_ref = None;
973    let mut prefix_fields = None;
974    let mut replacing_prefix_ref_docs = Vec::new();
975
976    input.for_each_separated(Token!(,), |input| {
977        if input.check_parse(kw::prefix_ref)? {
978            input.parse::<Token!(=)>()?;
979            prefix_ref = Some(arenas.alloc(input.parse::<Ident>()?));
980        } else if input.check_parse(kw::prefix_ref_docs)? {
981            input.parse::<Token!(=)>()?;
982            replacing_prefix_ref_docs.push(input.parse_expr()?);
983        } else if input.check_parse(kw::prefix_fields)? {
984            input.parse::<Token!(=)>()?;
985            prefix_fields = Some(arenas.alloc(input.parse::<Ident>()?));
986        } else {
987            return Err(input.error(
988                "invalid #[sabi(kind(Prefix(  )))] attribute, it must be one of:\n\
989                 - prefix_ref = NameOfPrefixPointerType\n\
990                 - prefix_fields = NameOfPrefixFieldsStruct\n\
991                ",
992            ));
993        }
994        Ok(())
995    })?;
996
997    Ok(UncheckedPrefixKind {
998        prefix_ref,
999        prefix_fields,
1000        replacing_prefix_ref_docs: arenas.alloc(replacing_prefix_ref_docs),
1001    })
1002}
1003
1004/// Parses the contents of #[sabi(kind(WithNonExhaustive( ... )))]
1005fn parse_non_exhaustive_list<'a>(
1006    input: &ParseBuffer,
1007    arenas: &'a Arenas,
1008) -> Result<UncheckedNonExhaustive<'a>, syn::Error> {
1009    let trait_set_strs = [
1010        "Clone",
1011        "Display",
1012        "Debug",
1013        "Eq",
1014        "PartialEq",
1015        "Ord",
1016        "PartialOrd",
1017        "Hash",
1018        "Deserialize",
1019        "Serialize",
1020        "Send",
1021        "Sync",
1022        "Error",
1023    ];
1024
1025    let trait_set = trait_set_strs
1026        .iter()
1027        .map(|e| arenas.alloc(Ident::new(e, Span::call_site())))
1028        .collect::<HashSet<&'a Ident>>();
1029
1030    let trait_err = |trait_ident: &Ident| -> syn::Error {
1031        spanned_err!(
1032            trait_ident,
1033            "Invalid trait in  #[sabi(kind(WithNonExhaustive(traits())))].\n\
1034             Valid traits:\n\t{}\
1035            ",
1036            trait_set_strs.join("\n\t")
1037        )
1038    };
1039
1040    fn both_err(span: Span) -> syn::Error {
1041        syn_err!(
1042            span,
1043            "Cannot use both `interface=\"...\"` and `traits(...)`"
1044        )
1045    }
1046
1047    let mut this = UncheckedNonExhaustive::default();
1048
1049    let mut errors = LinearResult::ok(());
1050
1051    input.for_each_separated(Token!(,), |input| {
1052        fn parse_expr_or_type<'a>(
1053            input: &ParseBuffer,
1054            arenas: &'a Arenas,
1055        ) -> Result<ExprOrType<'a>, syn::Error> {
1056            if input.peek(syn::LitInt) {
1057                Ok(ExprOrType::Int(input.parse_int::<usize>()?))
1058            } else if input.peek(syn::token::Brace) {
1059                let expr = input.parse::<syn::Expr>()?;
1060                Ok(ExprOrType::Expr(arenas.alloc(expr)))
1061            } else {
1062                ret_err_on_peek! {
1063                    input,
1064                    syn::LitStr,
1065                    "either integer literal or type",
1066                    "string literal",
1067                }
1068
1069                Ok(ExprOrType::Type(arenas.alloc(input.parse_type()?)))
1070            }
1071        }
1072
1073        if input.check_parse(kw::align)? {
1074            input.parse::<Token!(=)>()?;
1075            this.alignment = Some(parse_expr_or_type(input, arenas)?);
1076        } else if input.check_parse(kw::size)? {
1077            input.parse::<Token!(=)>()?;
1078            this.size = Some(parse_expr_or_type(input, arenas)?);
1079        } else if input.check_parse(kw::assert_nonexhaustive)? {
1080            if input.peek(syn::token::Paren) {
1081                input
1082                    .parse_paren_buffer()?
1083                    .for_each_separated(Token!(,), |input| {
1084                        let ty = arenas.alloc(input.parse_type()?);
1085                        this.assert_nonexh.push(ty);
1086                        Ok(())
1087                    })?;
1088            } else {
1089                input.parse::<Token!(=)>()?;
1090                let ty = arenas.alloc(input.parse_type()?);
1091                this.assert_nonexh.push(ty);
1092            }
1093        } else if let Some(in_token) = input.peek_parse(kw::interface)? {
1094            input.parse::<Token!(=)>()?;
1095            let ty = arenas.alloc(input.parse_type()?);
1096            if this.enum_interface.is_some() {
1097                return Err(both_err(in_token.span));
1098            }
1099            this.enum_interface = Some(EnumInterface::Old(ty));
1100        } else if let Some(traits_token) = input.peek_parse(kw::traits)? {
1101            let enum_interface = match &mut this.enum_interface {
1102                Some(EnumInterface::New(x)) => x,
1103                Some(EnumInterface::Old { .. }) => {
1104                    return Err(both_err(traits_token.span));
1105                }
1106                x @ None => {
1107                    *x = Some(EnumInterface::New(Default::default()));
1108                    match x {
1109                        Some(EnumInterface::New(x)) => x,
1110                        _ => unreachable!(),
1111                    }
1112                }
1113            };
1114
1115            input
1116                .parse_paren_buffer()?
1117                .for_each_separated(Token!(,), |input| {
1118                    let ident = input.parse::<Ident>()?;
1119
1120                    let is_impld = if input.check_parse(Token!(=))? {
1121                        input.parse::<syn::LitBool>()?.value
1122                    } else {
1123                        true
1124                    };
1125
1126                    match trait_set.get(&ident) {
1127                        Some(&trait_ident) => {
1128                            if is_impld {
1129                                &mut enum_interface.impld
1130                            } else {
1131                                &mut enum_interface.unimpld
1132                            }
1133                            .push(trait_ident);
1134                        }
1135                        None => errors.push_err(trait_err(&ident)),
1136                    }
1137
1138                    Ok(())
1139                })?;
1140        } else {
1141            return Err(input.error("invalid #[sabi(kind(WithNonExhaustive(....)))] attribute"));
1142        }
1143        Ok(())
1144    })?;
1145
1146    errors.into_result().map(|_| this)
1147}
1148
1149////////////////////////////////////////////////////////////////////////////////
1150
1151fn where_predicate_from(
1152    ty: syn::Type,
1153    bounds: Punctuated<TypeParamBound, syn::token::Add>,
1154) -> syn::WherePredicate {
1155    let x = syn::PredicateType {
1156        lifetimes: None,
1157        bounded_ty: ty,
1158        colon_token: Default::default(),
1159        bounds,
1160    };
1161    syn::WherePredicate::Type(x)
1162}