Skip Menu |

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

Report information
The Basics
Id: 127635
Status: rejected
Priority: 0/
Queue: Type-Tiny

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

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



Subject: Test::TypeTiny should_pass fails but check works
Date: Tue, 13 Nov 2018 19:39:40 +0000
To: bug-Type-Tiny [...] rt.cpan.org
From: Robert Rothenberg <rrwo [...] cpan.org>
The following test case demonstrates the issue: use Test::More; use Test::TypeTiny; use Types::Const qw/ Const /; use Const::Fast; const my $re => qr/foo/; # This passes, as it should ok Const->check($re); # This also passes ok Const->_strict_check($re); # This fails should_pass($re, Const); done_testing; This is for Type::Tiny 1.004002
Hmm, interesting. It's because Test::TypeTiny is basically doing something like this: sub should_pass { my ($value, $type) = @_; if ($type->check($value)) { pass; } else { fail; } } So it's creating a copy of $_[0] into $value and testing that. While $_[0] is a readonly SV, $value is not. It's mostly pure luck (and the fact that I've optimized a lot of stuff to avoid making copies of scalars) that Const->check($re) actually works. I wouldn't want to guarantee it always will. ScalarRef->of(Const)->check(\$re) should be guaranteed to always work.
Subject: Re: [rt.cpan.org #127635] Test::TypeTiny should_pass fails but check works
Date: Mon, 19 Nov 2018 14:05:55 +0000
To: bug-Type-Tiny [...] rt.cpan.org
From: Robert Rothenberg <rrwo [...] cpan.org>
On 18/11/2018 23:40, Toby Inkster via RT wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=127635 > > > Hmm, interesting. It's because Test::TypeTiny is basically doing something like this: > > sub should_pass { > my ($value, $type) = @_; > if ($type->check($value)) { > pass; > } > else { > fail; > } > } > > So it's creating a copy of $_[0] into $value and testing that. While $_[0] is a readonly SV, $value is not. > > It's mostly pure luck (and the fact that I've optimized a lot of stuff to avoid making copies of scalars) that Const->check($re) actually works. I wouldn't want to guarantee it always will. > > ScalarRef->of(Const)->check(\$re) should be guaranteed to always work.
Is that for regexp refs, or all refs? What about when using it in a Moo/Moose attribute? Do I need to wrap the type to ensure that it will work?
If you were using it in a Moo attribute, the constructor would basically be doing something like this: $self->{attributename} = $value; So would make a copy of the value anyway, and lose the constancy. Constancy is really a property of the variable, not a property of the value. It would be like trying to check whether a variable as a lexical (my) or global (our) variable in a type check.
This script should demonstrate that Regexp references lose their readonlyness pretty easily in most practical situations. It's because in the constructor, Moo does the equivalent of: $self->{attr} = $re; And even if $re was readonly, $self->{attr} won't be. ################################## use strict; use warnings; use Test::More; use Types::Const qw(Const); use Const::Fast; package Local::Foo { use Moo; has attr => (is => 'ro'); } const my $re => qr/foo/; ok Internals::SvREADONLY $re; my $obj = Local::Foo->new(attr => $re); ok not Internals::SvREADONLY $obj->attr; ok not Internals::SvREADONLY $obj->{attr}; done_testing;