Skip Menu |

This queue is for tickets about the YAML-Tiny CPAN distribution.

Report information
The Basics
Id: 89978
Status: resolved
Priority: 0/
Queue: YAML-Tiny

People
Owner: Nobody in particular
Requestors: jkeenan [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Unreachable code in Dump()
sub Dump() currently (Sat Nov 02 2013) contains code not exercised by the YAML-Tiny test suite (see: http://thenceforward.net/YAML-Tiny/coverage/lib-YAML-Tiny-pm.html starting at line 667). This could have one of two explanations: (a) we haven't gotten around to writing a test for the "not defined $string" case; or (b) the string can never be undefined, hence the code is unreachable and excisable. My hunch is that it's (b). We need to ask: Can the return value of "YAML::Tiny->new(@_)->write_string" ever be undefined? Suppose we refactor write_string() a bit to make its return values more self-evident: diff --git a/lib/YAML/Tiny.pm b/lib/YAML/Tiny.pm index b92286f..8f94492 100644 --- a/lib/YAML/Tiny.pm +++ b/lib/YAML/Tiny.pm @@ -527,11 +527,13 @@ sub write_string { }; if ( ref $@ eq 'SCALAR' ) { return $self->_error(${$@}); - } elsif ( $@ ) { - $self->_error($@); } - - join '', map { "$_\n" } @lines; + else { + if ( $@ ) { + $self->_error($@); + } + return join '', map { "$_\n" } @lines; + } } # use XXX -with => 'YAML::XS'; We now see clearly all the points where write_string() will return. (1) return '' unless ref $self && @$self; That's returning a defined, though false, value. (2) return $self->_error(${$@}); That returns a reference, which I doubt can be undefined. In any event, that statement is already being exercised by the test suite. (3) return join '', map { "$_\n" } @lines; That's going to be a defined, though perhaps empty, string. So I infer that write_string() cannot return an undefined value. If so, then the check for definedness inside Dump() is superfluous and can be removed. Do you agree? Thank you very much. Jim Keenan
Subject: write_string.diff
diff --git a/lib/YAML/Tiny.pm b/lib/YAML/Tiny.pm index b92286f..8f94492 100644 --- a/lib/YAML/Tiny.pm +++ b/lib/YAML/Tiny.pm @@ -527,11 +527,13 @@ sub write_string { }; if ( ref $@ eq 'SCALAR' ) { return $self->_error(${$@}); - } elsif ( $@ ) { - $self->_error($@); } - - join '', map { "$_\n" } @lines; + else { + if ( $@ ) { + $self->_error($@); + } + return join '', map { "$_\n" } @lines; + } } # use XXX -with => 'YAML::XS';
Subject: Re: [rt.cpan.org #89978] Unreachable code in Dump()
Date: Sat, 2 Nov 2013 13:11:20 -0400
To: bug-YAML-Tiny [...] rt.cpan.org
From: David Golden <dagolden [...] cpan.org>
On Sat, Nov 2, 2013 at 10:36 AM, James E Keenan via RT <bug-YAML-Tiny@rt.cpan.org> wrote: Show quoted text
> My hunch is that it's (b). We need to ask: Can the return value of "YAML::Tiny->new(@_)->write_string" ever be undefined?
Yes. $self->_error returns undef, not a reference. _error is a kludge to set $errstr and return undef. Personally, I would rather eliminate $errstr entirely and switch to using exceptions for error conditions. Then I think the sort of un-obvious logic you point out can be simplified a lot. For example, all the die \"error message" cases no longer need a reference and no longer need to be caught by an eval. David -- David Golden <dagolden@cpan.org> Take back your inbox! → http://www.bunchmail.com/ Twitter/IRC: @xdg
On Sat Nov 02 13:12:03 2013, DAGOLDEN wrote: Show quoted text
> On Sat, Nov 2, 2013 at 10:36 AM, James E Keenan via RT > <bug-YAML-Tiny@rt.cpan.org> wrote:
> > My hunch is that it's (b). We need to ask: Can the return value of > > "YAML::Tiny->new(@_)->write_string" ever be undefined?
> > Yes. $self->_error returns undef, not a reference. _error is a > kludge to set $errstr and return undef.
It may *evaluate* to undef, but it's not the *return value* of write_string() as that method is currently written. That's what I tried to make clear in my refactoring. Perhaps the code should have originally been written as: ##### } elsif ( $@ ) { return $self->_error($@); ##### But it wasn't, for whatever reason. If the 'elsif' branch is entered, then $self->_error($@) gets run but control continues to: ##### join '', map { "$_\n" } @lines; ##### which, being the last statement in the subroutine, is necessarily one of the points of return. Thank you very much. Jim Keenan Show quoted text
> > Personally, I would rather eliminate $errstr entirely and switch to > using exceptions for error conditions. Then I think the sort of > un-obvious logic you point out can be simplified a lot. For example, > all the die \"error message" cases no longer need a reference and no > longer need to be caught by an eval. > > David
On Sat Nov 02 16:10:02 2013, JKEENAN wrote: Show quoted text
> ##### > } elsif ( $@ ) { > return $self->_error($@); > ##### > > But it wasn't, for whatever reason. If the 'elsif' branch is entered, > then $self->_error($@) gets run but control continues to:
I'm pretty sure that was an oversight. I copied it verbatim from read_string and didn't think about the logic, but you're right it makes no sense.
I've added the "return" in to both read/write_string and committed it to the devel branch. I still think we should switch to exceptions, but until then, returning undef is consistent with the other error case.