1 use crate::syntax::discriminant::DiscriminantSet;
2 use crate::syntax::file::{Item, ItemForeignMod};
3 use crate::syntax::report::Errors;
4 use crate::syntax::Atom::*;
5 use crate::syntax::{
6     attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
7     Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice, Struct, Ty1, Type, TypeAlias,
8     Var, Variant,
9 };
10 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
11 use quote::{format_ident, quote, quote_spanned};
12 use syn::parse::{ParseStream, Parser};
13 use syn::punctuated::Punctuated;
14 use syn::{
15     Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
16     GenericArgument, Ident, ItemEnum, ItemImpl, ItemStruct, LitStr, Pat, PathArguments, Result,
17     ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
18 };
19 
20 pub mod kw {
21     syn::custom_keyword!(Result);
22 }
23 
parse_items( cx: &mut Errors, items: Vec<Item>, trusted: bool, namespace: &Namespace, ) -> Vec<Api>24 pub fn parse_items(
25     cx: &mut Errors,
26     items: Vec<Item>,
27     trusted: bool,
28     namespace: &Namespace,
29 ) -> Vec<Api> {
30     let mut apis = Vec::new();
31     for item in items {
32         match item {
33             Item::Struct(item) => match parse_struct(cx, item, namespace) {
34                 Ok(strct) => apis.push(strct),
35                 Err(err) => cx.push(err),
36             },
37             Item::Enum(item) => match parse_enum(cx, item, namespace) {
38                 Ok(enm) => apis.push(enm),
39                 Err(err) => cx.push(err),
40             },
41             Item::ForeignMod(foreign_mod) => {
42                 parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, namespace)
43             }
44             Item::Impl(item) => match parse_impl(item, namespace) {
45                 Ok(imp) => apis.push(imp),
46                 Err(err) => cx.push(err),
47             },
48             Item::Use(item) => cx.error(item, error::USE_NOT_ALLOWED),
49             Item::Other(item) => cx.error(item, "unsupported item"),
50         }
51     }
52     apis
53 }
54 
parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Result<Api>55 fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Result<Api> {
56     let generics = &item.generics;
57     if !generics.params.is_empty() || generics.where_clause.is_some() {
58         let struct_token = item.struct_token;
59         let ident = &item.ident;
60         let where_clause = &generics.where_clause;
61         let span = quote!(#struct_token #ident #generics #where_clause);
62         return Err(Error::new_spanned(
63             span,
64             "struct with generic parameters is not supported yet",
65         ));
66     }
67 
68     let mut doc = Doc::new();
69     let mut derives = Vec::new();
70     let mut namespace = namespace.clone();
71     attrs::parse(
72         cx,
73         &item.attrs,
74         attrs::Parser {
75             doc: Some(&mut doc),
76             derives: Some(&mut derives),
77             namespace: Some(&mut namespace),
78             ..Default::default()
79         },
80     );
81 
82     let named_fields = match item.fields {
83         Fields::Named(fields) => fields,
84         Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")),
85         Fields::Unnamed(_) => {
86             return Err(Error::new_spanned(item, "tuple structs are not supported"));
87         }
88     };
89 
90     let fields = named_fields
91         .named
92         .into_iter()
93         .map(|field| {
94             Ok(Var {
95                 ident: field.ident.unwrap(),
96                 ty: parse_type(&field.ty, &namespace)?,
97             })
98         })
99         .collect::<Result<_>>()?;
100 
101     Ok(Api::Struct(Struct {
102         doc,
103         derives,
104         struct_token: item.struct_token,
105         name: Pair::new(namespace, item.ident),
106         brace_token: named_fields.brace_token,
107         fields,
108     }))
109 }
110 
parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<Api>111 fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<Api> {
112     let generics = &item.generics;
113     if !generics.params.is_empty() || generics.where_clause.is_some() {
114         let enum_token = item.enum_token;
115         let ident = &item.ident;
116         let where_clause = &generics.where_clause;
117         let span = quote!(#enum_token #ident #generics #where_clause);
118         return Err(Error::new_spanned(
119             span,
120             "enums with generic parameters are not allowed",
121         ));
122     }
123 
124     let mut doc = Doc::new();
125     let mut repr = None;
126     let mut namespace = namespace.clone();
127     attrs::parse(
128         cx,
129         &item.attrs,
130         attrs::Parser {
131             doc: Some(&mut doc),
132             repr: Some(&mut repr),
133             namespace: Some(&mut namespace),
134             ..Default::default()
135         },
136     );
137 
138     let mut variants = Vec::new();
139     let mut discriminants = DiscriminantSet::new(repr);
140     for variant in item.variants {
141         match variant.fields {
142             Fields::Unit => {}
143             _ => {
144                 cx.error(variant, "enums with data are not supported yet");
145                 break;
146             }
147         }
148         let expr = variant.discriminant.as_ref().map(|(_, expr)| expr);
149         let try_discriminant = match &expr {
150             Some(lit) => discriminants.insert(lit),
151             None => discriminants.insert_next(),
152         };
153         let discriminant = match try_discriminant {
154             Ok(discriminant) => discriminant,
155             Err(err) => {
156                 cx.error(variant, err);
157                 break;
158             }
159         };
160         let expr = variant.discriminant.map(|(_, expr)| expr);
161         variants.push(Variant {
162             ident: variant.ident,
163             discriminant,
164             expr,
165         });
166     }
167 
168     let enum_token = item.enum_token;
169     let brace_token = item.brace_token;
170 
171     let mut repr = U8;
172     match discriminants.inferred_repr() {
173         Ok(inferred) => repr = inferred,
174         Err(err) => {
175             let span = quote_spanned!(brace_token.span=> #enum_token {});
176             cx.error(span, err);
177             variants.clear();
178         }
179     }
180 
181     let ident = Ident::new(repr.as_ref(), Span::call_site());
182     let repr_type = Type::Ident(ResolvableName::new(ident));
183 
184     Ok(Api::Enum(Enum {
185         doc,
186         enum_token,
187         name: Pair::new(namespace, item.ident),
188         brace_token,
189         variants,
190         repr,
191         repr_type,
192     }))
193 }
194 
parse_foreign_mod( cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec<Api>, trusted: bool, namespace: &Namespace, )195 fn parse_foreign_mod(
196     cx: &mut Errors,
197     foreign_mod: ItemForeignMod,
198     out: &mut Vec<Api>,
199     trusted: bool,
200     namespace: &Namespace,
201 ) {
202     let lang = match parse_lang(&foreign_mod.abi) {
203         Ok(lang) => lang,
204         Err(err) => return cx.push(err),
205     };
206 
207     match lang {
208         Lang::Rust => {
209             if foreign_mod.unsafety.is_some() {
210                 let unsafety = foreign_mod.unsafety;
211                 let abi = foreign_mod.abi;
212                 let span = quote!(#unsafety #abi);
213                 cx.error(span, "extern \"Rust\" block does not need to be unsafe");
214             }
215         }
216         Lang::Cxx => {}
217     }
218 
219     let trusted = trusted || foreign_mod.unsafety.is_some();
220 
221     let mut namespace = namespace.clone();
222     attrs::parse(
223         cx,
224         &foreign_mod.attrs,
225         attrs::Parser {
226             namespace: Some(&mut namespace),
227             ..Default::default()
228         },
229     );
230 
231     let mut items = Vec::new();
232     for foreign in &foreign_mod.items {
233         match foreign {
234             ForeignItem::Type(foreign) => {
235                 match parse_extern_type(cx, foreign, lang, trusted, &namespace) {
236                     Ok(ety) => items.push(ety),
237                     Err(err) => cx.push(err),
238                 }
239             }
240             ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang, &namespace) {
241                 Ok(efn) => items.push(efn),
242                 Err(err) => cx.push(err),
243             },
244             ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
245                 match foreign.mac.parse_body_with(parse_include) {
246                     Ok(include) => items.push(Api::Include(include)),
247                     Err(err) => cx.push(err),
248                 }
249             }
250             ForeignItem::Verbatim(tokens) => {
251                 match parse_extern_verbatim(cx, tokens, lang, &namespace) {
252                     Ok(api) => items.push(api),
253                     Err(err) => cx.push(err),
254                 }
255             }
256             _ => cx.error(foreign, "unsupported foreign item"),
257         }
258     }
259 
260     let mut types = items.iter().filter_map(|item| match item {
261         Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.name),
262         Api::TypeAlias(alias) => Some(&alias.name),
263         _ => None,
264     });
265     if let (Some(single_type), None) = (types.next(), types.next()) {
266         let single_type = single_type.clone();
267         for item in &mut items {
268             if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
269                 if let Some(receiver) = &mut efn.receiver {
270                     if receiver.ty.is_self() {
271                         receiver.ty = ResolvableName::new(single_type.rust.clone());
272                     }
273                 }
274             }
275         }
276     }
277 
278     out.extend(items);
279 }
280 
parse_lang(abi: &Abi) -> Result<Lang>281 fn parse_lang(abi: &Abi) -> Result<Lang> {
282     let name = match &abi.name {
283         Some(name) => name,
284         None => {
285             return Err(Error::new_spanned(
286                 abi,
287                 "ABI name is required, extern \"C++\" or extern \"Rust\"",
288             ));
289         }
290     };
291     match name.value().as_str() {
292         "C" | "C++" => Ok(Lang::Cxx),
293         "Rust" => Ok(Lang::Rust),
294         _ => Err(Error::new_spanned(abi, "unrecognized ABI")),
295     }
296 }
297 
parse_extern_type( cx: &mut Errors, foreign_type: &ForeignItemType, lang: Lang, trusted: bool, namespace: &Namespace, ) -> Result<Api>298 fn parse_extern_type(
299     cx: &mut Errors,
300     foreign_type: &ForeignItemType,
301     lang: Lang,
302     trusted: bool,
303     namespace: &Namespace,
304 ) -> Result<Api> {
305     let mut doc = Doc::new();
306     let mut namespace = namespace.clone();
307     attrs::parse(
308         cx,
309         &foreign_type.attrs,
310         attrs::Parser {
311             doc: Some(&mut doc),
312             namespace: Some(&mut namespace),
313             ..Default::default()
314         },
315     );
316     let type_token = foreign_type.type_token;
317     let ident = foreign_type.ident.clone();
318     let semi_token = foreign_type.semi_token;
319     let api_type = match lang {
320         Lang::Cxx => Api::CxxType,
321         Lang::Rust => Api::RustType,
322     };
323     Ok(api_type(ExternType {
324         doc,
325         type_token,
326         name: Pair::new(namespace, ident),
327         semi_token,
328         trusted,
329     }))
330 }
331 
parse_extern_fn( cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang, namespace: &Namespace, ) -> Result<Api>332 fn parse_extern_fn(
333     cx: &mut Errors,
334     foreign_fn: &ForeignItemFn,
335     lang: Lang,
336     namespace: &Namespace,
337 ) -> Result<Api> {
338     let generics = &foreign_fn.sig.generics;
339     if !generics.params.is_empty() || generics.where_clause.is_some() {
340         return Err(Error::new_spanned(
341             foreign_fn,
342             "extern function with generic parameters is not supported yet",
343         ));
344     }
345     if let Some(variadic) = &foreign_fn.sig.variadic {
346         return Err(Error::new_spanned(
347             variadic,
348             "variadic function is not supported yet",
349         ));
350     }
351 
352     let mut doc = Doc::new();
353     let mut cxx_name = None;
354     let mut rust_name = None;
355     let mut namespace = namespace.clone();
356     attrs::parse(
357         cx,
358         &foreign_fn.attrs,
359         attrs::Parser {
360             doc: Some(&mut doc),
361             cxx_name: Some(&mut cxx_name),
362             rust_name: Some(&mut rust_name),
363             namespace: Some(&mut namespace),
364             ..Default::default()
365         },
366     );
367 
368     let mut receiver = None;
369     let mut args = Punctuated::new();
370     for arg in foreign_fn.sig.inputs.pairs() {
371         let (arg, comma) = arg.into_tuple();
372         match arg {
373             FnArg::Receiver(arg) => {
374                 if let Some((ampersand, lifetime)) = &arg.reference {
375                     receiver = Some(Receiver {
376                         ampersand: *ampersand,
377                         lifetime: lifetime.clone(),
378                         mutability: arg.mutability,
379                         var: arg.self_token,
380                         ty: ResolvableName::make_self(arg.self_token.span),
381                         shorthand: true,
382                     });
383                     continue;
384                 }
385                 return Err(Error::new_spanned(arg, "unsupported signature"));
386             }
387             FnArg::Typed(arg) => {
388                 let ident = match arg.pat.as_ref() {
389                     Pat::Ident(pat) => pat.ident.clone(),
390                     Pat::Wild(pat) => {
391                         Ident::new(&format!("_{}", args.len()), pat.underscore_token.span)
392                     }
393                     _ => return Err(Error::new_spanned(arg, "unsupported signature")),
394                 };
395                 let ty = parse_type(&arg.ty, &namespace)?;
396                 if ident != "self" {
397                     args.push_value(Var { ident, ty });
398                     if let Some(comma) = comma {
399                         args.push_punct(*comma);
400                     }
401                     continue;
402                 }
403                 if let Type::Ref(reference) = ty {
404                     if let Type::Ident(ident) = reference.inner {
405                         receiver = Some(Receiver {
406                             ampersand: reference.ampersand,
407                             lifetime: reference.lifetime,
408                             mutability: reference.mutability,
409                             var: Token![self](ident.rust.span()),
410                             ty: ident,
411                             shorthand: false,
412                         });
413                         continue;
414                     }
415                 }
416                 return Err(Error::new_spanned(arg, "unsupported method receiver"));
417             }
418         }
419     }
420 
421     let mut throws_tokens = None;
422     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens, &namespace)?;
423     let throws = throws_tokens.is_some();
424     let unsafety = foreign_fn.sig.unsafety;
425     let fn_token = foreign_fn.sig.fn_token;
426     let name = Pair::new_from_differing_names(
427         namespace,
428         cxx_name.unwrap_or(foreign_fn.sig.ident.clone()),
429         rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
430     );
431     let paren_token = foreign_fn.sig.paren_token;
432     let semi_token = foreign_fn.semi_token;
433     let api_function = match lang {
434         Lang::Cxx => Api::CxxFunction,
435         Lang::Rust => Api::RustFunction,
436     };
437 
438     Ok(api_function(ExternFn {
439         lang,
440         doc,
441         name,
442         sig: Signature {
443             unsafety,
444             fn_token,
445             receiver,
446             args,
447             ret,
448             throws,
449             paren_token,
450             throws_tokens,
451         },
452         semi_token,
453     }))
454 }
455 
parse_extern_verbatim( cx: &mut Errors, tokens: &TokenStream, lang: Lang, namespace: &Namespace, ) -> Result<Api>456 fn parse_extern_verbatim(
457     cx: &mut Errors,
458     tokens: &TokenStream,
459     lang: Lang,
460     namespace: &Namespace,
461 ) -> Result<Api> {
462     // type Alias = crate::path::to::Type;
463     let parse = |input: ParseStream| -> Result<TypeAlias> {
464         let attrs = input.call(Attribute::parse_outer)?;
465         let type_token: Token![type] = match input.parse()? {
466             Some(type_token) => type_token,
467             None => {
468                 let span = input.cursor().token_stream();
469                 return Err(Error::new_spanned(span, "unsupported foreign item"));
470             }
471         };
472         let ident: Ident = input.parse()?;
473         let eq_token: Token![=] = input.parse()?;
474         let ty: RustType = input.parse()?;
475         let semi_token: Token![;] = input.parse()?;
476         let mut doc = Doc::new();
477         let mut namespace = namespace.clone();
478         attrs::parse(
479             cx,
480             &attrs,
481             attrs::Parser {
482                 doc: Some(&mut doc),
483                 namespace: Some(&mut namespace),
484                 ..Default::default()
485             },
486         );
487 
488         Ok(TypeAlias {
489             doc,
490             type_token,
491             name: Pair::new(namespace, ident),
492             eq_token,
493             ty,
494             semi_token,
495         })
496     };
497 
498     let type_alias = parse.parse2(tokens.clone())?;
499     match lang {
500         Lang::Cxx => Ok(Api::TypeAlias(type_alias)),
501         Lang::Rust => {
502             let (type_token, semi_token) = (type_alias.type_token, type_alias.semi_token);
503             let span = quote!(#type_token #semi_token);
504             let msg = "type alias in extern \"Rust\" block is not supported";
505             Err(Error::new_spanned(span, msg))
506         }
507     }
508 }
509 
parse_impl(imp: ItemImpl, namespace: &Namespace) -> Result<Api>510 fn parse_impl(imp: ItemImpl, namespace: &Namespace) -> Result<Api> {
511     if !imp.items.is_empty() {
512         let mut span = Group::new(Delimiter::Brace, TokenStream::new());
513         span.set_span(imp.brace_token.span);
514         return Err(Error::new_spanned(span, "expected an empty impl block"));
515     }
516 
517     let self_ty = &imp.self_ty;
518     if let Some((bang, path, for_token)) = &imp.trait_ {
519         let span = quote!(#bang #path #for_token #self_ty);
520         return Err(Error::new_spanned(
521             span,
522             "unexpected impl, expected something like `impl UniquePtr<T> {}`",
523         ));
524     }
525 
526     let generics = &imp.generics;
527     if !generics.params.is_empty() || generics.where_clause.is_some() {
528         return Err(Error::new_spanned(
529             imp,
530             "generic parameters on an impl is not supported",
531         ));
532     }
533 
534     Ok(Api::Impl(Impl {
535         impl_token: imp.impl_token,
536         ty: parse_type(&self_ty, namespace)?,
537         brace_token: imp.brace_token,
538     }))
539 }
540 
parse_include(input: ParseStream) -> Result<Include>541 fn parse_include(input: ParseStream) -> Result<Include> {
542     if input.peek(LitStr) {
543         let lit: LitStr = input.parse()?;
544         let span = lit.span();
545         return Ok(Include {
546             path: lit.value(),
547             kind: IncludeKind::Quoted,
548             begin_span: span,
549             end_span: span,
550         });
551     }
552 
553     if input.peek(Token![<]) {
554         let mut path = String::new();
555 
556         let langle: Token![<] = input.parse()?;
557         while !input.is_empty() && !input.peek(Token![>]) {
558             let token: TokenTree = input.parse()?;
559             match token {
560                 TokenTree::Ident(token) => path += &token.to_string(),
561                 TokenTree::Literal(token)
562                     if token
563                         .to_string()
564                         .starts_with(|ch: char| ch.is_ascii_digit()) =>
565                 {
566                     path += &token.to_string();
567                 }
568                 TokenTree::Punct(token) => path.push(token.as_char()),
569                 _ => return Err(Error::new(token.span(), "unexpected token in include path")),
570             }
571         }
572         let rangle: Token![>] = input.parse()?;
573 
574         return Ok(Include {
575             path,
576             kind: IncludeKind::Bracketed,
577             begin_span: langle.span,
578             end_span: rangle.span,
579         });
580     }
581 
582     Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))
583 }
584 
parse_type(ty: &RustType, namespace: &Namespace) -> Result<Type>585 fn parse_type(ty: &RustType, namespace: &Namespace) -> Result<Type> {
586     match ty {
587         RustType::Reference(ty) => parse_type_reference(ty, namespace),
588         RustType::Path(ty) => parse_type_path(ty, namespace),
589         RustType::Slice(ty) => parse_type_slice(ty, namespace),
590         RustType::BareFn(ty) => parse_type_fn(ty, namespace),
591         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
592         _ => Err(Error::new_spanned(ty, "unsupported type")),
593     }
594 }
595 
parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Type>596 fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Type> {
597     let inner = parse_type(&ty.elem, namespace)?;
598     let which = match &inner {
599         Type::Ident(ident) if ident.rust == "str" => {
600             if ty.mutability.is_some() {
601                 return Err(Error::new_spanned(ty, "unsupported type"));
602             } else {
603                 Type::Str
604             }
605         }
606         Type::Slice(slice) => match &slice.inner {
607             Type::Ident(ident) if ident.rust == U8 && ty.mutability.is_none() => Type::SliceRefU8,
608             _ => Type::Ref,
609         },
610         _ => Type::Ref,
611     };
612     Ok(which(Box::new(Ref {
613         ampersand: ty.and_token,
614         lifetime: ty.lifetime.clone(),
615         mutability: ty.mutability,
616         inner,
617     })))
618 }
619 
parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type>620 fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
621     let path = &ty.path;
622     if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
623         let segment = &path.segments[0];
624         let ident = segment.ident.clone();
625         match &segment.arguments {
626             PathArguments::None => return Ok(Type::Ident(ResolvableName::new(ident))),
627             PathArguments::AngleBracketed(generic) => {
628                 if ident == "UniquePtr" && generic.args.len() == 1 {
629                     if let GenericArgument::Type(arg) = &generic.args[0] {
630                         let inner = parse_type(arg, namespace)?;
631                         return Ok(Type::UniquePtr(Box::new(Ty1 {
632                             name: ident,
633                             langle: generic.lt_token,
634                             inner,
635                             rangle: generic.gt_token,
636                         })));
637                     }
638                 } else if ident == "CxxVector" && generic.args.len() == 1 {
639                     if let GenericArgument::Type(arg) = &generic.args[0] {
640                         let inner = parse_type(arg, namespace)?;
641                         return Ok(Type::CxxVector(Box::new(Ty1 {
642                             name: ident,
643                             langle: generic.lt_token,
644                             inner,
645                             rangle: generic.gt_token,
646                         })));
647                     }
648                 } else if ident == "Box" && generic.args.len() == 1 {
649                     if let GenericArgument::Type(arg) = &generic.args[0] {
650                         let inner = parse_type(arg, namespace)?;
651                         return Ok(Type::RustBox(Box::new(Ty1 {
652                             name: ident,
653                             langle: generic.lt_token,
654                             inner,
655                             rangle: generic.gt_token,
656                         })));
657                     }
658                 } else if ident == "Vec" && generic.args.len() == 1 {
659                     if let GenericArgument::Type(arg) = &generic.args[0] {
660                         let inner = parse_type(arg, namespace)?;
661                         return Ok(Type::RustVec(Box::new(Ty1 {
662                             name: ident,
663                             langle: generic.lt_token,
664                             inner,
665                             rangle: generic.gt_token,
666                         })));
667                     }
668                 }
669             }
670             PathArguments::Parenthesized(_) => {}
671         }
672     }
673     Err(Error::new_spanned(ty, "unsupported type"))
674 }
675 
parse_type_slice(ty: &TypeSlice, namespace: &Namespace) -> Result<Type>676 fn parse_type_slice(ty: &TypeSlice, namespace: &Namespace) -> Result<Type> {
677     let inner = parse_type(&ty.elem, namespace)?;
678     Ok(Type::Slice(Box::new(Slice {
679         bracket: ty.bracket_token,
680         inner,
681     })))
682 }
683 
parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type>684 fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {
685     if ty.lifetimes.is_some() {
686         return Err(Error::new_spanned(
687             ty,
688             "function pointer with lifetime parameters is not supported yet",
689         ));
690     }
691     if ty.variadic.is_some() {
692         return Err(Error::new_spanned(
693             ty,
694             "variadic function pointer is not supported yet",
695         ));
696     }
697     let args = ty
698         .inputs
699         .iter()
700         .enumerate()
701         .map(|(i, arg)| {
702             let ty = parse_type(&arg.ty, namespace)?;
703             let ident = match &arg.name {
704                 Some(ident) => ident.0.clone(),
705                 None => format_ident!("_{}", i),
706             };
707             Ok(Var { ident, ty })
708         })
709         .collect::<Result<_>>()?;
710     let mut throws_tokens = None;
711     let ret = parse_return_type(&ty.output, &mut throws_tokens, namespace)?;
712     let throws = throws_tokens.is_some();
713     Ok(Type::Fn(Box::new(Signature {
714         unsafety: ty.unsafety,
715         fn_token: ty.fn_token,
716         receiver: None,
717         args,
718         ret,
719         throws,
720         paren_token: ty.paren_token,
721         throws_tokens,
722     })))
723 }
724 
parse_return_type( ty: &ReturnType, throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>, namespace: &Namespace, ) -> Result<Option<Type>>725 fn parse_return_type(
726     ty: &ReturnType,
727     throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>,
728     namespace: &Namespace,
729 ) -> Result<Option<Type>> {
730     let mut ret = match ty {
731         ReturnType::Default => return Ok(None),
732         ReturnType::Type(_, ret) => ret.as_ref(),
733     };
734     if let RustType::Path(ty) = ret {
735         let path = &ty.path;
736         if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
737             let segment = &path.segments[0];
738             let ident = segment.ident.clone();
739             if let PathArguments::AngleBracketed(generic) = &segment.arguments {
740                 if ident == "Result" && generic.args.len() == 1 {
741                     if let GenericArgument::Type(arg) = &generic.args[0] {
742                         ret = arg;
743                         *throws_tokens =
744                             Some((kw::Result(ident.span()), generic.lt_token, generic.gt_token));
745                     }
746                 }
747             }
748         }
749     }
750     match parse_type(ret, namespace)? {
751         Type::Void(_) => Ok(None),
752         ty => Ok(Some(ty)),
753     }
754 }
755