@@ -1766,7 +1766,7 @@ impl Ty {
1766
1766
write ! ( f, "..." ) ?;
1767
1767
}
1768
1768
write ! ( f, ")" ) ?;
1769
- write ! ( f, "{}" , result_type. fn_return ( ) ) ?;
1769
+ write ! ( f, "{}" , result_type. fn_type_return ( ) ) ?;
1770
1770
if * nullability != Nullability :: NonNull {
1771
1771
write ! ( f, ">" ) ?;
1772
1772
}
@@ -1880,7 +1880,7 @@ impl Ty {
1880
1880
write ! ( f, "{}, " , arg. plain( ) ) ?;
1881
1881
}
1882
1882
write ! ( f, ")" ) ?;
1883
- write ! ( f, "{}" , result_type. fn_return ( ) ) ?;
1883
+ write ! ( f, "{}" , result_type. fn_type_return ( ) ) ?;
1884
1884
if * no_escape {
1885
1885
write ! ( f, " + '_" ) ?;
1886
1886
} else {
@@ -1900,6 +1900,20 @@ impl Ty {
1900
1900
1901
1901
pub ( crate ) fn method_return ( & self ) -> impl fmt:: Display + ' _ {
1902
1902
FormatterFn ( move |f| match self {
1903
+ // Don't output anything here.
1904
+ Self :: Primitive ( Primitive :: Void ) => Ok ( ( ) ) ,
1905
+ Self :: Pointer {
1906
+ nullability,
1907
+ pointee,
1908
+ ..
1909
+ } if pointee. is_static_object ( ) => {
1910
+ if * nullability == Nullability :: NonNull {
1911
+ // TODO: Add runtime nullability check here.
1912
+ write ! ( f, " -> &'static {}" , pointee. behind_pointer( ) )
1913
+ } else {
1914
+ write ! ( f, " -> Option<&'static {}>" , pointee. behind_pointer( ) )
1915
+ }
1916
+ }
1903
1917
Self :: Pointer {
1904
1918
nullability,
1905
1919
lifetime : _, // TODO: Use this somehow?
@@ -1921,7 +1935,7 @@ impl Ty {
1921
1935
write ! ( f, " -> bool" )
1922
1936
}
1923
1937
Self :: Primitive ( Primitive :: ObjcBool ) => write ! ( f, " -> bool" ) ,
1924
- _ => write ! ( f, "{}" , self . fn_return ( ) ) ,
1938
+ _ => write ! ( f, " -> {}" , self . plain ( ) ) ,
1925
1939
} )
1926
1940
}
1927
1941
@@ -1983,88 +1997,117 @@ impl Ty {
1983
1997
} )
1984
1998
}
1985
1999
1986
- pub ( crate ) fn fn_return ( & self ) -> impl fmt:: Display + ' _ {
1987
- FormatterFn ( move |f| {
1988
- if let Self :: Primitive ( Primitive :: Void ) = self {
1989
- // Don't output anything
1990
- return Ok ( ( ) ) ;
1991
- }
1992
-
1993
- match self {
1994
- Self :: Pointer {
1995
- nullability,
1996
- pointee,
1997
- ..
1998
- } if pointee. is_static_object ( ) => {
1999
- if * nullability == Nullability :: NonNull {
2000
- write ! ( f, " -> &'static {}" , pointee. behind_pointer( ) )
2001
- } else {
2002
- write ! ( f, " -> Option<&'static {}>" , pointee. behind_pointer( ) )
2003
- }
2000
+ fn fn_type_return ( & self ) -> impl fmt:: Display + ' _ {
2001
+ FormatterFn ( move |f| match self {
2002
+ // Don't output anything here.
2003
+ Self :: Primitive ( Primitive :: Void ) => Ok ( ( ) ) ,
2004
+ Self :: Pointer {
2005
+ nullability,
2006
+ pointee,
2007
+ ..
2008
+ } if pointee. is_static_object ( ) => {
2009
+ if * nullability == Nullability :: NonNull {
2010
+ // TODO: Add runtime nullability check here (can we even
2011
+ // do that?).
2012
+ write ! ( f, " -> &'static {}" , pointee. behind_pointer( ) )
2013
+ } else {
2014
+ write ! ( f, " -> Option<&'static {}>" , pointee. behind_pointer( ) )
2004
2015
}
2005
- _ => write ! ( f, " -> {}" , self . plain( ) ) ,
2006
2016
}
2017
+ _ => write ! ( f, " -> {}" , self . plain( ) ) ,
2007
2018
} )
2008
2019
}
2009
2020
2010
2021
pub ( crate ) fn fn_return_required_items ( & self ) -> impl Iterator < Item = ItemTree > {
2011
2022
let mut items: Vec < _ > = self . required_items ( ) . collect ( ) ;
2012
2023
match self {
2013
- Self :: Pointer {
2014
- lifetime : Lifetime :: Unspecified ,
2015
- pointee,
2016
- ..
2017
- } if pointee. is_cf_type ( ) => {
2024
+ Self :: Pointer { pointee, .. } if pointee. is_cf_type ( ) => {
2018
2025
items. push ( ItemTree :: cf ( "CFRetained" ) ) ;
2019
2026
items. push ( ItemTree :: core_ptr_nonnull ( ) ) ;
2020
2027
}
2021
- Self :: Pointer {
2022
- lifetime : Lifetime :: Unspecified ,
2023
- pointee,
2024
- ..
2025
- } if pointee. is_object_like ( ) && !pointee. is_static_object ( ) => {
2028
+ Self :: Pointer { pointee, .. }
2029
+ if pointee. is_object_like ( ) && !pointee. is_static_object ( ) =>
2030
+ {
2026
2031
items. push ( ItemTree :: objc ( "Retained" ) ) ;
2027
2032
}
2028
2033
_ => { }
2029
2034
}
2030
2035
items. into_iter ( )
2031
2036
}
2032
2037
2033
- pub ( crate ) fn fn_return_converter (
2038
+ pub ( crate ) fn fn_return (
2034
2039
& self ,
2035
2040
returns_retained : bool ,
2036
- ) -> Option < (
2037
- impl fmt:: Display + ' _ ,
2038
- impl fmt:: Display + ' _ ,
2041
+ ) -> (
2039
2042
impl fmt:: Display + ' _ ,
2040
- ) > {
2043
+ Option < (
2044
+ impl fmt:: Display + ' _ ,
2045
+ impl fmt:: Display + ' _ ,
2046
+ impl fmt:: Display + ' _ ,
2047
+ ) > ,
2048
+ ) {
2041
2049
let start = "let ret = " ;
2042
2050
// SAFETY: The function is marked with the correct retain semantics,
2043
2051
// otherwise it'd be invalid to use from Obj-C with ARC and Swift too.
2052
+ let end_cf = |nullability| {
2053
+ match ( nullability, returns_retained) {
2054
+ // TODO: Avoid NULL check, and let CFRetain do that instead?
2055
+ ( Nullability :: NonNull , true ) => ";\n let ret = ret.expect(\" function was marked as returning non-null, but actually returned NULL\" );\n unsafe { CFRetained::from_raw(ret) }" ,
2056
+ ( Nullability :: NonNull , false ) => ";\n let ret = ret.expect(\" function was marked as returning non-null, but actually returned NULL\" );\n unsafe { CFRetained::retain(ret) }" ,
2057
+ // CFRetain aborts on NULL pointers, so there's not really a more
2058
+ // efficient way to do this (except if we were to use e.g.
2059
+ // `CGColorRetain`/`CVOpenGLBufferRetain`/..., but that's a huge
2060
+ // hassle).
2061
+ ( _, true ) => ";\n ret.map(|ret| unsafe { CFRetained::from_raw(ret) })" ,
2062
+ ( _, false ) => ";\n ret.map(|ret| unsafe { CFRetained::retain(ret) })" ,
2063
+ }
2064
+ } ;
2044
2065
let end_objc = |nullability| {
2045
2066
match ( nullability, returns_retained) {
2046
2067
( Nullability :: NonNull , true ) => {
2047
- ";\n unsafe { Retained::from_raw(ret.as_ptr() ) }.expect(\" function was marked as returning non-null, but actually returned NULL\" )"
2068
+ ";\n unsafe { Retained::from_raw(ret) }.expect(\" function was marked as returning non-null, but actually returned NULL\" )"
2048
2069
}
2049
2070
( Nullability :: NonNull , false ) => {
2050
- ";\n unsafe { Retained::retain_autoreleased(ret.as_ptr() ) }.expect(\" function was marked as returning non-null, but actually returned NULL\" )"
2071
+ ";\n unsafe { Retained::retain_autoreleased(ret) }.expect(\" function was marked as returning non-null, but actually returned NULL\" )"
2051
2072
}
2052
2073
( _, true ) => ";\n unsafe { Retained::from_raw(ret) }" ,
2053
2074
( _, false ) => ";\n unsafe { Retained::retain_autoreleased(ret) }" ,
2054
2075
}
2055
2076
} ;
2056
- let end_cf = |nullability| match ( nullability, returns_retained) {
2057
- ( Nullability :: NonNull , true ) => ";\n unsafe { CFRetained::from_raw(ret) }" ,
2058
- ( Nullability :: NonNull , false ) => ";\n unsafe { CFRetained::retain(ret) }" ,
2059
- // CFRetain aborts on NULL pointers, so there's not really a more
2060
- // efficient way to do this (except if we were to use e.g.
2061
- // `CGColorRetain`/`CVOpenGLBufferRetain`/..., but that's a huge
2062
- // hassle).
2063
- ( _, true ) => ";\n NonNull::new(ret).map(|ret| unsafe { CFRetained::from_raw(ret) })" ,
2064
- ( _, false ) => ";\n NonNull::new(ret).map(|ret| unsafe { CFRetained::retain(ret) })" ,
2065
- } ;
2066
2077
2067
- match self {
2078
+ let ret = FormatterFn ( move |f| match self {
2079
+ // Don't output anything here.
2080
+ Self :: Primitive ( Primitive :: Void ) => Ok ( ( ) ) ,
2081
+ Self :: Pointer {
2082
+ nullability,
2083
+ is_const,
2084
+ pointee,
2085
+ ..
2086
+ } => {
2087
+ // Ignore nullability, always emit a nullable pointer. We will
2088
+ // unwrap it later in `fn_return_converter`.
2089
+ //
2090
+ // This is required because nullability attributes in Clang
2091
+ // are a hint, and not an ABI stable promise.
2092
+ if pointee. is_static_object ( ) {
2093
+ write ! ( f, "-> Option<&'static {}>" , pointee. behind_pointer( ) )
2094
+ } else if pointee. is_cf_type ( ) {
2095
+ write ! ( f, "-> Option<NonNull<{}>>" , pointee. behind_pointer( ) )
2096
+ } else if pointee. is_object_like ( ) {
2097
+ write ! ( f, "-> *mut {}" , pointee. behind_pointer( ) )
2098
+ } else {
2099
+ if * nullability == Nullability :: NonNull {
2100
+ write ! ( f, "-> Option<NonNull<{}>>" , pointee. behind_pointer( ) )
2101
+ } else if * is_const {
2102
+ write ! ( f, " -> *const {}" , pointee. behind_pointer( ) )
2103
+ } else {
2104
+ write ! ( f, " -> *mut {}" , pointee. behind_pointer( ) )
2105
+ }
2106
+ }
2107
+ }
2108
+ _ => write ! ( f, " -> {}" , self . plain( ) ) ,
2109
+ } ) ;
2110
+ let converter = match self {
2068
2111
_ if self . is_objc_bool ( ) => Some ( ( " -> bool" . to_string ( ) , "" , ".as_bool()" ) ) ,
2069
2112
Self :: TypeDef { id, .. } if matches ! ( & * id. name, "Boolean" | "boolean_t" ) => {
2070
2113
Some ( ( " -> bool" . to_string ( ) , start, ";\n ret != 0" ) )
@@ -2082,7 +2125,15 @@ impl Ty {
2082
2125
_ => error ! ( ?lifetime, returns_retained, "invalid lifetime" ) ,
2083
2126
}
2084
2127
2085
- if pointee. is_cf_type ( ) {
2128
+ if pointee. is_static_object ( ) {
2129
+ if * nullability == Nullability :: NonNull {
2130
+ let res = format ! ( " -> &'static {}" , pointee. behind_pointer( ) ) ;
2131
+ Some ( ( res, start, ";\n ret.expect(\" function was marked as returning non-null, but actually returned NULL\" )" ) )
2132
+ } else {
2133
+ // No conversion necessary
2134
+ None
2135
+ }
2136
+ } else if pointee. is_cf_type ( ) {
2086
2137
let res = if * nullability == Nullability :: NonNull {
2087
2138
format ! ( " -> CFRetained<{}>" , pointee. behind_pointer( ) )
2088
2139
} else {
@@ -2097,11 +2148,17 @@ impl Ty {
2097
2148
} ;
2098
2149
Some ( ( res, start, end_objc ( * nullability) ) )
2099
2150
} else {
2100
- None
2151
+ if * nullability == Nullability :: NonNull {
2152
+ let res = format ! ( " -> NonNull<{}>" , pointee. behind_pointer( ) ) ;
2153
+ Some ( ( res, start, ";\n ret.expect(\" function was marked as returning non-null, but actually returned NULL\" )" ) )
2154
+ } else {
2155
+ None
2156
+ }
2101
2157
}
2102
2158
}
2103
2159
_ => None ,
2104
- }
2160
+ } ;
2161
+ ( ret, converter)
2105
2162
}
2106
2163
2107
2164
pub ( crate ) fn var ( & self ) -> impl fmt:: Display + ' _ {
0 commit comments