[cs] DCE seems to strip interfaces fields when using theirs in abstract inline functions
I met compilation error (error CS1061: Type `haxe.IMap<object,int>' does not contain a definition for `keys' and no extension method `keys' of type `haxe.IMap<object,int>' could be found. Are you missing an assembly reference?) when try to compile next code:
This can be workarounded one of next ways:
- Removing
inlinefromEquatableMap#tryGetKey - Adding
--macro keep("haxe.Constraints.IMap")inbuild.hxml - Move declaration of
Main#fooMaptomain
Main.hx
package;
import haxe.Constraints.IMap;
import haxe.ds.ObjectMap;
interface IEquatable<T> {
function equals(other:T):Bool;
}
@:multiType(K)
abstract EquatableMap<K, V>(IMap<K, V>) {
public function new();
public inline function containsKey(key:K):Bool {
key = tryGetKey(key);
return this.exists(key);
}
inline function tryGetKey(key:K):K {
var result = key;
if(Std.is(key, IEquatable)) {
var keyHolder:IEquatable<Dynamic> = cast key;
for(it in this.keys()) {
var currentKeyHolder:IEquatable<Dynamic> = cast it;
if(currentKeyHolder.equals(keyHolder)) {
result = it;
break;
}
}
}
return result;
}
@:to static inline function toObjectMap<K:{}, V>(t:IMap<K, V>):ObjectMap<K,V> {
return new ObjectMap<K, V>();
}
}
class Foo implements IEquatable<Foo> {
public function new() {
}
public function equals(other:Foo):Bool {
return this == other;
}
}
class Main {
private static var fooMap:EquatableMap<Foo, Int> = new EquatableMap<Foo, Int>();
public static function main():Void {
var foo:Foo = new Foo();
var exists:Bool = fooMap.containsKey(foo);
trace(exists);
}
}
build.hxml
-cs output/
-cp .
-main Main
-dce full
-debug
-D real-position
-cmd mono output/bin/Main-Debug.exe
Console output
$ haxe build.hxml
haxelib run hxcs hxcs_build.txt --haxe-version 3402 --feature-level 1
Note: dmcs is deprecated, please use mcs instead!
src/Main.cs(145,24): error CS1061: Type `haxe.IMap<object,int>' does not contain a definition for `keys' and no extension method `keys' of type `haxe.IMap<object,int>' could be found. Are you missing an assembly reference?
src/haxe/Constraints.cs(5,19): (Location of the symbol related to previous error)
Compilation failed: 1 error(s), 0 warnings
Compilation error
Native compilation failed
Error: Build failed
Minimal reproducible example without maps and generics (using the same build.hxml):
Main.hx
package;
interface IInterface {
function interfaceMethod1():Void;
function interfaceMethod2():Void;
}
class InterfaceImplementation implements IInterface {
public function new() {}
public function interfaceMethod1():Void {
trace('interfaceMethod1');
}
public function interfaceMethod2():Void {
trace('interfaceMethod2');
}
}
@:multiType
abstract AbstractOnInterface(IInterface) {
public function new();
public inline function abstractMethod1():Void {
abstractMethod2();
this.interfaceMethod1();
}
public inline function abstractMethod2():Void {
this.interfaceMethod2();
}
@:to static inline function toObject(t:IInterface):InterfaceImplementation {
return new InterfaceImplementation();
}
}
class Main {
private static var abstractOnInterface:AbstractOnInterface = new AbstractOnInterface();
public static function main():Void {
abstractOnInterface.abstractMethod1();
}
}
Console output:
$ haxe build.hxml
haxelib run hxcs hxcs_build.txt --haxe-version 3402 --feature-level 1
Note: dmcs is deprecated, please use mcs instead!
src/Main.cs(133,9): error CS1061: Type `IInterface' does not contain a definition for `interfaceMethod2' and no extension method `interfaceMethod2' of type `IInterface' could be found. Are you missing an assembly reference?
src/Main.cs(4,18): (Location of the symbol related to previous error)
Compilation failed: 1 error(s), 0 warnings
Compilation error
Native compilation failed
Error: Build failed
I also encountered this when doing my Reflaxe/Dart target (although tbf it could be me implementing it wrong) having to add @:keep to IMap to stop it from DCEing the fields.
Hmm, seems like we missed some C# issues. See #11551 (or provide a way to reproduce this on other targets and reopen)