Issue 170: an == fails (vs. neko, js, flash). guessing incorrect types generated for cpp.
Status:  Fixed
Owner: ----
Closed:  May 2012
Reported by rao...@gmail.com, Apr 28, 2012
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.

HxcppBug.zip
42.9 KB   Download
Apr 28, 2012
#1 rao...@gmail.com
the first .zip file has a slightly incorrect Makefile. i'm attaching a new zip with a more correct Makefile. it doesn't change the results, but makes the 3 different targets all have the asserts (oopsy) to truly show that hxcpp is different. (i think.)

HxcppBug.zip
42.9 KB   Download
Apr 29, 2012
#2 rao...@gmail.com
ok whittled down the code even more, this is more minimal, see attachment.
HxcppBug.zip
13.5 KB   Download
May 3, 2012
#3 rao...@gmail.com
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
#4 rao...@gmail.com
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
Project Member #5 gameh...@gmail.com
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
#6 rao...@gmail.com
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
#7 rao...@gmail.com
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.

HxcppRayBug.zip
17.3 KB   Download
May 8, 2012
#8 rao...@gmail.com
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
#9 rao...@gmail.com
(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
Project Member #10 gameh...@gmail.com
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
Project Member #11 gameh...@gmail.com
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
Project Member #12 gameh...@gmail.com
Should be fixed on SVN now
Status: Fixed