From 8f1a9edaaa88dbceaa52ca5305fd77b2ce2e1bd7 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Fri, 7 Oct 2022 16:07:28 +0200 Subject: [PATCH] Clean up how return types work --- header-translator/src/method.rs | 29 +++----- header-translator/src/rust_type.rs | 116 ++++++++++++++++------------- 2 files changed, 76 insertions(+), 69 deletions(-) diff --git a/header-translator/src/method.rs b/header-translator/src/method.rs index 7a8ee56a6..fdf5a7270 100644 --- a/header-translator/src/method.rs +++ b/header-translator/src/method.rs @@ -1,11 +1,11 @@ -use clang::{Entity, EntityKind, EntityVisitResult, ObjCQualifiers, TypeKind}; +use clang::{Entity, EntityKind, EntityVisitResult, ObjCQualifiers}; use proc_macro2::TokenStream; use quote::{format_ident, quote, ToTokens, TokenStreamExt}; use crate::availability::Availability; use crate::config::ClassData; use crate::objc2_utils::in_selector_family; -use crate::rust_type::RustType; +use crate::rust_type::{RustType, RustTypeReturn}; #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] enum Qualifier { @@ -120,7 +120,7 @@ pub struct Method { memory_management: MemoryManagement, designated_initializer: bool, arguments: Vec<(String, Option, RustType)>, - result_type: Option, + result_type: RustTypeReturn, safe: bool, } @@ -201,7 +201,6 @@ impl Method { }) .collect(); - let result_type = entity.get_result_type().expect("method return type"); if let Some(qualifiers) = entity.get_objc_qualifiers() { let qualifier = Qualifier::parse(qualifiers); panic!( @@ -209,11 +208,9 @@ impl Method { qualifier, entity ); } - let result_type = if result_type.get_kind() != TypeKind::Void { - Some(RustType::parse_return(result_type)) - } else { - None - }; + + let result_type = entity.get_result_type().expect("method return type"); + let result_type = RustTypeReturn::parse(result_type); let mut designated_initializer = false; let mut consumes_self = false; @@ -273,10 +270,8 @@ impl Method { } // Verify that memory management is as expected - if let Some(type_) = &result_type { - if type_.is_id() { - memory_management.verify_sel(&selector); - } + if result_type.is_id() { + memory_management.verify_sel(&selector); } Some(Self { @@ -333,13 +328,9 @@ impl ToTokens for Method { quote!(#sel) }; - let (ret, is_id) = if let Some(type_) = &self.result_type { - (quote!(-> #type_), type_.is_id()) - } else { - (quote!(), false) - }; + let ret = &self.result_type; - let macro_name = if is_id { + let macro_name = if self.result_type.is_id() { format_ident!("msg_send_id") } else { format_ident!("msg_send") diff --git a/header-translator/src/rust_type.rs b/header-translator/src/rust_type.rs index c66b2dc37..f78a45713 100644 --- a/header-translator/src/rust_type.rs +++ b/header-translator/src/rust_type.rs @@ -36,10 +36,9 @@ impl GenericType { .get_objc_type_arguments() .into_iter() .map(|param| { - match RustType::parse(param, false, false) { + match RustType::parse(param, false) { RustType::Id { type_, - is_return: _, is_const: _, lifetime: _, nullability: _, @@ -267,7 +266,6 @@ pub enum RustType { // Objective-C Id { type_: GenericType, - is_return: bool, is_const: bool, lifetime: Lifetime, nullability: Nullability, @@ -297,11 +295,7 @@ pub enum RustType { } impl RustType { - pub fn is_id(&self) -> bool { - matches!(self, Self::Id { .. }) - } - - fn parse(ty: Type<'_>, is_return: bool, is_consumed: bool) -> Self { + fn parse(ty: Type<'_>, is_consumed: bool) -> Self { use TypeKind::*; // println!("{:?}, {:?}", ty, ty.get_class_type()); @@ -333,7 +327,6 @@ impl RustType { name: "Object".to_string(), generics: Vec::new(), }, - is_return, is_const: ty.is_const_qualified(), lifetime, nullability, @@ -345,7 +338,7 @@ impl RustType { let ty = ty.get_pointee_type().expect("pointer type to have pointee"); // Note: Can't handle const id pointers // assert!(!ty.is_const_qualified(), "expected pointee to not be const"); - let pointee = Self::parse(ty, false, is_consumed); + let pointee = Self::parse(ty, is_consumed); Self::Pointer { nullability, is_const, @@ -360,7 +353,6 @@ impl RustType { Self::Id { type_, - is_return, is_const: ty.is_const_qualified(), lifetime, nullability, @@ -378,21 +370,15 @@ impl RustType { "uint32_t" => Self::U32, "int164_t" => Self::I64, "uint64_t" => Self::U64, - "instancetype" => { - if !is_return { - panic!("instancetype in non-return position") - } - Self::Id { - type_: GenericType { - name: "Self".to_string(), - generics: Vec::new(), - }, - is_return, - is_const: ty.is_const_qualified(), - lifetime, - nullability, - } - } + "instancetype" => Self::Id { + type_: GenericType { + name: "Self".to_string(), + generics: Vec::new(), + }, + is_const: ty.is_const_qualified(), + lifetime, + nullability, + }, _ => { let ty = ty.get_canonical_type(); match ty.get_kind() { @@ -409,7 +395,6 @@ impl RustType { name: typedef_name, generics: Vec::new(), }, - is_return, is_const: ty.is_const_qualified(), lifetime, nullability, @@ -432,7 +417,6 @@ impl RustType { ConstantArray => { let element_type = Self::parse( ty.get_element_type().expect("array to have element type"), - false, is_consumed, ); let num_elements = ty @@ -460,20 +444,8 @@ impl RustType { } } - pub fn parse_return(ty: Type<'_>) -> Self { - let this = Self::parse(ty, true, false); - - this.visit_lifetime(|lifetime| { - if lifetime != Lifetime::Unspecified { - panic!("unexpected lifetime in return {this:?}"); - } - }); - - this - } - pub fn parse_argument(ty: Type<'_>, is_consumed: bool) -> Self { - let this = Self::parse(ty, false, is_consumed); + let this = Self::parse(ty, is_consumed); match &this { Self::Pointer { pointee, .. } => pointee.visit_lifetime(|lifetime| { @@ -492,7 +464,7 @@ impl RustType { } pub fn parse_typedef(ty: Type<'_>) -> Self { - let this = Self::parse(ty, false, false); + let this = Self::parse(ty, false); this.visit_lifetime(|lifetime| { if lifetime != Lifetime::Unspecified { @@ -536,18 +508,13 @@ impl ToTokens for RustType { // Objective-C Id { type_, - is_return, // Ignore is_const: _, // Ignore lifetime: _, nullability, } => { - let tokens = if *is_return { - quote!(Id<#type_, Shared>) - } else { - quote!(&#type_) - }; + let tokens = quote!(&#type_); if *nullability == Nullability::NonNull { tokens } else { @@ -578,7 +545,6 @@ impl ToTokens for RustType { } => match &**pointee { Self::Id { type_: tokens, - is_return: false, is_const: false, lifetime: Lifetime::Autoreleasing, nullability: inner_nullability, @@ -603,7 +569,6 @@ impl ToTokens for RustType { } Self::Id { type_: tokens, - is_return: false, is_const: false, lifetime: Lifetime::Unspecified, nullability: inner_nullability, @@ -649,3 +614,54 @@ impl ToTokens for RustType { tokens.append_all(result); } } + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RustTypeReturn { + inner: RustType, +} + +impl RustTypeReturn { + pub fn is_id(&self) -> bool { + matches!(self.inner, RustType::Id { .. }) + } + + pub fn new(inner: RustType) -> Self { + Self { inner } + } + + pub fn parse(ty: Type<'_>) -> Self { + let inner = RustType::parse(ty, false); + + inner.visit_lifetime(|lifetime| { + if lifetime != Lifetime::Unspecified { + panic!("unexpected lifetime in return {inner:?}"); + } + }); + + Self::new(inner) + } +} + +impl ToTokens for RustTypeReturn { + fn to_tokens(&self, tokens: &mut TokenStream) { + let result = match &self.inner { + RustType::Void => return, + RustType::Id { + type_, + // Ignore + is_const: _, + // Ignore + lifetime: _, + nullability, + } => { + if *nullability == Nullability::NonNull { + quote!(Id<#type_, Shared>) + } else { + quote!(Option>) + } + } + type_ => quote!(#type_), + }; + tokens.append_all(quote!(-> #result)); + } +}