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 = Lifetimes {
493 lt_token: None,
494 lifetimes: Punctuated::new(),
495 gt_token: None,
496 };
497 let colon_token = None;
498 let bounds = Vec::new();
499 let semi_token = foreign_type.semi_token;
500
501 (match lang {
502 Lang::Cxx => Api::CxxType,
503 Lang::Rust => Api::RustType,
504 })(ExternType {
505 cfg,
506 lang,
507 doc,
508 derives,
509 attrs,
510 visibility,
511 type_token,
512 name,
513 generics,
514 colon_token,
515 bounds,
516 semi_token,
517 trusted,
518 })
519 }
520
parse_extern_fn( cx: &mut Errors, mut foreign_fn: ForeignItemFn, lang: Lang, trusted: bool, extern_block_cfg: &CfgExpr, namespace: &Namespace, attrs: &OtherAttrs, ) -> Result<Api>521 fn parse_extern_fn(
522 cx: &mut Errors,
523 mut foreign_fn: ForeignItemFn,
524 lang: Lang,
525 trusted: bool,
526 extern_block_cfg: &CfgExpr,
527 namespace: &Namespace,
528 attrs: &OtherAttrs,
529 ) -> Result<Api> {
530 let mut cfg = extern_block_cfg.clone();
531 let mut doc = Doc::new();
532 let mut namespace = namespace.clone();
533 let mut cxx_name = None;
534 let mut rust_name = None;
535 let mut attrs = attrs.clone();
536 attrs.extend(attrs::parse(
537 cx,
538 mem::take(&mut foreign_fn.attrs),
539 attrs::Parser {
540 cfg: Some(&mut cfg),
541 doc: Some(&mut doc),
542 namespace: Some(&mut namespace),
543 cxx_name: Some(&mut cxx_name),
544 rust_name: Some(&mut rust_name),
545 ..Default::default()
546 },
547 ));
548
549 let generics = &foreign_fn.sig.generics;
550 if generics.where_clause.is_some()
551 || generics.params.iter().any(|param| match param {
552 GenericParam::Lifetime(lifetime) => !lifetime.bounds.is_empty(),
553 GenericParam::Type(_) | GenericParam::Const(_) => true,
554 })
555 {
556 return Err(Error::new_spanned(
557 foreign_fn,
558 "extern function with generic parameters is not supported yet",
559 ));
560 }
561
562 if let Some(variadic) = &foreign_fn.sig.variadic {
563 return Err(Error::new_spanned(
564 variadic,
565 "variadic function is not supported yet",
566 ));
567 }
568
569 if foreign_fn.sig.asyncness.is_some() && !cfg!(feature = "experimental-async-fn") {
570 return Err(Error::new_spanned(
571 foreign_fn,
572 "async function is not directly supported yet, but see https://cxx.rs/async.html \
573 for a working approach, and https://github.com/pcwalton/cxx-async for some helpers; \
574 eventually what you wrote will work but it isn't integrated into the cxx::bridge \
575 macro yet",
576 ));
577 }
578
579 if foreign_fn.sig.constness.is_some() {
580 return Err(Error::new_spanned(
581 foreign_fn,
582 "const extern function is not supported",
583 ));
584 }
585
586 if let Some(abi) = &foreign_fn.sig.abi {
587 return Err(Error::new_spanned(
588 abi,
589 "explicit ABI on extern function is not supported",
590 ));
591 }
592
593 let mut receiver = None;
594 let mut args = Punctuated::new();
595 for arg in foreign_fn.sig.inputs.pairs() {
596 let (arg, comma) = arg.into_tuple();
597 match arg {
598 FnArg::Receiver(arg) => {
599 if let Some((ampersand, lifetime)) = &arg.reference {
600 receiver = Some(Receiver {
601 pinned: false,
602 ampersand: *ampersand,
603 lifetime: lifetime.clone(),
604 mutable: arg.mutability.is_some(),
605 var: arg.self_token,
606 colon_token: Token![:](arg.self_token.span),
607 ty: NamedType::new(Ident::new("Self", arg.self_token.span)),
608 shorthand: true,
609 pin_tokens: None,
610 mutability: arg.mutability,
611 });
612 continue;
613 }
614 return Err(Error::new_spanned(arg, "unsupported signature"));
615 }
616 FnArg::Typed(arg) => {
617 let ident = match arg.pat.as_ref() {
618 Pat::Ident(pat) => pat.ident.clone(),
619 Pat::Wild(pat) => {
620 Ident::new(&format!("arg{}", args.len()), pat.underscore_token.span)
621 }
622 _ => return Err(Error::new_spanned(arg, "unsupported signature")),
623 };
624 let ty = parse_type(&arg.ty)?;
625 if ident != "self" {
626 let cfg = CfgExpr::Unconditional;
627 let doc = Doc::new();
628 let attrs = OtherAttrs::none();
629 let visibility = Token![pub](ident.span());
630 let name = pair(Namespace::default(), &ident, None, None);
631 let colon_token = arg.colon_token;
632 args.push_value(Var {
633 cfg,
634 doc,
635 attrs,
636 visibility,
637 name,
638 colon_token,
639 ty,
640 });
641 if let Some(comma) = comma {
642 args.push_punct(*comma);
643 }
644 continue;
645 }
646 if let Type::Ref(reference) = ty {
647 if let Type::Ident(ident) = reference.inner {
648 receiver = Some(Receiver {
649 pinned: reference.pinned,
650 ampersand: reference.ampersand,
651 lifetime: reference.lifetime,
652 mutable: reference.mutable,
653 var: Token![self](ident.rust.span()),
654 colon_token: arg.colon_token,
655 ty: ident,
656 shorthand: false,
657 pin_tokens: reference.pin_tokens,
658 mutability: reference.mutability,
659 });
660 continue;
661 }
662 }
663 return Err(Error::new_spanned(arg, "unsupported method receiver"));
664 }
665 }
666 }
667
668 let mut throws_tokens = None;
669 let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
670 let throws = throws_tokens.is_some();
671 let asyncness = foreign_fn.sig.asyncness;
672 let unsafety = foreign_fn.sig.unsafety;
673 let fn_token = foreign_fn.sig.fn_token;
674 let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span);
675 let visibility = visibility_pub(&foreign_fn.vis, inherited_span);
676 let name = pair(namespace, &foreign_fn.sig.ident, cxx_name, rust_name);
677 let generics = generics.clone();
678 let paren_token = foreign_fn.sig.paren_token;
679 let semi_token = foreign_fn.semi_token;
680
681 Ok(match lang {
682 Lang::Cxx => Api::CxxFunction,
683 Lang::Rust => Api::RustFunction,
684 }(ExternFn {
685 cfg,
686 lang,
687 doc,
688 attrs,
689 visibility,
690 name,
691 sig: Signature {
692 asyncness,
693 unsafety,
694 fn_token,
695 generics,
696 receiver,
697 args,
698 ret,
699 throws,
700 paren_token,
701 throws_tokens,
702 },
703 semi_token,
704 trusted,
705 }))
706 }
707
parse_extern_verbatim( cx: &mut Errors, tokens: TokenStream, lang: Lang, trusted: bool, extern_block_cfg: &CfgExpr, namespace: &Namespace, attrs: &OtherAttrs, ) -> Result<Api>708 fn parse_extern_verbatim(
709 cx: &mut Errors,
710 tokens: TokenStream,
711 lang: Lang,
712 trusted: bool,
713 extern_block_cfg: &CfgExpr,
714 namespace: &Namespace,
715 attrs: &OtherAttrs,
716 ) -> Result<Api> {
717 |input: ParseStream| -> Result<Api> {
718 let unparsed_attrs = input.call(Attribute::parse_outer)?;
719 let visibility: Visibility = input.parse()?;
720 if input.peek(Token![type]) {
721 parse_extern_verbatim_type(
722 cx,
723 unparsed_attrs,
724 visibility,
725 input,
726 lang,
727 trusted,
728 extern_block_cfg,
729 namespace,
730 attrs,
731 )
732 } else if input.peek(Token![fn]) {
733 parse_extern_verbatim_fn(input)
734 } else {
735 let span = input.cursor().token_stream();
736 Err(Error::new_spanned(
737 span,
738 "unsupported foreign item, expected `type` or `fn`",
739 ))
740 }
741 }
742 .parse2(tokens)
743 }
744
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>745 fn parse_extern_verbatim_type(
746 cx: &mut Errors,
747 unparsed_attrs: Vec<Attribute>,
748 visibility: Visibility,
749 input: ParseStream,
750 lang: Lang,
751 trusted: bool,
752 extern_block_cfg: &CfgExpr,
753 namespace: &Namespace,
754 attrs: &OtherAttrs,
755 ) -> Result<Api> {
756 let type_token: Token![type] = input.parse()?;
757 let ident: Ident = input.parse()?;
758 let generics: Generics = input.parse()?;
759 let mut lifetimes = Punctuated::new();
760 let mut has_unsupported_generic_param = false;
761 for pair in generics.params.into_pairs() {
762 let (param, punct) = pair.into_tuple();
763 match param {
764 GenericParam::Lifetime(param) => {
765 if !param.bounds.is_empty() && !has_unsupported_generic_param {
766 let msg = "lifetime parameter with bounds is not supported yet";
767 cx.error(¶m, msg);
768 has_unsupported_generic_param = true;
769 }
770 lifetimes.push_value(param.lifetime);
771 if let Some(punct) = punct {
772 lifetimes.push_punct(punct);
773 }
774 }
775 GenericParam::Type(param) => {
776 if !has_unsupported_generic_param {
777 let msg = "extern type with generic type parameter is not supported yet";
778 cx.error(¶m, msg);
779 has_unsupported_generic_param = true;
780 }
781 }
782 GenericParam::Const(param) => {
783 if !has_unsupported_generic_param {
784 let msg = "extern type with const generic parameter is not supported yet";
785 cx.error(¶m, msg);
786 has_unsupported_generic_param = true;
787 }
788 }
789 }
790 }
791 let lifetimes = Lifetimes {
792 lt_token: generics.lt_token,
793 lifetimes,
794 gt_token: generics.gt_token,
795 };
796 let lookahead = input.lookahead1();
797 if lookahead.peek(Token![=]) {
798 // type Alias = crate::path::to::Type;
799 parse_type_alias(
800 cx,
801 unparsed_attrs,
802 visibility,
803 type_token,
804 ident,
805 lifetimes,
806 input,
807 lang,
808 extern_block_cfg,
809 namespace,
810 attrs,
811 )
812 } else if lookahead.peek(Token![:]) || lookahead.peek(Token![;]) {
813 // type Opaque: Bound2 + Bound2;
814 parse_extern_type_bounded(
815 cx,
816 unparsed_attrs,
817 visibility,
818 type_token,
819 ident,
820 lifetimes,
821 input,
822 lang,
823 trusted,
824 extern_block_cfg,
825 namespace,
826 attrs,
827 )
828 } else {
829 Err(lookahead.error())
830 }
831 }
832
parse_extern_verbatim_fn(input: ParseStream) -> Result<Api>833 fn parse_extern_verbatim_fn(input: ParseStream) -> Result<Api> {
834 input.parse::<RustSignature>()?;
835 input.parse::<Token![;]>()?;
836 unreachable!()
837 }
838
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>839 fn parse_type_alias(
840 cx: &mut Errors,
841 unparsed_attrs: Vec<Attribute>,
842 visibility: Visibility,
843 type_token: Token![type],
844 ident: Ident,
845 generics: Lifetimes,
846 input: ParseStream,
847 lang: Lang,
848 extern_block_cfg: &CfgExpr,
849 namespace: &Namespace,
850 attrs: &OtherAttrs,
851 ) -> Result<Api> {
852 let eq_token: Token![=] = input.parse()?;
853 let ty: RustType = input.parse()?;
854 let semi_token: Token![;] = input.parse()?;
855
856 let mut cfg = extern_block_cfg.clone();
857 let mut doc = Doc::new();
858 let mut derives = Vec::new();
859 let mut namespace = namespace.clone();
860 let mut cxx_name = None;
861 let mut rust_name = None;
862 let mut attrs = attrs.clone();
863 attrs.extend(attrs::parse(
864 cx,
865 unparsed_attrs,
866 attrs::Parser {
867 cfg: Some(&mut cfg),
868 doc: Some(&mut doc),
869 derives: Some(&mut derives),
870 namespace: Some(&mut namespace),
871 cxx_name: Some(&mut cxx_name),
872 rust_name: Some(&mut rust_name),
873 ..Default::default()
874 },
875 ));
876
877 if lang == Lang::Rust {
878 let span = quote!(#type_token #semi_token);
879 let msg = "type alias in extern \"Rust\" block is not supported";
880 return Err(Error::new_spanned(span, msg));
881 }
882
883 let visibility = visibility_pub(&visibility, type_token.span);
884 let name = pair(namespace, &ident, cxx_name, rust_name);
885
886 Ok(Api::TypeAlias(TypeAlias {
887 cfg,
888 doc,
889 derives,
890 attrs,
891 visibility,
892 type_token,
893 name,
894 generics,
895 eq_token,
896 ty,
897 semi_token,
898 }))
899 }
900
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>901 fn parse_extern_type_bounded(
902 cx: &mut Errors,
903 unparsed_attrs: Vec<Attribute>,
904 visibility: Visibility,
905 type_token: Token![type],
906 ident: Ident,
907 generics: Lifetimes,
908 input: ParseStream,
909 lang: Lang,
910 trusted: bool,
911 extern_block_cfg: &CfgExpr,
912 namespace: &Namespace,
913 attrs: &OtherAttrs,
914 ) -> Result<Api> {
915 let mut bounds = Vec::new();
916 let colon_token: Option<Token![:]> = input.parse()?;
917 if colon_token.is_some() {
918 loop {
919 match input.parse()? {
920 TypeParamBound::Trait(TraitBound {
921 paren_token: None,
922 modifier: TraitBoundModifier::None,
923 lifetimes: None,
924 path,
925 }) if if let Some(derive) = path.get_ident().and_then(Derive::from) {
926 bounds.push(derive);
927 true
928 } else {
929 false
930 } => {}
931 bound @ TypeParamBound::Trait(_) | bound @ TypeParamBound::Lifetime(_) => {
932 cx.error(bound, "unsupported trait");
933 }
934 }
935
936 let lookahead = input.lookahead1();
937 if lookahead.peek(Token![+]) {
938 input.parse::<Token![+]>()?;
939 } else if lookahead.peek(Token![;]) {
940 break;
941 } else {
942 return Err(lookahead.error());
943 }
944 }
945 }
946 let semi_token: Token![;] = input.parse()?;
947
948 let mut cfg = extern_block_cfg.clone();
949 let mut doc = Doc::new();
950 let mut derives = Vec::new();
951 let mut namespace = namespace.clone();
952 let mut cxx_name = None;
953 let mut rust_name = None;
954 let mut attrs = attrs.clone();
955 attrs.extend(attrs::parse(
956 cx,
957 unparsed_attrs,
958 attrs::Parser {
959 cfg: Some(&mut cfg),
960 doc: Some(&mut doc),
961 derives: Some(&mut derives),
962 namespace: Some(&mut namespace),
963 cxx_name: Some(&mut cxx_name),
964 rust_name: Some(&mut rust_name),
965 ..Default::default()
966 },
967 ));
968
969 let visibility = visibility_pub(&visibility, type_token.span);
970 let name = pair(namespace, &ident, cxx_name, rust_name);
971
972 Ok(match lang {
973 Lang::Cxx => Api::CxxType,
974 Lang::Rust => Api::RustType,
975 }(ExternType {
976 cfg,
977 lang,
978 doc,
979 derives,
980 attrs,
981 visibility,
982 type_token,
983 name,
984 generics,
985 colon_token,
986 bounds,
987 semi_token,
988 trusted,
989 }))
990 }
991
parse_impl(cx: &mut Errors, imp: ItemImpl) -> Result<Api>992 fn parse_impl(cx: &mut Errors, imp: ItemImpl) -> Result<Api> {
993 let impl_token = imp.impl_token;
994
995 let mut cfg = CfgExpr::Unconditional;
996 attrs::parse(
997 cx,
998 imp.attrs,
999 attrs::Parser {
1000 cfg: Some(&mut cfg),
1001 ..Default::default()
1002 },
1003 );
1004
1005 if !imp.items.is_empty() {
1006 let mut span = Group::new(Delimiter::Brace, TokenStream::new());
1007 span.set_span(imp.brace_token.span);
1008 return Err(Error::new_spanned(span, "expected an empty impl block"));
1009 }
1010
1011 if let Some((bang, path, for_token)) = &imp.trait_ {
1012 let self_ty = &imp.self_ty;
1013 let span = quote!(#bang #path #for_token #self_ty);
1014 return Err(Error::new_spanned(
1015 span,
1016 "unexpected impl, expected something like `impl UniquePtr<T> {}`",
1017 ));
1018 }
1019
1020 if let Some(where_clause) = imp.generics.where_clause {
1021 return Err(Error::new_spanned(
1022 where_clause,
1023 "where-clause on an impl is not supported yet",
1024 ));
1025 }
1026 let mut impl_generics = Lifetimes {
1027 lt_token: imp.generics.lt_token,
1028 lifetimes: Punctuated::new(),
1029 gt_token: imp.generics.gt_token,
1030 };
1031 for pair in imp.generics.params.into_pairs() {
1032 let (param, punct) = pair.into_tuple();
1033 match param {
1034 GenericParam::Lifetime(def) if def.bounds.is_empty() => {
1035 impl_generics.lifetimes.push_value(def.lifetime);
1036 if let Some(punct) = punct {
1037 impl_generics.lifetimes.push_punct(punct);
1038 }
1039 }
1040 _ => {
1041 let span = quote!(#impl_token #impl_generics);
1042 return Err(Error::new_spanned(
1043 span,
1044 "generic parameter on an impl is not supported yet",
1045 ));
1046 }
1047 }
1048 }
1049
1050 let mut negative_token = None;
1051 let mut self_ty = *imp.self_ty;
1052 if let RustType::Verbatim(ty) = &self_ty {
1053 let mut iter = ty.clone().into_iter();
1054 if let Some(TokenTree::Punct(punct)) = iter.next() {
1055 if punct.as_char() == '!' {
1056 let ty = iter.collect::<TokenStream>();
1057 if !ty.is_empty() {
1058 negative_token = Some(Token![!](punct.span()));
1059 self_ty = syn::parse2(ty)?;
1060 }
1061 }
1062 }
1063 }
1064
1065 let ty = parse_type(&self_ty)?;
1066 let ty_generics = match &ty {
1067 Type::RustBox(ty)
1068 | Type::RustVec(ty)
1069 | Type::UniquePtr(ty)
1070 | Type::SharedPtr(ty)
1071 | Type::WeakPtr(ty)
1072 | Type::CxxVector(ty) => match &ty.inner {
1073 Type::Ident(ident) => ident.generics.clone(),
1074 _ => Lifetimes::default(),
1075 },
1076 Type::Ident(_)
1077 | Type::Ref(_)
1078 | Type::Ptr(_)
1079 | Type::Str(_)
1080 | Type::Fn(_)
1081 | Type::Void(_)
1082 | Type::SliceRef(_)
1083 | Type::Array(_) => Lifetimes::default(),
1084 };
1085
1086 let negative = negative_token.is_some();
1087 let brace_token = imp.brace_token;
1088
1089 Ok(Api::Impl(Impl {
1090 cfg,
1091 impl_token,
1092 impl_generics,
1093 negative,
1094 ty,
1095 ty_generics,
1096 brace_token,
1097 negative_token,
1098 }))
1099 }
1100
parse_include(input: ParseStream) -> Result<Include>1101 fn parse_include(input: ParseStream) -> Result<Include> {
1102 if input.peek(LitStr) {
1103 let lit: LitStr = input.parse()?;
1104 let span = lit.span();
1105 return Ok(Include {
1106 cfg: CfgExpr::Unconditional,
1107 path: lit.value(),
1108 kind: IncludeKind::Quoted,
1109 begin_span: span,
1110 end_span: span,
1111 });
1112 }
1113
1114 if input.peek(Token![<]) {
1115 let mut path = String::new();
1116
1117 let langle: Token![<] = input.parse()?;
1118 while !input.is_empty() && !input.peek(Token![>]) {
1119 let token: TokenTree = input.parse()?;
1120 match token {
1121 TokenTree::Ident(token) => path += &token.to_string(),
1122 TokenTree::Literal(token)
1123 if token
1124 .to_string()
1125 .starts_with(|ch: char| ch.is_ascii_digit()) =>
1126 {
1127 path += &token.to_string();
1128 }
1129 TokenTree::Punct(token) => path.push(token.as_char()),
1130 _ => return Err(Error::new(token.span(), "unexpected token in include path")),
1131 }
1132 }
1133 let rangle: Token![>] = input.parse()?;
1134
1135 return Ok(Include {
1136 cfg: CfgExpr::Unconditional,
1137 path,
1138 kind: IncludeKind::Bracketed,
1139 begin_span: langle.span,
1140 end_span: rangle.span,
1141 });
1142 }
1143
1144 Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))
1145 }
1146
parse_type(ty: &RustType) -> Result<Type>1147 fn parse_type(ty: &RustType) -> Result<Type> {
1148 match ty {
1149 RustType::Reference(ty) => parse_type_reference(ty),
1150 RustType::Ptr(ty) => parse_type_ptr(ty),
1151 RustType::Path(ty) => parse_type_path(ty),
1152 RustType::Array(ty) => parse_type_array(ty),
1153 RustType::BareFn(ty) => parse_type_fn(ty),
1154 RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
1155 _ => Err(Error::new_spanned(ty, "unsupported type")),
1156 }
1157 }
1158
parse_type_reference(ty: &TypeReference) -> Result<Type>1159 fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
1160 let ampersand = ty.and_token;
1161 let lifetime = ty.lifetime.clone();
1162 let mutable = ty.mutability.is_some();
1163 let mutability = ty.mutability;
1164
1165 if let RustType::Slice(slice) = ty.elem.as_ref() {
1166 let inner = parse_type(&slice.elem)?;
1167 let bracket = slice.bracket_token;
1168 return Ok(Type::SliceRef(Box::new(SliceRef {
1169 ampersand,
1170 lifetime,
1171 mutable,
1172 bracket,
1173 inner,
1174 mutability,
1175 })));
1176 }
1177
1178 let inner = parse_type(&ty.elem)?;
1179 let pinned = false;
1180 let pin_tokens = None;
1181
1182 Ok(match &inner {
1183 Type::Ident(ident) if ident.rust == "str" => {
1184 if ty.mutability.is_some() {
1185 return Err(Error::new_spanned(ty, "unsupported type"));
1186 } else {
1187 Type::Str
1188 }
1189 }
1190 _ => Type::Ref,
1191 }(Box::new(Ref {
1192 pinned,
1193 ampersand,
1194 lifetime,
1195 mutable,
1196 inner,
1197 pin_tokens,
1198 mutability,
1199 })))
1200 }
1201
parse_type_ptr(ty: &TypePtr) -> Result<Type>1202 fn parse_type_ptr(ty: &TypePtr) -> Result<Type> {
1203 let star = ty.star_token;
1204 let mutable = ty.mutability.is_some();
1205 let constness = ty.const_token;
1206 let mutability = ty.mutability;
1207
1208 let inner = parse_type(&ty.elem)?;
1209
1210 Ok(Type::Ptr(Box::new(Ptr {
1211 star,
1212 mutable,
1213 inner,
1214 mutability,
1215 constness,
1216 })))
1217 }
1218
parse_type_path(ty: &TypePath) -> Result<Type>1219 fn parse_type_path(ty: &TypePath) -> Result<Type> {
1220 let path = &ty.path;
1221 if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
1222 let segment = &path.segments[0];
1223 let ident = segment.ident.clone();
1224 match &segment.arguments {
1225 PathArguments::None => return Ok(Type::Ident(NamedType::new(ident))),
1226 PathArguments::AngleBracketed(generic) => {
1227 if ident == "UniquePtr" && generic.args.len() == 1 {
1228 if let GenericArgument::Type(arg) = &generic.args[0] {
1229 let inner = parse_type(arg)?;
1230 return Ok(Type::UniquePtr(Box::new(Ty1 {
1231 name: ident,
1232 langle: generic.lt_token,
1233 inner,
1234 rangle: generic.gt_token,
1235 })));
1236 }
1237 } else if ident == "SharedPtr" && generic.args.len() == 1 {
1238 if let GenericArgument::Type(arg) = &generic.args[0] {
1239 let inner = parse_type(arg)?;
1240 return Ok(Type::SharedPtr(Box::new(Ty1 {
1241 name: ident,
1242 langle: generic.lt_token,
1243 inner,
1244 rangle: generic.gt_token,
1245 })));
1246 }
1247 } else if ident == "WeakPtr" && generic.args.len() == 1 {
1248 if let GenericArgument::Type(arg) = &generic.args[0] {
1249 let inner = parse_type(arg)?;
1250 return Ok(Type::WeakPtr(Box::new(Ty1 {
1251 name: ident,
1252 langle: generic.lt_token,
1253 inner,
1254 rangle: generic.gt_token,
1255 })));
1256 }
1257 } else if ident == "CxxVector" && generic.args.len() == 1 {
1258 if let GenericArgument::Type(arg) = &generic.args[0] {
1259 let inner = parse_type(arg)?;
1260 return Ok(Type::CxxVector(Box::new(Ty1 {
1261 name: ident,
1262 langle: generic.lt_token,
1263 inner,
1264 rangle: generic.gt_token,
1265 })));
1266 }
1267 } else if ident == "Box" && generic.args.len() == 1 {
1268 if let GenericArgument::Type(arg) = &generic.args[0] {
1269 let inner = parse_type(arg)?;
1270 return Ok(Type::RustBox(Box::new(Ty1 {
1271 name: ident,
1272 langle: generic.lt_token,
1273 inner,
1274 rangle: generic.gt_token,
1275 })));
1276 }
1277 } else if ident == "Vec" && generic.args.len() == 1 {
1278 if let GenericArgument::Type(arg) = &generic.args[0] {
1279 let inner = parse_type(arg)?;
1280 return Ok(Type::RustVec(Box::new(Ty1 {
1281 name: ident,
1282 langle: generic.lt_token,
1283 inner,
1284 rangle: generic.gt_token,
1285 })));
1286 }
1287 } else if ident == "Pin" && generic.args.len() == 1 {
1288 if let GenericArgument::Type(arg) = &generic.args[0] {
1289 let inner = parse_type(arg)?;
1290 let pin_token = kw::Pin(ident.span());
1291 if let Type::Ref(mut inner) = inner {
1292 inner.pinned = true;
1293 inner.pin_tokens =
1294 Some((pin_token, generic.lt_token, generic.gt_token));
1295 return Ok(Type::Ref(inner));
1296 }
1297 }
1298 } else {
1299 let mut lifetimes = Punctuated::new();
1300 let mut only_lifetimes = true;
1301 for pair in generic.args.pairs() {
1302 let (param, punct) = pair.into_tuple();
1303 if let GenericArgument::Lifetime(param) = param {
1304 lifetimes.push_value(param.clone());
1305 if let Some(punct) = punct {
1306 lifetimes.push_punct(*punct);
1307 }
1308 } else {
1309 only_lifetimes = false;
1310 break;
1311 }
1312 }
1313 if only_lifetimes {
1314 return Ok(Type::Ident(NamedType {
1315 rust: ident,
1316 generics: Lifetimes {
1317 lt_token: Some(generic.lt_token),
1318 lifetimes,
1319 gt_token: Some(generic.gt_token),
1320 },
1321 }));
1322 }
1323 }
1324 }
1325 PathArguments::Parenthesized(_) => {}
1326 }
1327 }
1328
1329 Err(Error::new_spanned(ty, "unsupported type"))
1330 }
1331
parse_type_array(ty: &TypeArray) -> Result<Type>1332 fn parse_type_array(ty: &TypeArray) -> Result<Type> {
1333 let inner = parse_type(&ty.elem)?;
1334
1335 let len_expr = if let Expr::Lit(lit) = &ty.len {
1336 lit
1337 } else {
1338 let msg = "unsupported expression, array length must be an integer literal";
1339 return Err(Error::new_spanned(&ty.len, msg));
1340 };
1341
1342 let len_token = if let Lit::Int(int) = &len_expr.lit {
1343 int.clone()
1344 } else {
1345 let msg = "array length must be an integer literal";
1346 return Err(Error::new_spanned(len_expr, msg));
1347 };
1348
1349 let len = len_token.base10_parse::<usize>()?;
1350 if len == 0 {
1351 let msg = "array with zero size is not supported";
1352 return Err(Error::new_spanned(ty, msg));
1353 }
1354
1355 let bracket = ty.bracket_token;
1356 let semi_token = ty.semi_token;
1357
1358 Ok(Type::Array(Box::new(Array {
1359 bracket,
1360 inner,
1361 semi_token,
1362 len,
1363 len_token,
1364 })))
1365 }
1366
parse_type_fn(ty: &TypeBareFn) -> Result<Type>1367 fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
1368 if ty.lifetimes.is_some() {
1369 return Err(Error::new_spanned(
1370 ty,
1371 "function pointer with lifetime parameters is not supported yet",
1372 ));
1373 }
1374
1375 if ty.variadic.is_some() {
1376 return Err(Error::new_spanned(
1377 ty,
1378 "variadic function pointer is not supported yet",
1379 ));
1380 }
1381
1382 let args = ty
1383 .inputs
1384 .iter()
1385 .enumerate()
1386 .map(|(i, arg)| {
1387 let (ident, colon_token) = match &arg.name {
1388 Some((ident, colon_token)) => (ident.clone(), *colon_token),
1389 None => {
1390 let fn_span = ty.paren_token.span;
1391 let ident = format_ident!("arg{}", i, span = fn_span);
1392 let colon_token = Token![:](fn_span);
1393 (ident, colon_token)
1394 }
1395 };
1396 let ty = parse_type(&arg.ty)?;
1397 let cfg = CfgExpr::Unconditional;
1398 let doc = Doc::new();
1399 let attrs = OtherAttrs::none();
1400 let visibility = Token![pub](ident.span());
1401 let name = pair(Namespace::default(), &ident, None, None);
1402 Ok(Var {
1403 cfg,
1404 doc,
1405 attrs,
1406 visibility,
1407 name,
1408 colon_token,
1409 ty,
1410 })
1411 })
1412 .collect::<Result<_>>()?;
1413
1414 let mut throws_tokens = None;
1415 let ret = parse_return_type(&ty.output, &mut throws_tokens)?;
1416 let throws = throws_tokens.is_some();
1417
1418 let asyncness = None;
1419 let unsafety = ty.unsafety;
1420 let fn_token = ty.fn_token;
1421 let generics = Generics::default();
1422 let receiver = None;
1423 let paren_token = ty.paren_token;
1424
1425 Ok(Type::Fn(Box::new(Signature {
1426 asyncness,
1427 unsafety,
1428 fn_token,
1429 generics,
1430 receiver,
1431 args,
1432 ret,
1433 throws,
1434 paren_token,
1435 throws_tokens,
1436 })))
1437 }
1438
parse_return_type( ty: &ReturnType, throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>, ) -> Result<Option<Type>>1439 fn parse_return_type(
1440 ty: &ReturnType,
1441 throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>,
1442 ) -> Result<Option<Type>> {
1443 let mut ret = match ty {
1444 ReturnType::Default => return Ok(None),
1445 ReturnType::Type(_, ret) => ret.as_ref(),
1446 };
1447
1448 if let RustType::Path(ty) = ret {
1449 let path = &ty.path;
1450 if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
1451 let segment = &path.segments[0];
1452 let ident = segment.ident.clone();
1453 if let PathArguments::AngleBracketed(generic) = &segment.arguments {
1454 if ident == "Result" && generic.args.len() == 1 {
1455 if let GenericArgument::Type(arg) = &generic.args[0] {
1456 ret = arg;
1457 *throws_tokens =
1458 Some((kw::Result(ident.span()), generic.lt_token, generic.gt_token));
1459 }
1460 }
1461 }
1462 }
1463 }
1464
1465 match parse_type(ret)? {
1466 Type::Void(_) => Ok(None),
1467 ty => Ok(Some(ty)),
1468 }
1469 }
1470
visibility_pub(vis: &Visibility, inherited: Span) -> Token![pub]1471 fn visibility_pub(vis: &Visibility, inherited: Span) -> Token![pub] {
1472 Token![pub](match vis {
1473 Visibility::Public(vis) => vis.pub_token.span,
1474 Visibility::Crate(vis) => vis.crate_token.span,
1475 Visibility::Restricted(vis) => vis.pub_token.span,
1476 Visibility::Inherited => inherited,
1477 })
1478 }
1479
pair( namespace: Namespace, default: &Ident, cxx: Option<ForeignName>, rust: Option<Ident>, ) -> Pair1480 fn pair(
1481 namespace: Namespace,
1482 default: &Ident,
1483 cxx: Option<ForeignName>,
1484 rust: Option<Ident>,
1485 ) -> Pair {
1486 Pair {
1487 namespace,
1488 cxx: cxx
1489 .unwrap_or_else(|| ForeignName::parse(&default.to_string(), default.span()).unwrap()),
1490 rust: rust.unwrap_or_else(|| default.clone()),
1491 }
1492 }
1493