Skip to content

Commit 5446818

Browse files
committed
implement Default trait
1 parent 7fa654c commit 5446818

File tree

153 files changed

+854
-179
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

153 files changed

+854
-179
lines changed

src/codegen/mod.rs

+51-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use aster;
66
use ir::annotations::FieldAccessorKind;
77
use ir::comp::{Base, CompInfo, CompKind, Field, Method, MethodKind};
88
use ir::context::{BindgenContext, ItemId};
9-
use ir::derive::{CanDeriveCopy, CanDeriveDebug};
9+
use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
1010
use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue};
1111
use ir::function::{Function, FunctionSig};
1212
use ir::int::IntKind;
@@ -685,10 +685,16 @@ impl<'a> CodeGenerator for Vtable<'a> {
685685
assert_eq!(item.id(), self.item_id);
686686
// For now, generate an empty struct, later we should generate function
687687
// pointers and whatnot.
688+
let mut attributes = vec![attributes::repr("C")];
689+
690+
if ctx.options().derive_default {
691+
attributes.push(attributes::derives(&["Default"]))
692+
}
693+
688694
let vtable = aster::AstBuilder::new()
689695
.item()
690696
.pub_()
691-
.with_attr(attributes::repr("C"))
697+
.with_attrs(attributes)
692698
.struct_(self.canonical_name(ctx))
693699
.build();
694700
result.push(vtable);
@@ -873,6 +879,7 @@ impl CodeGenerator for CompInfo {
873879

874880
let mut attributes = vec![];
875881
let mut needs_clone_impl = false;
882+
let mut needs_default_impl = false;
876883
if ctx.options().generate_comments {
877884
if let Some(comment) = item.comment() {
878885
attributes.push(attributes::doc(comment));
@@ -890,6 +897,12 @@ impl CodeGenerator for CompInfo {
890897
derives.push("Debug");
891898
}
892899

900+
if item.can_derive_default(ctx, ()) {
901+
derives.push("Default");
902+
} else {
903+
needs_default_impl = ctx.options().derive_default;
904+
}
905+
893906
if item.can_derive_copy(ctx, ()) &&
894907
!item.annotations().disallow_copy() {
895908
derives.push("Copy");
@@ -1354,8 +1367,14 @@ impl CodeGenerator for CompInfo {
13541367

13551368
// NB: We can't use to_rust_ty here since for opaque types this tries to
13561369
// use the specialization knowledge to generate a blob field.
1357-
let ty_for_impl =
1358-
aster::AstBuilder::new().ty().path().id(&canonical_name).build();
1370+
let ty_for_impl = aster::AstBuilder::new()
1371+
.ty()
1372+
.path()
1373+
.segment(&canonical_name)
1374+
.with_generics(generics.clone())
1375+
.build()
1376+
.build();
1377+
13591378
if needs_clone_impl {
13601379
let impl_ = quote_item!(ctx.ext_cx(),
13611380
impl X {
@@ -1381,6 +1400,32 @@ impl CodeGenerator for CompInfo {
13811400
result.push(clone_impl);
13821401
}
13831402

1403+
if needs_default_impl {
1404+
let prefix = ctx.trait_prefix();
1405+
let impl_ = quote_item!(ctx.ext_cx(),
1406+
impl X {
1407+
fn default() -> Self { unsafe { ::$prefix::mem::zeroed() } }
1408+
}
1409+
);
1410+
1411+
let impl_ = match impl_.unwrap().node {
1412+
ast::ItemKind::Impl(_, _, _, _, _, ref items) => items.clone(),
1413+
_ => unreachable!(),
1414+
};
1415+
1416+
let default_impl = aster::AstBuilder::new()
1417+
.item()
1418+
.impl_()
1419+
.trait_()
1420+
.id("Default")
1421+
.build()
1422+
.with_generics(generics.clone())
1423+
.with_items(impl_)
1424+
.build_ty(ty_for_impl.clone());
1425+
1426+
result.push(default_impl);
1427+
}
1428+
13841429
if !methods.is_empty() {
13851430
let methods = aster::AstBuilder::new()
13861431
.item()
@@ -2057,7 +2102,7 @@ impl ToRustTy for Type {
20572102
.map(|arg| arg.to_rust_ty(ctx))
20582103
.collect::<Vec<_>>();
20592104

2060-
path.segments.last_mut().unwrap().parameters = if
2105+
path.segments.last_mut().unwrap().parameters = if
20612106
template_args.is_empty() {
20622107
None
20632108
} else {
@@ -2498,6 +2543,7 @@ mod utils {
24982543

24992544
let incomplete_array_decl = quote_item!(ctx.ext_cx(),
25002545
#[repr(C)]
2546+
#[derive(Default)]
25012547
pub struct __IncompleteArrayField<T>(
25022548
::$prefix::marker::PhantomData<T>);
25032549
)

src/ir/comp.rs

+60-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use super::annotations::Annotations;
44
use super::context::{BindgenContext, ItemId};
5-
use super::derive::{CanDeriveCopy, CanDeriveDebug};
5+
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
66
use super::item::Item;
77
use super::layout::Layout;
88
use super::ty::Type;
@@ -162,6 +162,14 @@ impl CanDeriveDebug for Field {
162162
}
163163
}
164164

165+
impl CanDeriveDefault for Field {
166+
type Extra = ();
167+
168+
fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool {
169+
self.ty.can_derive_default(ctx, ())
170+
}
171+
}
172+
165173
impl<'a> CanDeriveCopy<'a> for Field {
166174
type Extra = ();
167175

@@ -287,6 +295,10 @@ pub struct CompInfo {
287295
/// around the template arguments.
288296
detect_derive_debug_cycle: Cell<bool>,
289297

298+
/// Used to detect if we've run in a can_derive_default cycle while cycling
299+
/// around the template arguments.
300+
detect_derive_default_cycle: Cell<bool>,
301+
290302
/// Used to detect if we've run in a has_destructor cycle while cycling
291303
/// around the template arguments.
292304
detect_has_destructor_cycle: Cell<bool>,
@@ -317,6 +329,7 @@ impl CompInfo {
317329
is_anonymous: false,
318330
found_unknown_attr: false,
319331
detect_derive_debug_cycle: Cell::new(false),
332+
detect_derive_default_cycle: Cell::new(false),
320333
detect_has_destructor_cycle: Cell::new(false),
321334
is_forward_declaration: false,
322335
}
@@ -892,6 +905,52 @@ impl CanDeriveDebug for CompInfo {
892905
}
893906
}
894907

908+
impl CanDeriveDefault for CompInfo {
909+
type Extra = Option<Layout>;
910+
911+
fn can_derive_default(&self,
912+
ctx: &BindgenContext,
913+
layout: Option<Layout>)
914+
-> bool {
915+
// We can reach here recursively via template parameters of a member,
916+
// for example.
917+
if self.detect_derive_default_cycle.get() {
918+
warn!("Derive default cycle detected!");
919+
return true;
920+
}
921+
922+
if self.kind == CompKind::Union {
923+
if ctx.options().unstable_rust {
924+
return false;
925+
}
926+
927+
return layout.unwrap_or_else(Layout::zero)
928+
.opaque()
929+
.can_derive_debug(ctx, ());
930+
}
931+
932+
self.detect_derive_default_cycle.set(true);
933+
934+
let can_derive_default = !self.has_vtable(ctx) &&
935+
!self.needs_explicit_vtable(ctx) &&
936+
self.base_members
937+
.iter()
938+
.all(|base| base.ty.can_derive_default(ctx, ())) &&
939+
self.template_args
940+
.iter()
941+
.all(|id| id.can_derive_default(ctx, ())) &&
942+
self.fields
943+
.iter()
944+
.all(|f| f.can_derive_default(ctx, ())) &&
945+
self.ref_template
946+
.map_or(true, |id| id.can_derive_default(ctx, ()));
947+
948+
self.detect_derive_default_cycle.set(false);
949+
950+
can_derive_default
951+
}
952+
}
953+
895954
impl<'a> CanDeriveCopy<'a> for CompInfo {
896955
type Extra = (&'a Item, Option<Layout>);
897956

src/ir/context.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Common context that is passed around during parsing and codegen.
22
3-
use super::derive::{CanDeriveCopy, CanDeriveDebug};
3+
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
44
use super::int::IntKind;
55
use super::item::{Item, ItemCanonicalPath};
66
use super::item_kind::ItemKind;
@@ -42,6 +42,14 @@ impl CanDeriveDebug for ItemId {
4242
}
4343
}
4444

45+
impl CanDeriveDefault for ItemId {
46+
type Extra = ();
47+
48+
fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool {
49+
ctx.resolve_item(*self).can_derive_default(ctx, ())
50+
}
51+
}
52+
4553
impl<'a> CanDeriveCopy<'a> for ItemId {
4654
type Extra = ();
4755

src/ir/derive.rs

+21
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,24 @@ pub trait CanDeriveCopy<'a> {
6565
extra: Self::Extra)
6666
-> bool;
6767
}
68+
69+
/// A trait that encapsulates the logic for whether or not we can derive `Default`
70+
/// for a given thing.
71+
///
72+
/// This should ideally be a no-op that just returns `true`, but instead needs
73+
/// to be a recursive method that checks whether all the proper members can
74+
/// derive default or not, because of the limit rust has on 32 items as max in the
75+
/// array.
76+
pub trait CanDeriveDefault {
77+
/// Implementations can define this type to get access to any extra
78+
/// information required to determine whether they can derive `Default`. If
79+
/// extra information is unneeded, then this should simply be the unit type.
80+
type Extra;
81+
82+
/// Return `true` if `Default` can be derived for this thing, `false`
83+
/// otherwise.
84+
fn can_derive_default(&self,
85+
ctx: &BindgenContext,
86+
extra: Self::Extra)
87+
-> bool;
88+
}

src/ir/item.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use super::annotations::Annotations;
44
use super::context::{BindgenContext, ItemId};
5-
use super::derive::{CanDeriveCopy, CanDeriveDebug};
5+
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
66
use super::function::Function;
77
use super::item_kind::ItemKind;
88
use super::module::Module;
@@ -235,6 +235,26 @@ impl CanDeriveDebug for Item {
235235
}
236236
}
237237

238+
impl CanDeriveDefault for Item {
239+
type Extra = ();
240+
241+
fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool {
242+
ctx.options().derive_default &&
243+
match self.kind {
244+
ItemKind::Type(ref ty) => {
245+
if self.is_opaque(ctx) {
246+
ty.layout(ctx)
247+
.map_or(false,
248+
|l| l.opaque().can_derive_default(ctx, ()))
249+
} else {
250+
ty.can_derive_default(ctx, ())
251+
}
252+
}
253+
_ => false,
254+
}
255+
}
256+
}
257+
238258
impl<'a> CanDeriveCopy<'a> for Item {
239259
type Extra = ();
240260

src/ir/layout.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Intermediate representation for the physical layout of some type.
22
33
use super::context::BindgenContext;
4-
use super::derive::{CanDeriveCopy, CanDeriveDebug};
4+
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
55
use super::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
66
use std::cmp;
77

@@ -79,6 +79,15 @@ impl CanDeriveDebug for Opaque {
7979
}
8080
}
8181

82+
impl CanDeriveDefault for Opaque {
83+
type Extra = ();
84+
85+
fn can_derive_default(&self, _: &BindgenContext, _: ()) -> bool {
86+
self.array_size()
87+
.map_or(false, |size| size <= RUST_DERIVE_IN_ARRAY_LIMIT)
88+
}
89+
}
90+
8291
impl<'a> CanDeriveCopy<'a> for Opaque {
8392
type Extra = ();
8493

src/ir/ty.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use super::comp::CompInfo;
44
use super::context::{BindgenContext, ItemId};
5-
use super::derive::{CanDeriveCopy, CanDeriveDebug};
5+
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
66
use super::enum_ty::Enum;
77
use super::function::FunctionSig;
88
use super::int::IntKind;
@@ -377,6 +377,39 @@ impl CanDeriveDebug for Type {
377377
}
378378
}
379379

380+
impl CanDeriveDefault for Type {
381+
type Extra = ();
382+
383+
fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool {
384+
match self.kind {
385+
TypeKind::Array(t, len) => {
386+
len <= RUST_DERIVE_IN_ARRAY_LIMIT &&
387+
t.can_derive_default(ctx, ())
388+
}
389+
TypeKind::ResolvedTypeRef(t) |
390+
TypeKind::TemplateAlias(t, _) |
391+
TypeKind::Alias(t) => t.can_derive_default(ctx, ()),
392+
TypeKind::Comp(ref info) => {
393+
info.can_derive_default(ctx, self.layout(ctx))
394+
}
395+
TypeKind::Void |
396+
TypeKind::Named |
397+
TypeKind::TemplateRef(..) |
398+
TypeKind::Reference(..) |
399+
TypeKind::NullPtr |
400+
TypeKind::Pointer(..) |
401+
TypeKind::BlockPointer |
402+
TypeKind::ObjCInterface(..) |
403+
TypeKind::Enum(..) => false,
404+
TypeKind::Function(..) |
405+
TypeKind::Int(..) |
406+
TypeKind::Float(..) |
407+
TypeKind::Complex(..) => true,
408+
TypeKind::UnresolvedTypeRef(..) => unreachable!(),
409+
}
410+
}
411+
}
412+
380413
impl<'a> CanDeriveCopy<'a> for Type {
381414
type Extra = &'a Item;
382415

0 commit comments

Comments
 (0)