class :isa(): check for not only a stash, but a class

If class Foo::Bar exists then the Foo stash exists, so checking
for that when Foo is the requested base class is meaningless.

Instead try to load the base class if it is not known as a class, not
just if it's not a stash, just as we do immediately following.

Fixes #21332
This commit is contained in:
Tony Cook 2023-08-10 14:01:50 +10:00
parent 6e0b8bd693
commit bcd084d7d8
5 changed files with 20 additions and 1 deletions

View File

@ -5790,6 +5790,8 @@ t/lib/caller/Foo.pm test Module for caller.t and t/op/hook/require.t
t/lib/caller/Tricycle.pm test Module for t/op/hook/require.t (cyclic)
t/lib/CannotParse.pm For test case in op/require_errors.t
t/lib/charnames/alias Tests of "use charnames" with aliases.
t/lib/class/A.pm Test class loading of hierarchical parent
t/lib/class/A/B.pm Test class loading of hierarchical parent
t/lib/Cname.pm Test charnames in regexes (op/pat.t)
t/lib/common.pl Helper for lib/{warnings,feature}.t
t/lib/commonsense.t See if configuration meets basic needs

View File

@ -508,7 +508,7 @@ apply_class_attribute_isa(pTHX_ HV *stash, SV *value)
croak("Class already has a superclass, cannot add another");
HV *superstash = gv_stashsv(superclassname, 0);
if(!superstash) {
if (!superstash || !HvSTASH_IS_CLASS(superstash)) {
/* Try to `require` the module then attempt a second time */
load_module(PERL_LOADMOD_NOIMPORT, newSVsv(superclassname), NULL, NULL);
superstash = gv_stashsv(superclassname, 0);

View File

@ -96,4 +96,13 @@ no warnings 'experimental::class';
is(Test5B->new->classname, "Test5B", '__CLASS__ yields correct class name for subclass');
}
{
# https://github.com/Perl/perl5/issues/21332
use lib 'lib/class';
ok(eval <<'EOS', "hierarchical base class loaded");
use A::B;
1;
EOS
}
done_testing;

4
t/lib/class/A.pm Normal file
View File

@ -0,0 +1,4 @@
no warnings 'experimental::class';
use feature 'class';
class A {}
1;

4
t/lib/class/A/B.pm Normal file
View File

@ -0,0 +1,4 @@
no warnings 'experimental::class';
use feature 'class';
class A::B :isa(A) {}
1;