Closed p5pRT closed 20 years ago
Void context is not propagated correctly in blead and maint\, which broke lots of tests in my Convert::Binary::C testsuite.
mhx@r2d2 /tmp $ cat test.pl sub context { my $w = wantarray; my $c = defined $w ? ($w ? 'list' : 'scalar') : 'void'; print "$c context\n"; }
eval { context() }; $a = eval { context() }; @a = eval { context() };
eval q{ context() }; $a = eval q{ context() }; @a = eval q{ context() }; mhx@r2d2 /tmp $ perl5.8.0 test.pl void context scalar context list context void context \<- correct scalar context list context mhx@r2d2 /tmp $ maintperl test.pl void context scalar context list context scalar context \<- should be void scalar context list context mhx@r2d2 /tmp $ bleadperl test.pl void context scalar context list context scalar context \<- should be void scalar context list context mhx@r2d2 /tmp $
I think the problem is in change #19126:
==== //depot/perl/pp_ctl.c#351 (text) ====
@@ -2884\,7 +2884\,13 @@
*startop = PL_eval_root;
} else
SAVEFREEOP(PL_eval_root);
- if (gimme & G_VOID)
+ if (gimme & G_VOID && ! PL_in_eval & EVAL_INREQUIRE)
+ /*
+ * EVAL_INREQUIRE (the code is being required) is special-cased :
+ * in this case we want scalar context to be forced\, instead
+ * of void context\, so a proper return value is returned from
+ * C\
I guess that
if (gimme & G_VOID && ! PL_in_eval & EVAL_INREQUIRE)
was supposed to be
if (gimme & G_VOID && ! (PL_in_eval & EVAL_INREQUIRE))
but due to the precedence of ! and & it is actually
if (gimme & G_VOID && (! PL_in_eval) & EVAL_INREQUIRE)
As PL_in_eval is nonzero most of the time (always?)\, the above condition is always false. Using
if (gimme & G_VOID && ! (PL_in_eval & EVAL_INREQUIRE))
does fix the general void context problem\, but re-introduces the 'require' problem addressed by change #19126. I have no idea what is going on ;-)
However\, I added some tests to t/op/eval.t in the attached patch\, of which the last one is currently failing.
-- Marcus
Marcus Holland-Moritz wrote:
Void context is not propagated correctly in blead and maint\, which broke lots of tests in my Convert::Binary::C testsuite. [snip evidence] I think the problem is in change #19126:
Yes\, a poor attempt at fixing #21742.
==== //depot/perl/pp_ctl.c#351 (text) ====
@@ -2884\,7 +2884\,13 @@ *startop = PL_eval_root; } else SAVEFREEOP(PL_eval_root); - if (gimme & G_VOID) + if (gimme & G_VOID && ! PL_in_eval & EVAL_INREQUIRE) + /* + * EVAL_INREQUIRE (the code is being required) is special-cased : + * in this case we want scalar context to be forced\, instead + * of void context\, so a proper return value is returned from + * C\
via this leaveeval op. + */ scalarvoid(PL_eval_root); else if (gimme & G_ARRAY) list(PL_eval_root); I guess that
if (gimme & G_VOID && ! PL_in_eval & EVAL_INREQUIRE)
was supposed to be
if (gimme & G_VOID && ! (PL_in_eval & EVAL_INREQUIRE))
but due to the precedence of ! and & it is actually
if (gimme & G_VOID && (! PL_in_eval) & EVAL_INREQUIRE)
As PL_in_eval is nonzero most of the time (always?)\, the above condition is always false.
Duh.
Using
if (gimme & G_VOID && ! (PL_in_eval & EVAL_INREQUIRE))
does fix the general void context problem\, but re-introduces the 'require' problem addressed by change #19126. I have no idea what is going on ;-)
It doesn't work because the require happens after the entereval. And this doeval function is executed twice : once for the entereval\, once for the require. That probably means that bug #21742 should not be fixed there\, but at an upper level.
However\, I added some tests to t/op/eval.t in the attached patch\, of which the last one is currently failing.
I've applied your test patch as #19801\, and reverted the pp_ctl.c part of #19126. Thanks for cleaning up my stables !
@rgs - Status changed from 'new' to 'resolved'
Migrated from rt.perl.org#22708 (status was 'resolved')
Searchable as RT22708$