Ответ 1
Замена Class::ISA::self_and_super_path
равна mro::get_linear_isa
. Это доступно либо из mro
, либо, если вы хотите поддерживать старые perls, через MRO::Compat
.
Кроме того, @ISA
является волшебной переменной.
$ 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)
Обратите внимание на PERL_MAGIC_isa
. Это то, что управляет этим конкретным механизмом.
Всякий раз, когда он изменяется, содержимое любых кешей, которые полагаются на его значение, должно быть обновлено.
$ perl -E'say Foo->isa(q[Bar]) || 0; @Foo::ISA = qw(Bar Baz); say Foo->isa(q[Bar]) || 0'
0
1
По-видимому, вы нашли случай, когда недействительность кэша не происходит. Я считаю это ошибкой. Шансы splice
по какой-то причине не призывают магию isa
соответственно. Вы можете попробовать изменить @ISA
альтернативным способом, например, используя unshift
или назначение, или, возможно, попробовать mro::method_changed_in
, что приведет к недействительности кэшей разрешения метода, которые привязаны к различным @ISA
s.
Если вы могли бы уменьшить эту ошибку до минимальной тестовой таблицы, это было бы очень полезно для исправления этой ошибки.
Update:
Минимальный тестовый тест оказался легким:
$ perl -E'say Foo->isa(q[Bar]) || 0; splice @Foo::ISA, 0, 0, q[Bar]; say Foo->isa(q[Bar]) || 0'
0
0
Это вызвано тем, что pp_splice
не делает что-то вроде mg_set((SV *)ary)
. push
, unshift
, и регулярные присваивания делают это правильно, поэтому использование одного из них должно исправить вашу проблему.
Другое обновление:
Это изменение, которое я только что зафиксировал в perl, исправляет проблему. Однако, поскольку нечетное поведение splice
не вызывающего магии уже присутствует в 5.8 и 5.10, оно не является регрессией и поэтому не будет частью 5.12.3 через несколько месяцев. 5.13.6, который будет выпущен на следующей неделе, и 5.14.0, следующий северный spring, вероятно, получит его.