Skip to content

Commit c3dff8a

Browse files
committed
op.c: call class_wrap_method_body() for lexical methods
Class method bodies must be wrapped by this function, which adds the OP_METHSTART op at the beginning, which is responsible for shifting the `$self` lexical from the arguments array, and setting up field bindings. This was already done for non-lexical (i.e. package) methods but was forgotten for lexical methods, so they didn't work properly, leading to the bug found in GH#23030 whereby the argument count in a signatured lexical method did not take account of the `$self` argument properly. In addition, fields accessed by the method body would not have been working, though originally this wasn't reported or tested either. A test for this has also been added.
1 parent 42e7ab1 commit c3dff8a

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

op.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10657,6 +10657,8 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
1065710657
}
1065810658

1065910659
if (block) {
10660+
if (CvIsMETHOD(PL_compcv))
10661+
block = class_wrap_method_body(block);
1066010662
/* This makes sub {}; work as expected. */
1066110663
if (block->op_type == OP_STUB) {
1066210664
const line_t l = PL_parser->copline;

t/class/method.t

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,10 @@ no warnings 'experimental::class';
106106
# ->& operator can invoke methods with lexical scope
107107
{
108108
class Testcase8 {
109+
field $f = "private-result";
110+
109111
my method priv {
110-
return "private-result";
112+
return $f;
111113
}
112114

113115
method notpriv {
@@ -134,4 +136,22 @@ no warnings 'experimental::class';
134136
'->&m operator does not follow inheritance');
135137
}
136138

139+
# lexical methods with signatures work correctly (GH#23030)
140+
{
141+
class Testcase9 {
142+
field $x = 123;
143+
144+
my method priv ( $y ) {
145+
return "X is $x and Y is $y for $self";
146+
}
147+
148+
method test {
149+
$self->&priv(456);
150+
}
151+
}
152+
153+
like(Testcase9->new->test, qr/^X is 123 and Y is 456 for Testcase9=OBJECT\(0x.*\)$/,
154+
'lexical method with signature counts $self correctly');
155+
}
156+
137157
done_testing;

0 commit comments

Comments
 (0)