Skip Menu |

This queue is for tickets about the MooseX-Types CPAN distribution.

Report information
The Basics
Id: 84651
Status: open
Priority: 0/
Queue: MooseX-Types

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

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



Subject: Union of parameterized types
Without a prototype, Perl parses: ArrayRef[Int] | HashRef[Int] as: ArrayRef( [Int] | HashRef[Int] ) This is clearly undesirable. Please consider the attached patch (+ test case). This adds a prototype to the type export sub, so Perl treats the sub as a named unary operator. This means the type union is parsed as: ArrayRef( [Int] ) | HashRef( [Int] )
Subject: 0001-Fix-parsing-of-unions-of-parameterized-types.patch
From 3ed0df19acc972774e05b24654105a7755549434 Mon Sep 17 00:00:00 2001 From: Michael Chapman <mike@very.puzzling.org> Date: Tue, 16 Apr 2013 12:16:37 +1000 Subject: [PATCH] Fix parsing of unions of parameterized types Without a prototype, Perl parses: ArrayRef[Int] | HashRef[Int] as: ArrayRef( [Int] | HashRef[Int] ) Attach a prototype to the type export sub so that Perl treats it as a named unary operator. This means it's parsed as: ArrayRef( [Int] ) | HashRef( [Int] ) --- lib/MooseX/Types.pm | 18 ++++-------------- t/25_union_parameterized_types.t | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 14 deletions(-) create mode 100644 t/25_union_parameterized_types.t diff --git a/lib/MooseX/Types.pm b/lib/MooseX/Types.pm index f066392..1f4e412 100644 --- a/lib/MooseX/Types.pm +++ b/lib/MooseX/Types.pm @@ -387,14 +387,14 @@ sub type_export_generator { ## Return an anonymous subroutine that will generate the proxied type ## constraint for you. - return subname "__TYPE__::$name" => sub { + return subname "__TYPE__::$name" => sub (;$) { my $type_constraint = $class->create_base_type_constraint($name); if(defined(my $params = shift @_)) { ## We currently only allow a TC to accept a single, ArrayRef ## parameter, as in HashRef[Int], where [Int] is what's inside the ## ArrayRef passed. - if(reftype $params eq 'ARRAY') { + if(ref $params and reftype $params eq 'ARRAY') { $type_constraint = $class->create_arged_type_constraint($name, @$params); } elsif(!defined $type_constraint) { croak "Syntax error in type definition (did you forget a comma" @@ -407,18 +407,8 @@ sub type_export_generator { $type_constraint = defined($type_constraint) ? $type_constraint : MooseX::Types::UndefinedType->new($name); - - my $type_decorator = $class->create_type_decorator($type_constraint); - - ## If there are additional args, that means it's probably stuff that - ## needs to be returned to the subtype. Not an ideal solution here but - ## doesn't seem to cause trouble. - - if(@_) { - return ($type_decorator, @_); - } else { - return $type_decorator; - } + + return $class->create_type_decorator($type_constraint); }; } diff --git a/t/25_union_parameterized_types.t b/t/25_union_parameterized_types.t new file mode 100644 index 0000000..a5af461 --- /dev/null +++ b/t/25_union_parameterized_types.t @@ -0,0 +1,15 @@ +use strict; +use warnings; + +use Test::More; +use Test::Fatal; + +use MooseX::Types::Moose qw( ArrayRef HashRef Int ); + +is( + exception { ArrayRef[Int] | HashRef[Int] }, + undef, + 'no exception with union of parameterized types' +); + +done_testing(); -- 1.8.1.4
Subject: Re: [rt.cpan.org #84651] Union of parameterized types
Date: Mon, 15 Apr 2013 21:35:01 -0500 (CDT)
To: Michael Chapman via RT <bug-MooseX-Types [...] rt.cpan.org>
From: Dave Rolsky <autarch [...] urth.org>
On Mon, 15 Apr 2013, Michael Chapman via RT wrote: Show quoted text
> Mon Apr 15 22:29:15 2013: Request 84651 was acted upon. > Transaction: Ticket created by MCHAPMAN > Queue: MooseX-Types > Subject: Union of parameterized types > Broken in: 0.35 > Severity: (no value) > Owner: Nobody > Requestors: cpan@very.puzzling.org > Status: new > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=84651 > > > > Without a prototype, Perl parses: > > ArrayRef[Int] | HashRef[Int] > > as: > > ArrayRef( [Int] | HashRef[Int] ) > > This is clearly undesirable. > > Please consider the attached patch (+ test case). This adds a prototype to the type export sub, so Perl treats the sub as a named unary operator. This means the type union is parsed as: > > ArrayRef( [Int] ) | HashRef( [Int] )
This changes some behavior that was clearly intentional, but apparently not tested. The type name subs are supposed to return all additional arguments. I don't know exactly what this is used for, but I wouldn't want to break code in the wild. -dave /*============================================================ http://VegGuide.org http://blog.urth.org Your guide to all that's veg House Absolute(ly Pointless) ============================================================*/
On Mon Apr 15 22:35:17 2013, autarch@urth.org wrote: Show quoted text
> This changes some behavior that was clearly intentional, but > apparently not tested. The type name subs are supposed to return > all additional arguments. I don't know exactly what this is used > for, but I wouldn't want to break code in the wild.
I don't think it will have any change in behaviour. Since the sub is unary, additional arguments aren't consumed by the sub call, so they are simply supplied to the caller's context. If we take this example: @list = (ArrayRef[Int], 1, 2, 3); This was previously parsed as: @list = ArrayRef([Int], 1, 2, 3); The sub would strip off the [Int] arrayref and return ($type_decorator, 1, 2, 3). With my patch this code is parsed as: @list = (ArrayRef([Int]), 1, 2, 3); Since the sub only returns the $type_decorator, the resulting list is exactly the same. With a non-parameterized type: @list = (Int, 1, 2, 3); both the old and new code parse it as: @list = (Int(), 1, 2, 3); In scalar context, the list evaluates to the final argument (i.e. 3) in all cases.
On Tue Apr 16 03:07:13 2013, MCHAPMAN wrote: Show quoted text
> In scalar context, the list evaluates to the final argument (i.e. 3) > in all cases.
Actually, it was only 3 before because the array @_ was being evaluated in scalar context. So, yes, the following would have different behaviour with and without the patch: $x = (ArrayRef[Int], 'a', 'b', 'c'); Without the patch, $x would be assigned 3. With the patch, $x would be assigned 'c'. I can't imagine any code relying on the old behaviour though.