blob: 15ee4f24e869ca1b61aa97492babb64a8c1864f0 [file] [log] [blame]
David Tolnay17e137f2020-05-08 15:55:28 -07001use crate::syntax::discriminant::DiscriminantSet;
David Tolnayc598a272020-08-29 15:10:18 -07002use crate::syntax::file::{Item, ItemForeignMod};
David Tolnay52759782020-05-03 23:59:40 -07003use crate::syntax::report::Errors;
David Tolnayeebe9b72020-04-14 16:32:18 -07004use crate::syntax::Atom::*;
David Tolnay7db73692019-10-20 14:51:12 -04005use crate::syntax::{
Xiangpeng Hao78762352020-11-12 10:24:18 +08006 attrs, error, Api, Array, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
David Tolnayd60c07b2020-10-29 13:18:49 -07007 Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice, Struct, Ty1, Type, TypeAlias,
8 Var, Variant,
David Tolnay7db73692019-10-20 14:51:12 -04009};
David Tolnay9a69d8a2020-11-16 09:16:41 -080010use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
David Tolnaye2e303f2020-05-10 20:52:00 -070011use quote::{format_ident, quote, quote_spanned};
David Tolnaye2f9ec42020-05-07 16:19:33 -070012use syn::parse::{ParseStream, Parser};
David Tolnaye3a48152020-04-08 19:38:05 -070013use syn::punctuated::Punctuated;
David Tolnay7db73692019-10-20 14:51:12 -040014use syn::{
Xiangpeng Hao78762352020-11-12 10:24:18 +080015 Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
16 GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
17 Pat, PathArguments, Result, ReturnType, Token, Type as RustType, TypeArray, TypeBareFn,
18 TypePath, TypeReference, TypeSlice,
David Tolnay7db73692019-10-20 14:51:12 -040019};
20
David Tolnaye3a48152020-04-08 19:38:05 -070021pub mod kw {
David Tolnayb27f7872020-11-15 15:07:04 -080022 syn::custom_keyword!(Pin);
David Tolnaye3a48152020-04-08 19:38:05 -070023 syn::custom_keyword!(Result);
24}
25
David Tolnayd7a3a182020-11-01 20:45:14 -080026pub fn parse_items(
27 cx: &mut Errors,
28 items: Vec<Item>,
29 trusted: bool,
30 namespace: &Namespace,
31) -> Vec<Api> {
David Tolnay7db73692019-10-20 14:51:12 -040032 let mut apis = Vec::new();
33 for item in items {
34 match item {
David Tolnay302b1752020-11-10 18:43:24 -080035 Item::Struct(item) => match parse_struct(cx, item, namespace) {
David Tolnay52759782020-05-03 23:59:40 -070036 Ok(strct) => apis.push(strct),
37 Err(err) => cx.push(err),
38 },
David Tolnay302b1752020-11-10 18:43:24 -080039 Item::Enum(item) => match parse_enum(cx, item, namespace) {
David Tolnay52759782020-05-03 23:59:40 -070040 Ok(enm) => apis.push(enm),
41 Err(err) => cx.push(err),
42 },
Adrian Taylorc8713432020-10-21 18:20:55 -070043 Item::ForeignMod(foreign_mod) => {
David Tolnayd7a3a182020-11-01 20:45:14 -080044 parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, namespace)
Adrian Taylorc8713432020-10-21 18:20:55 -070045 }
David Tolnay313cc0a2020-11-24 21:47:01 -080046 Item::Impl(item) => match parse_impl(item) {
David Tolnay7e69f892020-10-03 22:20:22 -070047 Ok(imp) => apis.push(imp),
48 Err(err) => cx.push(err),
49 },
David Tolnay52759782020-05-03 23:59:40 -070050 Item::Use(item) => cx.error(item, error::USE_NOT_ALLOWED),
David Tolnay00a83852020-08-29 15:06:16 -070051 Item::Other(item) => cx.error(item, "unsupported item"),
David Tolnay7db73692019-10-20 14:51:12 -040052 }
53 }
David Tolnay52759782020-05-03 23:59:40 -070054 apis
David Tolnay7db73692019-10-20 14:51:12 -040055}
56
David Tolnay302b1752020-11-10 18:43:24 -080057fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Result<Api> {
David Tolnay7db73692019-10-20 14:51:12 -040058 let generics = &item.generics;
59 if !generics.params.is_empty() || generics.where_clause.is_some() {
60 let struct_token = item.struct_token;
61 let ident = &item.ident;
62 let where_clause = &generics.where_clause;
63 let span = quote!(#struct_token #ident #generics #where_clause);
64 return Err(Error::new_spanned(
65 span,
66 "struct with generic parameters is not supported yet",
67 ));
68 }
69
70 let mut doc = Doc::new();
71 let mut derives = Vec::new();
David Tolnay302b1752020-11-10 18:43:24 -080072 let mut namespace = namespace.clone();
David Tolnayb129ea72020-05-10 14:29:30 -070073 attrs::parse(
David Tolnay3e628882020-05-10 15:30:14 -070074 cx,
David Tolnayb129ea72020-05-10 14:29:30 -070075 &item.attrs,
76 attrs::Parser {
77 doc: Some(&mut doc),
78 derives: Some(&mut derives),
David Tolnayd7a3a182020-11-01 20:45:14 -080079 namespace: Some(&mut namespace),
David Tolnayddf69e22020-05-10 22:08:20 -070080 ..Default::default()
David Tolnayb129ea72020-05-10 14:29:30 -070081 },
David Tolnay3e628882020-05-10 15:30:14 -070082 );
David Tolnay09462ac2020-03-20 14:58:41 -070083
David Tolnay302b1752020-11-10 18:43:24 -080084 let named_fields = match item.fields {
David Tolnay09462ac2020-03-20 14:58:41 -070085 Fields::Named(fields) => fields,
86 Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")),
87 Fields::Unnamed(_) => {
David Tolnay2c4b35f2020-10-04 21:22:30 -070088 return Err(Error::new_spanned(item, "tuple structs are not supported"));
David Tolnay09462ac2020-03-20 14:58:41 -070089 }
90 };
91
David Tolnay302b1752020-11-10 18:43:24 -080092 let fields = named_fields
93 .named
94 .into_iter()
95 .map(|field| {
96 Ok(Var {
97 ident: field.ident.unwrap(),
David Tolnay313cc0a2020-11-24 21:47:01 -080098 ty: parse_type(&field.ty)?,
David Tolnay302b1752020-11-10 18:43:24 -080099 })
100 })
101 .collect::<Result<_>>()?;
102
David Tolnay09462ac2020-03-20 14:58:41 -0700103 Ok(Api::Struct(Struct {
104 doc,
105 derives,
106 struct_token: item.struct_token,
David Tolnay302b1752020-11-10 18:43:24 -0800107 name: Pair::new(namespace, item.ident),
108 brace_token: named_fields.brace_token,
109 fields,
David Tolnay09462ac2020-03-20 14:58:41 -0700110 }))
David Tolnay7db73692019-10-20 14:51:12 -0400111}
112
David Tolnay302b1752020-11-10 18:43:24 -0800113fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<Api> {
Joel Galensonc03402a2020-04-23 17:31:09 -0700114 let generics = &item.generics;
115 if !generics.params.is_empty() || generics.where_clause.is_some() {
116 let enum_token = item.enum_token;
117 let ident = &item.ident;
118 let where_clause = &generics.where_clause;
119 let span = quote!(#enum_token #ident #generics #where_clause);
120 return Err(Error::new_spanned(
121 span,
122 "enums with generic parameters are not allowed",
123 ));
124 }
125
David Tolnayddf69e22020-05-10 22:08:20 -0700126 let mut doc = Doc::new();
127 let mut repr = None;
David Tolnay302b1752020-11-10 18:43:24 -0800128 let mut namespace = namespace.clone();
David Tolnayddf69e22020-05-10 22:08:20 -0700129 attrs::parse(
130 cx,
131 &item.attrs,
132 attrs::Parser {
133 doc: Some(&mut doc),
134 repr: Some(&mut repr),
David Tolnayd7a3a182020-11-01 20:45:14 -0800135 namespace: Some(&mut namespace),
David Tolnayddf69e22020-05-10 22:08:20 -0700136 ..Default::default()
137 },
138 );
Joel Galensonc03402a2020-04-23 17:31:09 -0700139
Joel Galenson88547732020-05-05 08:23:42 -0700140 let mut variants = Vec::new();
David Tolnayddf69e22020-05-10 22:08:20 -0700141 let mut discriminants = DiscriminantSet::new(repr);
Joel Galenson88547732020-05-05 08:23:42 -0700142 for variant in item.variants {
143 match variant.fields {
Joel Galensonc03402a2020-04-23 17:31:09 -0700144 Fields::Unit => {}
145 _ => {
David Tolnay0435a812020-05-10 21:58:15 -0700146 cx.error(variant, "enums with data are not supported yet");
147 break;
Joel Galensonc03402a2020-04-23 17:31:09 -0700148 }
149 }
David Tolnay17e137f2020-05-08 15:55:28 -0700150 let expr = variant.discriminant.as_ref().map(|(_, expr)| expr);
151 let try_discriminant = match &expr {
152 Some(lit) => discriminants.insert(lit),
153 None => discriminants.insert_next(),
154 };
155 let discriminant = match try_discriminant {
156 Ok(discriminant) => discriminant,
David Tolnay0435a812020-05-10 21:58:15 -0700157 Err(err) => {
158 cx.error(variant, err);
159 break;
160 }
David Tolnay17e137f2020-05-08 15:55:28 -0700161 };
David Tolnay2b8bf6d2020-05-10 17:37:16 -0700162 let expr = variant.discriminant.map(|(_, expr)| expr);
Joel Galenson88547732020-05-05 08:23:42 -0700163 variants.push(Variant {
164 ident: variant.ident,
David Tolnay7ae018f2020-05-05 10:11:30 -0700165 discriminant,
David Tolnay2b8bf6d2020-05-10 17:37:16 -0700166 expr,
Joel Galenson88547732020-05-05 08:23:42 -0700167 });
Joel Galensonc03402a2020-04-23 17:31:09 -0700168 }
169
David Tolnaye2e303f2020-05-10 20:52:00 -0700170 let enum_token = item.enum_token;
171 let brace_token = item.brace_token;
172
David Tolnay58eee392020-11-20 20:37:58 -0800173 let explicit_repr = repr.is_some();
David Tolnay0435a812020-05-10 21:58:15 -0700174 let mut repr = U8;
175 match discriminants.inferred_repr() {
176 Ok(inferred) => repr = inferred,
David Tolnaye2e303f2020-05-10 20:52:00 -0700177 Err(err) => {
178 let span = quote_spanned!(brace_token.span=> #enum_token {});
David Tolnay0435a812020-05-10 21:58:15 -0700179 cx.error(span, err);
180 variants.clear();
David Tolnaye2e303f2020-05-10 20:52:00 -0700181 }
David Tolnay0435a812020-05-10 21:58:15 -0700182 }
David Tolnaye2e303f2020-05-10 20:52:00 -0700183
David Tolnay9a69d8a2020-11-16 09:16:41 -0800184 let ident = Ident::new(repr.as_ref(), Span::call_site());
185 let repr_type = Type::Ident(ResolvableName::new(ident));
186
Joel Galensonc03402a2020-04-23 17:31:09 -0700187 Ok(Api::Enum(Enum {
188 doc,
David Tolnaye2e303f2020-05-10 20:52:00 -0700189 enum_token,
David Tolnay17a934c2020-11-02 00:40:04 -0800190 name: Pair::new(namespace, item.ident),
David Tolnaye2e303f2020-05-10 20:52:00 -0700191 brace_token,
David Tolnay7ae018f2020-05-05 10:11:30 -0700192 variants,
David Tolnaye2e303f2020-05-10 20:52:00 -0700193 repr,
David Tolnay9a69d8a2020-11-16 09:16:41 -0800194 repr_type,
David Tolnay58eee392020-11-20 20:37:58 -0800195 explicit_repr,
Joel Galensonc03402a2020-04-23 17:31:09 -0700196 }))
197}
198
David Tolnay805dca32020-08-29 19:09:55 -0700199fn parse_foreign_mod(
200 cx: &mut Errors,
201 foreign_mod: ItemForeignMod,
202 out: &mut Vec<Api>,
203 trusted: bool,
David Tolnayd7a3a182020-11-01 20:45:14 -0800204 namespace: &Namespace,
David Tolnay805dca32020-08-29 19:09:55 -0700205) {
David Tolnay3a451732020-08-29 18:54:55 -0700206 let lang = match parse_lang(&foreign_mod.abi) {
David Tolnay52759782020-05-03 23:59:40 -0700207 Ok(lang) => lang,
208 Err(err) => return cx.push(err),
209 };
David Tolnay7db73692019-10-20 14:51:12 -0400210
David Tolnay3a451732020-08-29 18:54:55 -0700211 match lang {
212 Lang::Rust => {
David Tolnay805dca32020-08-29 19:09:55 -0700213 if foreign_mod.unsafety.is_some() {
David Tolnay3a451732020-08-29 18:54:55 -0700214 let unsafety = foreign_mod.unsafety;
David Tolnay7be5b1f2020-11-11 10:48:32 -0800215 let abi = &foreign_mod.abi;
David Tolnay3a451732020-08-29 18:54:55 -0700216 let span = quote!(#unsafety #abi);
217 cx.error(span, "extern \"Rust\" block does not need to be unsafe");
218 }
219 }
220 Lang::Cxx => {}
221 }
222
David Tolnay805dca32020-08-29 19:09:55 -0700223 let trusted = trusted || foreign_mod.unsafety.is_some();
224
David Tolnay7feb2642020-11-10 18:49:04 -0800225 let mut namespace = namespace.clone();
226 attrs::parse(
227 cx,
228 &foreign_mod.attrs,
229 attrs::Parser {
230 namespace: Some(&mut namespace),
231 ..Default::default()
232 },
233 );
234
Joel Galensone1e969d2020-04-21 12:50:20 -0700235 let mut items = Vec::new();
236 for foreign in &foreign_mod.items {
237 match foreign {
Adrian Taylorc8713432020-10-21 18:20:55 -0700238 ForeignItem::Type(foreign) => {
David Tolnayf5ead102020-11-24 17:08:05 -0800239 let ety = parse_extern_type(cx, foreign, lang, trusted, &namespace);
240 items.push(ety);
Adrian Taylorc8713432020-10-21 18:20:55 -0700241 }
David Tolnay556738d2020-11-15 13:58:44 -0800242 ForeignItem::Fn(foreign) => {
243 match parse_extern_fn(cx, foreign, lang, trusted, &namespace) {
244 Ok(efn) => items.push(efn),
245 Err(err) => cx.push(err),
246 }
247 }
David Tolnay7db73692019-10-20 14:51:12 -0400248 ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
David Tolnay91e87fa2020-05-11 19:10:23 -0700249 match foreign.mac.parse_body_with(parse_include) {
David Tolnay52759782020-05-03 23:59:40 -0700250 Ok(include) => items.push(Api::Include(include)),
251 Err(err) => cx.push(err),
252 }
David Tolnay7db73692019-10-20 14:51:12 -0400253 }
Adrian Taylorc8713432020-10-21 18:20:55 -0700254 ForeignItem::Verbatim(tokens) => {
David Tolnay7feb2642020-11-10 18:49:04 -0800255 match parse_extern_verbatim(cx, tokens, lang, &namespace) {
Adrian Taylorc8713432020-10-21 18:20:55 -0700256 Ok(api) => items.push(api),
257 Err(err) => cx.push(err),
258 }
259 }
David Tolnay52759782020-05-03 23:59:40 -0700260 _ => cx.error(foreign, "unsupported foreign item"),
David Tolnay7db73692019-10-20 14:51:12 -0400261 }
262 }
David Tolnaya1f29c42020-04-22 18:01:38 -0700263
David Tolnay7be5b1f2020-11-11 10:48:32 -0800264 if !trusted
265 && items.iter().any(|api| match api {
266 Api::CxxFunction(efn) => efn.unsafety.is_none(),
267 _ => false,
268 })
269 {
270 cx.error(
271 foreign_mod.abi,
272 "block must be declared `unsafe extern \"C++\"` if it contains any safe-to-call C++ functions",
273 );
274 }
275
David Tolnaya1f29c42020-04-22 18:01:38 -0700276 let mut types = items.iter().filter_map(|item| match item {
David Tolnay17a934c2020-11-02 00:40:04 -0800277 Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.name),
278 Api::TypeAlias(alias) => Some(&alias.name),
David Tolnaya1f29c42020-04-22 18:01:38 -0700279 _ => None,
280 });
281 if let (Some(single_type), None) = (types.next(), types.next()) {
David Tolnaye5a015a2020-05-07 21:54:26 -0700282 let single_type = single_type.clone();
David Tolnaya1f29c42020-04-22 18:01:38 -0700283 for item in &mut items {
284 if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
285 if let Some(receiver) = &mut efn.receiver {
Adrian Taylorc8713432020-10-21 18:20:55 -0700286 if receiver.ty.is_self() {
Adrian Taylor565ddf02020-10-29 21:12:36 -0700287 receiver.ty = ResolvableName::new(single_type.rust.clone());
David Tolnaya1f29c42020-04-22 18:01:38 -0700288 }
289 }
290 }
291 }
292 }
293
David Tolnay52759782020-05-03 23:59:40 -0700294 out.extend(items);
David Tolnay7db73692019-10-20 14:51:12 -0400295}
296
David Tolnay3a451732020-08-29 18:54:55 -0700297fn parse_lang(abi: &Abi) -> Result<Lang> {
David Tolnay7db73692019-10-20 14:51:12 -0400298 let name = match &abi.name {
299 Some(name) => name,
300 None => {
301 return Err(Error::new_spanned(
302 abi,
David Tolnayc72a9f62020-11-11 10:56:26 -0800303 "ABI name is required, extern \"C++\" or extern \"Rust\"",
David Tolnay7db73692019-10-20 14:51:12 -0400304 ));
305 }
306 };
307 match name.value().as_str() {
David Tolnayea25ac82020-11-11 10:35:23 -0800308 "C++" => Ok(Lang::Cxx),
David Tolnay7db73692019-10-20 14:51:12 -0400309 "Rust" => Ok(Lang::Rust),
David Tolnay2757ca82020-11-14 15:12:06 -0800310 _ => Err(Error::new_spanned(
311 abi,
312 "unrecognized ABI, requires either \"C++\" or \"Rust\"",
313 )),
David Tolnay7db73692019-10-20 14:51:12 -0400314 }
315}
316
David Tolnay00f236a2020-08-29 19:07:18 -0700317fn parse_extern_type(
318 cx: &mut Errors,
319 foreign_type: &ForeignItemType,
320 lang: Lang,
321 trusted: bool,
David Tolnay302b1752020-11-10 18:43:24 -0800322 namespace: &Namespace,
David Tolnayf5ead102020-11-24 17:08:05 -0800323) -> Api {
Adrian Taylorc8713432020-10-21 18:20:55 -0700324 let mut doc = Doc::new();
David Tolnay302b1752020-11-10 18:43:24 -0800325 let mut namespace = namespace.clone();
Adrian Taylorc8713432020-10-21 18:20:55 -0700326 attrs::parse(
327 cx,
328 &foreign_type.attrs,
329 attrs::Parser {
330 doc: Some(&mut doc),
David Tolnayd7a3a182020-11-01 20:45:14 -0800331 namespace: Some(&mut namespace),
Adrian Taylorc8713432020-10-21 18:20:55 -0700332 ..Default::default()
333 },
334 );
David Tolnay7db73692019-10-20 14:51:12 -0400335 let type_token = foreign_type.type_token;
336 let ident = foreign_type.ident.clone();
David Tolnayc8361022020-08-25 21:57:53 -0700337 let semi_token = foreign_type.semi_token;
David Tolnay295ef6b2020-05-07 16:10:22 -0700338 let api_type = match lang {
339 Lang::Cxx => Api::CxxType,
340 Lang::Rust => Api::RustType,
341 };
David Tolnayf5ead102020-11-24 17:08:05 -0800342 api_type(ExternType {
David Tolnay7db73692019-10-20 14:51:12 -0400343 doc,
344 type_token,
David Tolnay17a934c2020-11-02 00:40:04 -0800345 name: Pair::new(namespace, ident),
David Tolnayc8361022020-08-25 21:57:53 -0700346 semi_token,
David Tolnay00f236a2020-08-29 19:07:18 -0700347 trusted,
David Tolnayf5ead102020-11-24 17:08:05 -0800348 })
David Tolnay7db73692019-10-20 14:51:12 -0400349}
350
Adrian Taylorc8713432020-10-21 18:20:55 -0700351fn parse_extern_fn(
352 cx: &mut Errors,
353 foreign_fn: &ForeignItemFn,
354 lang: Lang,
David Tolnay556738d2020-11-15 13:58:44 -0800355 trusted: bool,
David Tolnay302b1752020-11-10 18:43:24 -0800356 namespace: &Namespace,
Adrian Taylorc8713432020-10-21 18:20:55 -0700357) -> Result<Api> {
David Tolnay7db73692019-10-20 14:51:12 -0400358 let generics = &foreign_fn.sig.generics;
David Tolnay9938b642020-11-15 18:11:40 -0800359 if generics.where_clause.is_some()
360 || generics.params.iter().any(|param| match param {
361 GenericParam::Lifetime(lifetime) => !lifetime.bounds.is_empty(),
362 GenericParam::Type(_) | GenericParam::Const(_) => true,
363 })
364 {
David Tolnay7db73692019-10-20 14:51:12 -0400365 return Err(Error::new_spanned(
366 foreign_fn,
367 "extern function with generic parameters is not supported yet",
368 ));
369 }
370 if let Some(variadic) = &foreign_fn.sig.variadic {
371 return Err(Error::new_spanned(
372 variadic,
373 "variadic function is not supported yet",
374 ));
375 }
David Tolnay8de461f2020-11-19 13:46:14 -0800376 if foreign_fn.sig.asyncness.is_some() {
377 return Err(Error::new_spanned(
378 foreign_fn,
379 "async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach",
380 ));
381 }
David Tolnay80ef0682020-11-19 13:56:07 -0800382 if foreign_fn.sig.constness.is_some() {
383 return Err(Error::new_spanned(
384 foreign_fn,
385 "const extern function is not supported",
386 ));
387 }
388 if let Some(abi) = &foreign_fn.sig.abi {
389 return Err(Error::new_spanned(
390 abi,
391 "explicit ABI on extern function is not supported",
392 ));
393 }
David Tolnay7db73692019-10-20 14:51:12 -0400394
David Tolnay938ca852020-10-09 19:25:08 -0700395 let mut doc = Doc::new();
396 let mut cxx_name = None;
397 let mut rust_name = None;
David Tolnay302b1752020-11-10 18:43:24 -0800398 let mut namespace = namespace.clone();
David Tolnay938ca852020-10-09 19:25:08 -0700399 attrs::parse(
400 cx,
401 &foreign_fn.attrs,
402 attrs::Parser {
403 doc: Some(&mut doc),
404 cxx_name: Some(&mut cxx_name),
405 rust_name: Some(&mut rust_name),
David Tolnayd7a3a182020-11-01 20:45:14 -0800406 namespace: Some(&mut namespace),
David Tolnay938ca852020-10-09 19:25:08 -0700407 ..Default::default()
408 },
409 );
410
David Tolnay7db73692019-10-20 14:51:12 -0400411 let mut receiver = None;
David Tolnaye3a48152020-04-08 19:38:05 -0700412 let mut args = Punctuated::new();
413 for arg in foreign_fn.sig.inputs.pairs() {
414 let (arg, comma) = arg.into_tuple();
David Tolnay7db73692019-10-20 14:51:12 -0400415 match arg {
David Tolnay1dd11a12020-04-22 12:31:48 -0700416 FnArg::Receiver(arg) => {
David Tolnaya1f29c42020-04-22 18:01:38 -0700417 if let Some((ampersand, lifetime)) = &arg.reference {
418 receiver = Some(Receiver {
David Tolnay9c76c392020-11-15 16:07:08 -0800419 pinned: false,
David Tolnaya1f29c42020-04-22 18:01:38 -0700420 ampersand: *ampersand,
421 lifetime: lifetime.clone(),
David Tolnay9c4ac2e2020-11-15 21:14:03 -0800422 mutable: arg.mutability.is_some(),
David Tolnaya1f29c42020-04-22 18:01:38 -0700423 var: arg.self_token,
Adrian Taylorc8713432020-10-21 18:20:55 -0700424 ty: ResolvableName::make_self(arg.self_token.span),
David Tolnaya1f29c42020-04-22 18:01:38 -0700425 shorthand: true,
David Tolnay9c76c392020-11-15 16:07:08 -0800426 pin_tokens: None,
David Tolnay9c4ac2e2020-11-15 21:14:03 -0800427 mutability: arg.mutability,
David Tolnaya1f29c42020-04-22 18:01:38 -0700428 });
429 continue;
Joel Galensone1e969d2020-04-21 12:50:20 -0700430 }
David Tolnay1dd11a12020-04-22 12:31:48 -0700431 return Err(Error::new_spanned(arg, "unsupported signature"));
David Tolnay7db73692019-10-20 14:51:12 -0400432 }
433 FnArg::Typed(arg) => {
434 let ident = match arg.pat.as_ref() {
435 Pat::Ident(pat) => pat.ident.clone(),
Joel Galensonba676072020-04-27 15:55:45 -0700436 Pat::Wild(pat) => {
437 Ident::new(&format!("_{}", args.len()), pat.underscore_token.span)
438 }
David Tolnay7db73692019-10-20 14:51:12 -0400439 _ => return Err(Error::new_spanned(arg, "unsupported signature")),
440 };
David Tolnay313cc0a2020-11-24 21:47:01 -0800441 let ty = parse_type(&arg.ty)?;
David Tolnay7db73692019-10-20 14:51:12 -0400442 if ident != "self" {
David Tolnaye3a48152020-04-08 19:38:05 -0700443 args.push_value(Var { ident, ty });
444 if let Some(comma) = comma {
445 args.push_punct(*comma);
446 }
David Tolnay7db73692019-10-20 14:51:12 -0400447 continue;
448 }
449 if let Type::Ref(reference) = ty {
450 if let Type::Ident(ident) = reference.inner {
451 receiver = Some(Receiver {
David Tolnay9c76c392020-11-15 16:07:08 -0800452 pinned: reference.pinned,
David Tolnayfb6e3862020-04-20 01:33:23 -0700453 ampersand: reference.ampersand,
David Tolnay0bd50fa2020-04-22 15:31:33 -0700454 lifetime: reference.lifetime,
David Tolnay9c4ac2e2020-11-15 21:14:03 -0800455 mutable: reference.mutable,
Adrian Taylorc8713432020-10-21 18:20:55 -0700456 var: Token![self](ident.rust.span()),
David Tolnay05e11cc2020-04-20 02:13:56 -0700457 ty: ident,
David Tolnay62d360c2020-04-22 16:26:21 -0700458 shorthand: false,
David Tolnay9c76c392020-11-15 16:07:08 -0800459 pin_tokens: reference.pin_tokens,
David Tolnay9c4ac2e2020-11-15 21:14:03 -0800460 mutability: reference.mutability,
David Tolnay7db73692019-10-20 14:51:12 -0400461 });
462 continue;
463 }
464 }
465 return Err(Error::new_spanned(arg, "unsupported method receiver"));
466 }
467 }
468 }
David Tolnay59b7ede2020-03-16 00:30:23 -0700469
David Tolnaye3a48152020-04-08 19:38:05 -0700470 let mut throws_tokens = None;
David Tolnay313cc0a2020-11-24 21:47:01 -0800471 let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
David Tolnaye3a48152020-04-08 19:38:05 -0700472 let throws = throws_tokens.is_some();
David Tolnaybdb576c2020-09-06 23:45:55 -0700473 let unsafety = foreign_fn.sig.unsafety;
David Tolnay7db73692019-10-20 14:51:12 -0400474 let fn_token = foreign_fn.sig.fn_token;
David Tolnay17a934c2020-11-02 00:40:04 -0800475 let name = Pair::new_from_differing_names(
David Tolnayd7a3a182020-11-01 20:45:14 -0800476 namespace,
Adrian Taylor0f8ab222020-10-29 21:31:56 -0700477 cxx_name.unwrap_or(foreign_fn.sig.ident.clone()),
478 rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
479 );
David Tolnay9938b642020-11-15 18:11:40 -0800480 let generics = generics.clone();
David Tolnaye3a48152020-04-08 19:38:05 -0700481 let paren_token = foreign_fn.sig.paren_token;
David Tolnay7db73692019-10-20 14:51:12 -0400482 let semi_token = foreign_fn.semi_token;
David Tolnay295ef6b2020-05-07 16:10:22 -0700483 let api_function = match lang {
484 Lang::Cxx => Api::CxxFunction,
485 Lang::Rust => Api::RustFunction,
486 };
David Tolnayd95b1192020-03-18 20:07:46 -0700487
David Tolnay295ef6b2020-05-07 16:10:22 -0700488 Ok(api_function(ExternFn {
David Tolnay6cde49f2020-03-16 12:25:45 -0700489 lang,
David Tolnay7db73692019-10-20 14:51:12 -0400490 doc,
David Tolnay17a934c2020-11-02 00:40:04 -0800491 name,
David Tolnay16448732020-03-18 12:39:36 -0700492 sig: Signature {
David Tolnaybdb576c2020-09-06 23:45:55 -0700493 unsafety,
David Tolnay16448732020-03-18 12:39:36 -0700494 fn_token,
David Tolnay9938b642020-11-15 18:11:40 -0800495 generics,
David Tolnay16448732020-03-18 12:39:36 -0700496 receiver,
497 args,
498 ret,
499 throws,
David Tolnaye3a48152020-04-08 19:38:05 -0700500 paren_token,
501 throws_tokens,
David Tolnay16448732020-03-18 12:39:36 -0700502 },
David Tolnay7db73692019-10-20 14:51:12 -0400503 semi_token,
David Tolnay556738d2020-11-15 13:58:44 -0800504 trusted,
David Tolnay295ef6b2020-05-07 16:10:22 -0700505 }))
David Tolnay7db73692019-10-20 14:51:12 -0400506}
507
Adrian Taylorc8713432020-10-21 18:20:55 -0700508fn parse_extern_verbatim(
509 cx: &mut Errors,
510 tokens: &TokenStream,
511 lang: Lang,
David Tolnay302b1752020-11-10 18:43:24 -0800512 namespace: &Namespace,
Adrian Taylorc8713432020-10-21 18:20:55 -0700513) -> Result<Api> {
David Tolnaye2f9ec42020-05-07 16:19:33 -0700514 // type Alias = crate::path::to::Type;
David Tolnay3e628882020-05-10 15:30:14 -0700515 let parse = |input: ParseStream| -> Result<TypeAlias> {
David Tolnaye2f9ec42020-05-07 16:19:33 -0700516 let attrs = input.call(Attribute::parse_outer)?;
517 let type_token: Token![type] = match input.parse()? {
518 Some(type_token) => type_token,
519 None => {
520 let span = input.cursor().token_stream();
521 return Err(Error::new_spanned(span, "unsupported foreign item"));
522 }
523 };
524 let ident: Ident = input.parse()?;
525 let eq_token: Token![=] = input.parse()?;
526 let ty: RustType = input.parse()?;
527 let semi_token: Token![;] = input.parse()?;
Adrian Taylorc8713432020-10-21 18:20:55 -0700528 let mut doc = Doc::new();
David Tolnay302b1752020-11-10 18:43:24 -0800529 let mut namespace = namespace.clone();
Adrian Taylorc8713432020-10-21 18:20:55 -0700530 attrs::parse(
531 cx,
532 &attrs,
533 attrs::Parser {
534 doc: Some(&mut doc),
David Tolnayd7a3a182020-11-01 20:45:14 -0800535 namespace: Some(&mut namespace),
Adrian Taylorc8713432020-10-21 18:20:55 -0700536 ..Default::default()
537 },
538 );
David Tolnaye2f9ec42020-05-07 16:19:33 -0700539
540 Ok(TypeAlias {
Bryan Henry890083d2020-09-13 10:34:31 -0700541 doc,
David Tolnaye2f9ec42020-05-07 16:19:33 -0700542 type_token,
David Tolnay17a934c2020-11-02 00:40:04 -0800543 name: Pair::new(namespace, ident),
David Tolnaye2f9ec42020-05-07 16:19:33 -0700544 eq_token,
545 ty,
546 semi_token,
547 })
David Tolnay3e628882020-05-10 15:30:14 -0700548 };
David Tolnaye2f9ec42020-05-07 16:19:33 -0700549
550 let type_alias = parse.parse2(tokens.clone())?;
551 match lang {
552 Lang::Cxx => Ok(Api::TypeAlias(type_alias)),
553 Lang::Rust => {
554 let (type_token, semi_token) = (type_alias.type_token, type_alias.semi_token);
555 let span = quote!(#type_token #semi_token);
556 let msg = "type alias in extern \"Rust\" block is not supported";
557 Err(Error::new_spanned(span, msg))
558 }
559 }
560}
561
David Tolnay313cc0a2020-11-24 21:47:01 -0800562fn parse_impl(imp: ItemImpl) -> Result<Api> {
David Tolnay7e69f892020-10-03 22:20:22 -0700563 if !imp.items.is_empty() {
564 let mut span = Group::new(Delimiter::Brace, TokenStream::new());
565 span.set_span(imp.brace_token.span);
566 return Err(Error::new_spanned(span, "expected an empty impl block"));
567 }
568
569 let self_ty = &imp.self_ty;
570 if let Some((bang, path, for_token)) = &imp.trait_ {
571 let span = quote!(#bang #path #for_token #self_ty);
572 return Err(Error::new_spanned(
573 span,
574 "unexpected impl, expected something like `impl UniquePtr<T> {}`",
575 ));
576 }
577
578 let generics = &imp.generics;
579 if !generics.params.is_empty() || generics.where_clause.is_some() {
580 return Err(Error::new_spanned(
581 imp,
582 "generic parameters on an impl is not supported",
583 ));
584 }
585
586 Ok(Api::Impl(Impl {
587 impl_token: imp.impl_token,
David Tolnay313cc0a2020-11-24 21:47:01 -0800588 ty: parse_type(&self_ty)?,
David Tolnay7e69f892020-10-03 22:20:22 -0700589 brace_token: imp.brace_token,
590 }))
591}
592
David Tolnayb0cd3272020-10-27 21:32:54 -0700593fn parse_include(input: ParseStream) -> Result<Include> {
David Tolnay91e87fa2020-05-11 19:10:23 -0700594 if input.peek(LitStr) {
David Tolnayb0cd3272020-10-27 21:32:54 -0700595 let lit: LitStr = input.parse()?;
596 let span = lit.span();
597 return Ok(Include {
598 path: lit.value(),
599 kind: IncludeKind::Quoted,
600 begin_span: span,
601 end_span: span,
602 });
David Tolnay91e87fa2020-05-11 19:10:23 -0700603 }
604
605 if input.peek(Token![<]) {
606 let mut path = String::new();
David Tolnayb0cd3272020-10-27 21:32:54 -0700607
David Tolnay2cc2e3a2020-10-28 13:12:35 -0700608 let langle: Token![<] = input.parse()?;
David Tolnay91e87fa2020-05-11 19:10:23 -0700609 while !input.is_empty() && !input.peek(Token![>]) {
610 let token: TokenTree = input.parse()?;
611 match token {
612 TokenTree::Ident(token) => path += &token.to_string(),
613 TokenTree::Literal(token)
614 if token
615 .to_string()
616 .starts_with(|ch: char| ch.is_ascii_digit()) =>
617 {
618 path += &token.to_string();
619 }
620 TokenTree::Punct(token) => path.push(token.as_char()),
621 _ => return Err(Error::new(token.span(), "unexpected token in include path")),
622 }
623 }
David Tolnayb0cd3272020-10-27 21:32:54 -0700624 let rangle: Token![>] = input.parse()?;
David Tolnayb0cd3272020-10-27 21:32:54 -0700625
626 return Ok(Include {
627 path,
628 kind: IncludeKind::Bracketed,
David Tolnay2cc2e3a2020-10-28 13:12:35 -0700629 begin_span: langle.span,
630 end_span: rangle.span,
David Tolnayb0cd3272020-10-27 21:32:54 -0700631 });
David Tolnay91e87fa2020-05-11 19:10:23 -0700632 }
633
634 Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))
635}
636
David Tolnay313cc0a2020-11-24 21:47:01 -0800637fn parse_type(ty: &RustType) -> Result<Type> {
David Tolnay59b7ede2020-03-16 00:30:23 -0700638 match ty {
David Tolnay313cc0a2020-11-24 21:47:01 -0800639 RustType::Reference(ty) => parse_type_reference(ty),
640 RustType::Path(ty) => parse_type_path(ty),
641 RustType::Slice(ty) => parse_type_slice(ty),
642 RustType::Array(ty) => parse_type_array(ty),
643 RustType::BareFn(ty) => parse_type_fn(ty),
David Tolnayb40b9db2020-03-18 13:50:31 -0700644 RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
645 _ => Err(Error::new_spanned(ty, "unsupported type")),
646 }
647}
648
David Tolnay313cc0a2020-11-24 21:47:01 -0800649fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
650 let inner = parse_type(&ty.elem)?;
David Tolnayb40b9db2020-03-18 13:50:31 -0700651 let which = match &inner {
Adrian Taylorc8713432020-10-21 18:20:55 -0700652 Type::Ident(ident) if ident.rust == "str" => {
David Tolnayb40b9db2020-03-18 13:50:31 -0700653 if ty.mutability.is_some() {
654 return Err(Error::new_spanned(ty, "unsupported type"));
655 } else {
656 Type::Str
David Tolnay7db73692019-10-20 14:51:12 -0400657 }
658 }
David Tolnayeebe9b72020-04-14 16:32:18 -0700659 Type::Slice(slice) => match &slice.inner {
David Tolnayc5629f02020-11-23 18:32:46 -0800660 Type::Ident(ident) if ident.rust == U8 => Type::SliceRefU8,
David Tolnayeebe9b72020-04-14 16:32:18 -0700661 _ => Type::Ref,
David Tolnayeb952ba2020-04-14 15:02:24 -0700662 },
David Tolnayb40b9db2020-03-18 13:50:31 -0700663 _ => Type::Ref,
664 };
665 Ok(which(Box::new(Ref {
David Tolnayb27f7872020-11-15 15:07:04 -0800666 pinned: false,
David Tolnayb40b9db2020-03-18 13:50:31 -0700667 ampersand: ty.and_token,
David Tolnay0bd50fa2020-04-22 15:31:33 -0700668 lifetime: ty.lifetime.clone(),
David Tolnay9c4ac2e2020-11-15 21:14:03 -0800669 mutable: ty.mutability.is_some(),
David Tolnayb40b9db2020-03-18 13:50:31 -0700670 inner,
David Tolnayb27f7872020-11-15 15:07:04 -0800671 pin_tokens: None,
David Tolnay9c4ac2e2020-11-15 21:14:03 -0800672 mutability: ty.mutability,
David Tolnayb40b9db2020-03-18 13:50:31 -0700673 })))
674}
675
David Tolnay313cc0a2020-11-24 21:47:01 -0800676fn parse_type_path(ty: &TypePath) -> Result<Type> {
David Tolnayb40b9db2020-03-18 13:50:31 -0700677 let path = &ty.path;
678 if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
679 let segment = &path.segments[0];
680 let ident = segment.ident.clone();
681 match &segment.arguments {
David Tolnayda71ef62020-11-02 00:36:00 -0800682 PathArguments::None => return Ok(Type::Ident(ResolvableName::new(ident))),
David Tolnayb40b9db2020-03-18 13:50:31 -0700683 PathArguments::AngleBracketed(generic) => {
684 if ident == "UniquePtr" && generic.args.len() == 1 {
685 if let GenericArgument::Type(arg) = &generic.args[0] {
David Tolnay313cc0a2020-11-24 21:47:01 -0800686 let inner = parse_type(arg)?;
David Tolnayb40b9db2020-03-18 13:50:31 -0700687 return Ok(Type::UniquePtr(Box::new(Ty1 {
David Tolnayda71ef62020-11-02 00:36:00 -0800688 name: ident,
David Tolnayb40b9db2020-03-18 13:50:31 -0700689 langle: generic.lt_token,
690 inner,
691 rangle: generic.gt_token,
692 })));
693 }
David Tolnaye1dcdf72020-04-24 17:40:55 -0700694 } else if ident == "CxxVector" && generic.args.len() == 1 {
Myron Ahneba35cf2020-02-05 19:41:51 +0700695 if let GenericArgument::Type(arg) = &generic.args[0] {
David Tolnay313cc0a2020-11-24 21:47:01 -0800696 let inner = parse_type(arg)?;
David Tolnay4377a9e2020-04-24 15:20:26 -0700697 return Ok(Type::CxxVector(Box::new(Ty1 {
David Tolnayda71ef62020-11-02 00:36:00 -0800698 name: ident,
Myron Ahneba35cf2020-02-05 19:41:51 +0700699 langle: generic.lt_token,
700 inner,
701 rangle: generic.gt_token,
702 })));
703 }
David Tolnayb40b9db2020-03-18 13:50:31 -0700704 } else if ident == "Box" && generic.args.len() == 1 {
705 if let GenericArgument::Type(arg) = &generic.args[0] {
David Tolnay313cc0a2020-11-24 21:47:01 -0800706 let inner = parse_type(arg)?;
David Tolnayb40b9db2020-03-18 13:50:31 -0700707 return Ok(Type::RustBox(Box::new(Ty1 {
David Tolnayda71ef62020-11-02 00:36:00 -0800708 name: ident,
David Tolnayb40b9db2020-03-18 13:50:31 -0700709 langle: generic.lt_token,
710 inner,
711 rangle: generic.gt_token,
712 })));
713 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700714 } else if ident == "Vec" && generic.args.len() == 1 {
715 if let GenericArgument::Type(arg) = &generic.args[0] {
David Tolnay313cc0a2020-11-24 21:47:01 -0800716 let inner = parse_type(arg)?;
Myron Ahneba35cf2020-02-05 19:41:51 +0700717 return Ok(Type::RustVec(Box::new(Ty1 {
David Tolnayda71ef62020-11-02 00:36:00 -0800718 name: ident,
Myron Ahneba35cf2020-02-05 19:41:51 +0700719 langle: generic.lt_token,
720 inner,
721 rangle: generic.gt_token,
722 })));
723 }
David Tolnaycbc2a4b2020-11-15 15:08:44 -0800724 } else if ident == "Pin" && generic.args.len() == 1 {
725 if let GenericArgument::Type(arg) = &generic.args[0] {
David Tolnay313cc0a2020-11-24 21:47:01 -0800726 let inner = parse_type(arg)?;
David Tolnayc94035a2020-11-15 16:49:18 -0800727 let pin_token = kw::Pin(ident.span());
David Tolnaycbc2a4b2020-11-15 15:08:44 -0800728 if let Type::Ref(mut inner) = inner {
David Tolnaycbc2a4b2020-11-15 15:08:44 -0800729 inner.pinned = true;
730 inner.pin_tokens =
731 Some((pin_token, generic.lt_token, generic.gt_token));
732 return Ok(Type::Ref(inner));
733 }
734 }
David Tolnayb40b9db2020-03-18 13:50:31 -0700735 }
736 }
737 PathArguments::Parenthesized(_) => {}
David Tolnayfb134ed2020-03-15 23:17:48 -0700738 }
David Tolnay7db73692019-10-20 14:51:12 -0400739 }
740 Err(Error::new_spanned(ty, "unsupported type"))
741}
742
David Tolnay313cc0a2020-11-24 21:47:01 -0800743fn parse_type_slice(ty: &TypeSlice) -> Result<Type> {
744 let inner = parse_type(&ty.elem)?;
David Tolnayeebe9b72020-04-14 16:32:18 -0700745 Ok(Type::Slice(Box::new(Slice {
746 bracket: ty.bracket_token,
747 inner,
748 })))
749}
750
David Tolnay313cc0a2020-11-24 21:47:01 -0800751fn parse_type_array(ty: &TypeArray) -> Result<Type> {
752 let inner = parse_type(&ty.elem)?;
David Tolnayd9f97842020-11-24 21:00:05 -0800753
754 let len_expr = if let Expr::Lit(lit) = &ty.len {
755 lit
756 } else {
757 let msg = "unsupported expression, array length must be an integer literal";
758 return Err(Error::new_spanned(&ty.len, msg));
759 };
760
761 let len_token = if let Lit::Int(int) = &len_expr.lit {
762 int.clone()
763 } else {
764 let msg = "array length must be an integer literal";
765 return Err(Error::new_spanned(len_expr, msg));
766 };
767
768 let bracket = ty.bracket_token;
769 let semi_token = ty.semi_token;
770 let len = len_token.base10_parse::<usize>()?;
771
772 Ok(Type::Array(Box::new(Array {
773 bracket,
774 inner,
775 semi_token,
776 len,
777 len_token,
778 })))
David Tolnay2d0df232020-11-24 20:50:32 -0800779}
780
David Tolnay313cc0a2020-11-24 21:47:01 -0800781fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
David Tolnayc071b892020-03-18 16:59:53 -0700782 if ty.lifetimes.is_some() {
783 return Err(Error::new_spanned(
784 ty,
785 "function pointer with lifetime parameters is not supported yet",
786 ));
787 }
788 if ty.variadic.is_some() {
789 return Err(Error::new_spanned(
790 ty,
791 "variadic function pointer is not supported yet",
792 ));
793 }
794 let args = ty
795 .inputs
796 .iter()
797 .enumerate()
798 .map(|(i, arg)| {
David Tolnay313cc0a2020-11-24 21:47:01 -0800799 let ty = parse_type(&arg.ty)?;
David Tolnayc071b892020-03-18 16:59:53 -0700800 let ident = match &arg.name {
801 Some(ident) => ident.0.clone(),
802 None => format_ident!("_{}", i),
803 };
804 Ok(Var { ident, ty })
805 })
806 .collect::<Result<_>>()?;
David Tolnaye3a48152020-04-08 19:38:05 -0700807 let mut throws_tokens = None;
David Tolnay313cc0a2020-11-24 21:47:01 -0800808 let ret = parse_return_type(&ty.output, &mut throws_tokens)?;
David Tolnaye3a48152020-04-08 19:38:05 -0700809 let throws = throws_tokens.is_some();
David Tolnayc071b892020-03-18 16:59:53 -0700810 Ok(Type::Fn(Box::new(Signature {
David Tolnaybdb576c2020-09-06 23:45:55 -0700811 unsafety: ty.unsafety,
David Tolnayc071b892020-03-18 16:59:53 -0700812 fn_token: ty.fn_token,
David Tolnay9938b642020-11-15 18:11:40 -0800813 generics: Generics::default(),
David Tolnayc071b892020-03-18 16:59:53 -0700814 receiver: None,
815 args,
816 ret,
817 throws,
David Tolnaye3a48152020-04-08 19:38:05 -0700818 paren_token: ty.paren_token,
819 throws_tokens,
David Tolnayc071b892020-03-18 16:59:53 -0700820 })))
821}
822
David Tolnaye3a48152020-04-08 19:38:05 -0700823fn parse_return_type(
824 ty: &ReturnType,
825 throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>,
826) -> Result<Option<Type>> {
David Tolnayc071b892020-03-18 16:59:53 -0700827 let mut ret = match ty {
828 ReturnType::Default => return Ok(None),
829 ReturnType::Type(_, ret) => ret.as_ref(),
830 };
831 if let RustType::Path(ty) = ret {
832 let path = &ty.path;
833 if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
834 let segment = &path.segments[0];
835 let ident = segment.ident.clone();
836 if let PathArguments::AngleBracketed(generic) = &segment.arguments {
837 if ident == "Result" && generic.args.len() == 1 {
838 if let GenericArgument::Type(arg) = &generic.args[0] {
839 ret = arg;
David Tolnaye3a48152020-04-08 19:38:05 -0700840 *throws_tokens =
841 Some((kw::Result(ident.span()), generic.lt_token, generic.gt_token));
David Tolnayc071b892020-03-18 16:59:53 -0700842 }
843 }
844 }
845 }
846 }
David Tolnay313cc0a2020-11-24 21:47:01 -0800847 match parse_type(ret)? {
David Tolnayc071b892020-03-18 16:59:53 -0700848 Type::Void(_) => Ok(None),
849 ty => Ok(Some(ty)),
850 }
851}