cbindgen icon indicating copy to clipboard operation
cbindgen copied to clipboard

Const generics: Constants using const generic structs don't quite work.

Open emilio opened this issue 2 years ago • 3 comments

cc @jorendorff (not sure of a great fix for this, for the record, filing so that I don't lose track of it).

I wanted to do something like this today:

#[repr(C)]
pub struct FixedPoint<const FRACTION_BITS: u16> {
    value: u16,
}

pub const FONT_WEIGHT_FRACTION_BITS: u16 = 6;

#[repr(C)]
pub struct FontWeight(FixedPoint<FONT_WEIGHT_FRACTION_BITS>);

impl FontWeight {
    pub const NORMAL: FontWeight = FontWeight(FixedPoint { value: 400 << FONT_WEIGHT_FRACTION_BITS });
}

#[no_mangle]
pub extern "C" fn root(w: FontWeight) {}

That generates:

#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>

constexpr static const uint16_t FONT_WEIGHT_FRACTION_BITS = 6;

template<uint16_t FRACTION_BITS>
struct FixedPoint {
  uint16_t value;
};

struct FontWeight {
  FixedPoint<FONT_WEIGHT_FRACTION_BITS> _0;
};
constexpr static const FontWeight FontWeight_NORMAL = FontWeight{ /* ._0 = */ FixedPoint{ /* .value = */ (400 << FONT_WEIGHT_FRACTION_BITS) } };

extern "C" {

void root(FontWeight w);

} // extern "C"

Which looks like it could compile, but doesn't:

out.cpp:17:79: error: use of class template 'FixedPoint' requires template arguments
constexpr static const FontWeight FontWeight_NORMAL = FontWeight{ /* ._0 = */ FixedPoint{ /* .value = */ (400 << FONT_WEIGHT_FRACTION_BITS) } };
                                                                              ^
out.cpp:10:8: note: template is declared here
struct FixedPoint {
       ^
1 error generated.

A workaround could be adding a type alias:

#[repr(C)]
pub struct FixedPoint<const FRACTION_BITS: u16> {
    value: u16,
}

pub const FONT_WEIGHT_FRACTION_BITS: u16 = 6;

pub type FontWeightFixedPoint = FixedPoint<FONT_WEIGHT_FRACTION_BITS>;

#[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) {}

But that doesn't quite cut it either because it doesn't generate the inner expression:

constexpr static const FontWeight FontWeight_NORMAL = FontWeight{ /* ._0 = */ FontWeightFixedPoint{  } };

I think that should be fixable tho.

emilio avatar Jun 09 '22 17:06 emilio

https://github.com/eqrion/cbindgen/pull/768 allows the workaround to well, work.

emilio avatar Jun 09 '22 17:06 emilio

Fwiw, not 100% sure but with cbindgen 0.24.3 i fail to build mozilla-beta (actually 102.0b6), which fails this way:

In file included from Unified_cpp_accessible_base0.cpp:119: 
In file included from /usr/obj/ports/firefox-102.0beta6/firefox-102.0/accessible/base/FocusManager.cpp:21:                                                                                                          
In file included from /usr/obj/ports/firefox-102.0beta6/build-amd64/dist/include/mozilla/dom/BrowserParent.h:23:
In file included from /usr/obj/ports/firefox-102.0beta6/build-amd64/dist/include/mozilla/layout/RemoteLayerTreeOwner.h:17:
In file included from /usr/obj/ports/firefox-102.0beta6/build-amd64/dist/include/nsDisplayList.h:48:                                                                                                                 
In file included from /usr/obj/ports/firefox-102.0beta6/build-amd64/dist/include/nsCSSRenderingBorders.h:20:                                                                                                         
In file included from /usr/obj/ports/firefox-102.0beta6/build-amd64/dist/include/gfxUtils.h:23:                                                                                                                      
In file included from /usr/obj/ports/firefox-102.0beta6/build-amd64/dist/include/mozilla/webrender/WebRenderTypes.h:11:                                                                                              
In file included from /usr/obj/ports/firefox-102.0beta6/build-amd64/dist/include/mozilla/webrender/webrender_ffi.h:104:                                                                                              
/usr/obj/ports/firefox-102.0beta6/build-amd64/dist/include/mozilla/webrender/webrender_ffi_generated.h:24:33: error: redefinition of 'ROOT_CLIP_CHAIN'                                                               
constexpr static const uint64_t ROOT_CLIP_CHAIN = ~0;^
/usr/obj/ports/firefox-102.0beta6/build-amd64/dist/include/mozilla/webrender/webrender_ffi.h:76:16: note: previous definition is here
const uint64_t ROOT_CLIP_CHAIN = ~0;
               ^
1 error generated.  

im not saying this is due/related to this issue but i had no issue building 102.0b5 with cbindgen 0.23.0 on OpenBSD. Will revert cbindgen to 0.24.2 to check if that's related to this issue or to other commits done since 0.23.0.

landryb avatar Jun 11 '22 14:06 landryb

That's known, and it's not a cbindgen bug. Removing the manual definition from webrender_ffi.h should fix this. See https://bugzilla.mozilla.org/show_bug.cgi?id=1773259#c5 and following.

emilio avatar Jun 12 '22 10:06 emilio