Closed Atry closed 9 years ago
It seems that the test code is breaking on php now
@Simn, can you have a look? I still haven't disabled the test, ok?
I don't know how to address this, someone with any notion of PHP knowledge will have to check it.
class Main {
static function main() {
var s = Something;
var fn = s.somefunc;
fn();
}
}
@:keep private class Something {
public static function somefunc() {
trace("Hello World");
}
}
Generated code:
class Main {
public function __construct(){}
static function main() {
$s = _hx_qtype("_Main.Something");
$fn = (isset($s->somefunc) ? $s->somefunc: array($s, "somefunc"));
call_user_func($fn);
}
function __toString() { return 'Main'; }
}
This then fails with uncaught exception: call_user_func() expects parameter 1 to be a valid callback, class 'ReflectionClass' does not have a method 'somefunc' (errno: 2)
.
My uneducated guess is that the isset
fails and the call is made on that array
thing, which doesn't take into account some magical __call
function.
I will probably not look into this for 3.2. unless some PHP expert wants to chime in (ping @mockey, @tml).
For a static function somefunc
the call must be $s::$somefunc
.
$fn = (isset($s::$somefunc) ? $s::$somefunc: array($s, "somefunc"));
works, but I don't know where this is generated and I don't know if this array-access is correct...
It's generated in this general area: https://github.com/HaxeFoundation/haxe/blob/development/genphp.ml#L956
Ah, I think I understand now. array($s, "somefunc")
is apparently the fallback for a static function. Hm, that's pretty awful, actually.
Anyway, it seems that _hx_qtype("_Main.Something");
is the problem then. It returns "_Main.Something"
and it should be "_Main_Something"
.
Where does that hx_qtype
come from? Is that used somewhere else? I thought it returns a string but it's actually some kind of class construct.
There's a bunch of PHP defines in php/Boot.hx: https://github.com/HaxeFoundation/haxe/blob/development/std/php/Boot.hx#L540
Actually, iiuc the flow correctly, the _hx_qtype
call is returning the wrapped class, whose __call
method returns a ReflectionClass instance instead of a callable. I'm digging into Boot.hx to wrap my head around what the right thing is here.
Yeah, this is beyond me.
isset($s->somefunc)
is actually true for a static function (!), but that seems to be normal (I tried with haxe.Log.trace
), then $s->somefunc
is called and that __call -> __dynamics -> ReflectionClass
magic goes loose (but fails).
I might have a fix for that now in php.Boot.hx. Not sure if this breaks something but unit-tests seem to run OK. PR?
Sure!
isset($s->somefunc) is actually true for a static function (!)
Right, that's because of this block in _hx_type
.
Done. BTW: This travis-condition for the SPOD tests is still there in Test.hx. I have changed it locally for now.
@tml:
Yes, I think I understand now a bit better what's going on there. Lots of magic functions. A bit difficult to understand when you read the PHP-code. Did you see my fix? __get
returned an array($r, $n)
, $r
being the ReflectionClass
, now it's array($r->name, $n)
, class name and function name. I guess this was meant to be passed to call_user_func
. Makes sense?
Yeah, I saw your fix and it does make sense here, I'm just worried about what else it might affect. The other option I thought of was to add 'is_callable' into the conditional in genphp.ml, but that level of ML is beyond me at the moment, and I'm not entirely convinced it's provably a better solution.
@tml:
I thought maybe that returned array was meant to be like this. I can't really think of a situation where passing array(ReflectionClass, $function_name)
makes sense. But you never know...
Fixed in #3904.