Skip to content

Commit 3cd145e

Browse files
committed
Support inlining when deriving destructors / copy constructors.
1 parent 81f8e5f commit 3cd145e

11 files changed

Lines changed: 530 additions & 753 deletions

src/bindgen/ir/enumeration.rs

Lines changed: 56 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@ pub enum VariantBody {
3131
/// an unnamed struct is inlined at the point of use instead.
3232
/// This is a reasonable thing to do only for tuple variants with a single field.
3333
inline: bool,
34-
/// Generated cast methods return the variant's only field instead of the variant itself.
35-
/// For backward compatibility casts are inlined in a slightly
36-
/// larger set of cases than whole variants.
37-
inline_casts: bool,
3834
},
3935
}
4036

@@ -69,12 +65,10 @@ impl VariantBody {
6965
ref name,
7066
ref body,
7167
inline,
72-
inline_casts,
7368
} => Self::Body {
7469
name: name.clone(),
7570
body: body.specialize(generic_values, mappings, config),
7671
inline,
77-
inline_casts,
7872
},
7973
}
8074
}
@@ -98,7 +92,6 @@ impl EnumVariant {
9892
mod_cfg: Option<&Cfg>,
9993
self_path: &Path,
10094
enum_annotations: &AnnotationSet,
101-
config: &Config,
10295
) -> Result<Self, String> {
10396
let discriminant = match variant.discriminant {
10497
Some((_, ref expr)) => Some(Literal::load(expr)?),
@@ -169,24 +162,14 @@ impl EnumVariant {
169162
),
170163
name,
171164
inline: false,
172-
inline_casts: false,
173165
}
174166
}
175167
syn::Fields::Unnamed(ref fields) => {
176168
let path = Path::new(format!("{}_Body", variant.ident));
177169
let name = RenameRule::SnakeCase
178170
.apply(&variant.ident.to_string(), IdentifierType::StructMember)
179171
.into_owned();
180-
let inline_casts = fields.unnamed.len() == 1;
181-
// FIXME: It should be possible to support destructors and copy constructors
182-
// with inlined variants, but they are not supported yet.
183-
let inline = inline_casts
184-
&& !config
185-
.enumeration
186-
.derive_tagged_enum_destructor(enum_annotations)
187-
&& !config
188-
.enumeration
189-
.derive_tagged_enum_copy_constructor(enum_annotations);
172+
let inline = fields.unnamed.len() == 1;
190173
let inline_name = if inline { Some(&*name) } else { None };
191174
VariantBody::Body {
192175
body: Struct::new(
@@ -203,7 +186,6 @@ impl EnumVariant {
203186
),
204187
name,
205188
inline,
206-
inline_casts,
207189
}
208190
}
209191
};
@@ -381,7 +363,6 @@ impl Enum {
381363
mod_cfg,
382364
&path,
383365
&annotations,
384-
config,
385366
)?;
386367
has_data = has_data || !variant.body.is_empty();
387368
variants.push(variant);
@@ -559,12 +540,10 @@ impl Item for Enum {
559540
ref name,
560541
ref body,
561542
inline,
562-
inline_casts,
563543
} => VariantBody::Body {
564544
name: r.apply(&name, IdentifierType::StructMember).into_owned(),
565545
body: body.clone(),
566546
inline,
567-
inline_casts,
568547
},
569548
},
570549
variant.cfg.clone(),
@@ -1231,13 +1210,12 @@ impl Enum {
12311210
};
12321211

12331212
let mut derive_casts = |const_casts: bool| {
1234-
let (member_name, body, inline, inline_casts) = match variant.body {
1213+
let (member_name, body, inline) = match variant.body {
12351214
VariantBody::Body {
12361215
ref name,
12371216
ref body,
12381217
inline,
1239-
inline_casts,
1240-
} => (name, body, inline, inline_casts),
1218+
} => (name, body, inline),
12411219
VariantBody::Empty(..) => return,
12421220
};
12431221

@@ -1255,7 +1233,7 @@ impl Enum {
12551233
} else {
12561234
write_attrs!("mut-cast");
12571235
}
1258-
if inline_casts {
1236+
if inline {
12591237
let field = body.fields.last().unwrap();
12601238
let return_type = field.ty.clone();
12611239
let return_type = Type::Ptr {
@@ -1278,11 +1256,7 @@ impl Enum {
12781256
out.open_brace();
12791257
write!(out, "{}(Is{}());", assert_name, variant.export_name);
12801258
out.new_line();
1281-
write!(out, "return {}", member_name);
1282-
if inline_casts && !inline {
1283-
write!(out, "._0");
1284-
}
1285-
write!(out, ";");
1259+
write!(out, "return {};", member_name);
12861260
out.close_brace(false);
12871261
};
12881262

@@ -1407,19 +1381,28 @@ impl Enum {
14071381
let mut exhaustive = true;
14081382
for variant in &self.variants {
14091383
if let VariantBody::Body {
1410-
ref name, ref body, ..
1384+
ref name,
1385+
ref body,
1386+
inline,
14111387
} = variant.body
14121388
{
14131389
let condition = variant.cfg.to_condition(config);
14141390
condition.write_before(config, out);
14151391
write!(
14161392
out,
1417-
"case {}::{}: {}.~{}(); break;",
1393+
"case {}::{}: ",
14181394
self.tag.as_ref().unwrap(),
14191395
variant.export_name,
1420-
name,
1421-
body.export_name(),
14221396
);
1397+
if inline {
1398+
let field = body.fields.last().unwrap();
1399+
write!(out, "{}.~", field.name);
1400+
field.ty.write(config, out);
1401+
write!(out, "();");
1402+
} else {
1403+
write!(out, "{}.~{}();", name, body.export_name());
1404+
}
1405+
write!(out, "break;");
14231406
condition.write_after(config, out);
14241407
out.new_line();
14251408
} else {
@@ -1453,21 +1436,53 @@ impl Enum {
14531436
let mut exhaustive = true;
14541437
for variant in &self.variants {
14551438
if let VariantBody::Body {
1456-
ref name, ref body, ..
1439+
ref name,
1440+
ref body,
1441+
inline,
14571442
} = variant.body
14581443
{
14591444
let condition = variant.cfg.to_condition(config);
14601445
condition.write_before(config, out);
14611446
write!(
14621447
out,
1463-
"case {}::{}: ::new (&{}) ({})({}.{}); break;",
1448+
"case {}::{}:",
14641449
self.tag.as_ref().unwrap(),
14651450
variant.export_name,
1466-
name,
1467-
body.export_name(),
1468-
other,
1469-
name,
14701451
);
1452+
if inline {
1453+
let new_line = body.fields.len() > 1;
1454+
if new_line {
1455+
out.new_line();
1456+
out.push_tab();
1457+
} else {
1458+
write!(out, " ");
1459+
}
1460+
for field in body.fields.iter() {
1461+
write!(
1462+
out,
1463+
"new (&{}) (decltype({}))({}.{});",
1464+
field.name, field.name, other, field.name,
1465+
);
1466+
if new_line {
1467+
out.new_line();
1468+
}
1469+
}
1470+
if new_line {
1471+
out.pop_tab();
1472+
} else {
1473+
write!(out, " ");
1474+
}
1475+
} else {
1476+
write!(
1477+
out,
1478+
" new (&{}) ({})({}.{}); ",
1479+
name,
1480+
body.export_name(),
1481+
other,
1482+
name,
1483+
);
1484+
}
1485+
write!(out, "break;");
14711486
condition.write_after(config, out);
14721487
out.new_line();
14731488
} else {

tests/expectations/cfg.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ union C {
152152
~C() {
153153
switch (tag) {
154154
#if defined(PLATFORM_UNIX)
155-
case Tag::C5: c5.~C5_Body(); break;
155+
case Tag::C5: c5.~C5_Body();break;
156156
#endif
157157
default: break;
158158
}
@@ -162,7 +162,7 @@ union C {
162162
: tag(other.tag) {
163163
switch (tag) {
164164
#if defined(PLATFORM_UNIX)
165-
case Tag::C5: ::new (&c5) (C5_Body)(other.c5); break;
165+
case Tag::C5: new (&c5) (C5_Body)(other.c5); break;
166166
#endif
167167
default: break;
168168
}

0 commit comments

Comments
 (0)