Subject: | nested try block + return from inner + nonempty destructor = garbage in array |
The following example may look a bit artificial, but it's actually shorthand for "a project with multiple levels of indirection using Moo[se]".
WHEN try {} is nested, AND the outer block assigns an array to result of indirectly called inner block, AND the inner block is in scalar/void context, AND the inner block is left by a return statement, AND such return triggers a nonempty DESTROY block, THEN a $@ value is prepended to array for no apparent reason.
Subject: | 201807-try.pl |
#!/usr/bin/env perl
=head1 DESCRIPTION
Nested try block + return from the inner block + destructor called
= garbage in array
=cut
use strictures 2;
use Test::Most tests => 1;
use Syntax::Keyword::Try;
eq_or_diff [outer()], [ 1, 123 ], "No extra data in return";
sub outer {
my @result;
try {
@result = (1, scalar inner()); # scalar or void context is mandatory
1; # or catch will be triggered
} catch {
die "Something terrible happened: $@";
};
return @result;
}
sub inner {
my $canary = Canary->new; # is this line is commented, nothing happens
try {
return 123;
} catch {
die "Something terrible happened: $@";
}
}
package Canary;
sub new {
bless {}, shift;
};
sub DESTROY {
my $x; # Destructor MUST be nonempty
$@ = "oops"; # Assigning to $@ is optional
};