| Issue 170: | an == fails (vs. neko, js, flash). guessing incorrect types generated for cpp. | |
| 2 people starred this issue and may be notified of changes. | Back to list |
What steps will reproduce the problem? 1. use the attached Zip file, see the README in it. What is the expected output? Tests pass. What do you see instead? Assertion failure. What version of the product are you using? On what operating system? Haxe/neko 2.09 Nme 3.3.1 Hxcpp 2.09 Mac OS X 10.7.3 XCode 4.3 gcc i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00) Please provide any additional information below. see attached zip and README inside it.
Apr 29, 2012
ok whittled down the code even more, this is more minimal, see attachment.
May 3, 2012
so what i think is going on is that the "head" and the incoming "t" to DLList.remove(t:T) are compared, and in hxcpp they are not-equal, but in other targets (js, neko) they are equal.
May 3, 2012
so i am guessing that the way type parameters / generics / references are transliterated from haxe to cpp along with how equals is transliterated ends up causing this difference in behaviour.
May 3, 2012
Hi, I have not had time to look at this, but are your dealing with interfaces? A new interface object is created every time a "real" object is passed to a function that takes in interface. The comparison needs to look at the real object, but perhaps this in not happening - this could be the problem. HUgh
May 4, 2012
hi, thanks for thinking about this. it was guessing that it was more the <T> generics since when i look at the C++ code it is using Dynamic. (i will experiment to see if the particular failure involves interfaces, too.)
May 8, 2012
another different-but-related failure. and a better .zip of the code that reproduces it for me. the Makefile target "all" will run 2 tests, one time on neko, one time hxcpp, so you can see that neko passes (js does too i believe) but hxcpp fails.
May 8, 2012
the code uses "generics" that are constrained by interface:
interface IPool<T:IDLNode<T>> {}
class Pool<T:IDLNode<T>> implements IPool<T> {)
May 8, 2012
(is Dynamic maybe causing things to avoid pointer comparison? or there's too many wrapper instances so the pointers don't end up comparing right?)
looking at the code for cpp-fails2 from the latest .zip:
RayPool.cpp line 211 is:
bool valid = this->allocated->__Field(HX_CSTRING("remove"),true)(t);
that returns false, when it should return true (as in neko etc.).
that line of code is inside:
bool RayPool_obj::recycle( Dynamic _tmp_t){
where
Dynamic t = _tmp_t;
and the allocated variable is at line 31:
this->allocated = Dynamic( Array_obj<Dynamic>::__new() );
May 9, 2012
Hi,
I did some work narrowing it down (that is some pretty complex code - you must love interfaces!) and have a simpler example, so I should be able to get onto it soon. It looks like it might be in the generic version of array remove.
interface IDLNode<T:IDLNode<T>> { }
interface IPool<T:IDLNode<T>> {
function getCount():Int;
function allocate( ?d:Dynamic ):T;
function recycle( t:T ):Bool;
function recycleAll():Void;
}
class RayPool<T:IDLNode<T>>
implements IPool<T> {
public var name(default,null):String;
public var count(getCount,null):Int;
private var allocated:Array<T>;
private var malloc:Dynamic->T;
public function new( name:String, malloc:Dynamic->T ) {
this.name = name;
this.allocated = new Array<T>();
this.malloc = malloc;
}
public function getCount() {
return allocated.length;
}
public function allocate( ?d:Dynamic ):T {
var e:T;
e = malloc( d );
if( e != null ) {
allocated.push( e );
}
return e;
}
public function recycle( t:T ):Bool {
var valid = allocated.remove( t );
if (!valid)
throw ("Could not find " + t + " in "+ allocated ) ;
return valid;
}
public function recycleAll():Void {
allocated = new Array<T>();
}
}
interface IPoolSet
implements IDLNode<IPoolSet> {
function recycleAll():Void;
}
class PSV2
implements IDLNode<PSV2> {
public static var allocForPool = function(_:Dynamic) { return new PSV2(); };
public function new() { }
}
class RayPoolSet
implements IPoolSet {
static var id = 0;
var mID:Int;
public static var allocForPool = function(name:Dynamic) { return new RayPoolSet(name); };
private var name:String;
public var vectors:RayPool<PSV2>;
public function new( name:String ) {
this.name = name;
mID = id++;
this.vectors = new RayPool<PSV2>( "vectors", PSV2.allocForPool );
}
public function toString() { return "RayPoolSet " + mID; }
public function recycleAll():Void {
vectors.recycleAll();
}
}
class Main
{
static function main():Void
{
var pools:IPool<IPoolSet> = new RayPool<IPoolSet>( "pools", RayPoolSet.allocForPool );
var ps = pools.allocate( "test" );
trace("Pools before : " + pools.getCount());
ps.recycleAll();
pools.recycle( ps );
trace("Pools after : " + pools.getCount());
}
}
May 9, 2012
Ok, got it simpler:
interface I
{
public function foo():Void;
}
class C implements I
{
public function new() {}
public function foo():Void { }
}
class Main
{
static function main():Void
{
var a = new Array<Dynamic>();
var c = new C();
var i1:I = c;
var i2:I = c;
a.push(i1);
trace(a.remove(i2));
}
}
May 9, 2012
Should be fixed on SVN now
Status:
Fixed
|
42.9 KB Download