diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-01-24 14:37:27 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-24 14:37:27 -0800 |
commit | 3885130c0f04ec572bf7fea4dd85fcfc8acbc9fc (patch) | |
tree | 6c557d15429e49a8346a04719f4d3a3327f246c3 /src/codegen/mod.rs | |
parent | 0c07e9e70d924806a1f3c05491444c6564b866a0 (diff) | |
parent | 0df8441e6eed35fdde27d2ebc3a4da629d5ec732 (diff) |
Auto merge of #437 - emilio:constify-all-enums, r=fitzgen
codegen: Respect original repr for bitfield-like enums, add a constifying variant.
r? @fitzgen
Fixes #430
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r-- | src/codegen/mod.rs | 81 |
1 files changed, 64 insertions, 17 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index fa34d341..0991391a 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1479,6 +1479,7 @@ enum EnumBuilder<'a> { canonical_name: &'a str, aster: P<ast::Item>, }, + Consts { aster: P<ast::Item>, } } impl<'a> EnumBuilder<'a> { @@ -1486,21 +1487,25 @@ impl<'a> EnumBuilder<'a> { /// the representation, and whether it should be represented as a rust enum. fn new(aster: aster::item::ItemBuilder<aster::invoke::Identity>, name: &'a str, - repr_name: &str, - is_rust: bool) + repr: P<ast::Ty>, + bitfield_like: bool, + constify: bool) -> Self { - if is_rust { - EnumBuilder::Rust(aster.enum_(name)) - } else { + if bitfield_like { EnumBuilder::Bitfield { canonical_name: name, aster: aster.tuple_struct(name) .field() .pub_() - .ty() - .id(repr_name) + .build_ty(repr) .build(), } + } else if constify { + EnumBuilder::Consts { + aster: aster.type_(name).build_ty(repr), + } + } else { + EnumBuilder::Rust(aster.enum_(name)) } } @@ -1550,6 +1555,25 @@ impl<'a> EnumBuilder<'a> { result.push(constant); self } + EnumBuilder::Consts { .. } => { + let constant_name = match mangling_prefix { + Some(prefix) => { + Cow::Owned(format!("{}_{}", prefix, variant_name)) + } + None => variant_name, + }; + + let constant = aster::AstBuilder::new() + .item() + .pub_() + .const_(&*constant_name) + .expr() + .build(expr) + .build(rust_ty); + + result.push(constant); + self + } } } @@ -1579,6 +1603,7 @@ impl<'a> EnumBuilder<'a> { result.push(impl_); aster } + EnumBuilder::Consts { aster, .. } => aster, } } } @@ -1634,6 +1659,8 @@ impl CodeGenerator for Enum { let mut builder = aster::AstBuilder::new().item().pub_(); + // FIXME(emilio): These should probably use the path so it can + // disambiguate between namespaces, just like is_opaque etc. let is_bitfield = { ctx.options().bitfield_enums.matches(&name) || (enum_ty.name().is_none() && @@ -1642,15 +1669,25 @@ impl CodeGenerator for Enum { .any(|v| ctx.options().bitfield_enums.matches(&v.name()))) }; - let is_rust_enum = !is_bitfield; + let is_constified_enum = { + ctx.options().constified_enums.matches(&name) || + (enum_ty.name().is_none() && + self.variants() + .iter() + .any(|v| ctx.options().constified_enums.matches(&v.name()))) + }; + + let is_rust_enum = !is_bitfield && !is_constified_enum; // FIXME: Rust forbids repr with empty enums. Remove this condition when // this is allowed. + // + // TODO(emilio): Delegate this to the builders? if is_rust_enum { if !self.variants().is_empty() { builder = builder.with_attr(attributes::repr(repr_name)); } - } else { + } else if is_bitfield { builder = builder.with_attr(attributes::repr("C")); } @@ -1658,14 +1695,16 @@ impl CodeGenerator for Enum { builder = builder.with_attr(attributes::doc(comment)); } - let derives = attributes::derives(&["Debug", - "Copy", - "Clone", - "PartialEq", - "Eq", - "Hash"]); + if !is_constified_enum { + let derives = attributes::derives(&["Debug", + "Copy", + "Clone", + "PartialEq", + "Eq", + "Hash"]); - builder = builder.with_attr(derives); + builder = builder.with_attr(derives); + } fn add_constant<'a>(enum_: &Type, // Only to avoid recomputing every time. @@ -1695,8 +1734,16 @@ impl CodeGenerator for Enum { result.push(constant); } + let repr = self.repr() + .map(|repr| repr.to_rust_ty(ctx)) + .unwrap_or_else(|| helpers::ast_ty::raw_type(ctx, repr_name)); + let mut builder = - EnumBuilder::new(builder, &name, repr_name, is_rust_enum); + EnumBuilder::new(builder, + &name, + repr, + is_bitfield, + is_constified_enum); // A map where we keep a value -> variant relation. let mut seen_values = HashMap::<_, String>::new(); |