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

[cs] DCE seems to strip interfaces fields when using theirs in abstract inline functions #6473

Closed
romanmikhailov opened this issue Jul 28, 2017 · 3 comments
Labels
platform-cs Everything related to c#
Milestone

Comments

@romanmikhailov
Copy link

romanmikhailov commented Jul 28, 2017

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:

  1. Removing inline from EquatableMap#tryGetKey
  2. Adding --macro keep("haxe.Constraints.IMap") in build.hxml
  3. Move declaration of Main#fooMap to main

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
@romanmikhailov
Copy link
Author

romanmikhailov commented Jul 28, 2017

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

@romanmikhailov romanmikhailov changed the title DCE seems to strip interfaces fields when using theirs in abstract inline functions [cs] DCE seems to strip interfaces fields when using theirs in abstract inline functions Aug 1, 2017
@Simn Simn added the platform-cs Everything related to c# label Apr 17, 2018
@Simn Simn added this to the Bugs milestone Apr 17, 2018
@Simn Simn modified the milestones: Bugs, Later Mar 24, 2023
@fourst4r
Copy link
Contributor

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.

@kLabz
Copy link
Contributor

kLabz commented Jul 19, 2024

Hmm, seems like we missed some C# issues.
See #11551 (or provide a way to reproduce this on other targets and reopen)

@kLabz kLabz closed this as not planned Won't fix, can't repro, duplicate, stale Jul 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platform-cs Everything related to c#
Projects
None yet
Development

No branches or pull requests

4 participants