Skip to content

Commit 222b65d

Browse files
authored
Merge pull request #100 from fglock/fix-overload-autoload-interaction
Fix AUTOLOAD being triggered for overload methods
2 parents ccd2908 + 330b55c commit 222b65d

File tree

2 files changed

+107
-2
lines changed

2 files changed

+107
-2
lines changed

src/main/java/org/perlonjava/mro/InheritanceResolver.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,8 @@ public static RuntimeScalar findMethodInHierarchy(String methodName, String perl
328328
}
329329

330330
// Method not found in current class, check AUTOLOAD
331-
if (!autoloadEnabled || methodName.equals("((") || methodName.equals("()")) {
332-
// refuse to AUTOLOAD tie() flags and overload markers
331+
if (!autoloadEnabled || methodName.startsWith("(")) {
332+
// refuse to AUTOLOAD tie() flags and overload markers (all start with "(")
333333
} else {
334334
// Check for AUTOLOAD in current class
335335
String autoloadName = className + "::AUTOLOAD";
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use strict;
2+
use warnings;
3+
use Test::More tests => 3;
4+
5+
# Test that overload methods (which start with '(') do not trigger AUTOLOAD
6+
# This is a regression test for a bug where accessing a blessed hash element
7+
# would incorrectly trigger AUTOLOAD with an empty method name when the class
8+
# used 'use overload' and had an AUTOLOAD sub defined.
9+
10+
subtest 'overload with AUTOLOAD - basic hash access' => sub {
11+
plan tests => 3;
12+
13+
package TestOverloadAutoload1;
14+
use overload;
15+
16+
our $autoload_called = 0;
17+
our $autoload_name = '';
18+
19+
sub AUTOLOAD {
20+
our $AUTOLOAD;
21+
$autoload_called = 1;
22+
$autoload_name = $AUTOLOAD // '';
23+
}
24+
25+
sub new {
26+
my $class = shift;
27+
return bless {}, $class;
28+
}
29+
30+
package main;
31+
32+
my $obj = TestOverloadAutoload1->new;
33+
ok(defined $obj, 'Object created');
34+
35+
# This should NOT trigger AUTOLOAD
36+
$obj->{foo} = 1;
37+
38+
is($TestOverloadAutoload1::autoload_called, 0, 'AUTOLOAD was not called for hash access');
39+
is($obj->{foo}, 1, 'Hash element was set correctly');
40+
};
41+
42+
subtest 'overload with AUTOLOAD - nested hash access' => sub {
43+
plan tests => 3;
44+
45+
package TestOverloadAutoload2;
46+
use overload;
47+
48+
our $autoload_called = 0;
49+
50+
sub AUTOLOAD {
51+
our $AUTOLOAD;
52+
$autoload_called = 1;
53+
}
54+
55+
sub new {
56+
my $class = shift;
57+
my $self = bless {}, $class;
58+
$self->{OPTIONS} = { };
59+
return $self;
60+
}
61+
62+
package main;
63+
64+
$TestOverloadAutoload2::autoload_called = 0;
65+
my $obj = TestOverloadAutoload2->new;
66+
ok(defined $obj, 'Object with nested hash created');
67+
is($TestOverloadAutoload2::autoload_called, 0, 'AUTOLOAD was not called during construction');
68+
is(ref($obj->{OPTIONS}), 'HASH', 'Nested hash was created correctly');
69+
};
70+
71+
subtest 'AUTOLOAD still works for actual missing methods' => sub {
72+
plan tests => 3;
73+
74+
package TestOverloadAutoload3;
75+
use overload;
76+
77+
our $autoload_called = 0;
78+
our $autoload_name = '';
79+
80+
sub AUTOLOAD {
81+
our $AUTOLOAD;
82+
$autoload_called = 1;
83+
$autoload_name = $AUTOLOAD // '';
84+
return 'autoloaded';
85+
}
86+
87+
sub new {
88+
my $class = shift;
89+
return bless {}, $class;
90+
}
91+
92+
package main;
93+
94+
$TestOverloadAutoload3::autoload_called = 0;
95+
my $obj = TestOverloadAutoload3->new;
96+
97+
# This SHOULD trigger AUTOLOAD
98+
my $result = $obj->missing_method();
99+
100+
is($TestOverloadAutoload3::autoload_called, 1, 'AUTOLOAD was called for missing method');
101+
is($TestOverloadAutoload3::autoload_name, 'TestOverloadAutoload3::missing_method', 'AUTOLOAD received correct method name');
102+
is($result, 'autoloaded', 'AUTOLOAD returned correct value');
103+
};
104+
105+
1;

0 commit comments

Comments
 (0)