1 use crate::syntax::attrs::OtherAttrs;
2 use crate::syntax::cfg::CfgExpr;
3 use crate::syntax::discriminant::DiscriminantSet;
4 use crate::syntax::file::{Item, ItemForeignMod};
5 use crate::syntax::report::Errors;
6 use crate::syntax::Atom::*;
7 use crate::syntax::{
8 attrs, error, Api, Array, Derive, Doc, Enum, EnumRepr, ExternFn, ExternType, ForeignName, Impl,
9 Include, IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Ptr, Receiver, Ref,
10 Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var, Variant,
11 };
12 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
13 use quote::{format_ident, quote, quote_spanned};
14 use std::mem;
15 use syn::parse::{ParseStream, Parser};
16 use syn::punctuated::Punctuated;
17 use syn::{
18 Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
19 GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
20 Pat, PathArguments, Result, ReturnType, Signature as RustSignature, Token, TraitBound,
21 TraitBoundModifier, Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypePtr,
22 TypeReference, Variant as RustVariant, Visibility,
23 };
24
25 pub mod kw {
26 syn::custom_keyword!(Pin);
27 syn::custom_keyword!(Result);
28 }
29
parse_items( cx: &mut Errors, items: Vec<Item>, trusted: bool, namespace: &Namespace, ) -> Vec<Api>30 pub fn parse_items(
31 cx: &mut Errors,
32 items: Vec<Item>,
33 trusted: bool,
34 namespace: &Namespace,
35 ) -> Vec<Api> {
36 let mut apis = Vec::new();
37 for item in items {
38 match item {
39 Item::Struct(item) => match parse_struct(cx, item, namespace) {
40 Ok(strct) => apis.push(strct),
41 Err(err) => cx.push(err),
42 },
43 Item::Enum(item) => apis.push(parse_enum(cx, item, namespace)),
44 Item::ForeignMod(foreign_mod) => {
45 parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, namespace)
46 }
47 Item::Impl(item) => match parse_impl(cx, item) {
48 Ok(imp) => apis.push(imp),
49 Err(err) => cx.push(err),
50 },
51 Item::Use(item) => cx.error(item, error::USE_NOT_ALLOWED),
52 Item::Other(item) => cx.error(item, "unsupported item"),
53 }
54 }
55 apis
56 }
57
parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> Result<Api>58 fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> Result<Api> {
59 let mut cfg = CfgExpr::Unconditional;
60 let mut doc = Doc::new();
61 let mut derives = Vec::new();
62 let mut namespace = namespace.clone();
63 let mut cxx_name = None;
64 let mut rust_name = None;
65 let attrs = attrs::parse(
66 cx,
67 mem::take(&mut item.attrs),
68 attrs::Parser {
69 cfg: Some(&mut cfg),
70 doc: Some(&mut doc),
71 derives: Some(&mut derives),
72 namespace: Some(&mut namespace),
73 cxx_name: Some(&mut cxx_name),
74 rust_name: Some(&mut rust_name),
75 ..Default::default()
76 },
77 );
78
79 let named_fields = match item.fields {
80 Fields::Named(fields) => fields,
81 Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")),
82 Fields::Unnamed(_) => {
83 return Err(Error::new_spanned(item, "tuple structs are not supported"));
84 }
85 };
86
87 let mut lifetimes = Punctuated::new();
88 let mut has_unsupported_generic_param = false;
89 for pair in item.generics.params.into_pairs() {
90 let (param, punct) = pair.into_tuple();
91 match param {
92 GenericParam::Lifetime(param) => {
93 if !param.bounds.is_empty() && !has_unsupported_generic_param {
94 let msg = "lifetime parameter with bounds is not supported yet";
95 cx.error(¶m, msg);
96 has_unsupported_generic_param = true;
97 }
98 lifetimes.push_value(param.lifetime);
99 if let Some(punct) = punct {
100 lifetimes.push_punct(punct);
101 }
102 }
103 GenericParam::Type(param) => {
104 if !has_unsupported_generic_param {
105 let msg = "struct with generic type parameter is not supported yet";
106 cx.error(¶m, msg);
107 has_unsupported_generic_param = true;
108 }
109 }
110 GenericParam::Const(param) => {
111 if !has_unsupported_generic_param {
112 let msg = "struct with const generic parameter is not supported yet";
113 cx.error(¶m, msg);
114 has_unsupported_generic_param = true;
115 }
116 }
117 }
118 }
119
120 if let Some(where_clause) = &item.generics.where_clause {
121 cx.error(
122 where_clause,
123 "struct with where-clause is not supported yet",
124 );
125 }
126
127 let mut fields = Vec::new();
128 for field in named_fields.named {
129 let ident = field.ident.unwrap();
130 let mut cfg = CfgExpr::Unconditional;
131 let mut doc = Doc::new();
132 let mut cxx_name = None;
133 let mut rust_name = None;
134 let attrs = attrs::parse(
135 cx,
136 field.attrs,
137 attrs::Parser {
138 cfg: Some(&mut cfg),
139 doc: Some(&mut doc),
140 cxx_name: Some(&mut cxx_name),
141 rust_name: Some(&mut rust_name),
142 ..Default::default()
143 },
144 );
145 let ty = match parse_type(&field.ty) {
146 Ok(ty) => ty,
147 Err(err) => {
148 cx.push(err);
149 continue;
150 }
151 };
152 let visibility = visibility_pub(&field.vis, ident.span());
153 let name = pair(Namespace::default(), &ident, cxx_name, rust_name);
154 let colon_token = field.colon_token.unwrap();
155 fields.push(Var {
156 cfg,
157 doc,
158 attrs,
159 visibility,
160 name,
161 colon_token,
162 ty,
163 });
164 }
165
166 let struct_token = item.struct_token;
167 let visibility = visibility_pub(&item.vis, struct_token.span);
168 let name = pair(namespace, &item.ident, cxx_name, rust_name);
169 let generics = Lifetimes {
170 lt_token: item.generics.lt_token,
171 lifetimes,
172 gt_token: item.generics.gt_token,
173 };
174 let brace_token = named_fields.brace_token;
175
176 Ok(Api::Struct(Struct {
177 cfg,
178 doc,
179 derives,
180 attrs,
181 visibility,
182 struct_token,
183 name,
184 generics,
185 brace_token,
186 fields,
187 }))
188 }
189
parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api190 fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api {
191 let mut cfg = CfgExpr::Unconditional;
192 let mut doc = Doc::new();
193 let mut derives = Vec::new();
194 let mut repr = None;
195 let mut namespace = namespace.clone();
196 let mut cxx_name = None;
197 let mut rust_name = None;
198 let mut variants_from_header = None;
199 let attrs = attrs::parse(
200 cx,
201 item.attrs,
202 attrs::Parser {
203 cfg: Some(&mut cfg),
204 doc: Some(&mut doc),
205 derives: Some(&mut derives),
206 repr: Some(&mut repr),
207 namespace: Some(&mut namespace),
208 cxx_name: Some(&mut cxx_name),
209 rust_name: Some(&mut rust_name),
210 variants_from_header: Some(&mut variants_from_header),
211 ..Default::default()
212 },
213 );
214
215 if !item.generics.params.is_empty() {
216 let vis = &item.vis;
217 let enum_token = item.enum_token;
218 let ident = &item.ident;
219 let generics = &item.generics;
220 let span = quote!(#vis #enum_token #ident #generics);
221 cx.error(span, "enum with generic parameters is not supported");
222 } else if let Some(where_clause) = &item.generics.where_clause {
223 cx.error(where_clause, "enum with where-clause is not supported");
224 }
225
226 let mut variants = Vec::new();
227 let mut discriminants = DiscriminantSet::new(repr);
228 for variant in item.variants {
229 match parse_variant(cx, variant, &mut discriminants) {
230 Ok(variant) => variants.push(variant),
231 Err(err) => cx.push(err),
232 }
233 }
234
235 let enum_token = item.enum_token;
236 let visibility = visibility_pub(&item.vis, enum_token.span);
237 let brace_token = item.brace_token;
238
239 let explicit_repr = repr.is_some();
240 let mut repr = U8;
241 match discriminants.inferred_repr() {
242 Ok(inferred) => repr = inferred,
243 Err(err) => {
244 let span = quote_spanned!(brace_token.span=> #enum_token {});
245 cx.error(span, err);
246 variants.clear();
247 }
248 }
249
250 let name = pair(namespace, &item.ident, cxx_name, rust_name);
251 let repr_ident = Ident::new(repr.as_ref(), Span::call_site());
252 let repr_type = Type::Ident(NamedType::new(repr_ident));
253 let repr = EnumRepr::Native {
254 atom: repr,
255 repr_type,
256 };
257 let generics = Lifetimes {
258 lt_token: None,
259 lifetimes: Punctuated::new(),
260 gt_token: None,
261 };
262 let variants_from_header_attr = variants_from_header;
263 let variants_from_header = variants_from_header_attr.is_some();
264
265 Api::Enum(Enum {
266 cfg,
267 doc,
268 derives,
269 attrs,
270 visibility,
271 enum_token,
272 name,
273 generics,
274 brace_token,
275 variants,
276 variants_from_header,
277 variants_from_header_attr,
278 repr,
279 explicit_repr,
280 })
281 }
282
parse_variant( cx: &mut Errors, mut variant: RustVariant, discriminants: &mut DiscriminantSet, ) -> Result<Variant>283 fn parse_variant(
284 cx: &mut Errors,
285 mut variant: RustVariant,
286 discriminants: &mut DiscriminantSet,
287 ) -> Result<Variant> {
288 let mut cfg = CfgExpr::Unconditional;
289 let mut doc = Doc::new();
290 let mut cxx_name = None;
291 let mut rust_name = None;
292 let attrs = attrs::parse(
293 cx,
294 mem::take(&mut variant.attrs),
295 attrs::Parser {
296 cfg: Some(&mut cfg),
297 doc: Some(&mut doc),
298 cxx_name: Some(&mut cxx_name),
299 rust_name: Some(&mut rust_name),
300 ..Default::default()
301 },
302 );
303
304 match variant.fields {
305 Fields::Unit => {}
306 _ => {
307 let msg = "enums with data are not supported yet";
308 return Err(Error::new_spanned(variant, msg));
309 }
310 }
311
312 let expr = variant.discriminant.as_ref().map(|(_, expr)| expr);
313 let try_discriminant = match &expr {
314 Some(lit) => discriminants.insert(lit),
315 None => discriminants.insert_next(),
316 };
317 let discriminant = match try_discriminant {
318 Ok(discriminant) => discriminant,
319 Err(err) => return Err(Error::new_spanned(variant, err)),
320 };
321
322 let name = pair(Namespace::ROOT, &variant.ident, cxx_name, rust_name);
323 let expr = variant.discriminant.map(|(_, expr)| expr);
324
325 Ok(Variant {
326 cfg,
327 doc,
328 attrs,
329 name,
330 discriminant,
331 expr,
332 })
333 }
334
parse_foreign_mod( cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec<Api>, trusted: bool, namespace: &Namespace, )335 fn parse_foreign_mod(
336 cx: &mut Errors,
337 foreign_mod: ItemForeignMod,
338 out: &mut Vec<Api>,
339 trusted: bool,
340 namespace: &Namespace,
341 ) {
342 let lang = match parse_lang(&foreign_mod.abi) {
343 Ok(lang) => lang,
344 Err(err) => return cx.push(err),
345 };
346
347 match lang {
348 Lang::Rust => {
349 if foreign_mod.unsafety.is_some() {
350 let unsafety = foreign_mod.unsafety;
351 let abi = &foreign_mod.abi;
352 let span = quote!(#unsafety #abi);
353 cx.error(span, "extern \"Rust\" block does not need to be unsafe");
354 }
355 }
356 Lang::Cxx => {}
357 }
358
359 let trusted = trusted || foreign_mod.unsafety.is_some();
360
361 let mut cfg = CfgExpr::Unconditional;
362 let mut namespace = namespace.clone();
363 let attrs = attrs::parse(
364 cx,
365 foreign_mod.attrs,
366 attrs::Parser {
367 cfg: Some(&mut cfg),
368 namespace: Some(&mut namespace),
369 ..Default::default()
370 },
371 );
372
373 let mut items = Vec::new();
374 for foreign in foreign_mod.items {
375 match foreign {
376 ForeignItem::Type(foreign) => {
377 let ety = parse_extern_type(cx, foreign, lang, trusted, &cfg, &namespace, &attrs);
378 items.push(ety);
379 }
380 ForeignItem::Fn(foreign) => {
381 match parse_extern_fn(cx, foreign, lang, trusted, &cfg, &namespace, &attrs) {
382 Ok(efn) => items.push(efn),
383 Err(err) => cx.push(err),
384 }
385 }
386 ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
387 match foreign.mac.parse_body_with(parse_include) {
388 Ok(mut include) => {
389 include.cfg = cfg.clone();
390 items.push(Api::Include(include));
391 }
392 Err(err) => cx.push(err),
393 }
394 }
395 ForeignItem::Verbatim(tokens) => {
396 match parse_extern_verbatim(cx, tokens, lang, trusted, &cfg, &namespace, &attrs) {
397 Ok(api) => items.push(api),
398 Err(err) => cx.push(err),
399 }
400 }
401 _ => cx.error(foreign, "unsupported foreign item"),
402 }
403 }
404
405 if !trusted
406 && items.iter().any(|api| match api {
407 Api::CxxFunction(efn) => efn.unsafety.is_none(),
408 _ => false,
409 })
410 {
411 cx.error(
412 foreign_mod.abi,
413 "block must be declared `unsafe extern \"C++\"` if it contains any safe-to-call C++ functions",
414 );
415 }
416
417 let mut types = items.iter().filter_map(|item| match item {
418 Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.name),
419 Api::TypeAlias(alias) => Some(&alias.name),
420 _ => None,
421 });
422 if let (Some(single_type), None) = (types.next(), types.next()) {
423 let single_type = single_type.clone();
424 for item in &mut items {
425 if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
426 if let Some(receiver) = &mut efn.receiver {
427 if receiver.ty.rust == "Self" {
428 receiver.ty.rust = single_type.rust.clone();
429 }
430 }
431 }
432 }
433 }
434
435 out.extend(items);
436 }
437
parse_lang(abi: &Abi) -> Result<Lang>438 fn parse_lang(abi: &Abi) -> Result<Lang> {
439 let name = match &abi.name {
440 Some(name) => name,
441 None => {
442 return Err(Error::new_spanned(
443 abi,
444 "ABI name is required, extern \"C++\" or extern \"Rust\"",
445 ));
446 }
447 };
448
449 match name.value().as_str() {
450 "C++" => Ok(Lang::Cxx),
451 "Rust" => Ok(Lang::Rust),
452 _ => Err(Error::new_spanned(
453 abi,
454 "unrecognized ABI, requires either \"C++\" or \"Rust\"",
455 )),
456 }
457 }
458
parse_extern_type( cx: &mut Errors, foreign_type: ForeignItemType, lang: Lang, trusted: bool, extern_block_cfg: &CfgExpr, namespace: &Namespace, attrs: &OtherAttrs, ) -> Api459 fn parse_extern_type(
460 cx: &mut Errors,
461 foreign_type: ForeignItemType,
462 lang: Lang,
463 trusted: bool,
464 extern_block_cfg: &CfgExpr,
465 namespace: &Namespace,
466 attrs: &OtherAttrs,
467 ) -> Api {
468 let mut cfg = extern_block_cfg.clone();
469 let mut doc = Doc::new();
470 let mut derives = Vec::new();
471 let mut namespace = namespace.clone();
472 let mut cxx_name = None;
473 let mut rust_name = None;
474 let mut attrs = attrs.clone();
475 attrs.extend(attrs::parse(
476 cx,
477 foreign_type.attrs,
478 attrs::Parser {
479 cfg: Some(&mut cfg),
480 doc: Some(&mut doc),
481 derives: Some(&mut derives),
482 namespace: Some(&mut namespace),
483 cxx_name: Some(&mut cxx_name),
484 rust_name: Some(&mut rust_name),
485 ..Default::default()
486 },
487 ));
488
489 let type_token = foreign_type.type_token;
490 let visibility = visibility_pub(&foreign_type.vis, type_token.span);
491 let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name);
492 let generics = extern_type_lifetimes(cx, foreign_type.generics);
493 let colon_token = None;
494 let bounds = Vec::new();
495 let semi_token = foreign_type.semi_token;
496
497 (match lang {
498 Lang::Cxx => Api::CxxType,
499 Lang::Rust => Api::RustType,
500 })(ExternType {
501 cfg,
502 lang,
503 doc,
504 derives,
505 attrs,
506 visibility,
507 type_token,
508 name,
509 generics,
510 colon_token,
511 bounds,
512 semi_token,
513 trusted,
514 })
515 }
516
parse_extern_fn( cx: &mut Errors, mut foreign_fn: ForeignItemFn, lang: Lang, trusted: bool, extern_block_cfg: &CfgExpr, namespace: &Namespace, attrs: &OtherAttrs, ) -> Result<Api>517 fn parse_extern_fn(
518 cx: &mut Errors,
519 mut foreign_fn: ForeignItemFn,
520 lang: Lang,
521 trusted: bool,
522 extern_block_cfg: &CfgExpr,
523 namespace: &Namespace,
524 attrs: &OtherAttrs,
525 ) -> Result<Api> {
526 let mut cfg = extern_block_cfg.clone();
527 let mut doc = Doc::new();
528 let mut namespace = namespace.clone();
529 let mut cxx_name = None;
530 let mut rust_name = None;
531 let mut attrs = attrs.clone();
532 attrs.extend(attrs::parse(
533 cx,
534 mem::take(&mut foreign_fn.attrs),
535 attrs::Parser {
536 cfg: Some(&mut cfg),
537 doc: Some(&mut doc),
538 namespace: Some(&mut namespace),
539 cxx_name: Some(&mut cxx_name),
540 rust_name: Some(&mut rust_name),
541 ..Default::default()
542 },
543 ));
544
545 let generics = &foreign_fn.sig.generics;
546 if generics.where_clause.is_some()
547 || generics.params.iter().any(|param| match param {
548 GenericParam::Lifetime(lifetime) => !lifetime.bounds.is_empty(),
549 GenericParam::Type(_) | GenericParam::Const(_) => true,
550 })
551 {
552 return Err(Error::new_spanned(
553 foreign_fn,
554 "extern function with generic parameters is not supported yet",
555 ));
556 }
557
558 if let Some(variadic) = &foreign_fn.sig.variadic {
559 return Err(Error::new_spanned(
560 variadic,
561 "variadic function is not supported yet",
562 ));
563 }
564
565 if foreign_fn.sig.asyncness.is_some() && !cfg!(feature = "experimental-async-fn") {
566 return Err(Error::new_spanned(
567 foreign_fn,
568 "async function is not directly supported yet, but see https://cxx.rs/async.html \
569 for a working approach, and https://github.com/pcwalton/cxx-async for some helpers; \
570 eventually what you wrote will work but it isn't integrated into the cxx::bridge \
571 macro yet",
572 ));
573 }
574
575 if foreign_fn.sig.constness.is_some() {
576 return Err(Error::new_spanned(
577 foreign_fn,
578 "const extern function is not supported",
579 ));
580 }
581
582 if let Some(abi) = &foreign_fn.sig.abi {
583 return Err(Error::new_spanned(
584 abi,
585 "explicit ABI on extern function is not supported",
586 ));
587 }
588
589 let mut receiver = None;
590 let mut args = Punctuated::new();
591 for arg in foreign_fn.sig.inputs.pairs() {
592 let (arg, comma) = arg.into_tuple();
593 match arg {
594 FnArg::Receiver(arg) => {
595 if let Some((ampersand, lifetime)) = &arg.reference {
596 receiver = Some(Receiver {
597 pinned: false,
598 ampersand: *ampersand,
599 lifetime: lifetime.clone(),
600 mutable: arg.mutability.is_some(),
601 var: arg.self_token,
602 colon_token: Token,
603 ty: NamedType::new(Ident::new("Self", arg.self_token.span)),
604 shorthand: true,
605 pin_tokens: None,
606 mutability: arg.mutability,
607 });
608 continue;
609 }
610 if let Some(colon_token) = arg.colon_token {
611 let ty = parse_type(&arg.ty)?;
612 if let Type::Ref(reference) = ty {
613 if let Type::Ident(ident) = reference.inner {
614 receiver = Some(Receiver {
615 pinned: reference.pinned,
616 ampersand: reference.ampersand,
617 lifetime: reference.lifetime,
618 mutable: reference.mutable,
619 var: Token),
620 colon_token,
621 ty: ident,
622 shorthand: false,
623 pin_tokens: reference.pin_tokens,
624 mutability: reference.mutability,
625 });
626 continue;
627 }
628 }
629 }
630 return Err(Error::new_spanned(arg, "unsupported method receiver"));
631 }
632 FnArg::Typed(arg) => {
633 let ident = match arg.pat.as_ref() {
634 Pat::Ident(pat) => pat.ident.clone(),
635 Pat::Wild(pat) => {
636 Ident::new(&format!("arg{}", args.len()), pat.underscore_token.span)
637 }
638 _ => return Err(Error::new_spanned(arg, "unsupported signature")),
639 };
640 let ty = parse_type(&arg.ty)?;
641 let cfg = CfgExpr::Unconditional;
642 let doc = Doc::new();
643 let attrs = OtherAttrs::none();
644 let visibility = Token);
645 let name = pair(Namespace::default(), &ident, None, None);
646 let colon_token = arg.colon_token;
647 args.push_value(Var {
648 cfg,
649 doc,
650 attrs,
651 visibility,
652 name,
653 colon_token,
654 ty,
655 });
656 if let Some(comma) = comma {
657 args.push_punct(*comma);
658 }
659 }
660 }
661 }
662
663 let mut throws_tokens = None;
664 let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
665 let throws = throws_tokens.is_some();
666 let asyncness = foreign_fn.sig.asyncness;
667 let unsafety = foreign_fn.sig.unsafety;
668 let fn_token = foreign_fn.sig.fn_token;
669 let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span);
670 let visibility = visibility_pub(&foreign_fn.vis, inherited_span);
671 let name = pair(namespace, &foreign_fn.sig.ident, cxx_name, rust_name);
672 let generics = generics.clone();
673 let paren_token = foreign_fn.sig.paren_token;
674 let semi_token = foreign_fn.semi_token;
675
676 Ok(match lang {
677 Lang::Cxx => Api::CxxFunction,
678 Lang::Rust => Api::RustFunction,
679 }(ExternFn {
680 cfg,
681 lang,
682 doc,
683 attrs,
684 visibility,
685 name,
686 sig: Signature {
687 asyncness,
688 unsafety,
689 fn_token,
690 generics,
691 receiver,
692 args,
693 ret,
694 throws,
695 paren_token,
696 throws_tokens,
697 },
698 semi_token,
699 trusted,
700 }))
701 }
702
parse_extern_verbatim( cx: &mut Errors, tokens: TokenStream, lang: Lang, trusted: bool, extern_block_cfg: &CfgExpr, namespace: &Namespace, attrs: &OtherAttrs, ) -> Result<Api>703 fn parse_extern_verbatim(
704 cx: &mut Errors,
705 tokens: TokenStream,
706 lang: Lang,
707 trusted: bool,
708 extern_block_cfg: &CfgExpr,
709 namespace: &Namespace,
710 attrs: &OtherAttrs,
711 ) -> Result<Api> {
712 |input: ParseStream| -> Result<Api> {
713 let unparsed_attrs = input.call(Attribute::parse_outer)?;
714 let visibility: Visibility = input.parse()?;
715 if input.peek(Token![type]) {
716 parse_extern_verbatim_type(
717 cx,
718 unparsed_attrs,
719 visibility,
720 input,
721 lang,
722 trusted,
723 extern_block_cfg,
724 namespace,
725 attrs,
726 )
727 } else if input.peek(Token![fn]) {
728 parse_extern_verbatim_fn(input)
729 } else {
730 let span = input.cursor().token_stream();
731 Err(Error::new_spanned(
732 span,
733 "unsupported foreign item, expected `type` or `fn`",
734 ))
735 }
736 }
737 .parse2(tokens)
738 }
739
parse_extern_verbatim_type( cx: &mut Errors, unparsed_attrs: Vec<Attribute>, visibility: Visibility, input: ParseStream, lang: Lang, trusted: bool, extern_block_cfg: &CfgExpr, namespace: &Namespace, attrs: &OtherAttrs, ) -> Result<Api>740 fn parse_extern_verbatim_type(
741 cx: &mut Errors,
742 unparsed_attrs: Vec<Attribute>,
743 visibility: Visibility,
744 input: ParseStream,
745 lang: Lang,
746 trusted: bool,
747 extern_block_cfg: &CfgExpr,
748 namespace: &Namespace,
749 attrs: &OtherAttrs,
750 ) -> Result<Api> {
751 let type_token: Token![type] = input.parse()?;
752 let ident: Ident = input.parse()?;
753 let generics: Generics = input.parse()?;
754 let lifetimes = extern_type_lifetimes(cx, generics);
755 let lookahead = input.lookahead1();
756 if lookahead.peek(Token![=]) {
757 // type Alias = crate::path::to::Type;
758 parse_type_alias(
759 cx,
760 unparsed_attrs,
761 visibility,
762 type_token,
763 ident,
764 lifetimes,
765 input,
766 lang,
767 extern_block_cfg,
768 namespace,
769 attrs,
770 )
771 } else if lookahead.peek(Token![:]) {
772 // type Opaque: Bound2 + Bound2;
773 parse_extern_type_bounded(
774 cx,
775 unparsed_attrs,
776 visibility,
777 type_token,
778 ident,
779 lifetimes,
780 input,
781 lang,
782 trusted,
783 extern_block_cfg,
784 namespace,
785 attrs,
786 )
787 } else {
788 Err(lookahead.error())
789 }
790 }
791
extern_type_lifetimes(cx: &mut Errors, generics: Generics) -> Lifetimes792 fn extern_type_lifetimes(cx: &mut Errors, generics: Generics) -> Lifetimes {
793 let mut lifetimes = Punctuated::new();
794 let mut has_unsupported_generic_param = false;
795 for pair in generics.params.into_pairs() {
796 let (param, punct) = pair.into_tuple();
797 match param {
798 GenericParam::Lifetime(param) => {
799 if !param.bounds.is_empty() && !has_unsupported_generic_param {
800 let msg = "lifetime parameter with bounds is not supported yet";
801 cx.error(¶m, msg);
802 has_unsupported_generic_param = true;
803 }
804 lifetimes.push_value(param.lifetime);
805 if let Some(punct) = punct {
806 lifetimes.push_punct(punct);
807 }
808 }
809 GenericParam::Type(param) => {
810 if !has_unsupported_generic_param {
811 let msg = "extern type with generic type parameter is not supported yet";
812 cx.error(¶m, msg);
813 has_unsupported_generic_param = true;
814 }
815 }
816 GenericParam::Const(param) => {
817 if !has_unsupported_generic_param {
818 let msg = "extern type with const generic parameter is not supported yet";
819 cx.error(¶m, msg);
820 has_unsupported_generic_param = true;
821 }
822 }
823 }
824 }
825 Lifetimes {
826 lt_token: generics.lt_token,
827 lifetimes,
828 gt_token: generics.gt_token,
829 }
830 }
831
parse_extern_verbatim_fn(input: ParseStream) -> Result<Api>832 fn parse_extern_verbatim_fn(input: ParseStream) -> Result<Api> {
833 input.parse::<RustSignature>()?;
834 input.parse::<Token![;]>()?;
835 unreachable!()
836 }
837
parse_type_alias( cx: &mut Errors, unparsed_attrs: Vec<Attribute>, visibility: Visibility, type_token: Token![type], ident: Ident, generics: Lifetimes, input: ParseStream, lang: Lang, extern_block_cfg: &CfgExpr, namespace: &Namespace, attrs: &OtherAttrs, ) -> Result<Api>838 fn parse_type_alias(
839 cx: &mut Errors,
840 unparsed_attrs: Vec<Attribute>,
841 visibility: Visibility,
842 type_token: Token![type],
843 ident: Ident,
844 generics: Lifetimes,
845 input: ParseStream,
846 lang: Lang,
847 extern_block_cfg: &CfgExpr,
848 namespace: &Namespace,
849 attrs: &OtherAttrs,
850 ) -> Result<Api> {
851 let eq_token: Token![=] = input.parse()?;
852 let ty: RustType = input.parse()?;
853 let semi_token: Token![;] = input.parse()?;
854
855 let mut cfg = extern_block_cfg.clone();
856 let mut doc = Doc::new();
857 let mut derives = Vec::new();
858 let mut namespace = namespace.clone();
859 let mut cxx_name = None;
860 let mut rust_name = None;
861 let mut attrs = attrs.clone();
862 attrs.extend(attrs::parse(
863 cx,
864 unparsed_attrs,
865 attrs::Parser {
866 cfg: Some(&mut cfg),
867 doc: Some(&mut doc),
868 derives: Some(&mut derives),
869 namespace: Some(&mut namespace),
870 cxx_name: Some(&mut cxx_name),
871 rust_name: Some(&mut rust_name),
872 ..Default::default()
873 },
874 ));
875
876 if lang == Lang::Rust {
877 let span = quote!(#type_token #semi_token);
878 let msg = "type alias in extern \"Rust\" block is not supported";
879 return Err(Error::new_spanned(span, msg));
880 }
881
882 let visibility = visibility_pub(&visibility, type_token.span);
883 let name = pair(namespace, &ident, cxx_name, rust_name);
884
885 Ok(Api::TypeAlias(TypeAlias {
886 cfg,
887 doc,
888 derives,
889 attrs,
890 visibility,
891 type_token,
892 name,
893 generics,
894 eq_token,
895 ty,
896 semi_token,
897 }))
898 }
899
parse_extern_type_bounded( cx: &mut Errors, unparsed_attrs: Vec<Attribute>, visibility: Visibility, type_token: Token![type], ident: Ident, generics: Lifetimes, input: ParseStream, lang: Lang, trusted: bool, extern_block_cfg: &CfgExpr, namespace: &Namespace, attrs: &OtherAttrs, ) -> Result<Api>900 fn parse_extern_type_bounded(
901 cx: &mut Errors,
902 unparsed_attrs: Vec<Attribute>,
903 visibility: Visibility,
904 type_token: Token![type],
905 ident: Ident,
906 generics: Lifetimes,
907 input: ParseStream,
908 lang: Lang,
909 trusted: bool,
910 extern_block_cfg: &CfgExpr,
911 namespace: &Namespace,
912 attrs: &OtherAttrs,
913 ) -> Result<Api> {
914 let mut bounds = Vec::new();
915 let colon_token: Option<Token![:]> = input.parse()?;
916 if colon_token.is_some() {
917 loop {
918 match input.parse()? {
919 TypeParamBound::Trait(TraitBound {
920 paren_token: None,
921 modifier: TraitBoundModifier::None,
922 lifetimes: None,
923 path,
924 }) if if let Some(derive) = path.get_ident().and_then(Derive::from) {
925 bounds.push(derive);
926 true
927 } else {
928 false
929 } => {}
930 bound => cx.error(bound, "unsupported trait"),
931 }
932
933 let lookahead = input.lookahead1();
934 if lookahead.peek(Token![+]) {
935 input.parse::<Token![+]>()?;
936 } else if lookahead.peek(Token![;]) {
937 break;
938 } else {
939 return Err(lookahead.error());
940 }
941 }
942 }
943 let semi_token: Token![;] = input.parse()?;
944
945 let mut cfg = extern_block_cfg.clone();
946 let mut doc = Doc::new();
947 let mut derives = Vec::new();
948 let mut namespace = namespace.clone();
949 let mut cxx_name = None;
950 let mut rust_name = None;
951 let mut attrs = attrs.clone();
952 attrs.extend(attrs::parse(
953 cx,
954 unparsed_attrs,
955 attrs::Parser {
956 cfg: Some(&mut cfg),
957 doc: Some(&mut doc),
958 derives: Some(&mut derives),
959 namespace: Some(&mut namespace),
960 cxx_name: Some(&mut cxx_name),
961 rust_name: Some(&mut rust_name),
962 ..Default::default()
963 },
964 ));
965
966 let visibility = visibility_pub(&visibility, type_token.span);
967 let name = pair(namespace, &ident, cxx_name, rust_name);
968
969 Ok(match lang {
970 Lang::Cxx => Api::CxxType,
971 Lang::Rust => Api::RustType,
972 }(ExternType {
973 cfg,
974 lang,
975 doc,
976 derives,
977 attrs,
978 visibility,
979 type_token,
980 name,
981 generics,
982 colon_token,
983 bounds,
984 semi_token,
985 trusted,
986 }))
987 }
988
parse_impl(cx: &mut Errors, imp: ItemImpl) -> Result<Api>989 fn parse_impl(cx: &mut Errors, imp: ItemImpl) -> Result<Api> {
990 let impl_token = imp.impl_token;
991
992 let mut cfg = CfgExpr::Unconditional;
993 attrs::parse(
994 cx,
995 imp.attrs,
996 attrs::Parser {
997 cfg: Some(&mut cfg),
998 ..Default::default()
999 },
1000 );
1001
1002 if !imp.items.is_empty() {
1003 let mut span = Group::new(Delimiter::Brace, TokenStream::new());
1004 span.set_span(imp.brace_token.span.join());
1005 return Err(Error::new_spanned(span, "expected an empty impl block"));
1006 }
1007
1008 if let Some((bang, path, for_token)) = &imp.trait_ {
1009 let self_ty = &imp.self_ty;
1010 let span = quote!(#bang #path #for_token #self_ty);
1011 return Err(Error::new_spanned(
1012 span,
1013 "unexpected impl, expected something like `impl UniquePtr<T> {}`",
1014 ));
1015 }
1016
1017 if let Some(where_clause) = imp.generics.where_clause {
1018 return Err(Error::new_spanned(
1019 where_clause,
1020 "where-clause on an impl is not supported yet",
1021 ));
1022 }
1023 let mut impl_generics = Lifetimes {
1024 lt_token: imp.generics.lt_token,
1025 lifetimes: Punctuated::new(),
1026 gt_token: imp.generics.gt_token,
1027 };
1028 for pair in imp.generics.params.into_pairs() {
1029 let (param, punct) = pair.into_tuple();
1030 match param {
1031 GenericParam::Lifetime(def) if def.bounds.is_empty() => {
1032 impl_generics.lifetimes.push_value(def.lifetime);
1033 if let Some(punct) = punct {
1034 impl_generics.lifetimes.push_punct(punct);
1035 }
1036 }
1037 _ => {
1038 let span = quote!(#impl_token #impl_generics);
1039 return Err(Error::new_spanned(
1040 span,
1041 "generic parameter on an impl is not supported yet",
1042 ));
1043 }
1044 }
1045 }
1046
1047 let mut negative_token = None;
1048 let mut self_ty = *imp.self_ty;
1049 if let RustType::Verbatim(ty) = &self_ty {
1050 let mut iter = ty.clone().into_iter();
1051 if let Some(TokenTree::Punct(punct)) = iter.next() {
1052 if punct.as_char() == '!' {
1053 let ty = iter.collect::<TokenStream>();
1054 if !ty.is_empty() {
1055 negative_token = Some(Token));
1056 self_ty = syn::parse2(ty)?;
1057 }
1058 }
1059 }
1060 }
1061
1062 let ty = parse_type(&self_ty)?;
1063 let ty_generics = match &ty {
1064 Type::RustBox(ty)
1065 | Type::RustVec(ty)
1066 | Type::UniquePtr(ty)
1067 | Type::SharedPtr(ty)
1068 | Type::WeakPtr(ty)
1069 | Type::CxxVector(ty) => match &ty.inner {
1070 Type::Ident(ident) => ident.generics.clone(),
1071 _ => Lifetimes::default(),
1072 },
1073 Type::Ident(_)
1074 | Type::Ref(_)
1075 | Type::Ptr(_)
1076 | Type::Str(_)
1077 | Type::Fn(_)
1078 | Type::Void(_)
1079 | Type::SliceRef(_)
1080 | Type::Array(_) => Lifetimes::default(),
1081 };
1082
1083 let negative = negative_token.is_some();
1084 let brace_token = imp.brace_token;
1085
1086 Ok(Api::Impl(Impl {
1087 cfg,
1088 impl_token,
1089 impl_generics,
1090 negative,
1091 ty,
1092 ty_generics,
1093 brace_token,
1094 negative_token,
1095 }))
1096 }
1097
parse_include(input: ParseStream) -> Result<Include>1098 fn parse_include(input: ParseStream) -> Result<Include> {
1099 if input.peek(LitStr) {
1100 let lit: LitStr = input.parse()?;
1101 let span = lit.span();
1102 return Ok(Include {
1103 cfg: CfgExpr::Unconditional,
1104 path: lit.value(),
1105 kind: IncludeKind::Quoted,
1106 begin_span: span,
1107 end_span: span,
1108 });
1109 }
1110
1111 if input.peek(Token![<]) {
1112 let mut path = String::new();
1113
1114 let langle: Token![<] = input.parse()?;
1115 while !input.is_empty() && !input.peek(Token![>]) {
1116 let token: TokenTree = input.parse()?;
1117 match token {
1118 TokenTree::Ident(token) => path += &token.to_string(),
1119 TokenTree::Literal(token)
1120 if token
1121 .to_string()
1122 .starts_with(|ch: char| ch.is_ascii_digit()) =>
1123 {
1124 path += &token.to_string();
1125 }
1126 TokenTree::Punct(token) => path.push(token.as_char()),
1127 _ => return Err(Error::new(token.span(), "unexpected token in include path")),
1128 }
1129 }
1130 let rangle: Token![>] = input.parse()?;
1131
1132 return Ok(Include {
1133 cfg: CfgExpr::Unconditional,
1134 path,
1135 kind: IncludeKind::Bracketed,
1136 begin_span: langle.span,
1137 end_span: rangle.span,
1138 });
1139 }
1140
1141 Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))
1142 }
1143
parse_type(ty: &RustType) -> Result<Type>1144 fn parse_type(ty: &RustType) -> Result<Type> {
1145 match ty {
1146 RustType::Reference(ty) => parse_type_reference(ty),
1147 RustType::Ptr(ty) => parse_type_ptr(ty),
1148 RustType::Path(ty) => parse_type_path(ty),
1149 RustType::Array(ty) => parse_type_array(ty),
1150 RustType::BareFn(ty) => parse_type_fn(ty),
1151 RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span.join())),
1152 _ => Err(Error::new_spanned(ty, "unsupported type")),
1153 }
1154 }
1155
parse_type_reference(ty: &TypeReference) -> Result<Type>1156 fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
1157 let ampersand = ty.and_token;
1158 let lifetime = ty.lifetime.clone();
1159 let mutable = ty.mutability.is_some();
1160 let mutability = ty.mutability;
1161
1162 if let RustType::Slice(slice) = ty.elem.as_ref() {
1163 let inner = parse_type(&slice.elem)?;
1164 let bracket = slice.bracket_token;
1165 return Ok(Type::SliceRef(Box::new(SliceRef {
1166 ampersand,
1167 lifetime,
1168 mutable,
1169 bracket,
1170 inner,
1171 mutability,
1172 })));
1173 }
1174
1175 let inner = parse_type(&ty.elem)?;
1176 let pinned = false;
1177 let pin_tokens = None;
1178
1179 Ok(match &inner {
1180 Type::Ident(ident) if ident.rust == "str" => {
1181 if ty.mutability.is_some() {
1182 return Err(Error::new_spanned(ty, "unsupported type"));
1183 } else {
1184 Type::Str
1185 }
1186 }
1187 _ => Type::Ref,
1188 }(Box::new(Ref {
1189 pinned,
1190 ampersand,
1191 lifetime,
1192 mutable,
1193 inner,
1194 pin_tokens,
1195 mutability,
1196 })))
1197 }
1198
parse_type_ptr(ty: &TypePtr) -> Result<Type>1199 fn parse_type_ptr(ty: &TypePtr) -> Result<Type> {
1200 let star = ty.star_token;
1201 let mutable = ty.mutability.is_some();
1202 let constness = ty.const_token;
1203 let mutability = ty.mutability;
1204
1205 let inner = parse_type(&ty.elem)?;
1206
1207 Ok(Type::Ptr(Box::new(Ptr {
1208 star,
1209 mutable,
1210 inner,
1211 mutability,
1212 constness,
1213 })))
1214 }
1215
parse_type_path(ty: &TypePath) -> Result<Type>1216 fn parse_type_path(ty: &TypePath) -> Result<Type> {
1217 let path = &ty.path;
1218 if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
1219 let segment = &path.segments[0];
1220 let ident = segment.ident.clone();
1221 match &segment.arguments {
1222 PathArguments::None => return Ok(Type::Ident(NamedType::new(ident))),
1223 PathArguments::AngleBracketed(generic) => {
1224 if ident == "UniquePtr" && generic.args.len() == 1 {
1225 if let GenericArgument::Type(arg) = &generic.args[0] {
1226 let inner = parse_type(arg)?;
1227 return Ok(Type::UniquePtr(Box::new(Ty1 {
1228 name: ident,
1229 langle: generic.lt_token,
1230 inner,
1231 rangle: generic.gt_token,
1232 })));
1233 }
1234 } else if ident == "SharedPtr" && generic.args.len() == 1 {
1235 if let GenericArgument::Type(arg) = &generic.args[0] {
1236 let inner = parse_type(arg)?;
1237 return Ok(Type::SharedPtr(Box::new(Ty1 {
1238 name: ident,
1239 langle: generic.lt_token,
1240 inner,
1241 rangle: generic.gt_token,
1242 })));
1243 }
1244 } else if ident == "WeakPtr" && generic.args.len() == 1 {
1245 if let GenericArgument::Type(arg) = &generic.args[0] {
1246 let inner = parse_type(arg)?;
1247 return Ok(Type::WeakPtr(Box::new(Ty1 {
1248 name: ident,
1249 langle: generic.lt_token,
1250 inner,
1251 rangle: generic.gt_token,
1252 })));
1253 }
1254 } else if ident == "CxxVector" && generic.args.len() == 1 {
1255 if let GenericArgument::Type(arg) = &generic.args[0] {
1256 let inner = parse_type(arg)?;
1257 return Ok(Type::CxxVector(Box::new(Ty1 {
1258 name: ident,
1259 langle: generic.lt_token,
1260 inner,
1261 rangle: generic.gt_token,
1262 })));
1263 }
1264 } else if ident == "Box" && generic.args.len() == 1 {
1265 if let GenericArgument::Type(arg) = &generic.args[0] {
1266 let inner = parse_type(arg)?;
1267 return Ok(Type::RustBox(Box::new(Ty1 {
1268 name: ident,
1269 langle: generic.lt_token,
1270 inner,
1271 rangle: generic.gt_token,
1272 })));
1273 }
1274 } else if ident == "Vec" && generic.args.len() == 1 {
1275 if let GenericArgument::Type(arg) = &generic.args[0] {
1276 let inner = parse_type(arg)?;
1277 return Ok(Type::RustVec(Box::new(Ty1 {
1278 name: ident,
1279 langle: generic.lt_token,
1280 inner,
1281 rangle: generic.gt_token,
1282 })));
1283 }
1284 } else if ident == "Pin" && generic.args.len() == 1 {
1285 if let GenericArgument::Type(arg) = &generic.args[0] {
1286 let inner = parse_type(arg)?;
1287 let pin_token = kw::Pin(ident.span());
1288 if let Type::Ref(mut inner) = inner {
1289 inner.pinned = true;
1290 inner.pin_tokens =
1291 Some((pin_token, generic.lt_token, generic.gt_token));
1292 return Ok(Type::Ref(inner));
1293 }
1294 }
1295 } else {
1296 let mut lifetimes = Punctuated::new();
1297 let mut only_lifetimes = true;
1298 for pair in generic.args.pairs() {
1299 let (param, punct) = pair.into_tuple();
1300 if let GenericArgument::Lifetime(param) = param {
1301 lifetimes.push_value(param.clone());
1302 if let Some(punct) = punct {
1303 lifetimes.push_punct(*punct);
1304 }
1305 } else {
1306 only_lifetimes = false;
1307 break;
1308 }
1309 }
1310 if only_lifetimes {
1311 return Ok(Type::Ident(NamedType {
1312 rust: ident,
1313 generics: Lifetimes {
1314 lt_token: Some(generic.lt_token),
1315 lifetimes,
1316 gt_token: Some(generic.gt_token),
1317 },
1318 }));
1319 }
1320 }
1321 }
1322 PathArguments::Parenthesized(_) => {}
1323 }
1324 }
1325
1326 Err(Error::new_spanned(ty, "unsupported type"))
1327 }
1328
parse_type_array(ty: &TypeArray) -> Result<Type>1329 fn parse_type_array(ty: &TypeArray) -> Result<Type> {
1330 let inner = parse_type(&ty.elem)?;
1331
1332 let len_expr = if let Expr::Lit(lit) = &ty.len {
1333 lit
1334 } else {
1335 let msg = "unsupported expression, array length must be an integer literal";
1336 return Err(Error::new_spanned(&ty.len, msg));
1337 };
1338
1339 let len_token = if let Lit::Int(int) = &len_expr.lit {
1340 int.clone()
1341 } else {
1342 let msg = "array length must be an integer literal";
1343 return Err(Error::new_spanned(len_expr, msg));
1344 };
1345
1346 let len = len_token.base10_parse::<usize>()?;
1347 if len == 0 {
1348 let msg = "array with zero size is not supported";
1349 return Err(Error::new_spanned(ty, msg));
1350 }
1351
1352 let bracket = ty.bracket_token;
1353 let semi_token = ty.semi_token;
1354
1355 Ok(Type::Array(Box::new(Array {
1356 bracket,
1357 inner,
1358 semi_token,
1359 len,
1360 len_token,
1361 })))
1362 }
1363
parse_type_fn(ty: &TypeBareFn) -> Result<Type>1364 fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
1365 if ty.lifetimes.is_some() {
1366 return Err(Error::new_spanned(
1367 ty,
1368 "function pointer with lifetime parameters is not supported yet",
1369 ));
1370 }
1371
1372 if ty.variadic.is_some() {
1373 return Err(Error::new_spanned(
1374 ty,
1375 "variadic function pointer is not supported yet",
1376 ));
1377 }
1378
1379 let args = ty
1380 .inputs
1381 .iter()
1382 .enumerate()
1383 .map(|(i, arg)| {
1384 let (ident, colon_token) = match &arg.name {
1385 Some((ident, colon_token)) => (ident.clone(), *colon_token),
1386 None => {
1387 let fn_span = ty.paren_token.span.join();
1388 let ident = format_ident!("arg{}", i, span = fn_span);
1389 let colon_token = Token;
1390 (ident, colon_token)
1391 }
1392 };
1393 let ty = parse_type(&arg.ty)?;
1394 let cfg = CfgExpr::Unconditional;
1395 let doc = Doc::new();
1396 let attrs = OtherAttrs::none();
1397 let visibility = Token);
1398 let name = pair(Namespace::default(), &ident, None, None);
1399 Ok(Var {
1400 cfg,
1401 doc,
1402 attrs,
1403 visibility,
1404 name,
1405 colon_token,
1406 ty,
1407 })
1408 })
1409 .collect::<Result<_>>()?;
1410
1411 let mut throws_tokens = None;
1412 let ret = parse_return_type(&ty.output, &mut throws_tokens)?;
1413 let throws = throws_tokens.is_some();
1414
1415 let asyncness = None;
1416 let unsafety = ty.unsafety;
1417 let fn_token = ty.fn_token;
1418 let generics = Generics::default();
1419 let receiver = None;
1420 let paren_token = ty.paren_token;
1421
1422 Ok(Type::Fn(Box::new(Signature {
1423 asyncness,
1424 unsafety,
1425 fn_token,
1426 generics,
1427 receiver,
1428 args,
1429 ret,
1430 throws,
1431 paren_token,
1432 throws_tokens,
1433 })))
1434 }
1435
parse_return_type( ty: &ReturnType, throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>, ) -> Result<Option<Type>>1436 fn parse_return_type(
1437 ty: &ReturnType,
1438 throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>,
1439 ) -> Result<Option<Type>> {
1440 let mut ret = match ty {
1441 ReturnType::Default => return Ok(None),
1442 ReturnType::Type(_, ret) => ret.as_ref(),
1443 };
1444
1445 if let RustType::Path(ty) = ret {
1446 let path = &ty.path;
1447 if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
1448 let segment = &path.segments[0];
1449 let ident = segment.ident.clone();
1450 if let PathArguments::AngleBracketed(generic) = &segment.arguments {
1451 if ident == "Result" && generic.args.len() == 1 {
1452 if let GenericArgument::Type(arg) = &generic.args[0] {
1453 ret = arg;
1454 *throws_tokens =
1455 Some((kw::Result(ident.span()), generic.lt_token, generic.gt_token));
1456 }
1457 }
1458 }
1459 }
1460 }
1461
1462 match parse_type(ret)? {
1463 Type::Void(_) => Ok(None),
1464 ty => Ok(Some(ty)),
1465 }
1466 }
1467
visibility_pub(vis: &Visibility, inherited: Span) -> Token![pub]1468 fn visibility_pub(vis: &Visibility, inherited: Span) -> Token![pub] {
1469 Token => vis.span,
1471 Visibility::Restricted(vis) => vis.pub_token.span,
1472 Visibility::Inherited => inherited,
1473 })
1474 }
1475
pair( namespace: Namespace, default: &Ident, cxx: Option<ForeignName>, rust: Option<Ident>, ) -> Pair1476 fn pair(
1477 namespace: Namespace,
1478 default: &Ident,
1479 cxx: Option<ForeignName>,
1480 rust: Option<Ident>,
1481 ) -> Pair {
1482 Pair {
1483 namespace,
1484 cxx: cxx
1485 .unwrap_or_else(|| ForeignName::parse(&default.to_string(), default.span()).unwrap()),
1486 rust: rust.unwrap_or_else(|| default.clone()),
1487 }
1488 }
1489