diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 385373f40b..6495848e3a 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1861,7 +1861,6 @@ impl CodeGenerator for CompInfo { } let mut generic_param_names = vec![]; - let mut generic_params = vec![]; let used_dependent_qualified_types = item.used_dependent_qualified_types(ctx); @@ -1887,33 +1886,26 @@ impl CodeGenerator for CompInfo { } } - let empty = vec![]; + let mut where_constraints: std::collections::HashMap< + Ident, + Vec, + > = std::collections::HashMap::new(); for (idx, ty) in item.used_template_params(ctx).iter().enumerate() { let param = ctx.resolve_type(*ty); - let dependent_qualified_type_field_names = - dependent_qualified_types_by_param.get(ty).unwrap_or(&empty); - let name = param.name().unwrap(); let ident = ctx.rust_ident(name); - generic_param_names.push(ident.clone()); - let mut this_generic = quote! { - #ident - }; - for (count, field_name) in - dependent_qualified_type_field_names.into_iter().enumerate() + if let Some(dependent_qualified_type_field_names) = + dependent_qualified_types_by_param.get(ty) { - let trait_name = ctx.inner_type_trait_ident(field_name); - this_generic.extend(if count == 0 { - quote! { - : #trait_name - } - } else { - quote! { - + #trait_name - } - }); + where_constraints.entry(ident.clone()).or_default().extend( + dependent_qualified_type_field_names.into_iter().map( + |field_name| ctx.inner_type_trait_ident(field_name), + ), + ); } + generic_param_names.push(ident.clone()); + let prefix = ctx.trait_prefix(); let field_name = ctx.rust_ident(format!("_phantom_{}", idx)); fields.push(quote! { @@ -1921,12 +1913,12 @@ impl CodeGenerator for CompInfo { ::#prefix::cell::UnsafeCell<#ident> > , }); - generic_params.push(this_generic); } - let generics = if !generic_params.is_empty() { + let generics = if !generic_param_names.is_empty() { + let generic_param_names = generic_param_names.clone(); quote! { - < #( #generic_params ),* > + < #( #generic_param_names ),* > } } else { quote! {} @@ -2013,8 +2005,28 @@ impl CodeGenerator for CompInfo { } }; + let mut where_constraints_ts = quote! {}; + if !where_constraints.is_empty() { + for (i, (k, traits)) in where_constraints.into_iter().enumerate() { + let prefix = if i == 0 { + quote! { where } + } else { + quote! { , } + }; + where_constraints_ts.extend(quote! { #prefix #k }); + for (j, v) in traits.into_iter().enumerate() { + let sep = if j == 0 { + quote! {:} + } else { + quote! {+} + }; + where_constraints_ts.extend(quote! { #sep #v }); + } + } + } + tokens.append_all(quote! { - #generics { + #generics #where_constraints_ts { #( #fields )* } }); diff --git a/tests/expectations/tests/inner_type_complex.rs b/tests/expectations/tests/inner_type_complex.rs index 9ac1a4490c..11d14eb340 100644 --- a/tests/expectations/tests/inner_type_complex.rs +++ b/tests/expectations/tests/inner_type_complex.rs @@ -54,7 +54,10 @@ fn bindgen_test_layout_InnerType() { } #[repr(C)] #[derive(Debug, Default, Copy, Clone)] -pub struct Container { +pub struct Container +where + ContainedType: __bindgen_has_inner_type_related_type, +{ pub contents_: Container_content_ty, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, diff --git a/tests/expectations/tests/inner_type_simpler.rs b/tests/expectations/tests/inner_type_simpler.rs index 70802df6bd..47b120a34d 100644 --- a/tests/expectations/tests/inner_type_simpler.rs +++ b/tests/expectations/tests/inner_type_simpler.rs @@ -41,7 +41,10 @@ fn bindgen_test_layout_InnerType() { } #[repr(C)] #[derive(Debug, Default, Copy, Clone)] -pub struct Container { +pub struct Container +where + ContainedType: __bindgen_has_inner_type_related_type, +{ pub contents_: ::related_type, pub _phantom_0: diff --git a/tests/expectations/tests/inner_type_two.rs b/tests/expectations/tests/inner_type_two.rs index f026698bcc..94a51d3b2f 100644 --- a/tests/expectations/tests/inner_type_two.rs +++ b/tests/expectations/tests/inner_type_two.rs @@ -88,7 +88,10 @@ fn bindgen_test_layout_InnerTypeB() { } #[repr(C)] #[derive(Debug, Default, Copy, Clone)] -pub struct Container { +pub struct Container +where + ContainedType: __bindgen_has_inner_type_related_type, +{ pub contents_: Container_content_ty, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, diff --git a/tests/expectations/tests/issue-544-stylo-creduce-2.rs b/tests/expectations/tests/issue-544-stylo-creduce-2.rs index f4e89b8f56..80bc569a68 100644 --- a/tests/expectations/tests/issue-544-stylo-creduce-2.rs +++ b/tests/expectations/tests/issue-544-stylo-creduce-2.rs @@ -7,13 +7,17 @@ #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct Foo { +pub struct Foo +where + T: __bindgen_has_inner_type_Associated, +{ pub member: Foo_SecondAlias, + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, } pub type Foo_FirstAlias = ::Associated; -pub type Foo_SecondAlias = Foo; -impl Default for Foo { +pub type Foo_SecondAlias = Foo; +impl Default for Foo { fn default() -> Self { unsafe { ::std::mem::zeroed() } }