Skip Menu |

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

Report information
The Basics
Id: 92571
Status: resolved
Priority: 0/
Queue: Type-Tiny

People
Owner: perl [...] toby.ink
Requestors: djerius [...] cpan.org
Cc:
AdminCc:

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



Subject: unexpected error from on-the-fly type union coercions, e.g. ( Str | Str )->coercion
I tried to create a coercion routine from an "on-the-fly" union type: ------------------------------ $sub = ( Str | Str )->coercion; $sub->( 'x' ); ------------------------------ And got this explosion: ------------------------------ Undef did not pass type constraint "TypeTiny" at foo line 4 Undef did not pass type constraint "TypeTiny" "TypeTiny" is defined as: (Scalar::Util::blessed($_) && $_->isa(q[Type::Tiny])) ------------------------------ if I Dump $sub, I get ------------------------------ bless( { 'name' => '__ANON__', 'type_constraint' => undef }, 'Type::Coercion::Union' ); ------------------------------ Which looks suspiciously empty. If I make sure the union type hangs around: ------------------------------ $t = Str | Str; $sub = $t->coercion; $sub->( 'x' ); ------------------------------ everything works. I'm guessing there's a (too) weakened reference that's getting zapped when the temporary Type::Union is getting destroyed. Feature? Bug? I couldn't find any documentation either way. (Of course, there's a good probability I just missed it. Happens a lot to me.) For what it's worth, this code arose because I was adding a coercion to a Moo attribute which needed a one-off union of types and I didn't feel it warranted the extra code to create a type that hung around. Thanks! Diab
Here's another example of this behavior, resulting in silently incorrect results: -------------------------------------------------- use 5.10.1; use Data::Dumper; use Type::Library -base, -declare => qw[ ArrayRefFromAny ]; use Types::Standard -all; use Type::Utils -all; declare_coercion ArrayRefFromAny, to_type ArrayRef, from Any, via { [$_] } ; my $x = ( ArrayRef ) + ArrayRefFromAny; say Dumper $x->coerce( ['a'] ); # types hang around until after the coerce method is run say Dumper ( ( ( ArrayRef ) + ArrayRefFromAny )->coerce( ['a'] ) ); # types go away after generation of coercion sub, breaking it my $coerce = ( ( ArrayRef ) + ArrayRefFromAny )->coercion; say Dumper $coerce->( ['a'] ); -------------------------------------------------- This results in: -------------------------------------------------- $VAR1 = [ 'a' ]; $VAR1 = [ 'a' ]; $VAR1 = [ [ 'a' ] ]; -------------------------------------------------- While this code differs from the original report in that it adds a coercion to a type rather than generating a union; I think the underlying cause of the behavior is the same. Thanks, Diab
Yes, the coercion object only stores a weak reference back to the type constraint. I'll have a think about what to do in this situation.
OK, I've fixed the second part of this bug report, but the fix doesn't cover Type::Coercion::Union yet. Test case: https://github.com/tobyink/p5-type-tiny/blob/master/t/40-regression/rt92571.t It's passing: https://travis-ci.org/tobyink/p5-type-tiny/builds/18262530
OK, here's the test for Type::Coercion::Union: https://github.com/tobyink/p5-type-tiny/blob/master/t/40-regression/rt92571-2.t This seems to be passing too: https://travis-ci.org/tobyink/p5-type-tiny/builds/18263147 The basic technique I've used is this: Type::Coercion cannot keep a strong reference to its target type constraint because this would cause a reference cycle, and result in memory leaks. So instead, Type::Coercion stores enough information about its type constraint to be able to rebuilt an equivalent check if necessary.
Fixed in 0.040.
Also, unrelated to this bug... FYI, the "+" overload on Type::Tiny and Type::Coercion is going away in version 0.042. It causes a lot of precedence issues, and it's one of the main reasons that parameterized coercions are so broken. So instead of: $new_type = $type + $coercion Use: $new_type = $type->plus_coercions($coercion);
Subject: Re: [rt.cpan.org #92571] unexpected error from on-the-fly type union coercions, e.g. ( Str | Str )->coercion
Date: Mon, 17 Mar 2014 09:50:14 -0400
To: bug-Type-Tiny [...] rt.cpan.org
From: Diab Jerius <djerius [...] cpan.org>
On Mon, Mar 17, 2014 at 6:30 AM, Toby Inkster via RT <bug-Type-Tiny@rt.cpan.org> wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=92571 > > > Also, unrelated to this bug... FYI, the "+" overload on Type::Tiny and Type::Coercion is going away in version 0.042. It causes a lot of precedence issues, and it's one of the main reasons that parameterized coercions are so broken. > > So instead of: > > $new_type = $type + $coercion > > Use: > > $new_type = $type->plus_coercions($coercion);
Thanks for the heads up.