From fada89c7f4101be35d15378091e587390691fcbf Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 16 Nov 2017 04:08:43 +0000 Subject: [PATCH] Remove Specialization in favour of generic typedef --- src/bindgen/bindings.rs | 3 - src/bindgen/builder.rs | 1 - src/bindgen/ir/constant.rs | 7 +- src/bindgen/ir/enumeration.rs | 14 +-- src/bindgen/ir/global.rs | 6 +- src/bindgen/ir/item.rs | 14 +-- src/bindgen/ir/mod.rs | 2 - src/bindgen/ir/opaque.rs | 17 +--- src/bindgen/ir/specialization.rs | 143 ----------------------------- src/bindgen/ir/structure.rs | 25 +---- src/bindgen/ir/ty.rs | 7 +- src/bindgen/ir/typedef.rs | 62 ++++++++++--- src/bindgen/ir/union.rs | 25 +---- src/bindgen/library.rs | 79 ++-------------- src/bindgen/monomorph.rs | 31 ++++--- src/bindgen/parser.rs | 59 ++++-------- tests/expectations/alias.cpp | 8 +- tests/expectations/cdecl.cpp | 28 +++--- tests/expectations/euclid.c | 26 +----- tests/expectations/euclid.cpp | 36 ++------ tests/expectations/monomorph-1.c | 4 +- tests/expectations/monomorph-1.cpp | 5 +- tests/expectations/monomorph-3.c | 4 +- tests/expectations/monomorph-3.cpp | 5 +- tests/expectations/typedef.c | 4 +- tests/expectations/typedef.cpp | 11 ++- 26 files changed, 154 insertions(+), 472 deletions(-) delete mode 100644 src/bindgen/ir/specialization.rs diff --git a/src/bindgen/bindings.rs b/src/bindgen/bindings.rs index 4487b7f..998dce4 100644 --- a/src/bindgen/bindings.rs +++ b/src/bindgen/bindings.rs @@ -109,9 +109,6 @@ impl Bindings { &ItemContainer::Union(ref x) => x.write(&self.config, &mut out), &ItemContainer::OpaqueItem(ref x) => x.write(&self.config, &mut out), &ItemContainer::Typedef(ref x) => x.write(&self.config, &mut out), - &ItemContainer::Specialization(_) => { - unreachable!("should not encounter a specialization in a generated library") - } } out.new_line(); } diff --git a/src/bindgen/builder.rs b/src/bindgen/builder.rs index 57de111..cd0dd46 100644 --- a/src/bindgen/builder.rs +++ b/src/bindgen/builder.rs @@ -217,7 +217,6 @@ impl Builder { result.unions, result.opaque_items, result.typedefs, - result.specializations, result.functions).generate() } } diff --git a/src/bindgen/ir/constant.rs b/src/bindgen/ir/constant.rs index f5ed997..0d5bb43 100644 --- a/src/bindgen/ir/constant.rs +++ b/src/bindgen/ir/constant.rs @@ -8,8 +8,7 @@ use std::mem; use syn; use bindgen::config::{Config, Language}; -use bindgen::ir::{AnnotationSet, Cfg, Documentation, Item, ItemContainer, Specialization, Type}; -use bindgen::library::Library; +use bindgen::ir::{AnnotationSet, Cfg, Documentation, Item, ItemContainer, Type}; use bindgen::writer::{Source, SourceWriter}; #[derive(Debug, Clone)] @@ -120,10 +119,6 @@ impl Item for Constant { fn container(&self) -> ItemContainer { ItemContainer::Constant(self.clone()) } - - fn specialize(&self, _library: &Library, _aliasee: &Specialization) -> Result, String> { - unreachable!(); - } } impl Source for Constant { diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index 63bca08..e62266b 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -7,8 +7,7 @@ use std::io::Write; use syn; use bindgen::config::{Config, Language}; -use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, ItemContainer, Item, Repr, Specialization}; -use bindgen::library::Library; +use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, ItemContainer, Item, Repr}; use bindgen::rename::{IdentifierType, RenameRule}; use bindgen::utilities::{find_first_some}; use bindgen::writer::{Source, SourceWriter}; @@ -111,17 +110,6 @@ impl Item for Enum { ItemContainer::Enum(self.clone()) } - fn specialize(&self, _: &Library, aliasee: &Specialization) -> Result, String> { - Ok(Box::new(Enum { - name: aliasee.name.clone(), - repr: self.repr.clone(), - values: self.values.clone(), - cfg: aliasee.cfg.clone(), - annotations: aliasee.annotations.clone(), - documentation: aliasee.documentation.clone(), - })) - } - fn rename_for_config(&mut self, config: &Config) { if config.language == Language::C && (config.enumeration.prefix_with_name diff --git a/src/bindgen/ir/global.rs b/src/bindgen/ir/global.rs index 2c25ee7..0c33af5 100644 --- a/src/bindgen/ir/global.rs +++ b/src/bindgen/ir/global.rs @@ -8,7 +8,7 @@ use syn; use bindgen::config::Config; use bindgen::dependencies::Dependencies; -use bindgen::ir::{AnnotationSet, Cfg, Documentation, Item, ItemContainer, Specialization, Type}; +use bindgen::ir::{AnnotationSet, Cfg, Documentation, Item, ItemContainer, Type}; use bindgen::library::Library; use bindgen::writer::{Source, SourceWriter}; @@ -75,10 +75,6 @@ impl Item for Static { ItemContainer::Static(self.clone()) } - fn specialize(&self, _library: &Library, _aliasee: &Specialization) -> Result, String> { - unreachable!(); - } - fn add_dependencies(&self, library: &Library, out: &mut Dependencies) { self.ty.add_dependencies(library, out); } diff --git a/src/bindgen/ir/item.rs b/src/bindgen/ir/item.rs index c457d78..0dc447f 100644 --- a/src/bindgen/ir/item.rs +++ b/src/bindgen/ir/item.rs @@ -7,7 +7,7 @@ use std::mem; use bindgen::config::Config; use bindgen::dependencies::Dependencies; -use bindgen::ir::{AnnotationSet, Cfg, Constant, Enum, OpaqueItem, Specialization, Static, Struct, Type, Typedef, Union}; +use bindgen::ir::{AnnotationSet, Cfg, Constant, Enum, OpaqueItem, Static, Struct, Type, Typedef, Union}; use bindgen::library::Library; use bindgen::monomorph::Monomorphs; @@ -20,8 +20,6 @@ pub trait Item { fn container(&self) -> ItemContainer; - fn specialize(&self, library: &Library, aliasee: &Specialization) -> Result, String>; - fn rename_for_config(&mut self, _config: &Config) { } fn add_dependencies(&self, _library: &Library, _out: &mut Dependencies) { } fn instantiate_monomorph(&self, _generics: &Vec, _library: &Library, _out: &mut Monomorphs) { } @@ -36,7 +34,6 @@ pub enum ItemContainer { Union(Union), Enum(Enum), Typedef(Typedef), - Specialization(Specialization), } impl ItemContainer { @@ -49,7 +46,6 @@ impl ItemContainer { &ItemContainer::Union(ref x) => x, &ItemContainer::Enum(ref x) => x, &ItemContainer::Typedef(ref x) => x, - &ItemContainer::Specialization(ref x) => x, } } } @@ -72,14 +68,6 @@ impl ItemMap { } } - pub fn clear(&mut self) { - self.data.clear(); - } - - pub fn len(&self) -> usize { - self.data.len() - } - pub fn try_insert(&mut self, item: T) -> bool { match (item.cfg().is_some(), self.data.get_mut(item.name())) { (true, Some(&mut ItemValue::Cfg(ref mut items))) => { diff --git a/src/bindgen/ir/mod.rs b/src/bindgen/ir/mod.rs index 1f2e3cc..5a2c3e9 100644 --- a/src/bindgen/ir/mod.rs +++ b/src/bindgen/ir/mod.rs @@ -13,7 +13,6 @@ pub mod item; pub mod opaque; pub mod path; pub mod repr; -pub mod specialization; pub mod structure; pub mod ty; pub mod typedef; @@ -31,7 +30,6 @@ pub use self::item::*; pub use self::opaque::*; pub use self::path::*; pub use self::repr::*; -pub use self::specialization::*; pub use self::structure::*; pub use self::ty::*; pub use self::typedef::*; diff --git a/src/bindgen/ir/opaque.rs b/src/bindgen/ir/opaque.rs index 3d460e7..1bd75a5 100644 --- a/src/bindgen/ir/opaque.rs +++ b/src/bindgen/ir/opaque.rs @@ -8,7 +8,7 @@ use syn; use bindgen::config::{Config, Language}; use bindgen::dependencies::Dependencies; -use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, ItemContainer, Item, Path, Specialization, Type}; +use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, ItemContainer, Item, Path, Type}; use bindgen::library::Library; use bindgen::mangle; use bindgen::monomorph::Monomorphs; @@ -73,21 +73,6 @@ impl Item for OpaqueItem { ItemContainer::OpaqueItem(self.clone()) } - fn specialize(&self, _: &Library, aliasee: &Specialization) -> Result, String> { - if aliasee.aliased.generics.len() != - self.generic_params.len() { - return Err("Incomplete specialization, the amount of generics in the path doesn't match the amount of generics in the item.".to_owned()); - } - - Ok(Box::new(OpaqueItem { - name: aliasee.name.clone(), - generic_params: aliasee.generic_params.clone(), - cfg: aliasee.cfg.clone(), - annotations: aliasee.annotations.clone(), - documentation: aliasee.documentation.clone(), - })) - } - fn add_dependencies(&self, _: &Library, _: &mut Dependencies) { } } diff --git a/src/bindgen/ir/specialization.rs b/src/bindgen/ir/specialization.rs deleted file mode 100644 index 3f109d2..0000000 --- a/src/bindgen/ir/specialization.rs +++ /dev/null @@ -1,143 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use syn; - -use bindgen::dependencies::Dependencies; -use bindgen::ir::{AnnotationSet, Cfg, Documentation}; -use bindgen::ir::{GenericParams, GenericPath, ItemContainer, Item, PrimitiveType}; -use bindgen::library::Library; - -/// A type alias that generates a copy of its aliasee with a new name. If the type -/// alias has generic values, it specializes its aliasee. This is useful for -/// presenting an interface that includes generic types without mangling. -#[derive(Debug, Clone)] -pub struct Specialization { - pub name: String, - pub generic_params: GenericParams, - pub aliased: GenericPath, - pub cfg: Option, - pub annotations: AnnotationSet, - pub documentation: Documentation, -} - -impl Specialization { - pub fn load(name: String, - generics: &syn::Generics, - ty: &syn::Ty, - attrs: &Vec, - mod_cfg: &Option) -> Result - { - match ty { - &syn::Ty::Path(ref _q, ref p) => { - let path = GenericPath::load(p)?; - - if PrimitiveType::maybe(&path.name).is_some() { - return Err("Definition is a primitive, which cannot be specialized.".to_owned()); - } - - Ok(Specialization { - name: name, - generic_params: GenericParams::new(generics), - aliased: path, - cfg: Cfg::append(mod_cfg, Cfg::load(attrs)), - annotations: AnnotationSet::load(attrs)?, - documentation: Documentation::load(attrs), - }) - } - _ => { - Err("Definition is not a path.".to_owned()) - } - } - } - - pub fn resolve_specialization(&self, library: &Library) -> Result, String> { - if let Some(items) = library.get_items(&self.aliased.name) { - assert!(items.len() > 0); - - if items.len() > 1 { - warn!("Specializing an aliased type with multiple definitions is possible but unsupported currently."); - } - - match items[0] { - ItemContainer::Constant(..) => { - unreachable!() - } - ItemContainer::Static(..) => { - unreachable!() - } - ItemContainer::OpaqueItem(ref aliased) => { - aliased.specialize(library, self) - } - ItemContainer::Struct(ref aliased) => { - aliased.specialize(library, self) - } - ItemContainer::Union(ref aliased) => { - aliased.specialize(library, self) - } - ItemContainer::Enum(ref aliased) => { - aliased.specialize(library, self) - } - ItemContainer::Typedef(ref aliased) => { - aliased.specialize(library, self) - } - ItemContainer::Specialization(ref aliased) => { - aliased.specialize(library, self) - } - } - } else { - Err(format!("Couldn't find aliased type {:?} for specializing.", self.aliased)) - } - } -} - -impl Item for Specialization { - fn name(&self) -> &str { - &self.name - } - - fn cfg(&self) -> &Option { - &self.cfg - } - - fn annotations(&self) -> &AnnotationSet { - &self.annotations - } - - fn annotations_mut(&mut self) -> &mut AnnotationSet { - &mut self.annotations - } - - fn container(&self) -> ItemContainer { - ItemContainer::Specialization(self.clone()) - } - - fn specialize(&self, library: &Library, aliasee: &Specialization) -> Result, String> { - if aliasee.aliased.generics.len() != - self.generic_params.len() { - return Err("Incomplete specialization, the amount of generics in the path doesn't match the amount of generics in the item.".to_owned()); - } - - let mappings = self.generic_params.iter() - .zip(aliasee.aliased.generics.iter()) - .collect::>(); - - let generics = self.aliased.generics.iter() - .map(|x| x.specialize(&mappings)) - .collect(); - - Specialization { - name: aliasee.name.clone(), - generic_params: aliasee.generic_params.clone(), - aliased: GenericPath::new(self.aliased.name.clone(), generics), - cfg: aliasee.cfg.clone(), - annotations: aliasee.annotations.clone(), - documentation: aliasee.documentation.clone(), - }.resolve_specialization(library) - } - - fn add_dependencies(&self, _: &Library, _: &mut Dependencies) { - unreachable!("Specializations must be specialized before dependency gathering."); - } -} diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index deb8c7d..80a4c23 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -8,7 +8,7 @@ use syn; use bindgen::config::{Config, Language}; use bindgen::dependencies::Dependencies; -use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, ItemContainer, Item, Repr, Specialization, Type}; +use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, ItemContainer, Item, Repr, Type}; use bindgen::library::Library; use bindgen::mangle; use bindgen::monomorph::Monomorphs; @@ -184,29 +184,6 @@ impl Item for Struct { out.insert_struct(self, monomorph, generic_values.clone()); } - - fn specialize(&self, _: &Library, aliasee: &Specialization) -> Result, String> { - if aliasee.aliased.generics.len() != - self.generic_params.len() { - return Err("Incomplete specialization, the amount of generics in the path doesn't match the amount of generics in the item.".to_owned()); - } - - let mappings = self.generic_params.iter() - .zip(aliasee.aliased.generics.iter()) - .collect::>(); - - Ok(Box::new(Struct { - name: aliasee.name.clone(), - generic_params: aliasee.generic_params.clone(), - fields: self.fields.iter() - .map(|x| (x.0.clone(), x.1.specialize(&mappings), x.2.clone())) - .collect(), - tuple_struct: self.tuple_struct, - cfg: aliasee.cfg.clone(), - annotations: aliasee.annotations.clone(), - documentation: aliasee.documentation.clone(), - })) - } } impl Source for Struct { diff --git a/src/bindgen/ir/ty.rs b/src/bindgen/ir/ty.rs index 82b6c4d..c42b7f9 100644 --- a/src/bindgen/ir/ty.rs +++ b/src/bindgen/ir/ty.rs @@ -438,11 +438,8 @@ impl Type { ItemContainer::Enum(..) => { warn!("Cannot instantiate a generic enum.") }, - ItemContainer::Typedef(..) => { - warn!("Cannot instantiate a generic typedef.") - }, - ItemContainer::Specialization(..) => { - warn!("Cannot instantiate a generic specialization.") + ItemContainer::Typedef(ref x) => { + x.instantiate_monomorph(&path.generics, library, out); }, } } diff --git a/src/bindgen/ir/typedef.rs b/src/bindgen/ir/typedef.rs index 5439f9a..bce6bf9 100644 --- a/src/bindgen/ir/typedef.rs +++ b/src/bindgen/ir/typedef.rs @@ -7,10 +7,11 @@ use std::io::Write; use syn; -use bindgen::config::Config; +use bindgen::config::{Config, Language}; use bindgen::dependencies::Dependencies; -use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, ItemContainer, Item, Path, Specialization, Type}; +use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, ItemContainer, Item, Path, Type}; use bindgen::library::Library; +use bindgen::mangle; use bindgen::monomorph::Monomorphs; use bindgen::writer::{Source, SourceWriter}; @@ -18,6 +19,7 @@ use bindgen::writer::{Source, SourceWriter}; #[derive(Debug, Clone)] pub struct Typedef { pub name: String, + pub generic_params: GenericParams, pub aliased: Type, pub cfg: Option, pub annotations: AnnotationSet, @@ -27,11 +29,13 @@ pub struct Typedef { impl Typedef { pub fn load(name: String, ty: &syn::Ty, + generics: &syn::Generics, attrs: &Vec, mod_cfg: &Option) -> Result { if let Some(x) = Type::load(ty)? { Ok(Typedef { name: name, + generic_params: GenericParams::new(generics), aliased: x, cfg: Cfg::append(mod_cfg, Cfg::load(attrs)), annotations: AnnotationSet::load(attrs)?, @@ -66,7 +70,17 @@ impl Typedef { } } + pub fn is_generic(&self) -> bool { + self.generic_params.len() > 0 + } + pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) { + // Generic structs can instantiate monomorphs only once they've been + // instantiated. See `instantiate_monomorph` for more details. + if self.is_generic() { + return; + } + self.aliased.add_monomorphs(library, out); } @@ -96,18 +110,31 @@ impl Item for Typedef { ItemContainer::Typedef(self.clone()) } - fn specialize(&self, _: &Library, aliasee: &Specialization) -> Result, String> { - Ok(Box::new(Typedef { - name: aliasee.name.clone(), - aliased: self.aliased.clone(), - cfg: aliasee.cfg.clone(), - annotations: aliasee.annotations.clone(), - documentation: aliasee.documentation.clone(), - })) + fn add_dependencies(&self, library: &Library, out: &mut Dependencies) { + self.aliased.add_dependencies_ignoring_generics(&self.generic_params, library, out); } - fn add_dependencies(&self, library: &Library, out: &mut Dependencies) { - self.aliased.add_dependencies(library, out); + fn instantiate_monomorph(&self, generic_values: &Vec, library: &Library, out: &mut Monomorphs) { + assert!(self.generic_params.len() > 0 && + self.generic_params.len() == generic_values.len()); + + let mappings = self.generic_params.iter() + .zip(generic_values.iter()) + .collect::>(); + + let monomorph = Typedef { + name: mangle::mangle_path(&self.name, generic_values), + generic_params: GenericParams::default(), + aliased: self.aliased.specialize(&mappings), + cfg: self.cfg.clone(), + annotations: self.annotations.clone(), + documentation: self.documentation.clone(), + }; + + // Instantiate any monomorphs for any generic paths we may have just created. + monomorph.add_monomorphs(library, out); + + out.insert_typedef(self, monomorph, generic_values.clone()); } } @@ -117,8 +144,15 @@ impl Source for Typedef { self.documentation.write(config, out); - out.write("typedef "); - (self.name.clone(), self.aliased.clone()).write(config, out); + self.generic_params.write(config, out); + + if config.language == Language::C { + out.write("typedef "); + (self.name.clone(), self.aliased.clone()).write(config, out); + } else { + write!(out, "using {} = ", self.name); + self.aliased.write(config, out); + } out.write(";"); self.cfg.write_after(config, out); diff --git a/src/bindgen/ir/union.rs b/src/bindgen/ir/union.rs index 1429ea7..8de076a 100644 --- a/src/bindgen/ir/union.rs +++ b/src/bindgen/ir/union.rs @@ -8,7 +8,7 @@ use syn; use bindgen::config::{Config, Language}; use bindgen::dependencies::Dependencies; -use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, ItemContainer, Item, Repr, Specialization, Type}; +use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, ItemContainer, Item, Repr, Type}; use bindgen::ir::SynFieldHelpers; use bindgen::library::Library; use bindgen::mangle; @@ -185,29 +185,6 @@ impl Item for Union { out.insert_union(self, monomorph, generic_values.clone()); } - - fn specialize(&self, _: &Library, aliasee: &Specialization) -> Result, String> { - if aliasee.aliased.generics.len() != - self.generic_params.len() { - return Err("Incomplete specialization, the amount of generics in the path doesn't match the amount of generics in the item.".to_owned()); - } - - let mappings = self.generic_params.iter() - .zip(aliasee.aliased.generics.iter()) - .collect::>(); - - Ok(Box::new(Union { - name: aliasee.name.clone(), - generic_params: aliasee.generic_params.clone(), - fields: self.fields.iter() - .map(|x| (x.0.clone(), x.1.specialize(&mappings), x.2.clone())) - .collect(), - tuple_union: self.tuple_union, - cfg: aliasee.cfg.clone(), - annotations: aliasee.annotations.clone(), - documentation: aliasee.documentation.clone(), - })) - } } impl Source for Union { diff --git a/src/bindgen/library.rs b/src/bindgen/library.rs index af534ea..cb1fdcf 100644 --- a/src/bindgen/library.rs +++ b/src/bindgen/library.rs @@ -9,7 +9,7 @@ use bindgen::bindings::Bindings; use bindgen::config::{Config, Language}; use bindgen::dependencies::Dependencies; use bindgen::ir::{Constant, Enum, Function, ItemContainer, ItemMap, Item}; -use bindgen::ir::{OpaqueItem, Path, Specialization, Static, Struct, Typedef, Union}; +use bindgen::ir::{OpaqueItem, Path, Static, Struct, Typedef, Union}; use bindgen::monomorph::Monomorphs; #[derive(Debug, Clone)] @@ -22,7 +22,6 @@ pub struct Library { unions: ItemMap, opaque_items: ItemMap, typedefs: ItemMap, - specializations: ItemMap, functions: Vec, } @@ -35,7 +34,6 @@ impl Library { unions: ItemMap, opaque_items: ItemMap, typedefs: ItemMap, - specializations: ItemMap, functions: Vec) -> Library { Library { config: config, @@ -46,7 +44,6 @@ impl Library { unions: unions, opaque_items: opaque_items, typedefs: typedefs, - specializations: specializations, functions: functions, } } @@ -56,7 +53,6 @@ impl Library { self.transfer_annotations(); self.rename_items(); - self.specialize_items(); self.simplify_option_to_ptr(); if self.config.language == Language::C { @@ -102,42 +98,10 @@ impl Library { if let Some(x) = self.typedefs.get_items(p) { return Some(x); } - if let Some(x) = self.specializations.get_items(p) { - return Some(x); - } None } - fn insert_item(&mut self, item: ItemContainer) { - match item { - ItemContainer::Constant(x) => { - self.constants.try_insert(x); - }, - ItemContainer::Static(x) => { - self.globals.try_insert(x); - }, - ItemContainer::OpaqueItem(x) => { - self.opaque_items.try_insert(x); - }, - ItemContainer::Struct(x) => { - self.structs.try_insert(x); - }, - ItemContainer::Union(x) => { - self.unions.try_insert(x); - }, - ItemContainer::Enum(x) => { - self.enums.try_insert(x); - }, - ItemContainer::Typedef(x) => { - self.typedefs.try_insert(x); - }, - ItemContainer::Specialization(x) => { - self.specializations.try_insert(x); - }, - }; - } - fn transfer_annotations(&mut self) { let mut annotations = HashMap::new(); @@ -197,18 +161,6 @@ impl Library { if transferred { continue; } - self.specializations.for_items_mut(&alias_path, |x| { - if x.annotations().is_empty() { - *x.annotations_mut() = annotations.clone(); - transferred = true; - } else { - warn!("Can't transfer annotations from typedef to alias ({}) that already has annotations.", - alias_path); - } - }); - if transferred { - continue; - } self.typedefs.for_items_mut(&alias_path, |x| { if x.annotations().is_empty() { *x.annotations_mut() = annotations.clone(); @@ -235,27 +187,6 @@ impl Library { } } - fn specialize_items(&mut self) { - let mut specializations = Vec::new(); - - self.specializations.for_all_items(|x| { - match x.resolve_specialization(&self) { - Ok(specialization) => { - specializations.push(specialization); - } - Err(msg) => { - warn!("Specializing {} failed - ({}).", x.name.clone(), msg); - } - } - }); - - for specialization in specializations { - self.insert_item(specialization.container()); - } - - self.specializations.clear(); - } - fn simplify_option_to_ptr(&mut self) { self.structs.for_all_items_mut(|x| { x.simplify_option_to_ptr(); @@ -275,10 +206,8 @@ impl Library { } fn instantiate_monomorphs(&mut self) { - assert!(self.specializations.len() == 0); - // Collect a list of monomorphs - let mut monomorphs = Monomorphs::new(); + let mut monomorphs = Monomorphs::default(); self.structs.for_all_items(|x| { x.add_monomorphs(self, &mut monomorphs); @@ -303,11 +232,15 @@ impl Library { for monomorph in monomorphs.drain_opaques() { self.opaque_items.try_insert(monomorph); } + for monomorph in monomorphs.drain_typedefs() { + self.typedefs.try_insert(monomorph); + } // Remove structs and opaque items that are generic self.opaque_items.filter(|x| x.generic_params.len() > 0); self.structs.filter(|x| x.generic_params.len() > 0); self.unions.filter(|x| x.generic_params.len() > 0); + self.typedefs.filter(|x| x.generic_params.len() > 0); // Mangle the paths that remain self.unions.for_all_items_mut(|x| x.mangle_paths(&monomorphs)); diff --git a/src/bindgen/monomorph.rs b/src/bindgen/monomorph.rs index ea70009..f6225da 100644 --- a/src/bindgen/monomorph.rs +++ b/src/bindgen/monomorph.rs @@ -5,26 +5,18 @@ use std::collections::HashMap; use std::mem; -use bindgen::ir::{GenericPath, OpaqueItem, Path, Struct, Type, Union}; +use bindgen::ir::{GenericPath, OpaqueItem, Path, Struct, Type, Typedef, Union}; -#[derive(Clone, Debug)] +#[derive(Default, Clone, Debug)] pub struct Monomorphs { replacements: HashMap, opaques: Vec, structs: Vec, unions: Vec, + typedefs: Vec, } impl Monomorphs { - pub fn new() -> Monomorphs { - Monomorphs { - replacements: HashMap::new(), - opaques: Vec::new(), - structs: Vec::new(), - unions: Vec::new(), - } - } - pub fn contains(&self, path: &GenericPath) -> bool { self.replacements.contains_key(path) } @@ -68,6 +60,19 @@ impl Monomorphs { self.opaques.push(monomorph); } + pub fn insert_typedef(&mut self, + generic: &Typedef, + monomorph: Typedef, + parameters: Vec) { + let replacement_path = GenericPath::new(generic.name.clone(), parameters); + + debug_assert!(generic.generic_params.len() > 0); + debug_assert!(!self.contains(&replacement_path)); + + self.replacements.insert(replacement_path, monomorph.name.clone()); + self.typedefs.push(monomorph); + } + pub fn mangle_path(&self, path: &GenericPath) -> Option<&Path> { self.replacements.get(path) } @@ -83,4 +88,8 @@ impl Monomorphs { pub fn drain_unions(&mut self) -> Vec { mem::replace(&mut self.unions, Vec::new()) } + + pub fn drain_typedefs(&mut self) -> Vec { + mem::replace(&mut self.typedefs, Vec::new()) + } } diff --git a/src/bindgen/parser.rs b/src/bindgen/parser.rs index 93e4451..1e83af3 100644 --- a/src/bindgen/parser.rs +++ b/src/bindgen/parser.rs @@ -11,7 +11,7 @@ use syn; use bindgen::cargo::{Cargo, PackageRef}; use bindgen::ir::{AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParams}; -use bindgen::ir::{ItemMap, OpaqueItem, Specialization, Static, Struct, Typedef, Union}; +use bindgen::ir::{ItemMap, OpaqueItem, Static, Struct, Typedef, Union}; use bindgen::utilities::{SynAbiHelpers, SynItemHelpers}; const STD_CRATES: &'static [&'static str] = &["std", @@ -348,7 +348,6 @@ pub struct Parse { pub unions: ItemMap, pub opaque_items: ItemMap, pub typedefs: ItemMap, - pub specializations: ItemMap, pub functions: Vec, } @@ -362,7 +361,6 @@ impl Parse { unions: ItemMap::new(), opaque_items: ItemMap::new(), typedefs: ItemMap::new(), - specializations: ItemMap::new(), functions: Vec::new(), } } @@ -405,7 +403,6 @@ impl Parse { self.unions.extend_with(&other.unions); self.opaque_items.extend_with(&other.opaque_items); self.typedefs.extend_with(&other.typedefs); - self.specializations.extend_with(&other.specializations); self.functions.extend_from_slice(&other.functions); } @@ -742,42 +739,26 @@ impl Parse { generics: &syn::Generics) { let alias_name = item.ident.to_string(); - let fail1 = if generics.lifetimes.is_empty() && - generics.ty_params.is_empty() - { - match Typedef::load(alias_name.clone(), - ty, - &item.attrs, - mod_cfg) - { - Ok(typedef) => { - info!("Take {}::{}.", crate_name, &item.ident); - self.typedefs.try_insert(typedef); - return; - } - Err(msg) => msg, - } - } else { - format!("Cannot have generics in typedef.") - }; - - let fail2 = match Specialization::load(alias_name.clone(), - generics, - ty, - &item.attrs, - mod_cfg) { - Ok(spec) => { + match Typedef::load(alias_name.clone(), + ty, + generics, + &item.attrs, + mod_cfg) { + Ok(st) => { info!("Take {}::{}.", crate_name, &item.ident); - self.specializations.try_insert(spec); - return; - } - Err(msg) => msg, - }; - info!("Skip {}::{} - ({} and {}).", - crate_name, - &item.ident, - fail1, - fail2); + self.typedefs.try_insert(st); + } + Err(msg) => { + info!("Take {}::{} - opaque ({}).", + crate_name, + &item.ident, + msg); + self.opaque_items.try_insert(OpaqueItem::new(alias_name, + generics, + &item.attrs, + mod_cfg)); + } + } } } diff --git a/tests/expectations/alias.cpp b/tests/expectations/alias.cpp index d770f0c..a9ee951 100644 --- a/tests/expectations/alias.cpp +++ b/tests/expectations/alias.cpp @@ -18,13 +18,13 @@ struct Foo { Dep c; }; -typedef Foo IntFoo; +using IntFoo = Foo; -typedef Foo DoubleFoo; +using DoubleFoo = Foo; -typedef int32_t Unit; +using Unit = int32_t; -typedef Status SpecialStatus; +using SpecialStatus = Status; extern "C" { diff --git a/tests/expectations/cdecl.cpp b/tests/expectations/cdecl.cpp index dd8c421..6419078 100644 --- a/tests/expectations/cdecl.cpp +++ b/tests/expectations/cdecl.cpp @@ -1,33 +1,33 @@ #include #include -typedef void (*A)(); +using A = void(*)(); -typedef void (*B)(); +using B = void(*)(); -typedef bool (*C)(int32_t, int32_t); +using C = bool(*)(int32_t, int32_t); -typedef bool (*(*D)(int32_t))(float); +using D = bool(*(*)(int32_t))(float); -typedef int32_t (*(*E)())[16]; +using E = int32_t(*(*)())[16]; -typedef const int32_t *F; +using F = const int32_t*; -typedef const int32_t *const *G; +using G = const int32_t*const *; -typedef int32_t *const *H; +using H = int32_t*const *; -typedef int32_t (*I)[16]; +using I = int32_t(*)[16]; -typedef double (**J)(float); +using J = double(**)(float); -typedef int32_t K[16]; +using K = int32_t[16]; -typedef const int32_t *L[16]; +using L = const int32_t*[16]; -typedef bool (*M[16])(int32_t, int32_t); +using M = bool(*[16])(int32_t, int32_t); -typedef void (*N[16])(int32_t, int32_t); +using N = void(*[16])(int32_t, int32_t); extern "C" { diff --git a/tests/expectations/euclid.c b/tests/expectations/euclid.c index 1a79e4a..ee1cc35 100644 --- a/tests/expectations/euclid.c +++ b/tests/expectations/euclid.c @@ -10,9 +10,7 @@ typedef struct { float _0; } TypedLength_f32__LayoutUnit; -typedef struct { - float _0; -} Length_f32; +typedef TypedLength_f32__UnknownUnit Length_f32; typedef TypedLength_f32__LayoutUnit LayoutLength; @@ -30,12 +28,7 @@ typedef struct { float left; } TypedSideOffsets2D_f32__LayoutUnit; -typedef struct { - float top; - float right; - float bottom; - float left; -} SideOffsets2D_f32; +typedef TypedSideOffsets2D_f32__UnknownUnit SideOffsets2D_f32; typedef TypedSideOffsets2D_f32__LayoutUnit LayoutSideOffsets2D; @@ -49,10 +42,7 @@ typedef struct { float height; } TypedSize2D_f32__LayoutUnit; -typedef struct { - float width; - float height; -} Size2D_f32; +typedef TypedSize2D_f32__UnknownUnit Size2D_f32; typedef TypedSize2D_f32__LayoutUnit LayoutSize2D; @@ -66,10 +56,7 @@ typedef struct { float y; } TypedPoint2D_f32__LayoutUnit; -typedef struct { - float x; - float y; -} Point2D_f32; +typedef TypedPoint2D_f32__UnknownUnit Point2D_f32; typedef TypedPoint2D_f32__LayoutUnit LayoutPoint2D; @@ -83,10 +70,7 @@ typedef struct { TypedSize2D_f32__LayoutUnit size; } TypedRect_f32__LayoutUnit; -typedef struct { - TypedPoint2D_f32__UnknownUnit origin; - TypedSize2D_f32__UnknownUnit size; -} Rect_f32; +typedef TypedRect_f32__UnknownUnit Rect_f32; typedef TypedRect_f32__LayoutUnit LayoutRect; diff --git a/tests/expectations/euclid.cpp b/tests/expectations/euclid.cpp index 7fd0d9a..bb7b53d 100644 --- a/tests/expectations/euclid.cpp +++ b/tests/expectations/euclid.cpp @@ -11,11 +11,9 @@ struct TypedLength { }; template -struct Length { - T _0; -}; +using Length = TypedLength; -typedef TypedLength LayoutLength; +using LayoutLength = TypedLength; template struct TypedSideOffsets2D { @@ -26,14 +24,9 @@ struct TypedSideOffsets2D { }; template -struct SideOffsets2D { - T top; - T right; - T bottom; - T left; -}; +using SideOffsets2D = TypedSideOffsets2D; -typedef TypedSideOffsets2D LayoutSideOffsets2D; +using LayoutSideOffsets2D = TypedSideOffsets2D; template struct TypedSize2D { @@ -42,12 +35,9 @@ struct TypedSize2D { }; template -struct Size2D { - T width; - T height; -}; +using Size2D = TypedSize2D; -typedef TypedSize2D LayoutSize2D; +using LayoutSize2D = TypedSize2D; template struct TypedPoint2D { @@ -56,12 +46,9 @@ struct TypedPoint2D { }; template -struct Point2D { - T x; - T y; -}; +using Point2D = TypedPoint2D; -typedef TypedPoint2D LayoutPoint2D; +using LayoutPoint2D = TypedPoint2D; template struct TypedRect { @@ -70,12 +57,9 @@ struct TypedRect { }; template -struct Rect { - TypedPoint2D origin; - TypedSize2D size; -}; +using Rect = TypedRect; -typedef TypedRect LayoutRect; +using LayoutRect = TypedRect; template struct TypedTransform2D { diff --git a/tests/expectations/monomorph-1.c b/tests/expectations/monomorph-1.c index 4d3cef6..ec54c94 100644 --- a/tests/expectations/monomorph-1.c +++ b/tests/expectations/monomorph-1.c @@ -28,7 +28,9 @@ typedef struct { typedef struct { const float *a; const float *b; -} Indirection_f32; +} Tuple_f32__f32; + +typedef Tuple_f32__f32 Indirection_f32; void root(Foo_i32 a, Foo_f32 b, diff --git a/tests/expectations/monomorph-1.cpp b/tests/expectations/monomorph-1.cpp index ef1c47e..454a08a 100644 --- a/tests/expectations/monomorph-1.cpp +++ b/tests/expectations/monomorph-1.cpp @@ -16,10 +16,7 @@ struct Tuple { }; template -struct Indirection { - const T *a; - const float *b; -}; +using Indirection = Tuple; extern "C" { diff --git a/tests/expectations/monomorph-3.c b/tests/expectations/monomorph-3.c index 04a9ab3..aba9214 100644 --- a/tests/expectations/monomorph-3.c +++ b/tests/expectations/monomorph-3.c @@ -28,7 +28,9 @@ typedef union { typedef union { const float *a; const float *b; -} Indirection_f32; +} Tuple_f32__f32; + +typedef Tuple_f32__f32 Indirection_f32; void root(Foo_i32 a, Foo_f32 b, diff --git a/tests/expectations/monomorph-3.cpp b/tests/expectations/monomorph-3.cpp index 3a2060d..f1c9a8a 100644 --- a/tests/expectations/monomorph-3.cpp +++ b/tests/expectations/monomorph-3.cpp @@ -16,10 +16,7 @@ union Tuple { }; template -union Indirection { - const T *a; - const float *b; -}; +using Indirection = Tuple; extern "C" { diff --git a/tests/expectations/typedef.c b/tests/expectations/typedef.c index 1e2dbf9..4cb83af 100644 --- a/tests/expectations/typedef.c +++ b/tests/expectations/typedef.c @@ -5,6 +5,8 @@ typedef struct { int32_t x; int32_t y; -} IntFoo_i32; +} Foo_i32__i32; + +typedef Foo_i32__i32 IntFoo_i32; void root(IntFoo_i32 a); diff --git a/tests/expectations/typedef.cpp b/tests/expectations/typedef.cpp index 3e54bf7..bdd2977 100644 --- a/tests/expectations/typedef.cpp +++ b/tests/expectations/typedef.cpp @@ -1,12 +1,15 @@ #include #include -template -struct IntFoo { - int32_t x; - T y; +template +struct Foo { + T x; + U y; }; +template +using IntFoo = Foo; + extern "C" { void root(IntFoo a);