Version in base suite: 0.23.0-1~deb11u1 Base version: rust-cbindgen_0.23.0-1~deb11u1 Target version: rust-cbindgen_0.24.3-2~deb11u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/r/rust-cbindgen/rust-cbindgen_0.23.0-1~deb11u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/r/rust-cbindgen/rust-cbindgen_0.24.3-2~deb11u1.dsc .cargo_vcs_info.json | 2 CHANGES | 18 +++ Cargo.lock | 2 Cargo.toml | 3 Cargo.toml.orig | 2 debian/changelog | 25 ++-- debian/control | 15 +- debian/patches/relax-dep.diff | 13 ++ debian/patches/series | 1 debian/tests/control | 16 +- src/bindgen/bindings.rs | 37 ++++++ src/bindgen/cdecl.rs | 6 - src/bindgen/ir/constant.rs | 24 +++- src/bindgen/ir/enumeration.rs | 36 +----- src/bindgen/ir/generic_path.rs | 184 +++++++++++++++++++++++++++++----- src/bindgen/ir/item.rs | 10 + src/bindgen/ir/opaque.rs | 8 - src/bindgen/ir/structure.rs | 71 ++++++------- src/bindgen/ir/ty.rs | 131 ++++++++++++++++-------- src/bindgen/ir/typedef.rs | 27 ---- src/bindgen/ir/union.rs | 27 ---- src/bindgen/library.rs | 2 src/bindgen/mangle.rs | 87 +++++++++++++--- src/bindgen/monomorph.rs | 24 ++-- src/bindgen/parser.rs | 9 + tests/rust/bitflags.rs | 12 ++ tests/rust/const_generics.rs | 15 ++ tests/rust/const_generics_arrayvec.rs | 17 +++ tests/rust/const_generics_bool.rs | 57 ++++++++++ tests/rust/const_generics_byte.rs | 29 +++++ tests/rust/const_generics_char.rs | 20 +++ tests/rust/const_generics_constant.rs | 18 +++ tests/rust/const_generics_thru.rs | 22 ++++ 33 files changed, 719 insertions(+), 251 deletions(-) diff -Nru rust-cbindgen-0.23.0/.cargo_vcs_info.json rust-cbindgen-0.24.3/.cargo_vcs_info.json --- rust-cbindgen-0.23.0/.cargo_vcs_info.json 1970-01-01 00:00:01.000000000 +0000 +++ rust-cbindgen-0.24.3/.cargo_vcs_info.json 1970-01-01 00:00:01.000000000 +0000 @@ -1,6 +1,6 @@ { "git": { - "sha1": "798cfab52bced65a749443faa16990ec3a8e0cfe" + "sha1": "f43ccfc047a1a160267f32355c5e5e7154a2665a" }, "path_in_vcs": "" } \ No newline at end of file diff -Nru rust-cbindgen-0.23.0/CHANGES rust-cbindgen-0.24.3/CHANGES --- rust-cbindgen-0.23.0/CHANGES 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/CHANGES 1973-11-29 21:33:09.000000000 +0000 @@ -1,3 +1,21 @@ +## 0.24.3 + + * Make struct expressions correctly generated through typedefs (#768). + +## 0.24.2 + + * Make bitfield operators use explicit constructors. + +## 0.24.1 + + * Add support for unary negation (#765). + * Make more bitfield operators constexpr (#765). + +## 0.24.0 + + * Basic const generic support (#759, #760 #762). + * Suffixes on integer literals are now honored to avoid narrowing (#764). + ## 0.23.0 * Better support for constexpr. (#756) diff -Nru rust-cbindgen-0.23.0/Cargo.lock rust-cbindgen-0.24.3/Cargo.lock --- rust-cbindgen-0.23.0/Cargo.lock 1970-01-01 00:00:01.000000000 +0000 +++ rust-cbindgen-0.24.3/Cargo.lock 1970-01-01 00:00:01.000000000 +0000 @@ -27,7 +27,7 @@ [[package]] name = "cbindgen" -version = "0.23.0" +version = "0.24.3" dependencies = [ "clap", "heck", diff -Nru rust-cbindgen-0.23.0/Cargo.toml rust-cbindgen-0.24.3/Cargo.toml --- rust-cbindgen-0.23.0/Cargo.toml 1970-01-01 00:00:01.000000000 +0000 +++ rust-cbindgen-0.24.3/Cargo.toml 1970-01-01 00:00:01.000000000 +0000 @@ -12,7 +12,7 @@ [package] edition = "2018" name = "cbindgen" -version = "0.23.0" +version = "0.24.3" authors = [ "Emilio Cobos Álvarez ", "Jeff Muizelaar ", @@ -21,6 +21,7 @@ ] exclude = ["tests/profile.rs"] description = "A tool for generating C bindings to Rust code." +readme = "README.md" keywords = [ "bindings", "ffi", diff -Nru rust-cbindgen-0.23.0/Cargo.toml.orig rust-cbindgen-0.24.3/Cargo.toml.orig --- rust-cbindgen-0.23.0/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 @@ -1,6 +1,6 @@ [package] name = "cbindgen" -version = "0.23.0" +version = "0.24.3" authors = [ "Emilio Cobos Álvarez ", "Jeff Muizelaar ", diff -Nru rust-cbindgen-0.23.0/debian/changelog rust-cbindgen-0.24.3/debian/changelog --- rust-cbindgen-0.23.0/debian/changelog 2022-07-04 08:53:21.000000000 +0000 +++ rust-cbindgen-0.24.3/debian/changelog 2023-07-28 12:16:44.000000000 +0000 @@ -1,4 +1,4 @@ -rust-cbindgen (0.23.0-1~deb11u1) bullseye; urgency=medium +rust-cbindgen (0.24.3-2~deb11u1) bullseye; urgency=medium * Non-maintainer upload. * Backport to bullseye. @@ -7,26 +7,27 @@ * Lower dh-cargo build-dep. * Build with rust-mozilla. - -- Emilio Pozuelo Monfort Mon, 04 Jul 2022 10:53:21 +0200 + -- Emilio Pozuelo Monfort Fri, 28 Jul 2023 14:16:44 +0200 -rust-cbindgen (0.23.0-1) unstable; urgency=medium +rust-cbindgen (0.24.3-2) unstable; urgency=medium - * Package cbindgen 0.23.0 from crates.io using debcargo 2.5.0 + * Team upload. + * Package cbindgen 0.24.3 from crates.io using debcargo 2.6.0 + * Relax dev-dependency on serial-test. - -- Sylvestre Ledru Fri, 03 Jun 2022 11:20:37 +0200 + -- Peter Michael Green Thu, 17 Nov 2022 20:11:36 +0000 -rust-cbindgen (0.20.0-1~deb11u1) bullseye; urgency=medium +rust-cbindgen (0.24.3-1) unstable; urgency=medium - * Non-maintainer upload. - * Backport to bullseye. + * Package cbindgen 0.24.3 from crates.io using debcargo 2.5.0 - -- Emilio Pozuelo Monfort Thu, 02 Dec 2021 12:49:31 +0100 + -- Sylvestre Ledru Sat, 25 Jun 2022 15:27:28 +0200 -rust-cbindgen (0.20.0-1) unstable; urgency=medium +rust-cbindgen (0.23.0-1) unstable; urgency=medium - * Package cbindgen 0.20.0 from crates.io using debcargo 2.4.4-alpha.0 + * Package cbindgen 0.23.0 from crates.io using debcargo 2.5.0 - -- Sylvestre Ledru Sun, 22 Aug 2021 14:26:42 +0200 + -- Sylvestre Ledru Fri, 03 Jun 2022 11:20:37 +0200 rust-cbindgen (0.19.0-1) experimental; urgency=medium diff -Nru rust-cbindgen-0.23.0/debian/control rust-cbindgen-0.24.3/debian/control --- rust-cbindgen-0.23.0/debian/control 2022-06-17 11:33:38.000000000 +0000 +++ rust-cbindgen-0.24.3/debian/control 2023-07-28 12:16:44.000000000 +0000 @@ -27,9 +27,10 @@ Maintainer: Debian Rust Maintainers Uploaders: Sylvestre Ledru -Standards-Version: 4.5.1 +Standards-Version: 4.6.1 Vcs-Git: https://salsa.debian.org/rust-team/debcargo-conf.git [src/cbindgen] Vcs-Browser: https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/cbindgen +X-Cargo-Crate: cbindgen Rules-Requires-Root: no #Package: librust-cbindgen-dev @@ -55,8 +56,8 @@ # librust-cbindgen+clap-dev (= ${binary:Version}) #Provides: # librust-cbindgen-0-dev (= ${binary:Version}), -# librust-cbindgen-0.23-dev (= ${binary:Version}), -# librust-cbindgen-0.23.0-dev (= ${binary:Version}) +# librust-cbindgen-0.24-dev (= ${binary:Version}), +# librust-cbindgen-0.24.3-dev (= ${binary:Version}) #Description: Generating C bindings to Rust code - Rust source code # This package contains the source for the Rust cbindgen crate, packaged by # debcargo for use with cargo and dh-cargo. @@ -72,10 +73,10 @@ # librust-cbindgen+default-dev (= ${binary:Version}), # librust-cbindgen-0+clap-dev (= ${binary:Version}), # librust-cbindgen-0+default-dev (= ${binary:Version}), -# librust-cbindgen-0.23+clap-dev (= ${binary:Version}), -# librust-cbindgen-0.23+default-dev (= ${binary:Version}), -# librust-cbindgen-0.23.0+clap-dev (= ${binary:Version}), -# librust-cbindgen-0.23.0+default-dev (= ${binary:Version}) +# librust-cbindgen-0.24+clap-dev (= ${binary:Version}), +# librust-cbindgen-0.24+default-dev (= ${binary:Version}), +# librust-cbindgen-0.24.3+clap-dev (= ${binary:Version}), +# librust-cbindgen-0.24.3+default-dev (= ${binary:Version}) #Description: Generating C bindings to Rust code - feature "clap" and 1 more # This metapackage enables feature "clap" for the Rust cbindgen crate, by pulling # in any additional dependencies needed by that feature. diff -Nru rust-cbindgen-0.23.0/debian/patches/relax-dep.diff rust-cbindgen-0.24.3/debian/patches/relax-dep.diff --- rust-cbindgen-0.23.0/debian/patches/relax-dep.diff 1970-01-01 00:00:00.000000000 +0000 +++ rust-cbindgen-0.24.3/debian/patches/relax-dep.diff 2022-11-17 20:11:36.000000000 +0000 @@ -0,0 +1,13 @@ +Index: cbindgen/Cargo.toml +=================================================================== +--- cbindgen.orig/Cargo.toml ++++ cbindgen/Cargo.toml +@@ -89,7 +89,7 @@ version = "3.0" + version = "0.5" + + [dev-dependencies.serial_test] +-version = "0.5.0" ++version = ">= 0.5.0, < 0.10" + + [features] + default = ["clap"] diff -Nru rust-cbindgen-0.23.0/debian/patches/series rust-cbindgen-0.24.3/debian/patches/series --- rust-cbindgen-0.23.0/debian/patches/series 2022-06-17 11:21:49.000000000 +0000 +++ rust-cbindgen-0.24.3/debian/patches/series 2023-07-28 12:16:44.000000000 +0000 @@ -1,3 +1,4 @@ use-cython3-for-tests.patch use-tmpdir-for-tests.patch +relax-dep.diff vendor-deps-config.patch diff -Nru rust-cbindgen-0.23.0/debian/tests/control rust-cbindgen-0.24.3/debian/tests/control --- rust-cbindgen-0.23.0/debian/tests/control 2022-06-03 09:20:37.000000000 +0000 +++ rust-cbindgen-0.24.3/debian/tests/control 2022-11-17 20:11:36.000000000 +0000 @@ -1,19 +1,19 @@ -Test-Command: /usr/share/cargo/bin/cargo-auto-test cbindgen 0.23.0 --all-targets --all-features +Test-Command: /usr/share/cargo/bin/cargo-auto-test cbindgen 0.24.3 --all-targets --all-features Features: test-name=rust-cbindgen:@ -Depends: dh-cargo (>= 18), gcc, g++, cython3, librust-serial-test-0.5+default-dev, @ +Depends: dh-cargo (>= 18), gcc, g++, cython3, librust-serial-test-0.9+default-dev | librust-serial-test-0.8+default-dev | librust-serial-test-0.7+default-dev | librust-serial-test-0.6+default-dev | librust-serial-test-0.5+default-dev, @ Restrictions: allow-stderr, skip-not-installable, flaky -Test-Command: /usr/share/cargo/bin/cargo-auto-test cbindgen 0.23.0 --all-targets --no-default-features +Test-Command: /usr/share/cargo/bin/cargo-auto-test cbindgen 0.24.3 --all-targets --no-default-features Features: test-name=librust-cbindgen-dev: -Depends: dh-cargo (>= 18), gcc, g++, cython3, librust-serial-test-0.5+default-dev, @ +Depends: dh-cargo (>= 18), gcc, g++, cython3, librust-serial-test-0.9+default-dev | librust-serial-test-0.8+default-dev | librust-serial-test-0.7+default-dev | librust-serial-test-0.6+default-dev | librust-serial-test-0.5+default-dev, @ Restrictions: allow-stderr, skip-not-installable, flaky -Test-Command: /usr/share/cargo/bin/cargo-auto-test cbindgen 0.23.0 --all-targets +Test-Command: /usr/share/cargo/bin/cargo-auto-test cbindgen 0.24.3 --all-targets Features: test-name=librust-cbindgen+clap-dev:default -Depends: dh-cargo (>= 18), gcc, g++, cython3, librust-serial-test-0.5+default-dev, @ +Depends: dh-cargo (>= 18), gcc, g++, cython3, librust-serial-test-0.9+default-dev | librust-serial-test-0.8+default-dev | librust-serial-test-0.7+default-dev | librust-serial-test-0.6+default-dev | librust-serial-test-0.5+default-dev, @ Restrictions: allow-stderr, skip-not-installable -Test-Command: /usr/share/cargo/bin/cargo-auto-test cbindgen 0.23.0 --all-targets --no-default-features --features clap +Test-Command: /usr/share/cargo/bin/cargo-auto-test cbindgen 0.24.3 --all-targets --no-default-features --features clap Features: test-name=librust-cbindgen+clap-dev:clap -Depends: dh-cargo (>= 18), gcc, g++, cython3, librust-serial-test-0.5+default-dev, @ +Depends: dh-cargo (>= 18), gcc, g++, cython3, librust-serial-test-0.9+default-dev | librust-serial-test-0.8+default-dev | librust-serial-test-0.7+default-dev | librust-serial-test-0.6+default-dev | librust-serial-test-0.5+default-dev, @ Restrictions: allow-stderr, skip-not-installable diff -Nru rust-cbindgen-0.23.0/src/bindgen/bindings.rs rust-cbindgen-0.24.3/src/bindgen/bindings.rs --- rust-cbindgen-0.23.0/src/bindgen/bindings.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/bindings.rs 1973-11-29 21:33:09.000000000 +0000 @@ -2,6 +2,7 @@ * 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 std::borrow::Cow; use std::cell::RefCell; use std::collections::HashMap; use std::fs; @@ -12,7 +13,7 @@ use crate::bindgen::config::{Config, Language}; use crate::bindgen::ir::{ - Constant, Function, ItemContainer, ItemMap, Path as BindgenPath, Static, Struct, + Constant, Function, ItemContainer, ItemMap, Path as BindgenPath, Static, Struct, Typedef, }; use crate::bindgen::writer::{Source, SourceWriter}; @@ -22,6 +23,7 @@ /// The map from path to struct, used to lookup whether a given type is a /// transparent struct. This is needed to generate code for constants. struct_map: ItemMap, + typedef_map: ItemMap, struct_fileds_memo: RefCell>>>, globals: Vec, constants: Vec, @@ -39,9 +41,11 @@ } impl Bindings { + #[allow(clippy::too_many_arguments)] pub(crate) fn new( config: Config, struct_map: ItemMap, + typedef_map: ItemMap, constants: Vec, globals: Vec, items: Vec, @@ -51,6 +55,7 @@ Bindings { config, struct_map, + typedef_map, struct_fileds_memo: Default::default(), globals, constants, @@ -67,9 +72,30 @@ any } + /// Peels through typedefs to allow resolving structs. + fn resolved_struct_path<'a>(&self, path: &'a BindgenPath) -> Cow<'a, BindgenPath> { + use crate::bindgen::ir::Type; + + let mut resolved_path = Cow::Borrowed(path); + loop { + let mut found = None; + self.typedef_map.for_items(&resolved_path, |item| { + if let Type::Path(ref p) = item.aliased { + found = Some(p.path().clone()); + } + }); + resolved_path = match found { + Some(p) => Cow::Owned(p), + None => break, + } + } + resolved_path + } + pub fn struct_exists(&self, path: &BindgenPath) -> bool { let mut any = false; - self.struct_map.for_items(path, |_| any = true); + self.struct_map + .for_items(&self.resolved_struct_path(path), |_| any = true); any } @@ -79,8 +105,10 @@ return memo.clone(); } + let resolved_path = self.resolved_struct_path(path); + let mut fields = Vec::::new(); - self.struct_map.for_items(path, |st| { + self.struct_map.for_items(&resolved_path, |st| { let mut pos: usize = 0; for field in &st.fields { if let Some(found_pos) = fields.iter().position(|v| *v == field.name) { @@ -94,6 +122,9 @@ let fields = Rc::new(fields); memos.insert(path.clone(), fields.clone()); + if let Cow::Owned(p) = resolved_path { + memos.insert(p, fields.clone()); + } fields } diff -Nru rust-cbindgen-0.23.0/src/bindgen/cdecl.rs rust-cbindgen-0.24.3/src/bindgen/cdecl.rs --- rust-cbindgen-0.23.0/src/bindgen/cdecl.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/cdecl.rs 1973-11-29 21:33:09.000000000 +0000 @@ -5,7 +5,7 @@ use std::io::Write; use crate::bindgen::declarationtyperesolver::DeclarationType; -use crate::bindgen::ir::{ArrayLength, Function, Type}; +use crate::bindgen::ir::{ConstExpr, Function, GenericArgument, Type}; use crate::bindgen::writer::{ListType, SourceWriter}; use crate::bindgen::{Config, Language}; @@ -35,7 +35,7 @@ struct CDecl { type_qualifers: String, type_name: String, - type_generic_args: Vec, + type_generic_args: Vec, declarators: Vec, type_ctype: Option, } @@ -70,7 +70,7 @@ t ), }; - let ptr_as_array = Type::Array(ty.clone(), ArrayLength::Value(length.to_string())); + let ptr_as_array = Type::Array(ty.clone(), ConstExpr::Value(length.to_string())); cdecl.build_type(&ptr_as_array, *is_const, config); cdecl } diff -Nru rust-cbindgen-0.23.0/src/bindgen/ir/constant.rs rust-cbindgen-0.24.3/src/bindgen/ir/constant.rs --- rust-cbindgen-0.23.0/src/bindgen/ir/constant.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/ir/constant.rs 1973-11-29 21:33:09.000000000 +0000 @@ -340,11 +340,18 @@ other_code => format!(r"U'\U{:08X}'", other_code), })), syn::Lit::Int(ref value) => { - if value.base10_parse::().is_err() { - Ok(Literal::Expr(format!("{}ULL", value.base10_digits()))) - } else { - Ok(Literal::Expr(value.base10_digits().to_string())) - } + let suffix = match value.suffix() { + "u64" => "ull", + "i64" => "ll", + "u32" => "u", + _ if value.base10_parse::().is_err() => "ull", + _ => "", + }; + Ok(Literal::Expr(format!( + "{}{}", + value.base10_digits(), + suffix + ))) } syn::Lit::Float(ref value) => { Ok(Literal::Expr(value.base10_digits().to_string())) @@ -410,6 +417,13 @@ syn::Expr::Unary(syn::ExprUnary { ref op, ref expr, .. }) => match *op { + UnOp::Not(_) => { + let val = Self::load(expr)?; + Ok(Literal::PostfixUnaryOp { + op: "~", + value: Box::new(val), + }) + } UnOp::Neg(_) => { let val = Self::load(expr)?; Ok(Literal::PostfixUnaryOp { diff -Nru rust-cbindgen-0.23.0/src/bindgen/ir/enumeration.rs rust-cbindgen-0.24.3/src/bindgen/ir/enumeration.rs --- rust-cbindgen-0.23.0/src/bindgen/ir/enumeration.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/ir/enumeration.rs 1973-11-29 21:33:09.000000000 +0000 @@ -10,8 +10,9 @@ use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; use crate::bindgen::dependencies::Dependencies; use crate::bindgen::ir::{ - AnnotationSet, AnnotationValue, Cfg, ConditionWrite, Documentation, Field, GenericParams, - GenericPath, Item, ItemContainer, Literal, Path, Repr, ReprStyle, Struct, ToCondition, Type, + AnnotationSet, AnnotationValue, Cfg, ConditionWrite, Documentation, Field, GenericArgument, + GenericParams, GenericPath, Item, ItemContainer, Literal, Path, Repr, ReprStyle, Struct, + ToCondition, Type, }; use crate::bindgen::library::Library; use crate::bindgen::mangle; @@ -61,8 +62,8 @@ fn specialize( &self, - generic_values: &[Type], - mappings: &[(&Path, &Type)], + generic_values: &[GenericArgument], + mappings: &[(&Path, &GenericArgument)], config: &Config, ) -> Self { match *self { @@ -265,8 +266,8 @@ fn specialize( &self, - generic_values: &[Type], - mappings: &[(&Path, &Type)], + generic_values: &[GenericArgument], + mappings: &[(&Path, &GenericArgument)], config: &Config, ) -> Self { Self::new( @@ -382,7 +383,7 @@ } let path = Path::new(item.ident.unraw().to_string()); - let generic_params = GenericParams::new(&item.generics); + let generic_params = GenericParams::load(&item.generics)?; let mut variants = Vec::new(); let mut has_data = false; @@ -611,28 +612,11 @@ fn instantiate_monomorph( &self, - generic_values: &[Type], + generic_values: &[GenericArgument], library: &Library, out: &mut Monomorphs, ) { - assert!( - self.generic_params.len() > 0, - "{} is not generic", - self.path.name() - ); - assert!( - self.generic_params.len() == generic_values.len(), - "{} has {} params but is being instantiated with {} values", - self.path.name(), - self.generic_params.len(), - generic_values.len(), - ); - - let mappings = self - .generic_params - .iter() - .zip(generic_values.iter()) - .collect::>(); + let mappings = self.generic_params.call(self.path.name(), generic_values); for variant in &self.variants { if let VariantBody::Body { ref body, .. } = variant.body { diff -Nru rust-cbindgen-0.23.0/src/bindgen/ir/generic_path.rs rust-cbindgen-0.24.3/src/bindgen/ir/generic_path.rs --- rust-cbindgen-0.23.0/src/bindgen/ir/generic_path.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/ir/generic_path.rs 1973-11-29 21:33:09.000000000 +0000 @@ -3,29 +3,95 @@ use syn::ext::IdentExt; +use crate::bindgen::cdecl; use crate::bindgen::config::{Config, Language}; use crate::bindgen::declarationtyperesolver::{DeclarationType, DeclarationTypeResolver}; -use crate::bindgen::ir::{Path, Type}; +use crate::bindgen::ir::{ConstExpr, Path, Type}; use crate::bindgen::utilities::IterHelpers; use crate::bindgen::writer::{Source, SourceWriter}; +#[derive(Debug, Clone)] +pub enum GenericParamType { + Type, + Const(Type), +} + +#[derive(Debug, Clone)] +pub struct GenericParam { + name: Path, + ty: GenericParamType, +} + +impl GenericParam { + pub fn new_type_param(name: &str) -> Self { + GenericParam { + name: Path::new(name), + ty: GenericParamType::Type, + } + } + + pub fn load(param: &syn::GenericParam) -> Result, String> { + match *param { + syn::GenericParam::Type(syn::TypeParam { ref ident, .. }) => Ok(Some(GenericParam { + name: Path::new(ident.unraw().to_string()), + ty: GenericParamType::Type, + })), + + syn::GenericParam::Lifetime(_) => Ok(None), + + syn::GenericParam::Const(syn::ConstParam { + ref ident, ref ty, .. + }) => match Type::load(ty)? { + None => { + // A type that evaporates, like PhantomData. + Err(format!("unsupported const generic type: {:?}", ty)) + } + Some(ty) => Ok(Some(GenericParam { + name: Path::new(ident.unraw().to_string()), + ty: GenericParamType::Const(ty), + })), + }, + } + } + + pub fn name(&self) -> &Path { + &self.name + } +} + #[derive(Default, Debug, Clone)] -pub struct GenericParams(pub Vec); +pub struct GenericParams(pub Vec); impl GenericParams { - pub fn new(generics: &syn::Generics) -> Self { - GenericParams( - generics - .params - .iter() - .filter_map(|x| match *x { - syn::GenericParam::Type(syn::TypeParam { ref ident, .. }) => { - Some(Path::new(ident.unraw().to_string())) - } - _ => None, - }) - .collect(), - ) + pub fn load(generics: &syn::Generics) -> Result { + let mut params = vec![]; + for param in &generics.params { + if let Some(p) = GenericParam::load(param)? { + params.push(p); + } + } + + Ok(GenericParams(params)) + } + + /// Associate each parameter with an argument. + pub fn call<'out>( + &'out self, + item_name: &str, + arguments: &'out [GenericArgument], + ) -> Vec<(&'out Path, &'out GenericArgument)> { + assert!(self.len() > 0, "{} is not generic", item_name); + assert!( + self.len() == arguments.len(), + "{} has {} params but is being instantiated with {} values", + item_name, + self.len(), + arguments.len(), + ); + self.iter() + .map(|param| param.name()) + .zip(arguments.iter()) + .collect() } fn write_internal( @@ -40,9 +106,19 @@ if i != 0 { out.write(", "); } - write!(out, "typename {}", item); - if with_default { - write!(out, " = void"); + match item.ty { + GenericParamType::Type => { + write!(out, "typename {}", item.name); + if with_default { + write!(out, " = void"); + } + } + GenericParamType::Const(ref ty) => { + cdecl::write_field(out, ty, item.name.name(), config); + if with_default { + write!(out, " = 0"); + } + } } } out.write(">"); @@ -56,9 +132,9 @@ } impl Deref for GenericParams { - type Target = [Path]; + type Target = [GenericParam]; - fn deref(&self) -> &[Path] { + fn deref(&self) -> &[GenericParam] { &self.0 } } @@ -69,16 +145,65 @@ } } +/// A (non-lifetime) argument passed to a generic, either a type or a constant expression. +/// +/// Note: Both arguments in a type like `Array` are represented as +/// `GenericArgument::Type`s, even if `N` is actually the name of a const. This +/// is a consequence of `syn::GenericArgument` doing the same thing. +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum GenericArgument { + Type(Type), + Const(ConstExpr), +} + +impl GenericArgument { + pub fn specialize(&self, mappings: &[(&Path, &GenericArgument)]) -> GenericArgument { + match *self { + GenericArgument::Type(ref ty) => { + if let Type::Path(ref path) = *ty { + if path.is_single_identifier() { + // See note on `GenericArgument` above: `ty` may + // actually be the name of a const. Check for that now. + for &(name, value) in mappings { + if *name == path.path { + return value.clone(); + } + } + } + } + GenericArgument::Type(ty.specialize(mappings)) + } + GenericArgument::Const(ref expr) => GenericArgument::Const(expr.clone()), + } + } + + pub fn rename_for_config(&mut self, config: &Config, generic_params: &GenericParams) { + match *self { + GenericArgument::Type(ref mut ty) => ty.rename_for_config(config, generic_params), + GenericArgument::Const(ref mut expr) => expr.rename_for_config(config), + } + } +} + +impl Source for GenericArgument { + fn write(&self, config: &Config, out: &mut SourceWriter) { + match *self { + GenericArgument::Type(ref ty) => ty.write(config, out), + GenericArgument::Const(ref expr) => expr.write(config, out), + } + } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct GenericPath { path: Path, export_name: String, - generics: Vec, + generics: Vec, ctype: Option, } impl GenericPath { - pub fn new(path: Path, generics: Vec) -> Self { + pub fn new(path: Path, generics: Vec) -> Self { let export_name = path.name().to_owned(); Self { path, @@ -103,11 +228,11 @@ &self.path } - pub fn generics(&self) -> &[Type] { + pub fn generics(&self) -> &[GenericArgument] { &self.generics } - pub fn generics_mut(&mut self) -> &mut [Type] { + pub fn generics_mut(&mut self) -> &mut [GenericArgument] { &mut self.generics } @@ -123,11 +248,15 @@ &self.export_name } + pub fn is_single_identifier(&self) -> bool { + self.generics.is_empty() + } + pub fn rename_for_config(&mut self, config: &Config, generic_params: &GenericParams) { for generic in &mut self.generics { generic.rename_for_config(config, generic_params); } - if !generic_params.contains(&self.path) { + if !generic_params.iter().any(|param| param.name == self.path) { config.export.rename(&mut self.export_name); } } @@ -156,8 +285,11 @@ ref args, .. }) => args.iter().try_skip_map(|x| match *x { - syn::GenericArgument::Type(ref x) => Type::load(x), + syn::GenericArgument::Type(ref x) => Ok(Type::load(x)?.map(GenericArgument::Type)), syn::GenericArgument::Lifetime(_) => Ok(None), + syn::GenericArgument::Const(ref x) => { + Ok(Some(GenericArgument::Const(ConstExpr::load(x)?))) + } _ => Err(format!("can't handle generic argument {:?}", x)), })?, syn::PathArguments::Parenthesized(_) => { diff -Nru rust-cbindgen-0.23.0/src/bindgen/ir/item.rs rust-cbindgen-0.24.3/src/bindgen/ir/item.rs --- rust-cbindgen-0.23.0/src/bindgen/ir/item.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/ir/item.rs 1973-11-29 21:33:09.000000000 +0000 @@ -9,7 +9,8 @@ use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; use crate::bindgen::dependencies::Dependencies; use crate::bindgen::ir::{ - AnnotationSet, Cfg, Constant, Enum, OpaqueItem, Path, Static, Struct, Type, Typedef, Union, + AnnotationSet, Cfg, Constant, Enum, GenericArgument, OpaqueItem, Path, Static, Struct, Typedef, + Union, }; use crate::bindgen::library::Library; use crate::bindgen::monomorph::Monomorphs; @@ -37,7 +38,12 @@ } fn rename_for_config(&mut self, _config: &Config) {} fn add_dependencies(&self, _library: &Library, _out: &mut Dependencies) {} - fn instantiate_monomorph(&self, _generics: &[Type], _library: &Library, _out: &mut Monomorphs) { + fn instantiate_monomorph( + &self, + _generics: &[GenericArgument], + _library: &Library, + _out: &mut Monomorphs, + ) { unreachable!("Cannot instantiate {} as a generic.", self.name()) } } diff -Nru rust-cbindgen-0.23.0/src/bindgen/ir/opaque.rs rust-cbindgen-0.24.3/src/bindgen/ir/opaque.rs --- rust-cbindgen-0.23.0/src/bindgen/ir/opaque.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/ir/opaque.rs 1973-11-29 21:33:09.000000000 +0000 @@ -8,8 +8,8 @@ use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; use crate::bindgen::dependencies::Dependencies; use crate::bindgen::ir::{ - AnnotationSet, Cfg, ConditionWrite, Documentation, GenericParams, Item, ItemContainer, Path, - ToCondition, Type, + AnnotationSet, Cfg, ConditionWrite, Documentation, GenericArgument, GenericParams, Item, + ItemContainer, Path, ToCondition, }; use crate::bindgen::library::Library; use crate::bindgen::mangle; @@ -35,7 +35,7 @@ ) -> Result { Ok(Self::new( path, - GenericParams::new(generics), + GenericParams::load(generics)?, Cfg::append(mod_cfg, Cfg::load(attrs)), AnnotationSet::load(attrs).unwrap_or_else(|_| AnnotationSet::new()), Documentation::load(attrs), @@ -98,7 +98,7 @@ fn instantiate_monomorph( &self, - generic_values: &[Type], + generic_values: &[GenericArgument], library: &Library, out: &mut Monomorphs, ) { diff -Nru rust-cbindgen-0.23.0/src/bindgen/ir/structure.rs rust-cbindgen-0.24.3/src/bindgen/ir/structure.rs --- rust-cbindgen-0.23.0/src/bindgen/ir/structure.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/ir/structure.rs 1973-11-29 21:33:09.000000000 +0000 @@ -10,8 +10,9 @@ use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; use crate::bindgen::dependencies::Dependencies; use crate::bindgen::ir::{ - AnnotationSet, Cfg, ConditionWrite, Constant, Documentation, Field, GenericParams, Item, - ItemContainer, Path, Repr, ReprAlign, ReprStyle, ToCondition, Type, Typedef, + AnnotationSet, Cfg, ConditionWrite, Constant, Documentation, Field, GenericArgument, + GenericParams, Item, ItemContainer, Path, Repr, ReprAlign, ReprStyle, ToCondition, Type, + Typedef, }; use crate::bindgen::library::Library; use crate::bindgen::mangle; @@ -102,7 +103,7 @@ Ok(Struct::new( path, - GenericParams::new(&item.generics), + GenericParams::load(&item.generics)?, fields, has_tag_field, is_enum_variant_body, @@ -174,8 +175,8 @@ pub fn specialize( &self, - generic_values: &[Type], - mappings: &[(&Path, &Type)], + generic_values: &[GenericArgument], + mappings: &[(&Path, &GenericArgument)], config: &Config, ) -> Self { let mangled_path = mangle::mangle_path(&self.path, generic_values, &config.export.mangle); @@ -204,6 +205,7 @@ fn emit_bitflags_binop( &self, + constexpr_prefix: &str, operator: char, other: &str, out: &mut SourceWriter, @@ -211,7 +213,8 @@ out.new_line(); write!( out, - "{} operator{}(const {}& {}) const", + "{}{} operator{}(const {}& {}) const", + constexpr_prefix, self.export_name(), operator, self.export_name(), @@ -220,8 +223,10 @@ out.open_brace(); write!( out, - "return {{static_cast(this->bits {} {}.bits)}};", - operator, other + "return {} {{ static_cast(this->bits {} {}.bits) }};", + self.export_name(), + operator, + other ); out.close_brace(false); @@ -365,29 +370,11 @@ fn instantiate_monomorph( &self, - generic_values: &[Type], + generic_values: &[GenericArgument], library: &Library, out: &mut Monomorphs, ) { - assert!( - self.generic_params.len() > 0, - "{} is not generic", - self.path - ); - assert!( - self.generic_params.len() == generic_values.len(), - "{} has {} params but is being instantiated with {} values", - self.path, - self.generic_params.len(), - generic_values.len(), - ); - - let mappings = self - .generic_params - .iter() - .zip(generic_values.iter()) - .collect::>(); - + let mappings = self.generic_params.call(self.path.name(), generic_values); let monomorph = self.specialize(generic_values, &mappings, library.get_config()); out.insert_struct(library, self, monomorph, generic_values.to_owned()); } @@ -548,21 +535,35 @@ wrote_start_newline = true; out.new_line(); } + let constexpr_prefix = if config.constant.allow_constexpr { + "constexpr " + } else { + "" + }; + out.new_line(); - write!(out, "explicit operator bool() const"); + write!(out, "{}explicit operator bool() const", constexpr_prefix); out.open_brace(); write!(out, "return !!bits;"); out.close_brace(false); out.new_line(); - write!(out, "{} operator~() const", self.export_name()); + write!( + out, + "{}{} operator~() const", + constexpr_prefix, + self.export_name() + ); out.open_brace(); - write!(out, "return {{static_cast(~bits)}};"); + write!( + out, + "return {} {{ static_cast(~bits) }};", + self.export_name() + ); out.close_brace(false); - - self.emit_bitflags_binop('|', &other, out); - self.emit_bitflags_binop('&', &other, out); - self.emit_bitflags_binop('^', &other, out); + self.emit_bitflags_binop(constexpr_prefix, '|', &other, out); + self.emit_bitflags_binop(constexpr_prefix, '&', &other, out); + self.emit_bitflags_binop(constexpr_prefix, '^', &other, out); } // Generate a serializer function that allows dumping this struct diff -Nru rust-cbindgen-0.23.0/src/bindgen/ir/ty.rs rust-cbindgen-0.24.3/src/bindgen/ir/ty.rs --- rust-cbindgen-0.23.0/src/bindgen/ir/ty.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/ir/ty.rs 1973-11-29 21:33:09.000000000 +0000 @@ -11,7 +11,7 @@ use crate::bindgen::config::{Config, Language}; use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; use crate::bindgen::dependencies::Dependencies; -use crate::bindgen::ir::{GenericParams, GenericPath, Path}; +use crate::bindgen::ir::{GenericArgument, GenericParams, GenericPath, Path}; use crate::bindgen::library::Library; use crate::bindgen::monomorph::Monomorphs; use crate::bindgen::utilities::IterHelpers; @@ -311,25 +311,82 @@ } } -// The `U` part of `[T; U]` +/// Constant expressions. +/// +/// Used for the `U` part of `[T; U]` and const generics. We support a very +/// limited vocabulary here: only identifiers and literals. #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub enum ArrayLength { +pub enum ConstExpr { Name(String), Value(String), } -impl ArrayLength { +impl ConstExpr { pub fn as_str(&self) -> &str { - match self { - ArrayLength::Name(ref string) | ArrayLength::Value(ref string) => string, + match *self { + ConstExpr::Name(ref string) | ConstExpr::Value(ref string) => string, } } - fn rename_for_config(&mut self, config: &Config) { - if let ArrayLength::Name(ref mut name) = self { + pub fn rename_for_config(&mut self, config: &Config) { + if let ConstExpr::Name(ref mut name) = self { config.export.rename(name); } } + + pub fn load(expr: &syn::Expr) -> Result { + match *expr { + syn::Expr::Lit(syn::ExprLit { ref lit, .. }) => { + let val = match *lit { + syn::Lit::Bool(syn::LitBool { value, .. }) => value.to_string(), + syn::Lit::Int(ref len) => len.base10_digits().to_string(), + syn::Lit::Byte(ref byte) => u8::to_string(&byte.value()), + syn::Lit::Char(ref ch) => u32::to_string(&ch.value().into()), + _ => return Err(format!("can't handle const expression {:?}", lit)), + }; + Ok(ConstExpr::Value(val)) + } + syn::Expr::Path(ref path) => { + let generic_path = GenericPath::load(&path.path)?; + Ok(ConstExpr::Name(generic_path.export_name().to_owned())) + } + _ => Err(format!("can't handle const expression {:?}", expr)), + } + } + + pub fn specialize(&self, mappings: &[(&Path, &GenericArgument)]) -> ConstExpr { + match *self { + ConstExpr::Name(ref name) => { + let path = Path::new(name); + for &(param, value) in mappings { + if path == *param { + match *value { + GenericArgument::Type(Type::Path(ref path)) + if path.is_single_identifier() => + { + // This happens when the generic argument is a path. + return ConstExpr::Name(path.name().to_string()); + } + GenericArgument::Const(ref expr) => { + return expr.clone(); + } + _ => { + // unsupported argument type - really should be an error + } + } + } + } + } + ConstExpr::Value(_) => {} + } + self.clone() + } +} + +impl Source for ConstExpr { + fn write(&self, _config: &Config, out: &mut SourceWriter) { + write!(out, "{}", self.as_str()); + } } #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] @@ -345,7 +402,7 @@ }, Path(GenericPath), Primitive(PrimitiveType), - Array(Box, ArrayLength), + Array(Box, ConstExpr), FuncPtr { ret: Box, args: Vec<(Option, Type)>, @@ -415,9 +472,7 @@ } } syn::Type::Array(syn::TypeArray { - ref elem, - len: syn::Expr::Path(ref path), - .. + ref elem, ref len, .. }) => { let converted = Type::load(elem)?; @@ -425,28 +480,8 @@ Some(converted) => converted, None => return Err("Cannot have an array of zero sized types.".to_owned()), }; - let generic_path = GenericPath::load(&path.path)?; - let len = ArrayLength::Name(generic_path.export_name().to_owned()); - Type::Array(Box::new(converted), len) - } - syn::Type::Array(syn::TypeArray { - ref elem, - len: - syn::Expr::Lit(syn::ExprLit { - lit: syn::Lit::Int(ref len), - .. - }), - .. - }) => { - let converted = Type::load(elem)?; - let converted = match converted { - Some(converted) => converted, - None => return Err("Cannot have an array of zero sized types.".to_owned()), - }; - - let len = ArrayLength::Value(len.base10_digits().to_string()); - // panic!("panic -> value: {:?}", len); + let len = ConstExpr::load(len)?; Type::Array(Box::new(converted), len) } syn::Type::BareFn(ref function) => { @@ -609,7 +644,11 @@ return None; } - let unsimplified_generic = &path.generics()[0]; + let unsimplified_generic = match path.generics()[0] { + GenericArgument::Type(ref ty) => ty, + GenericArgument::Const(_) => return None, + }; + let generic = match unsimplified_generic.simplified_type(config) { Some(generic) => Cow::Owned(generic), None => Cow::Borrowed(unsimplified_generic), @@ -663,7 +702,10 @@ Type::Array(ref mut ty, ..) | Type::Ptr { ref mut ty, .. } => visitor(ty), Type::Path(ref mut path) => { for generic in path.generics_mut() { - visitor(generic); + match *generic { + GenericArgument::Type(ref mut ty) => visitor(ty), + GenericArgument::Const(_) => {} + } } } Type::Primitive(..) => {} @@ -701,7 +743,7 @@ } } - pub fn specialize(&self, mappings: &[(&Path, &Type)]) -> Type { + pub fn specialize(&self, mappings: &[(&Path, &GenericArgument)]) -> Type { match *self { Type::Ptr { ref ty, @@ -717,7 +759,9 @@ Type::Path(ref generic_path) => { for &(param, value) in mappings { if generic_path.path() == param { - return value.clone(); + if let GenericArgument::Type(ref ty) = *value { + return ty.clone(); + } } } @@ -732,9 +776,10 @@ Type::Path(specialized) } Type::Primitive(ref primitive) => Type::Primitive(primitive.clone()), - Type::Array(ref ty, ref constant) => { - Type::Array(Box::new(ty.specialize(mappings)), constant.clone()) - } + Type::Array(ref ty, ref constant) => Type::Array( + Box::new(ty.specialize(mappings)), + constant.specialize(mappings), + ), Type::FuncPtr { ref ret, ref args, @@ -763,10 +808,12 @@ } Type::Path(ref generic) => { for generic_value in generic.generics() { - generic_value.add_dependencies_ignoring_generics(generic_params, library, out); + if let GenericArgument::Type(ref ty) = *generic_value { + ty.add_dependencies_ignoring_generics(generic_params, library, out); + } } let path = generic.path(); - if !generic_params.contains(path) { + if !generic_params.iter().any(|param| param.name() == path) { if let Some(items) = library.get_items(path) { if !out.items.contains(path) { out.items.insert(path.clone()); diff -Nru rust-cbindgen-0.23.0/src/bindgen/ir/typedef.rs rust-cbindgen-0.24.3/src/bindgen/ir/typedef.rs --- rust-cbindgen-0.23.0/src/bindgen/ir/typedef.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/ir/typedef.rs 1973-11-29 21:33:09.000000000 +0000 @@ -11,8 +11,8 @@ use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; use crate::bindgen::dependencies::Dependencies; use crate::bindgen::ir::{ - AnnotationSet, Cfg, ConditionWrite, Documentation, Field, GenericParams, Item, ItemContainer, - Path, ToCondition, Type, + AnnotationSet, Cfg, ConditionWrite, Documentation, Field, GenericArgument, GenericParams, Item, + ItemContainer, Path, ToCondition, Type, }; use crate::bindgen::library::Library; use crate::bindgen::mangle; @@ -37,7 +37,7 @@ let path = Path::new(item.ident.unraw().to_string()); Ok(Typedef::new( path, - GenericParams::new(&item.generics), + GenericParams::load(&item.generics)?, x, Cfg::append(mod_cfg, Cfg::load(&item.attrs)), AnnotationSet::load(&item.attrs)?, @@ -155,28 +155,11 @@ fn instantiate_monomorph( &self, - generic_values: &[Type], + generic_values: &[GenericArgument], library: &Library, out: &mut Monomorphs, ) { - assert!( - self.generic_params.len() > 0, - "{} is not generic", - self.path - ); - assert!( - self.generic_params.len() == generic_values.len(), - "{} has {} params but is being instantiated with {} values", - self.path, - self.generic_params.len(), - generic_values.len(), - ); - - let mappings = self - .generic_params - .iter() - .zip(generic_values.iter()) - .collect::>(); + let mappings = self.generic_params.call(self.path.name(), generic_values); let mangled_path = mangle::mangle_path( &self.path, diff -Nru rust-cbindgen-0.23.0/src/bindgen/ir/union.rs rust-cbindgen-0.24.3/src/bindgen/ir/union.rs --- rust-cbindgen-0.23.0/src/bindgen/ir/union.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/ir/union.rs 1973-11-29 21:33:09.000000000 +0000 @@ -10,8 +10,8 @@ use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; use crate::bindgen::dependencies::Dependencies; use crate::bindgen::ir::{ - AnnotationSet, Cfg, ConditionWrite, Documentation, Field, GenericParams, Item, ItemContainer, - Path, Repr, ReprAlign, ReprStyle, ToCondition, Type, + AnnotationSet, Cfg, ConditionWrite, Documentation, Field, GenericArgument, GenericParams, Item, + ItemContainer, Path, Repr, ReprAlign, ReprStyle, ToCondition, }; use crate::bindgen::library::Library; use crate::bindgen::mangle; @@ -62,7 +62,7 @@ Ok(Union::new( path, - GenericParams::new(&item.generics), + GenericParams::load(&item.generics)?, fields, repr.align, tuple_union, @@ -223,28 +223,11 @@ fn instantiate_monomorph( &self, - generic_values: &[Type], + generic_values: &[GenericArgument], library: &Library, out: &mut Monomorphs, ) { - assert!( - self.generic_params.len() > 0, - "{} is not generic", - self.path - ); - assert!( - self.generic_params.len() == generic_values.len(), - "{} has {} params but is being instantiated with {} values", - self.path, - self.generic_params.len(), - generic_values.len(), - ); - - let mappings = self - .generic_params - .iter() - .zip(generic_values.iter()) - .collect::>(); + let mappings = self.generic_params.call(self.path.name(), generic_values); let mangled_path = mangle::mangle_path( &self.path, diff -Nru rust-cbindgen-0.23.0/src/bindgen/library.rs rust-cbindgen-0.24.3/src/bindgen/library.rs --- rust-cbindgen-0.23.0/src/bindgen/library.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/library.rs 1973-11-29 21:33:09.000000000 +0000 @@ -67,6 +67,7 @@ Default::default(), Default::default(), Default::default(), + Default::default(), true, )); } @@ -147,6 +148,7 @@ Ok(Bindings::new( self.config, self.structs, + self.typedefs, constants, globals, items, diff -Nru rust-cbindgen-0.23.0/src/bindgen/mangle.rs rust-cbindgen-0.24.3/src/bindgen/mangle.rs --- rust-cbindgen-0.23.0/src/bindgen/mangle.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/mangle.rs 1973-11-29 21:33:09.000000000 +0000 @@ -3,14 +3,18 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::bindgen::config::MangleConfig; -use crate::bindgen::ir::{Path, Type}; +use crate::bindgen::ir::{ConstExpr, GenericArgument, GenericPath, Path, Type}; use crate::bindgen::rename::IdentifierType; -pub fn mangle_path(path: &Path, generic_values: &[Type], config: &MangleConfig) -> Path { +pub fn mangle_path(path: &Path, generic_values: &[GenericArgument], config: &MangleConfig) -> Path { Path::new(mangle_name(path.name(), generic_values, config)) } -pub fn mangle_name(name: &str, generic_values: &[Type], config: &MangleConfig) -> String { +pub fn mangle_name( + name: &str, + generic_values: &[GenericArgument], + config: &MangleConfig, +) -> String { Mangler::new(name, generic_values, /* last = */ true, config).mangle() } @@ -27,7 +31,7 @@ struct Mangler<'a> { input: &'a str, - generic_values: &'a [Type], + generic_values: &'a [GenericArgument], output: String, last: bool, config: &'a MangleConfig, @@ -36,7 +40,7 @@ impl<'a> Mangler<'a> { fn new( input: &'a str, - generic_values: &'a [Type], + generic_values: &'a [GenericArgument], last: bool, config: &'a MangleConfig, ) -> Self { @@ -64,6 +68,20 @@ self.output.extend(std::iter::repeat(separator).take(count)); } + fn append_mangled_argument(&mut self, arg: &GenericArgument, last: bool) { + match *arg { + GenericArgument::Type(ref ty) => self.append_mangled_type(ty, last), + GenericArgument::Const(ConstExpr::Name(ref name)) => { + // This must behave the same as a GenericArgument::Type, + // because const arguments are commonly represented as Types; + // see the comment on `enum GenericArgument`. + let fake_ty = Type::Path(GenericPath::new(Path::new(name), vec![])); + self.append_mangled_type(&fake_ty, last); + } + GenericArgument::Const(ConstExpr::Value(ref val)) => self.output.push_str(val), + } + } + fn append_mangled_type(&mut self, ty: &Type, last: bool) { match *ty { Type::Path(ref generic) => { @@ -128,12 +146,12 @@ } self.push(Separator::OpeningAngleBracket); - for (i, ty) in self.generic_values.iter().enumerate() { + for (i, arg) in self.generic_values.iter().enumerate() { if i != 0 { self.push(Separator::Comma); } let last = self.last && i == self.generic_values.len() - 1; - self.append_mangled_type(ty, last); + self.append_mangled_argument(arg, last); } // Skip writing the trailing '>' mangling when possible @@ -148,22 +166,22 @@ use crate::bindgen::ir::{GenericPath, PrimitiveType}; use crate::bindgen::rename::RenameRule::{self, PascalCase}; - fn float() -> Type { - Type::Primitive(PrimitiveType::Float) + fn float() -> GenericArgument { + GenericArgument::Type(Type::Primitive(PrimitiveType::Float)) } - fn c_char() -> Type { - Type::Primitive(PrimitiveType::Char) + fn c_char() -> GenericArgument { + GenericArgument::Type(Type::Primitive(PrimitiveType::Char)) } - fn path(path: &str) -> Type { + fn path(path: &str) -> GenericArgument { generic_path(path, &[]) } - fn generic_path(path: &str, generics: &[Type]) -> Type { + fn generic_path(path: &str, arguments: &[GenericArgument]) -> GenericArgument { let path = Path::new(path); - let generic_path = GenericPath::new(path, generics.to_owned()); - Type::Path(generic_path) + let generic_path = GenericPath::new(path, arguments.to_owned()); + GenericArgument::Type(Type::Path(generic_path)) } // Foo => Foo_f32 @@ -288,4 +306,43 @@ ), Path::new("FooBarTBarE") ); + + assert_eq!( + mangle_path( + &Path::new("Top"), + &[GenericArgument::Const(ConstExpr::Value("40".to_string()))], + &MangleConfig::default(), + ), + Path::new("Top_40") + ); + + assert_eq!( + mangle_path( + &Path::new("Top"), + &[GenericArgument::Const(ConstExpr::Name("N".to_string()))], + &MangleConfig::default(), + ), + Path::new("Top_N") + ); + + assert_eq!( + mangle_path( + &Path::new("Top"), + &[generic_path("N", &[])], + &MangleConfig::default(), + ), + Path::new("Top_N") + ); + + assert_eq!( + mangle_path( + &Path::new("Foo"), + &[ + float(), + GenericArgument::Const(ConstExpr::Value("40".to_string())) + ], + &MangleConfig::default(), + ), + Path::new("Foo_f32__40") + ); } diff -Nru rust-cbindgen-0.23.0/src/bindgen/monomorph.rs rust-cbindgen-0.24.3/src/bindgen/monomorph.rs --- rust-cbindgen-0.23.0/src/bindgen/monomorph.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/monomorph.rs 1973-11-29 21:33:09.000000000 +0000 @@ -5,7 +5,9 @@ use std::collections::HashMap; use std::mem; -use crate::bindgen::ir::{Enum, GenericPath, OpaqueItem, Path, Struct, Type, Typedef, Union}; +use crate::bindgen::ir::{ + Enum, GenericArgument, GenericPath, OpaqueItem, Path, Struct, Typedef, Union, +}; use crate::bindgen::library::Library; #[derive(Default, Clone, Debug)] @@ -28,9 +30,9 @@ library: &Library, generic: &Struct, monomorph: Struct, - parameters: Vec, + arguments: Vec, ) { - let replacement_path = GenericPath::new(generic.path.clone(), parameters); + let replacement_path = GenericPath::new(generic.path.clone(), arguments); debug_assert!(generic.generic_params.len() > 0); debug_assert!(!self.contains(&replacement_path)); @@ -48,9 +50,9 @@ library: &Library, generic: &Enum, monomorph: Enum, - parameters: Vec, + arguments: Vec, ) { - let replacement_path = GenericPath::new(generic.path.clone(), parameters); + let replacement_path = GenericPath::new(generic.path.clone(), arguments); debug_assert!(generic.generic_params.len() > 0); debug_assert!(!self.contains(&replacement_path)); @@ -68,9 +70,9 @@ library: &Library, generic: &Union, monomorph: Union, - parameters: Vec, + arguments: Vec, ) { - let replacement_path = GenericPath::new(generic.path.clone(), parameters); + let replacement_path = GenericPath::new(generic.path.clone(), arguments); debug_assert!(generic.generic_params.len() > 0); debug_assert!(!self.contains(&replacement_path)); @@ -87,9 +89,9 @@ &mut self, generic: &OpaqueItem, monomorph: OpaqueItem, - parameters: Vec, + arguments: Vec, ) { - let replacement_path = GenericPath::new(generic.path.clone(), parameters); + let replacement_path = GenericPath::new(generic.path.clone(), arguments); debug_assert!(generic.generic_params.len() > 0); debug_assert!(!self.contains(&replacement_path)); @@ -104,9 +106,9 @@ library: &Library, generic: &Typedef, monomorph: Typedef, - parameters: Vec, + arguments: Vec, ) { - let replacement_path = GenericPath::new(generic.path.clone(), parameters); + let replacement_path = GenericPath::new(generic.path.clone(), arguments); debug_assert!(generic.generic_params.len() > 0); debug_assert!(!self.contains(&replacement_path)); diff -Nru rust-cbindgen-0.23.0/src/bindgen/parser.rs rust-cbindgen-0.24.3/src/bindgen/parser.rs --- rust-cbindgen-0.23.0/src/bindgen/parser.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/src/bindgen/parser.rs 1973-11-29 21:33:09.000000000 +0000 @@ -15,8 +15,8 @@ use crate::bindgen::config::{Config, ParseConfig}; use crate::bindgen::error::Error; use crate::bindgen::ir::{ - AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParams, ItemMap, - OpaqueItem, Path, Static, Struct, Type, Typedef, Union, + AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParam, GenericParams, + ItemMap, OpaqueItem, Path, Static, Struct, Type, Typedef, Union, }; use crate::bindgen::utilities::{SynAbiHelpers, SynAttributeHelpers, SynItemFnHelpers}; @@ -425,7 +425,10 @@ pub fn add_std_types(&mut self) { let mut add_opaque = |path: &str, generic_params: Vec<&str>| { let path = Path::new(path); - let generic_params: Vec<_> = generic_params.into_iter().map(Path::new).collect(); + let generic_params: Vec<_> = generic_params + .into_iter() + .map(GenericParam::new_type_param) + .collect(); self.opaque_items.try_insert(OpaqueItem::new( path, GenericParams(generic_params), diff -Nru rust-cbindgen-0.23.0/tests/rust/bitflags.rs rust-cbindgen-0.24.3/tests/rust/bitflags.rs --- rust-cbindgen-0.23.0/tests/rust/bitflags.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-cbindgen-0.24.3/tests/rust/bitflags.rs 1973-11-29 21:33:09.000000000 +0000 @@ -29,5 +29,15 @@ } } +bitflags! { + #[repr(C)] + pub struct LargeFlags: u64 { + /// Flag with a very large shift that usually would be narrowed. + const LARGE_SHIFT = 1u64 << 44; + const INVERTED = !Self::LARGE_SHIFT.bits; + } +} + + #[no_mangle] -pub extern "C" fn root(flags: AlignFlags, bigger_flags: DebugFlags) {} +pub extern "C" fn root(flags: AlignFlags, bigger_flags: DebugFlags, largest_flags: LargeFlags) {} diff -Nru rust-cbindgen-0.23.0/tests/rust/const_generics.rs rust-cbindgen-0.24.3/tests/rust/const_generics.rs --- rust-cbindgen-0.23.0/tests/rust/const_generics.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-cbindgen-0.24.3/tests/rust/const_generics.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,15 @@ +#[repr(transparent)] +pub struct CArrayString { + pub chars: [i8; CAP], +} + +pub const TITLE_SIZE: usize = 80; + +#[repr(C)] +pub struct Book { + pub title: CArrayString, + pub author: CArrayString<40>, +} + +#[no_mangle] +pub extern "C" fn root(a: *mut Book) {} diff -Nru rust-cbindgen-0.23.0/tests/rust/const_generics_arrayvec.rs rust-cbindgen-0.24.3/tests/rust/const_generics_arrayvec.rs --- rust-cbindgen-0.23.0/tests/rust/const_generics_arrayvec.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-cbindgen-0.24.3/tests/rust/const_generics_arrayvec.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,17 @@ +#[repr(C)] +pub struct ArrayVec { + // the `len` first elements of the array are initialized + xs: [T; CAP], + len: u32, +} + +#[no_mangle] +pub unsafe extern "C" fn push(v: *mut ArrayVec<*mut u8, 100>, elem: *mut u8) -> i32 { + if (*v).len < 100 { + (*v).xs[(*v).len] = elem; + (*v).len += 1; + 1 + } else { + 0 + } +} diff -Nru rust-cbindgen-0.23.0/tests/rust/const_generics_bool.rs rust-cbindgen-0.24.3/tests/rust/const_generics_bool.rs --- rust-cbindgen-0.23.0/tests/rust/const_generics_bool.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-cbindgen-0.24.3/tests/rust/const_generics_bool.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,57 @@ +use std::mem::MaybeUninit; + +use libc::c_char; + +#[repr(C)] +pub struct HashTable { + num_buckets: usize, + capacity: usize, + occupied: *mut u8, + keys: *mut MaybeUninit, + vals: *mut MaybeUninit, +} + +type Str = *const c_char; +pub type HashMap = HashTable; +pub type HashSet = HashTable; + +impl HashTable +{ + pub fn new() -> Self { + HashTable { + num_buckets: 0, + capacity: 0, + occupied: std::ptr::null_mut(), + keys: std::ptr::null_mut(), + vals: std::ptr::null_mut(), + } + } +} + +// with alias +type MySet = HashTable; + +#[no_mangle] +pub extern "C" fn new_set() -> *mut MySet { + Box::into_raw(Box::new(HashSet::new())) +} + +type SetCallback = unsafe extern "C" fn(key: Str); + +#[no_mangle] +pub unsafe extern "C" fn set_for_each(set: *const MySet, callback: SetCallback) { + todo!(); +} + +// without alias +#[no_mangle] +pub extern "C" fn new_map() -> *mut HashTable { + Box::into_raw(Box::new(HashMap::new())) +} + +type MapCallback = unsafe extern "C" fn(key: Str, val: u64); + +#[no_mangle] +pub unsafe extern "C" fn map_for_each(map: *const HashTable, callback: MapCallback) { + todo!(); +} diff -Nru rust-cbindgen-0.23.0/tests/rust/const_generics_byte.rs rust-cbindgen-0.24.3/tests/rust/const_generics_byte.rs --- rust-cbindgen-0.23.0/tests/rust/const_generics_byte.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-cbindgen-0.24.3/tests/rust/const_generics_byte.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,29 @@ +// Name mangling can cope with char-like byte literals. + +#[repr(C)] +pub struct Parser { + pub buf: *mut u8, + pub len: usize, +} + +#[no_mangle] +pub unsafe extern "C" fn init_parens_parser(p: *mut Parser, buf: *mut u8, len: usize) { + unsafe { + *p = Parser { buf, len }; + } +} + +// The same type as above, because `b'(' == 40 && b')' == 41`. And it happens +// to mangle to the same C identifier. It doesn't always work out that way! +#[no_mangle] +pub unsafe extern "C" fn destroy_parens_parser(p: *mut Parser<40, 41>) { + // nothing to do +} + + +#[no_mangle] +pub unsafe extern "C" fn init_braces_parser(p: *mut Parser, buf: *mut u8, len: usize) { + unsafe { + *p = Parser { buf, len }; + } +} diff -Nru rust-cbindgen-0.23.0/tests/rust/const_generics_char.rs rust-cbindgen-0.24.3/tests/rust/const_generics_char.rs --- rust-cbindgen-0.23.0/tests/rust/const_generics_char.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-cbindgen-0.24.3/tests/rust/const_generics_char.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,20 @@ +use std::marker::PhantomData; + +#[repr(C)] +struct TakeUntil<'a, const V: char> +{ + marker: PhantomData<&'a str>, + start: *const u8, + len: usize, + point: usize, +} + +#[no_mangle] +pub unsafe extern "C" fn until_nul(start: *const u8, len: usize) -> TakeUntil<'a, '\0'> { + TakeUntil { + marker: PhantomData, + start, + len, + point: 0, + } +} diff -Nru rust-cbindgen-0.23.0/tests/rust/const_generics_constant.rs rust-cbindgen-0.24.3/tests/rust/const_generics_constant.rs --- rust-cbindgen-0.23.0/tests/rust/const_generics_constant.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-cbindgen-0.24.3/tests/rust/const_generics_constant.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,18 @@ +#[repr(C)] +pub struct FixedPoint { + value: u16, +} + +pub const FONT_WEIGHT_FRACTION_BITS: u16 = 6; + +pub type FontWeightFixedPoint = FixedPoint; + +#[repr(C)] +pub struct FontWeight(FontWeightFixedPoint); + +impl FontWeight { + pub const NORMAL: FontWeight = FontWeight(FontWeightFixedPoint { value: 400 << FONT_WEIGHT_FRACTION_BITS }); +} + +#[no_mangle] +pub extern "C" fn root(w: FontWeight) {} diff -Nru rust-cbindgen-0.23.0/tests/rust/const_generics_thru.rs rust-cbindgen-0.24.3/tests/rust/const_generics_thru.rs --- rust-cbindgen-0.23.0/tests/rust/const_generics_thru.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-cbindgen-0.24.3/tests/rust/const_generics_thru.rs 1973-11-29 21:33:09.000000000 +0000 @@ -0,0 +1,22 @@ +// Propagating const arguments through generics that use generics. + +#[repr(C)] +pub struct Inner { + pub bytes: [u8; N], +} + +#[repr(C)] +pub struct Outer { + pub inner: Inner, // don't declare two different structs named `Inner_N` +} + +#[no_mangle] +pub extern "C" fn one() -> Outer<1> { + Outer { inner: Inner { bytes: [0] } } +} + +#[no_mangle] +pub extern "C" fn two() -> Outer<2> { + Outer { inner: Inner { bytes: [0, 0] } } +} +