Skip to content

Commit f899fa2

Browse files
committed
generate type alias for the block type
1 parent 0db9588 commit f899fa2

19 files changed

+249
-58
lines changed

src/clang.rs

+1
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,7 @@ impl Type {
940940
CXType_RValueReference |
941941
CXType_LValueReference |
942942
CXType_MemberPointer |
943+
CXType_BlockPointer |
943944
CXType_ObjCObjectPointer => {
944945
let ret = Type {
945946
x: unsafe { clang_getPointeeType(self.x) },

src/codegen/impl_debug.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ impl<'a> ImplDebug<'a> for Item {
156156
TypeKind::Function(..) |
157157
TypeKind::Enum(..) |
158158
TypeKind::Reference(..) |
159-
TypeKind::BlockPointer |
160159
TypeKind::UnresolvedTypeRef(..) |
161160
TypeKind::ObjCInterface(..) |
162161
TypeKind::ObjCId |
@@ -227,7 +226,8 @@ impl<'a> ImplDebug<'a> for Item {
227226

228227
TypeKind::ResolvedTypeRef(t) |
229228
TypeKind::TemplateAlias(t, _) |
230-
TypeKind::Alias(t) => {
229+
TypeKind::Alias(t) |
230+
TypeKind::BlockPointer(t) => {
231231
// We follow the aliases
232232
ctx.resolve_item(t).impl_debug(ctx, name)
233233
}

src/codegen/impl_partialeq.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ fn gen_field(ctx: &BindgenContext, ty_item: &Item, name: &str) -> quote::Tokens
8888
TypeKind::Enum(..) |
8989
TypeKind::TypeParam |
9090
TypeKind::UnresolvedTypeRef(..) |
91-
TypeKind::BlockPointer |
9291
TypeKind::Reference(..) |
9392
TypeKind::ObjCInterface(..) |
9493
TypeKind::ObjCId |
@@ -125,7 +124,8 @@ fn gen_field(ctx: &BindgenContext, ty_item: &Item, name: &str) -> quote::Tokens
125124

126125
TypeKind::ResolvedTypeRef(t) |
127126
TypeKind::TemplateAlias(t, _) |
128-
TypeKind::Alias(t) => {
127+
TypeKind::Alias(t) |
128+
TypeKind::BlockPointer(t) => {
129129
let inner_item = ctx.resolve_item(t);
130130
gen_field(ctx, inner_item, name)
131131
}

src/codegen/mod.rs

+144-22
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ struct CodegenResult<'a> {
103103
/// Whether Objective C types have been seen at least once.
104104
saw_objc: bool,
105105

106+
/// Whether Apple block types have been seen at least once.
107+
saw_block: bool,
108+
106109
/// Whether a bitfield allocation unit has been seen at least once.
107110
saw_bitfield_unit: bool,
108111

@@ -140,6 +143,7 @@ impl<'a> CodegenResult<'a> {
140143
saw_bindgen_union: false,
141144
saw_incomplete_array: false,
142145
saw_objc: false,
146+
saw_block: false,
143147
saw_bitfield_unit: false,
144148
codegen_id: codegen_id,
145149
items_seen: Default::default(),
@@ -166,6 +170,10 @@ impl<'a> CodegenResult<'a> {
166170
self.saw_objc = true;
167171
}
168172

173+
fn saw_block(&mut self) {
174+
self.saw_block = true;
175+
}
176+
169177
fn saw_bitfield_unit(&mut self) {
170178
self.saw_bitfield_unit = true;
171179
}
@@ -215,6 +223,7 @@ impl<'a> CodegenResult<'a> {
215223
self.saw_union |= new.saw_union;
216224
self.saw_incomplete_array |= new.saw_incomplete_array;
217225
self.saw_objc |= new.saw_objc;
226+
self.saw_block |= new.saw_block;
218227
self.saw_bitfield_unit |= new.saw_bitfield_unit;
219228

220229
new.items
@@ -293,7 +302,6 @@ impl AppendImplicitTemplateParams for quote::Tokens {
293302
TypeKind::Opaque |
294303
TypeKind::Function(..) |
295304
TypeKind::Enum(..) |
296-
TypeKind::BlockPointer |
297305
TypeKind::ObjCId |
298306
TypeKind::ObjCSel |
299307
TypeKind::TemplateInstantiation(..) => return,
@@ -406,6 +414,9 @@ impl CodeGenerator for Module {
406414
if result.saw_objc {
407415
utils::prepend_objc_header(ctx, &mut *result);
408416
}
417+
if result.saw_block {
418+
utils::prepend_block_header(ctx, &mut *result);
419+
}
409420
if result.saw_bitfield_unit {
410421
utils::prepend_bitfield_unit_type(&mut *result);
411422
}
@@ -597,7 +608,6 @@ impl CodeGenerator for Type {
597608
TypeKind::Array(..) |
598609
TypeKind::Vector(..) |
599610
TypeKind::Pointer(..) |
600-
TypeKind::BlockPointer |
601611
TypeKind::Reference(..) |
602612
TypeKind::Function(..) |
603613
TypeKind::ResolvedTypeRef(..) |
@@ -610,6 +620,38 @@ impl CodeGenerator for Type {
610620
TypeKind::TemplateInstantiation(ref inst) => {
611621
inst.codegen(ctx, result, item)
612622
}
623+
TypeKind::BlockPointer(inner) => {
624+
let inner_item = inner.into_resolver()
625+
.through_type_refs()
626+
.resolve(ctx);
627+
let name = item.canonical_name(ctx);
628+
629+
let inner_rust_type = {
630+
// Its possible that we have better layout information than
631+
// the inner type does, so fall back to an opaque blob based
632+
// on our layout if converting the inner item fails.
633+
if let TypeKind::Function(fnsig) = inner_item.kind().expect_type().kind() {
634+
utils::fnsig_block(ctx, fnsig)
635+
} else {
636+
panic!("invalid block typedef")
637+
}
638+
};
639+
640+
let rust_name = ctx.rust_ident(&name);
641+
642+
let mut tokens = if let Some(comment) = item.comment(ctx) {
643+
attributes::doc(comment)
644+
} else {
645+
quote! {}
646+
};
647+
648+
tokens.append_all(quote! {
649+
pub type #rust_name = #inner_rust_type ;
650+
});
651+
652+
result.push(tokens);
653+
result.saw_block();
654+
}
613655
TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item),
614656
TypeKind::TemplateAlias(inner, _) |
615657
TypeKind::Alias(inner) => {
@@ -636,9 +678,10 @@ impl CodeGenerator for Type {
636678

637679
// If this is a known named type, disallow generating anything
638680
// for it too.
639-
let spelling = self.name().expect("Unnamed alias?");
640-
if utils::type_from_named(ctx, spelling).is_some() {
641-
return;
681+
if let Some(spelling) = self.name() {
682+
if utils::type_from_named(ctx, spelling).is_some() {
683+
return;
684+
}
642685
}
643686

644687
let mut outer_params = item.used_template_params(ctx);
@@ -3071,23 +3114,25 @@ impl TryToRustTy for Type {
30713114
}
30723115
TypeKind::ResolvedTypeRef(inner) => inner.try_to_rust_ty(ctx, &()),
30733116
TypeKind::TemplateAlias(..) |
3074-
TypeKind::Alias(..) => {
3117+
TypeKind::Alias(..) |
3118+
TypeKind::BlockPointer(..) => {
30753119
let template_params = item.used_template_params(ctx)
30763120
.into_iter()
30773121
.filter(|param| param.is_template_param(ctx, &()))
30783122
.collect::<Vec<_>>();
30793123

3080-
let spelling = self.name().expect("Unnamed alias?");
30813124
if item.is_opaque(ctx, &()) && !template_params.is_empty() {
30823125
self.try_to_opaque(ctx, item)
3083-
} else if let Some(ty) = utils::type_from_named(
3084-
ctx,
3085-
spelling,
3086-
)
3087-
{
3088-
Ok(ty)
30893126
} else {
3090-
utils::build_path(item, ctx)
3127+
if let Some(spelling) = self.name() {
3128+
if let Some(ty) = utils::type_from_named(ctx, spelling) {
3129+
Ok(ty)
3130+
} else {
3131+
utils::build_path(item, ctx)
3132+
}
3133+
} else {
3134+
utils::build_path(item, ctx)
3135+
}
30913136
}
30923137
}
30933138
TypeKind::Comp(ref info) => {
@@ -3101,13 +3146,6 @@ impl TryToRustTy for Type {
31013146
utils::build_path(item, ctx)
31023147
}
31033148
TypeKind::Opaque => self.try_to_opaque(ctx, item),
3104-
TypeKind::BlockPointer => {
3105-
let void = raw_type(ctx, "c_void");
3106-
Ok(void.to_ptr(
3107-
/* is_const = */
3108-
false
3109-
))
3110-
}
31113149
TypeKind::Pointer(inner) |
31123150
TypeKind::Reference(inner) => {
31133151
let is_const = ctx.resolve_type(inner).is_const();
@@ -3517,7 +3555,7 @@ pub(crate) fn codegen(context: BindgenContext) -> (Vec<quote::Tokens>, BindgenOp
35173555
}
35183556

35193557
mod utils {
3520-
use super::{ToRustTyOrOpaque, error};
3558+
use super::{ToRustTyOrOpaque, error, helpers};
35213559
use ir::context::BindgenContext;
35223560
use ir::function::FunctionSig;
35233561
use ir::item::{Item, ItemCanonicalPath};
@@ -3560,6 +3598,46 @@ mod utils {
35603598
result.extend(old_items.into_iter());
35613599
}
35623600

3601+
pub fn prepend_block_header(
3602+
ctx: &BindgenContext,
3603+
result: &mut Vec<quote::Tokens>,
3604+
) {
3605+
let use_block = if ctx.options().block_extern_crate {
3606+
quote! {
3607+
#[macro_use]
3608+
extern crate block;
3609+
}
3610+
} else {
3611+
quote! {
3612+
use block;
3613+
}
3614+
};
3615+
3616+
let void = helpers::ast_ty::raw_type(ctx, "c_void");
3617+
let def_block = quote! {
3618+
pub fn block<A, R, F>(closure: F) -> *const ::block::Block<A, R>
3619+
where
3620+
A: ::block::BlockArguments,
3621+
F: 'static + ::block::IntoConcreteBlock<A, Ret = R>,
3622+
{
3623+
let block = ::block::ConcreteBlock::new(closure);
3624+
let block = block.copy();
3625+
let ptr = (&*block) as *const _;
3626+
let ptr = unsafe { _Block_copy(ptr as *const #void) };
3627+
3628+
ptr as *const ::block::Block<A, R>
3629+
}
3630+
3631+
extern "C" {
3632+
pub fn _Block_copy(block: *const #void) -> *mut #void;
3633+
}
3634+
};
3635+
3636+
let items = vec![use_block, def_block];
3637+
let old_items = mem::replace(result, items);
3638+
result.extend(old_items.into_iter());
3639+
}
3640+
35633641
pub fn prepend_union_types(
35643642
ctx: &BindgenContext,
35653643
result: &mut Vec<quote::Tokens>,
@@ -3871,4 +3949,48 @@ mod utils {
38713949

38723950
args
38733951
}
3952+
3953+
pub fn fnsig_block(
3954+
ctx: &BindgenContext,
3955+
sig: &FunctionSig,
3956+
) -> quote::Tokens {
3957+
use super::ToPtr;
3958+
3959+
let args = sig.argument_types().iter().map(|&(_, ty)| {
3960+
let arg_item = ctx.resolve_item(ty);
3961+
let arg_ty = arg_item.kind().expect_type();
3962+
3963+
match *arg_ty.canonical_type(ctx).kind() {
3964+
TypeKind::Array(t, _) => {
3965+
t.to_rust_ty_or_opaque(ctx, &())
3966+
.to_ptr(ctx.resolve_type(t).is_const())
3967+
},
3968+
TypeKind::Pointer(inner) => {
3969+
let inner = ctx.resolve_item(inner);
3970+
let inner_ty = inner.expect_type();
3971+
if let TypeKind::ObjCInterface(_) = *inner_ty.canonical_type(ctx).kind() {
3972+
quote! {
3973+
id
3974+
}
3975+
} else {
3976+
arg_item.to_rust_ty_or_opaque(ctx, &())
3977+
}
3978+
},
3979+
_ => {
3980+
arg_item.to_rust_ty_or_opaque(ctx, &())
3981+
}
3982+
}
3983+
});
3984+
3985+
let return_item = ctx.resolve_item(sig.return_type());
3986+
let ret_ty = if let TypeKind::Void = *return_item.kind().expect_type().kind() {
3987+
quote! { () }
3988+
} else {
3989+
return_item.to_rust_ty_or_opaque(ctx, &())
3990+
};
3991+
3992+
quote! {
3993+
*const ::block::Block<(#(#args),*), #ret_ty>
3994+
}
3995+
}
38743996
}

src/ir/analysis/derive_copy.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,6 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
173173
TypeKind::Enum(..) |
174174
TypeKind::Reference(..) |
175175
TypeKind::TypeParam |
176-
TypeKind::BlockPointer |
177176
TypeKind::Pointer(..) |
178177
TypeKind::UnresolvedTypeRef(..) |
179178
TypeKind::ObjCInterface(..) |
@@ -204,7 +203,8 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
204203

205204
TypeKind::ResolvedTypeRef(t) |
206205
TypeKind::TemplateAlias(t, _) |
207-
TypeKind::Alias(t) => {
206+
TypeKind::Alias(t) |
207+
TypeKind::BlockPointer(t) => {
208208
let cant_derive_copy = self.is_not_copy(t);
209209
if cant_derive_copy {
210210
trace!(

src/ir/analysis/derive_debug.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,6 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
183183
TypeKind::Enum(..) |
184184
TypeKind::Reference(..) |
185185
TypeKind::Vector(..) |
186-
TypeKind::BlockPointer |
187186
TypeKind::TypeParam |
188187
TypeKind::UnresolvedTypeRef(..) |
189188
TypeKind::ObjCInterface(..) |
@@ -213,7 +212,8 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
213212

214213
TypeKind::ResolvedTypeRef(t) |
215214
TypeKind::TemplateAlias(t, _) |
216-
TypeKind::Alias(t) => {
215+
TypeKind::Alias(t) |
216+
TypeKind::BlockPointer(t) => {
217217
if self.is_not_debug(t) {
218218
trace!(
219219
" aliases and type refs to T which cannot derive \

src/ir/analysis/derive_default.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
215215
TypeKind::Reference(..) |
216216
TypeKind::NullPtr |
217217
TypeKind::Pointer(..) |
218-
TypeKind::BlockPointer |
219218
TypeKind::ObjCId |
220219
TypeKind::ObjCSel |
221220
TypeKind::ObjCInterface(..) |
@@ -244,7 +243,8 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
244243

245244
TypeKind::ResolvedTypeRef(t) |
246245
TypeKind::TemplateAlias(t, _) |
247-
TypeKind::Alias(t) => {
246+
TypeKind::Alias(t) |
247+
TypeKind::BlockPointer(t) => {
248248
if self.is_not_default(t) {
249249
trace!(
250250
" aliases and type refs to T which cannot derive \

src/ir/analysis/derive_hash.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
167167
TypeKind::Enum(..) |
168168
TypeKind::TypeParam |
169169
TypeKind::UnresolvedTypeRef(..) |
170-
TypeKind::BlockPointer |
171170
TypeKind::Reference(..) |
172171
TypeKind::ObjCInterface(..) |
173172
TypeKind::ObjCId |
@@ -241,7 +240,8 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
241240

242241
TypeKind::ResolvedTypeRef(t) |
243242
TypeKind::TemplateAlias(t, _) |
244-
TypeKind::Alias(t) => {
243+
TypeKind::Alias(t) |
244+
TypeKind::BlockPointer(t) => {
245245
if self.cannot_derive_hash.contains(&t.into()) {
246246
trace!(
247247
" aliases and type refs to T which cannot derive \

0 commit comments

Comments
 (0)