Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explicitly instantiate function return values that are template classes #1024

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
more cleanups
  • Loading branch information
scovich committed Nov 1, 2024
commit 8105224ee2d921518b6aa3b196854c496365654a
9 changes: 4 additions & 5 deletions src/bindgen/ir/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::collections::HashSet;
use std::io::Write;

use syn::ext::IdentExt;
Expand Down Expand Up @@ -317,20 +318,18 @@ impl Enum {
repr.style != ReprStyle::C
}

pub fn find_return_value_monomorphs(
&self,
library: &Library,
out: &mut std::collections::HashSet<GenericPath>,
) {
pub fn find_return_value_monomorphs(&self, library: &Library, out: &mut HashSet<GenericPath>) {
if self.is_generic() {
return;
}

for v in &self.variants {
if let VariantBody::Body { ref body, .. } = v.body {
body.find_return_value_monomorphs(library, out);
}
}
}

pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {
if self.is_generic() {
return;
Expand Down
8 changes: 2 additions & 6 deletions src/bindgen/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +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::collections::HashMap;
use std::collections::{HashMap, HashSet};

use syn::ext::IdentExt;

Expand Down Expand Up @@ -129,11 +129,7 @@ impl Function {
}
}

pub fn find_return_value_monomorphs(
&self,
library: &Library,
out: &mut std::collections::HashSet<GenericPath>,
) {
pub fn find_return_value_monomorphs(&self, library: &Library, out: &mut HashSet<GenericPath>) {
self.ret.find_return_value_monomorphs(library, out, true);
for arg in &self.args {
arg.ty.find_return_value_monomorphs(library, out, false);
Expand Down
16 changes: 7 additions & 9 deletions src/bindgen/ir/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::collections::HashSet;
use std::io::Write;

use syn::ext::IdentExt;
Expand Down Expand Up @@ -168,24 +169,21 @@ impl Struct {

/// Attempts to convert this struct to a typedef (only works for transparent structs).
pub fn as_typedef(&self) -> Option<Typedef> {
match self.fields.first() {
Some(field) if self.is_transparent => Some(Typedef::new_from_struct_field(self, field)),
_ => None,
}
let field = self.fields.first()?;
self.is_transparent
.then(|| Typedef::new_from_struct_field(self, field))
}

pub fn find_return_value_monomorphs(
&self,
library: &Library,
out: &mut std::collections::HashSet<GenericPath>,
) {
pub fn find_return_value_monomorphs(&self, library: &Library, out: &mut HashSet<GenericPath>) {
if self.is_generic() {
return;
}

for field in &self.fields {
field.ty.find_return_value_monomorphs(library, out, false);
}
}

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.
Expand Down
13 changes: 6 additions & 7 deletions src/bindgen/ir/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::borrow::Cow;
use std::collections::HashSet;

use syn::ext::IdentExt;

Expand Down Expand Up @@ -742,19 +743,17 @@ impl Type {
pub fn find_return_value_monomorphs(
&self,
library: &Library,
out: &mut std::collections::HashSet<GenericPath>,
is_function_ret_val: bool,
out: &mut HashSet<GenericPath>,
is_return_value: bool,
) {
match *self {
Type::Ptr { ref ty, .. } => ty.find_return_value_monomorphs(library, out, false),
Type::Path(ref generic) => {
if !is_function_ret_val || generic.generics().is_empty() {
if !is_return_value || generic.generics().is_empty() {
return;
}
let Some(items) = library.get_items(generic.path()) else {
return;
};
for item in items {

for item in library.get_items(generic.path()).into_iter().flatten() {
match item {
// Constants and statics cannot be function return types
ItemContainer::Constant(_) | ItemContainer::Static(_) => {}
Expand Down
9 changes: 5 additions & 4 deletions src/bindgen/ir/typedef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +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::collections::HashMap;
use std::collections::{HashMap, HashSet};

use syn::ext::IdentExt;

Expand Down Expand Up @@ -105,14 +105,15 @@ impl Typedef {
pub fn find_return_value_monomorphs(
&self,
library: &Library,
out: &mut std::collections::HashSet<GenericPath>,
is_function_ret_val: bool,
out: &mut HashSet<GenericPath>,
is_return_value: bool,
) {
if !self.is_generic() {
self.aliased
.find_return_value_monomorphs(library, out, is_function_ret_val);
.find_return_value_monomorphs(library, out, is_return_value);
}
}

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.
Expand Down
8 changes: 3 additions & 5 deletions src/bindgen/ir/union.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::collections::HashSet;
use syn::ext::IdentExt;

use crate::bindgen::config::{Config, LayoutConfig};
Expand Down Expand Up @@ -100,14 +101,11 @@ impl Union {
}
}

pub fn find_return_value_monomorphs(
&self,
library: &Library,
out: &mut std::collections::HashSet<GenericPath>,
) {
pub fn find_return_value_monomorphs(&self, library: &Library, out: &mut HashSet<GenericPath>) {
if self.is_generic() {
return;
}

for field in &self.fields {
field.ty.find_return_value_monomorphs(library, out, false);
}
Expand Down
32 changes: 13 additions & 19 deletions src/bindgen/library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +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::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::path::PathBuf;

use crate::bindgen::bindings::Bindings;
Expand Down Expand Up @@ -457,35 +457,29 @@ impl Library {
}

fn instantiate_return_value_monomorphs(&mut self, dependencies: &mut Dependencies) {
let mut found = std::collections::HashSet::new();
self.structs.for_all_items(|x| {
x.find_return_value_monomorphs(self, &mut found);
});
self.unions.for_all_items(|x| {
x.find_return_value_monomorphs(self, &mut found);
});
self.enums.for_all_items(|x| {
x.find_return_value_monomorphs(self, &mut found);
});
self.typedefs.for_all_items(|x| {
x.find_return_value_monomorphs(self, &mut found, false);
});
let mut found = HashSet::new();
self.structs
.for_all_items(|x| x.find_return_value_monomorphs(self, &mut found));
self.unions
.for_all_items(|x| x.find_return_value_monomorphs(self, &mut found));
self.enums
.for_all_items(|x| x.find_return_value_monomorphs(self, &mut found));
self.typedefs
.for_all_items(|x| x.find_return_value_monomorphs(self, &mut found, false));
for x in &self.functions {
x.find_return_value_monomorphs(self, &mut found);
}

// Emit all instantiated monomorphs as fields of a giant struct, which silences warnings
// Emit all instantiated monomorphs as fields of a dummy struct, which silences warnings
// and errors on several compilers.
let struct_name = match self.config.export.return_value_monomorphs_struct_name {
Some(ref name) => name,
_ => "__cbindgen_monomorph_struct",
_ => "__cbindgen_return_value_monomorphs",
};
let fields = found
.into_iter()
.enumerate()
.map(|(i, path)| {
Field::from_name_and_type(format!("field{}", i), Type::Path(path))
})
.map(|(i, path)| Field::from_name_and_type(format!("field{}", i), Type::Path(path)))
.collect();
let monomorph_struct = Struct::new(
Path::new(struct_name),
Expand Down
Loading