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
150pub struct ConstIdents {
154 pub(crate) strings: Ident,
156}
157
158#[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#[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
204pub(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 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#[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
462pub(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
513fn 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
587fn 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
891fn 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
912fn 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
967fn 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
1004fn 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
1149fn 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}