Skip Menu |

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

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

People
Owner: Nobody in particular
Requestors: perl [...] toby.ink
Cc:
AdminCc:

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



Subject: Weird Perl <5.14 error with Union Types
A possible fix is attached.
Subject: 0001-Fix-chained-union-overloads-on-perl-5.14.patch
From 84f9012c5c4b4fc92e1d994a2b33ae547d509008 Mon Sep 17 00:00:00 2001 From: Graham Knop <haarg@haarg.org> Date: Thu, 18 May 2017 13:40:58 +0200 Subject: [PATCH] Fix chained union overloads on perl < 5.14 With a type like ArrayRef[Str] | Undef, the overload operation would be between [Str] and Undef. This would be result in a "half op", an incomplete overload operation. When ArrayRef would be parameterized with that half op, it would unwrap it, use [Str] to parameterize itself, then trigger the overload between itself and the Undef type. Using ArrayRef[Str] | Undef | Str will first generate the half op of [Str] | Undef, then trigger the overload with Str. This needs to unwrap the half op, union the types, then generate a new half op between the unwrapped [Str] and the union. --- lib/Type/Tiny.pm | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/lib/Type/Tiny.pm b/lib/Type/Tiny.pm index 8c5d2fc8..d163d3cd 100644 --- a/lib/Type/Tiny.pm +++ b/lib/Type/Tiny.pm @@ -59,18 +59,44 @@ BEGIN q(&{}) => "_overload_coderef", q(|) => sub { my @tc = _swap @_; - if (!_FIXED_PRECEDENCE && !blessed $tc[0] && ref $tc[0] eq 'ARRAY') { - require Type::Tiny::_HalfOp; - return "Type::Tiny::_HalfOp"->new('|', @tc); + if (!_FIXED_PRECEDENCE && $_[2]) { + if (blessed $tc[0]) { + if (blessed $tc[0] eq "Type::Tiny::_HalfOp") { + my $type = $tc[0]->{type}; + my $params = $tc[0]->{params}; + my $op = $tc[0]->{op}; + require Type::Tiny::Union; + $tc[1] = "Type::Tiny::Union"->new(type_constraints => [$type, $tc[1]]); + Type::Tiny::_HalfOp->new($op, @tc); + return $tc[0]; + } + } + elsif (ref $tc[0] eq 'ARRAY') { + require Type::Tiny::_HalfOp; + return "Type::Tiny::_HalfOp"->new('|', @tc); + } } require Type::Tiny::Union; "Type::Tiny::Union"->new(type_constraints => \@tc) }, q(&) => sub { my @tc = _swap @_; - if (!_FIXED_PRECEDENCE && !blessed $tc[0] && ref $tc[0] eq 'ARRAY') { - require Type::Tiny::_HalfOp; - return "Type::Tiny::_HalfOp"->new('&', @tc); + if (!_FIXED_PRECEDENCE && $_[2]) { + if (blessed $tc[0]) { + if (blessed $tc[0] eq "Type::Tiny::_HalfOp") { + my $type = $tc[0]->{type}; + my $params = $tc[0]->{params}; + my $op = $tc[0]->{op}; + require Type::Tiny::Intersection; + $tc[1] = "Type::Tiny::Intersection"->new(type_constraints => [$type, $tc[1]]); + Type::Tiny::_HalfOp->new($op, @tc); + return $tc[0]; + } + } + elsif (ref $tc[0] eq 'ARRAY') { + require Type::Tiny::_HalfOp; + return "Type::Tiny::_HalfOp"->new('&', @tc); + } } require Type::Tiny::Intersection; "Type::Tiny::Intersection"->new(type_constraints => \@tc) -- 2.12.2
Awesome. Thanks. I'll write some test cases hopefully tomorrow and try to get it included.
Your code didn't quite work, but I managed to figure it out based on your explanation of how to fix it. Fixed in 1.001_015.