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