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

Tweak the UNIVERSAL::can override to allow SUPER::foo to work #3

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

TvdW
Copy link

@TvdW TvdW commented Mar 2, 2018

SUPER:: is always sort-of broken:

* $obj->SUPER::foo will never actually use $obj for the method
  resolution -- it will use the *package in which the code was
  compiled in*.
* $obj->can('SUPER::foo'), similarly, will use the "current"
  place in the callstack to find the next one.

The problem here is that Class::Std overrides UNIVERSAL::can,
so when it calls $original_can->($class, $method) and $method
is SUPER::foo, the SUPER code will look at the 'current' place
in the callstack.. which is the UNIVERSAL::can override in
Class::Std.

Whoops.

In particular, this was breaking AnyEvent, which uses this
lovely construct:

goto &{ UNIVERSAL::can AnyEvent => "SUPER::$name" }

Previously, SUPER::$name broke if Class::Std was loaded.

SUPER:: is always sort-of broken:

    * $obj->SUPER::foo will never actually use $obj for the method
      resolution -- it will use the *package in which the code was
      compiled in*.
    * $obj->can('SUPER::foo'), similarly, will use the "current"
      place in the callstack to find the next one.

The problem here is that Class::Std overrides UNIVERSAL::can,
so when it calls $original_can->($class, $method) and $method
is SUPER::foo, the SUPER code will look at the 'current' place
in the callstack.. which is the UNIVERSAL::can override in
Class::Std.

Whoops.

In particular, this was breaking AnyEvent, which uses this
lovely construct:

    goto &{ UNIVERSAL::can AnyEvent => "SUPER::$name" }

Previously, SUPER::$name broke if Class::Std was loaded.
@cpansprout
Copy link

What if something tries to call UNIVERSAL::can($thing, "SUPER::isa")? With this patch it will return &UNIVERSAL::isa (which Class::Std inherits), instead of whatever other &isa might be in the inheritance chain.

Wouldn’t it be better to goto &$real_can if the method name begins with SUPER::?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants