See this 3v4l (contents at bottom of the message): http://3v4l.org/pHkf7
I think Bar::bar() should definitely return 'Bar' (currently returns 'Foo')
but what about the Bar::Baz() call?
Until today I didn't even know you could declare a static anonymous
function, so I'm not really sure what the expected behavior is.
Script contents:
<?php
class Foo {
static function bar() {
$foo = static function() {
return get_called_class()
;
};
return $foo();
}
static function baz() {
$foo = function() {
return get_called_class()
;
};
return $foo();
}
}
class Bar extends Foo {
}
assert(Bar::bar() === 'Bar');
assert(Bar::baz() === 'Bar');
Hi
See this 3v4l (contents at bottom of the message): http://3v4l.org/pHkf7
I think Bar::bar() should definitely return 'Bar' (currently returns 'Foo')
but what about the Bar::Baz() call?Until today I didn't even know you could declare a static anonymous
function, so I'm not really sure what the expected behavior is.Script contents:
<?phpclass Foo {
static function bar() {
$foo = static function() {
returnget_called_class()
;
};
From what I gather, the use of static on closures only limits as to what you can bind it to, i.e. ->bindTo() will not accept an instance to bind to.
return $foo();
}
static function baz() {
$foo = function() {
returnget_called_class()
;
};return $foo();
}
}class Bar extends Foo {
}
assert(Bar::bar() === 'Bar');
assert(Bar::baz() === 'Bar');
I think Bar::bar() should definitely return 'Bar' (currently returns
'Foo') but what about the Bar::Baz() call?
I kinda agree, but that ship has sailed and it would be a BC break.
You can do $foo->bindTo(null,Bar) even if the closure is static.
Actually, it seems that when you call the parent function statically,
the child closure is considered static no matter what else you do. So
even force-running a parent function statically at runtime
(disregarding the warning) means it and its child closures will
behave as if they had the static
keyword.
I note in your 3v4l that HHVM does not follow the same rules.
-- S.
Hi!
Until today I didn't even know you could declare a static anonymous
function, so I'm not really sure what the expected behavior is.
Static anon function means no $this is captured if this function is
declared within method and no $this will be available inside.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
There was a reply to this list from Sanford Whiteman which I never
received: http://marc.info/?l=php-internals&m=139959267615452&w=2
Contents posted below:
I think Bar::bar() should definitely return 'Bar' (currently returns
'Foo') but what about the Bar::Baz() call?
I kinda agree, but that ship has sailed and it would be a BC break.
You can do $foo->bindTo(null,Bar) even if the closure is static.
Actually, it seems that when you call the parent function statically,
the child closure is considered static no matter what else you do. So
even force-running a parent function statically at runtime
(disregarding the warning) means it and its child closures
will behave as if they had the static
keyword.
I note in your 3v4l that HHVM does not follow the same rules.
-- S.
On Sat, May 10, 2014 at 9:12 PM, Levi Morrison morrison.levi@gmail.comwrote:
I think Bar::bar() should definitely return 'Bar' (currently returns
'Foo') but what about the Bar::Baz() call?I kinda agree, but that ship has sailed and it would be a BC break.
Yes... but we fix bugs all the time that are technically BC breaks. Do you
really think we shouldn't fix this?
I note in your 3v4l that HHVM does not follow the same rules.
I think HHVM gets the Bar::bar() case correct and we should fix it.
I'm not sure if I agree with HHVM's outcome on Bar::baz(). To me the
closure is non-static which means it won't invoke late static binding. This
is something I'd like to discuss; what do you guys think about that?
Another option is to implicitly promote closures inside of static contexts
to be also be static; this is basically what HHVM does.
Yes... but we fix bugs all the time that are technically BC breaks. Do you
really think we shouldn't fix this?
My thought was: if there's a place for get_called_class()
in a closure
in production code, it's been tested to expect the current behavior.
Every time I've used g_c_c() it was to set up some delicate runtime
logic.
But if g_c_c() always returns the compile-time class of the parent
method, that's a value you already know from inspecting the code. So
the call is likely unnecessary. It could come from cut-and-paste...
things happen. But probably not doing anything that can't be done
without it.
So I'm coming around to agreeing on a necessary BC break.
Another option is to implicitly promote closures inside of static contexts
to be also be static; this is basically what HHVM does.
PHP does this! That's why you get 'Cannot bind an instance to a static
closure' if you closure->bindTo() inside a static method, even if the
closure itself is not keyworded static
.
The difference between HHVM and PHP is the default class scope of the
closure. PHP makes the decision that the owning class scope of the
closure is the compile-time class of the parent method. Why this was
done I couldn't say.
-- S.
Another option is to implicitly promote closures inside of static
contexts
to be also be static; this is basically what HHVM does.
PHP does this! That's why you get 'Cannot bind an instance to a static
closure' if you closure->bindTo() inside a static method, even if
the closure itself is not keywordedstatic
.
I didn't explain that well enough; I meant that it automatically promotes
the
closure to be 'static' in that it uses late static binding.
The difference between HHVM and PHP is the default class scope of the
closure. PHP makes the decision that the owning class scope of the
closure is the compile-time class of the parent method. Why this was
done I couldn't say.
This is actually the same issue as the one above. Basically the closures
aren't respecting late static binding and I am pretty sure it was just an
oversight, not a conscious decision.
Basically the closures aren't respecting late static binding and I
am pretty sure it was just an oversight, not a conscious decision.
I feel you're right and a bug should be submitted.
Closures (speaking across languages) are supposed to stay aware of
their lexical scope, but that is what get_class()
is for, not
get_called_class()
.
-- S.