Is there a problem in perl 5.12.2 using splice on @ISA?

故事扮演 提交于 2019-12-04 02:33:57

The replacement for Class::ISA::self_and_super_path is mro::get_linear_isa. That's available either from mro itself, or, if you want to support old perls, via MRO::Compat.

Also, @ISA is a magic variable.

$ perl -MDevel::Peek -e'Dump \@ISA'
SV = IV(0x1b92e20) at 0x1b92e28
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x1bbcd58
  SV = PVAV(0x1b93cf8) at 0x1bbcd58
    REFCNT = 2
    FLAGS = (SMG,RMG)
    MAGIC = 0x1bc0f68
      MG_VIRTUAL = &PL_vtbl_isa
      MG_TYPE = PERL_MAGIC_isa(I)
      MG_OBJ = 0x1bbcd40
    ARRAY = 0x0
    FILL = -1
    MAX = -1
    ARYLEN = 0x0
    FLAGS = (REAL)

Note the PERL_MAGIC_isa. That's what drives this particular mechanism.

Whenever it is changed, the contents of any caches that rely on its value are supposed to be updated.

$ perl -E'say Foo->isa(q[Bar]) || 0; @Foo::ISA = qw(Bar Baz); say Foo->isa(q[Bar]) || 0'
0
1

Apparently you've found a case where the cache invalidation doesn't happen. I consider this a bug. Chances are splice, for some reason, doesn't invoke the isa magic appropriately. You could try to modify @ISA in an alternative way, for example using unshift or an assignment, or possibly try mro::method_changed_in, which would invalidate the method resolution caches, which are bound to the various @ISAs.

If you could reduce this bug to a minimal testcase, that'd be hugely helpful in getting this bug fixed.

Update:

A minimal testcase turned out to be easy:

$ perl -E'say Foo->isa(q[Bar]) || 0; splice @Foo::ISA, 0, 0, q[Bar]; say Foo->isa(q[Bar]) || 0'
0
0

This is caused by pp_splice not doing something like mg_set((SV *)ary). push, unshift, and regular assignments do that correctly, so using one of these should fix your issue.

Another Update:

This change, which I just committed to perl, fixes the issue. However, as the odd behaviour of splice not invoking magic is already present in 5.8 and 5.10, it's not a regression and therefore not going to be part of 5.12.3 in a few months. 5.13.6, which will be released next week, and 5.14.0, next northern spring, will probably have it.

Yes, there is a cache. But if you can modify @ISA without invalidating that cache, I would consider it a bug in perl.

Does your problem disappear if you add the line @ISA = @ISA; after your splice line?

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!