Functions which take Void as an argument cause the C++ compiler to error
package;
class Main {
public static function main():Void {
var x:(Void)->Void = _ -> {
// bad function
}
}
}
Compiling this code gives an error from the C++ compiler:
$ haxe --cpp out Main.hx
haxelib run hxcpp Build.xml haxe -Dhaxe="4.3.7" -Dhaxe3="1" -Dhaxe4="1" -Dhaxe_ver="4.307" -Dhxcpp_api_level="430" -Dhxcpp_smart_strings="1" -Dsource_header="Generated by Haxe 4.3.7" -Dstatic="1" -Dtarget.atomics="1" -Dtarget.name="cpp" -Dtarget.static="1" -Dtarget.sys="1" -Dtarget.threaded="1" -Dtarget.unicode="1" -Dtarget.utf16="1" -Dutf16="1" -I -I/usr/share/haxe/std/cpp/_std/ -I/usr/share/haxe/std/
Creating /home/user/bug_report_hxcpp/out/obj/linux64/__pch/haxe/hxcpp.h.gch...
Compiling group: haxe
g++ -Iinclude -c -fvisibility=hidden -O2 -fpic -fPIC -Wno-overflow -DHX_LINUX -DHXCPP_M64 -DHXCPP_VISIT_ALLOCS(haxe) -DHX_SMART_STRINGS(haxe) -DHXCPP_API_LEVEL=430(haxe) -m64 -DHXCPP_M64 -I/home/user/haxe/hxcpp/4,3,2/include ... tags=[haxe,static]
- src/Main.cpp
Error: ./src/Main.cpp: In static member function ‘static void Main_obj::main()’:
./src/Main.cpp:29:43: error: invalid use of type ‘void’ in parameter declaration
29 | void _hx_run(void _){
| ~~~~~^
On other targets, this compiles without emitting an error. I am using Linux, Haxe version 4.3.7, hxcpp version 4.3.2, and g++ version 15.1.1
The syntax Void->Void doesn't mean that the function takes Void as an argument (Void cannot be used as a value in haxe) but rather that it accepts no arguments. So assigning it to a function which does have one argument _ -> {} causes the problem, what you want to do is assign a function which accepts no arguments () -> {}.
This only "works" due to a very cursed haxe "feature" involving dynamic and function arguments, In your case _ defaults to dynamic since it's not explicitly typed or infered from use.
https://github.com/HaxeFoundation/haxe/wiki/Haxe-function-typing-incompatibilities-with-static-targets
Strictly speaking hxcpp should support this to match other targets but there's no reason to be writing code like this so I have no intention in changing it.
I wrote (Void)->Void, which is interpreted as a function taking a Void argument.
Changing it to Void->Void fails to compile (as expected):
Main.hx:5: lines 5-7 : (_ : Unknown<0>) -> Void should be () -> Void
The code I wrote was somewhat of a bad example, but it could be confusing if you're using inferred types, for example:
static function foo<T>(func:(Int, T)->T) {
// ...
}
public static function main():Void {
foo((x, y) -> 5);
// y is inferred here to be Void, because the return is also Void.
foo((x, y) -> {
trace("Hello, World!");
});
}
This gives the same error as the other example, and no information as to which line is causing the problem.
I wonder if https://github.com/HaxeFoundation/haxe/pull/11558 might turn the (Void)->Void case into a haxe-side compiler error.