If you pass coerce => 1 for an attr, its type must have a coercion or an error is...
Dave Rolsky [Sun, 4 Jul 2010 16:58:25 +0000 (11:58 -0500)]
Changes
lib/Moose/Manual/Delta.pod
lib/Moose/Meta/Attribute.pm
lib/Moose/Meta/Method/Constructor.pm
t/020_attributes/034_bad_coerce.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index 86403b6..319efa2 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,6 +1,12 @@
 Also see Moose::Manual::Delta for more details of, and workarounds
 for, noteworthy changes.
 
+  [API CHANGES]
+
+  * You cannot pass "coerce => 1" for an attribute unless its type constraint
+    has a coercion defined. If it doesn't, an error will be thrown when the
+    attribute is defined. (Dave Rolsky)
+
   [NEW FEATURES]
 
   * We no longer unimport strict and warnings when Moose, Moose::Role, or
index 69a08b8..c1b8f57 100644 (file)
@@ -20,6 +20,14 @@ send us a patch.
 
 =over 4
 
+=item You cannot pass C<< coerce => 1 >> unless the attribute's type constraint has a coercion
+
+Previously, this was accepted, and it sort of worked, except that if you
+attempted to set the attribute after the object was created, you would get a
+runtime error.
+
+Now you will get an error when you attempt to define the attribute.
+
 =item C<no Moose>, C<no Moose::Role>, and C<no Moose::Exporter> no longer unimport strict and warnings
 
 This change was made in 1.05, and has now been reverted. We don't know if the
index 61188a7..f82b863 100644 (file)
@@ -322,6 +322,9 @@ sub _process_options {
             || $class->throw_error("You cannot have coercion without specifying a type constraint on attribute ($name)", data => $options);
         $class->throw_error("You cannot have a weak reference to a coerced value on attribute ($name)", data => $options)
             if $options->{weak_ref};
+
+        $options->{type_constraint}->has_coercion
+            || $class->throw_error("You cannot coerce an attribute ($name) unless its type has a coercion", data => $options);
     }
 
     if (exists $options->{trigger}) {
@@ -732,10 +735,8 @@ sub _coerce_and_verify {
 
     return $val unless $self->has_type_constraint;
 
-    my $type_constraint = $self->type_constraint;
-    if ($self->should_coerce && $type_constraint->has_coercion) {
-        $val = $type_constraint->coerce($val);
-    }
+    $val = $self->type_constraint->coerce($val)
+        if $self->should_coerce;
 
     $self->verify_against_type_constraint($val, instance => $instance);
 
index 9550412..68de04a 100644 (file)
@@ -242,7 +242,7 @@ sub _generate_slot_initializer {
 
             push @source => ('my $val = $params->{\'' . $init_arg . '\'};');
             if ($is_moose && $attr->has_type_constraint) {
-                if ($attr->should_coerce && $attr->type_constraint->has_coercion) {
+                if ($attr->should_coerce) {
                     push @source => $self->_generate_type_coercion(
                         $attr,
                         '$type_constraints[' . $index . ']',
@@ -307,7 +307,7 @@ sub _generate_type_constraint_and_coercion {
     return unless $attr->has_type_constraint;
 
     my @source;
-    if ($attr->should_coerce && $attr->type_constraint->has_coercion) {
+    if ($attr->should_coerce) {
         push @source => $self->_generate_type_coercion(
             $attr,
             '$type_constraints[' . $index . ']',
diff --git a/t/020_attributes/034_bad_coerce.t b/t/020_attributes/034_bad_coerce.t
new file mode 100644 (file)
index 0000000..10d234b
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More;
+use Test::Exception;
+
+{
+    package Foo;
+
+    use Moose;
+
+    ::throws_ok{ has foo => (
+            is     => 'ro',
+            isa    => 'Str',
+            coerce => 1,
+        );
+        } qr/\QYou cannot coerce an attribute (foo) unless its type has a coercion/,
+        'Cannot coerce unless the type has a coercion';
+}
+
+done_testing;