5f1c441047f45f895ad1904f8e59e372bf10bfbd
[p5sagit/Class-Accessor-Grouped.git] / lib / Class / Accessor / Grouped.pm
1 package Class::Accessor::Grouped;
2 use strict;
3 use warnings;
4 use Carp ();
5 use Scalar::Util ();
6 use Module::Runtime ();
7
8 BEGIN {
9   # use M::R to work around the 5.8 require bugs
10   if ($] < 5.009_005) {
11     Module::Runtime::require_module('MRO::Compat');
12   }
13   else {
14     require mro;
15   }
16 }
17
18 our $VERSION = '0.10006';
19 $VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
20
21 # when changing minimum version don't forget to adjust Makefile.PL as well
22 our $__minimum_xsa_version;
23 BEGIN { $__minimum_xsa_version = '1.13' }
24
25 our $USE_XS;
26 # the unless defined is here so that we can override the value
27 # before require/use, *regardless* of the state of $ENV{CAG_USE_XS}
28 $USE_XS = $ENV{CAG_USE_XS}
29   unless defined $USE_XS;
30
31 BEGIN {
32   package __CAG_ENV__;
33
34   die "Huh?! No minimum C::XSA version?!\n"
35     unless $__minimum_xsa_version;
36
37   local $@;
38   require constant;
39
40   # individual (one const at a time) imports so we are 5.6.2 compatible
41   # if we can - why not ;)
42   constant->import( NO_SUBNAME => eval {
43     Module::Runtime::require_module('Sub::Name')
44   } ? 0 : "$@" );
45
46   constant->import( NO_CXSA => ( !NO_SUBNAME() and eval {
47     Module::Runtime::use_module('Class::XSAccessor' => $__minimum_xsa_version)
48   } ) ? 0 : "$@" );
49
50   constant->import( BROKEN_GOTO => ($] < '5.008009') ? 1 : 0 );
51
52   constant->import( UNSTABLE_DOLLARAT => ($] < '5.013002') ? 1 : 0 );
53
54   constant->import( TRACK_UNDEFER_FAIL => (
55     $INC{'Test/Builder.pm'} || $INC{'Test/Builder2.pm'}
56       and
57     $0 =~ m|^ x?t / .+ \.t $|x
58   ) ? 1 : 0 );
59 }
60
61 # Yes this method is undocumented
62 # Yes it should be a private coderef like all the rest at the end of this file
63 # No we can't do that (yet) because the DBIC-CDBI compat layer overrides it
64 # %$*@!?&!&#*$!!!
65 sub _mk_group_accessors {
66   my($self, $maker, $group, @fields) = @_;
67   my $class = Scalar::Util::blessed $self || $self;
68
69   no strict 'refs';
70   no warnings 'redefine';
71
72   # So we don't have to do lots of lookups inside the loop.
73   $maker = $self->can($maker) unless ref $maker;
74
75   for (@fields) {
76
77     my ($name, $field) = (ref $_) ? (@$_) : ($_, $_);
78
79     for (qw/DESTROY AUTOLOAD CLONE/) {
80       Carp::carp("Having a data accessor named '$name' in '$class' is unwise.")
81         if $name eq $_;
82     }
83
84     my $alias = "_${name}_accessor";
85
86     for my $meth ($name, $alias) {
87
88       # the maker may elect to not return anything, meaning it already
89       # installed the coderef for us (e.g. lack of Sub::Name)
90       my $cref = $self->$maker($group, $field, $meth)
91         or next;
92
93       my $fq_meth = "${class}::${meth}";
94
95       *$fq_meth = Sub::Name::subname($fq_meth, $cref);
96         #unless defined &{$class."\:\:$field"}
97     }
98   }
99 };
100
101 # coderef is setup at the end for clarity
102 my $gen_accessor;
103
104 =head1 NAME
105
106 Class::Accessor::Grouped - Lets you build groups of accessors
107
108 =head1 SYNOPSIS
109
110  use base 'Class::Accessor::Grouped';
111
112  # make basic accessors for objects
113  __PACKAGE__->mk_group_accessors(simple => qw(id name email));
114
115  # make accessor that works for objects and classes
116  __PACKAGE__->mk_group_accessors(inherited => 'awesome_level');
117
118 =head1 DESCRIPTION
119
120 This class lets you build groups of accessors that will call different
121 getters and setters.
122
123 =head1 METHODS
124
125 =head2 mk_group_accessors
126
127  __PACKAGE__->mk_group_accessors(simple => 'hair_length', [ hair_color => 'hc' ]);
128
129 =over 4
130
131 =item Arguments: $group, @fieldspec
132
133 Returns: none
134
135 =back
136
137 Creates a set of accessors in a given group.
138
139 $group is the name of the accessor group for the generated accessors; they
140 will call get_$group($field) on get and set_$group($field, $value) on set.
141
142 If you want to mimic Class::Accessor's mk_accessors $group has to be 'simple'
143 to tell Class::Accessor::Grouped to use its own get_simple and set_simple
144 methods.
145
146 @fieldspec is a list of field/accessor names; if a fieldspec is a scalar
147 this is used as both field and accessor name, if a listref it is expected to
148 be of the form [ $accessor, $field ].
149
150 =cut
151
152 sub mk_group_accessors {
153   my ($self, $group, @fields) = @_;
154
155   $self->_mk_group_accessors('make_group_accessor', $group, @fields);
156   return;
157 }
158
159 =head2 mk_group_ro_accessors
160
161  __PACKAGE__->mk_group_ro_accessors(simple => 'birthdate', [ social_security_number => 'ssn' ]);
162
163 =over 4
164
165 =item Arguments: $group, @fieldspec
166
167 Returns: none
168
169 =back
170
171 Creates a set of read only accessors in a given group. Identical to
172 L</mk_group_accessors> but accessors will throw an error if passed a value
173 rather than setting the value.
174
175 =cut
176
177 sub mk_group_ro_accessors {
178   my($self, $group, @fields) = @_;
179
180   $self->_mk_group_accessors('make_group_ro_accessor', $group, @fields);
181 }
182
183 =head2 mk_group_wo_accessors
184
185  __PACKAGE__->mk_group_wo_accessors(simple => 'lie', [ subject => 'subj' ]);
186
187 =over 4
188
189 =item Arguments: $group, @fieldspec
190
191 Returns: none
192
193 =back
194
195 Creates a set of write only accessors in a given group. Identical to
196 L</mk_group_accessors> but accessors will throw an error if not passed a
197 value rather than getting the value.
198
199 =cut
200
201 sub mk_group_wo_accessors {
202   my($self, $group, @fields) = @_;
203
204   $self->_mk_group_accessors('make_group_wo_accessor', $group, @fields);
205 }
206
207 =head2 get_simple
208
209 =over 4
210
211 =item Arguments: $field
212
213 Returns: $value
214
215 =back
216
217 Simple getter for hash-based objects which returns the value for the field
218 name passed as an argument.
219
220 =cut
221
222 sub get_simple {
223   return $_[0]->{$_[1]};
224 }
225
226 =head2 set_simple
227
228 =over 4
229
230 =item Arguments: $field, $new_value
231
232 Returns: $new_value
233
234 =back
235
236 Simple setter for hash-based objects which sets and then returns the value
237 for the field name passed as an argument.
238
239 =cut
240
241 sub set_simple {
242   return $_[0]->{$_[1]} = $_[2];
243 }
244
245
246 =head2 get_inherited
247
248 =over 4
249
250 =item Arguments: $field
251
252 Returns: $value
253
254 =back
255
256 Simple getter for Classes and hash-based objects which returns the value for
257 the field name passed as an argument. This behaves much like
258 L<Class::Data::Accessor> where the field can be set in a base class,
259 inherited and changed in subclasses, and inherited and changed for object
260 instances.
261
262 =cut
263
264 sub get_inherited {
265   my $class;
266
267   if ( defined( $class = Scalar::Util::blessed $_[0] ) ) {
268     if (Scalar::Util::reftype $_[0] eq 'HASH') {
269       return $_[0]->{$_[1]} if exists $_[0]->{$_[1]};
270     }
271     else {
272       Carp::croak('Cannot get inherited value on an object instance that is not hash-based');
273     }
274   }
275   else {
276     $class = $_[0];
277   }
278
279   no strict 'refs';
280   no warnings 'uninitialized';
281
282   my $cag_slot = '::__cag_'. $_[1];
283   return ${$class.$cag_slot} if defined(${$class.$cag_slot});
284
285   do { return ${$_.$cag_slot} if defined(${$_.$cag_slot}) }
286     for $_[0]->get_super_paths;
287
288   return undef;
289 }
290
291 =head2 set_inherited
292
293 =over 4
294
295 =item Arguments: $field, $new_value
296
297 Returns: $new_value
298
299 =back
300
301 Simple setter for Classes and hash-based objects which sets and then returns
302 the value for the field name passed as an argument. When called on a hash-based
303 object it will set the appropriate hash key value. When called on a class, it
304 will set a class level variable.
305
306 B<Note:>: This method will die if you try to set an object variable on a non
307 hash-based object.
308
309 =cut
310
311 sub set_inherited {
312   if (defined Scalar::Util::blessed $_[0]) {
313     if (Scalar::Util::reftype $_[0] eq 'HASH') {
314       return $_[0]->{$_[1]} = $_[2];
315     } else {
316       Carp::croak('Cannot set inherited value on an object instance that is not hash-based');
317     };
318   } else {
319     no strict 'refs';
320
321     return ${$_[0].'::__cag_'.$_[1]} = $_[2];
322   };
323 }
324
325 =head2 get_component_class
326
327 =over 4
328
329 =item Arguments: $field
330
331 Returns: $value
332
333 =back
334
335 Gets the value of the specified component class.
336
337  __PACKAGE__->mk_group_accessors('component_class' => 'result_class');
338
339  $self->result_class->method();
340
341  ## same as
342  $self->get_component_class('result_class')->method();
343
344 =cut
345
346 sub get_component_class {
347   return $_[0]->get_inherited($_[1]);
348 };
349
350 =head2 set_component_class
351
352 =over 4
353
354 =item Arguments: $field, $class
355
356 Returns: $new_value
357
358 =back
359
360 Inherited accessor that automatically loads the specified class before setting
361 it. This method will die if the specified class could not be loaded.
362
363  __PACKAGE__->mk_group_accessors('component_class' => 'result_class');
364  __PACKAGE__->result_class('MyClass');
365
366  $self->result_class->method();
367
368 =cut
369
370 sub set_component_class {
371   if (defined $_[2] and length $_[2]) {
372     # disable warnings, and prevent $_ being eaten away by a behind-the-scenes
373     # module loading
374     local ($^W, $_);
375
376     if (__CAG_ENV__::UNSTABLE_DOLLARAT) {
377       my $err;
378       {
379         local $@;
380         eval { Module::Runtime::use_package_optimistically($_[2]) }
381           or $err = $@;
382       }
383       Carp::croak("Could not load $_[1] '$_[2]': $err") if defined $err;
384
385     }
386     else {
387       eval { Module::Runtime::use_package_optimistically($_[2]) }
388         or Carp::croak("Could not load $_[1] '$_[2]': $@");
389     }
390   };
391
392   return $_[0]->set_inherited($_[1], $_[2]);
393 };
394
395 =head1 INTERNAL METHODS
396
397 These methods are documented for clarity, but are never meant to be called
398 directly, and are not really meant for overriding either.
399
400 =head2 get_super_paths
401
402 Returns a list of 'parent' or 'super' class names that the current class
403 inherited from. This is what drives the traversal done by L</get_inherited>.
404
405 =cut
406
407 sub get_super_paths {
408   return @{mro::get_linear_isa( ref($_[0]) || $_[0] )};
409 };
410
411 =head2 make_group_accessor
412
413  __PACKAGE__->make_group_accessor('simple', 'hair_length', 'hair_length');
414  __PACKAGE__->make_group_accessor('simple', 'hc', 'hair_color');
415
416 =over 4
417
418 =item Arguments: $group, $field, $accessor
419
420 Returns: \&accessor_coderef ?
421
422 =back
423
424 Called by mk_group_accessors for each entry in @fieldspec. Either returns
425 a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns
426 C<undef> if it elects to install the coderef on its own.
427
428 =cut
429
430 sub make_group_accessor { $gen_accessor->('rw', @_) }
431
432 =head2 make_group_ro_accessor
433
434  __PACKAGE__->make_group_ro_accessor('simple', 'birthdate', 'birthdate');
435  __PACKAGE__->make_group_ro_accessor('simple', 'ssn', 'social_security_number');
436
437 =over 4
438
439 =item Arguments: $group, $field, $accessor
440
441 Returns: \&accessor_coderef ?
442
443 =back
444
445 Called by mk_group_ro_accessors for each entry in @fieldspec. Either returns
446 a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns
447 C<undef> if it elects to install the coderef on its own.
448
449 =cut
450
451 sub make_group_ro_accessor { $gen_accessor->('ro', @_) }
452
453 =head2 make_group_wo_accessor
454
455  __PACKAGE__->make_group_wo_accessor('simple', 'lie', 'lie');
456  __PACKAGE__->make_group_wo_accessor('simple', 'subj', 'subject');
457
458 =over 4
459
460 =item Arguments: $group, $field, $accessor
461
462 Returns: \&accessor_coderef ?
463
464 =back
465
466 Called by mk_group_wo_accessors for each entry in @fieldspec. Either returns
467 a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns
468 C<undef> if it elects to install the coderef on its own.
469
470 =cut
471
472 sub make_group_wo_accessor { $gen_accessor->('wo', @_) }
473
474
475 =head1 PERFORMANCE
476
477 To provide total flexibility L<Class::Accessor::Grouped> calls methods
478 internally while performing get/set actions, which makes it noticeably
479 slower than similar modules. To compensate, this module will automatically
480 use the insanely fast L<Class::XSAccessor> to generate the C<simple>-group
481 accessors if this module is available on your system.
482
483 =head2 Benchmark
484
485 This is the result of a set/get/set loop benchmark on perl 5.12.1 with
486 thread support, showcasing most popular accessor builders: L<Moose>, L<Mouse>,
487 L<Moo>, L<CAF|Class::Accessor::Fast>, L<CAF_XS|Class::Accessor::Fast::XS>,
488 L<XSA|Class::XSAccessor>, and L<CAF_XSA|Class::XSAccessor::Compat>:
489
490            Rate  CAG moOse  CAF moUse  moo HANDMADE CAF_XS moUse_XS moo_XS CAF_XSA  XSA CAG_XS
491  CAG      169/s   --  -21% -24%  -32% -32%     -34%   -59%     -63%   -67%    -67% -67%   -67%
492  moOse    215/s  27%    --  -3%  -13% -13%     -15%   -48%     -53%   -58%    -58% -58%   -58%
493  CAF      222/s  31%    3%   --  -10% -10%     -13%   -46%     -52%   -57%    -57% -57%   -57%
494  moUse    248/s  46%   15%  11%    --  -0%      -3%   -40%     -46%   -52%    -52% -52%   -52%
495  moo      248/s  46%   15%  11%    0%   --      -3%   -40%     -46%   -52%    -52% -52%   -52%
496  HANDMADE 255/s  50%   18%  14%    3%   3%       --   -38%     -45%   -50%    -51% -51%   -51%
497  CAF_XS   411/s 143%   91%  85%   66%  66%      61%     --     -11%   -20%    -20% -21%   -21%
498  moUse_XS 461/s 172%  114% 107%   86%  86%      81%    12%       --   -10%    -11% -11%   -11%
499  moo_XS   514/s 204%  139% 131%  107% 107%     102%    25%      12%     --     -0%  -1%    -1%
500  CAF_XSA  516/s 205%  140% 132%  108% 108%     103%    26%      12%     0%      --  -0%    -0%
501  XSA      519/s 206%  141% 133%  109% 109%     104%    26%      13%     1%      0%   --    -0%
502  CAG_XS   519/s 206%  141% 133%  109% 109%     104%    26%      13%     1%      0%   0%     --
503
504 Benchmark program is available in the root of the
505 L<repository|http://search.cpan.org/dist/Class-Accessor-Grouped/>:
506
507 =head2 Notes on Class::XSAccessor
508
509 You can force (or disable) the use of L<Class::XSAccessor> before creating a
510 particular C<simple> accessor by either manipulating the global variable
511 C<$Class::Accessor::Grouped::USE_XS> to true or false (preferably with
512 L<localization|perlfunc/local>, or you can do so before runtime via the
513 C<CAG_USE_XS> environment variable.
514
515 Since L<Class::XSAccessor> has no knowledge of L</get_simple> and
516 L</set_simple> this module does its best to detect if you are overriding
517 one of these methods and will fall back to using the perl version of the
518 accessor in order to maintain consistency. However be aware that if you
519 enable use of C<Class::XSAccessor> (automatically or explicitly), create
520 an object, invoke a simple accessor on that object, and B<then> manipulate
521 the symbol table to install a C<get/set_simple> override - you get to keep
522 all the pieces.
523
524 =head1 AUTHORS
525
526 Matt S. Trout <mst@shadowcatsystems.co.uk>
527
528 Christopher H. Laco <claco@chrislaco.com>
529
530 =head1 CONTRIBUTORS
531
532 Caelum: Rafael Kitover <rkitover@cpan.org>
533
534 frew: Arthur Axel "fREW" Schmidt <frioux@gmail.com>
535
536 groditi: Guillermo Roditi <groditi@cpan.org>
537
538 Jason Plum <jason.plum@bmmsi.com>
539
540 ribasushi: Peter Rabbitson <ribasushi@cpan.org>
541
542
543 =head1 COPYRIGHT & LICENSE
544
545 Copyright (c) 2006-2010 Matt S. Trout <mst@shadowcatsystems.co.uk>
546
547 This program is free software; you can redistribute it and/or modify
548 it under the same terms as perl itself.
549
550 =cut
551
552 ########################################################################
553 ########################################################################
554 ########################################################################
555 #
556 # Here be many angry dragons
557 # (all code is in private coderefs since everything inherits CAG)
558 #
559 ########################################################################
560 ########################################################################
561
562 # Autodetect unless flag supplied
563 my $xsa_autodetected;
564 if (! defined $USE_XS) {
565   $USE_XS = __CAG_ENV__::NO_CXSA ? 0 : 1;
566   $xsa_autodetected++;
567 }
568
569 my $maker_templates = {
570   rw => {
571     xs_call => 'accessors',
572     pp_code => sub {
573       my $set = "set_$_[0]";
574       my $get = "get_$_[0]";
575       my $field = $_[1];
576       $field =~ s/'/\\'/g;
577
578       "
579         \@_ != 1
580           ? shift->$set('$field', \@_)
581           : shift->$get('$field')
582       "
583     },
584   },
585   ro => {
586     xs_call => 'getters',
587     pp_code => sub {
588       my $get = "get_$_[0]";
589       my $field = $_[1];
590       $field =~ s/'/\\'/g;
591
592       "
593         \@_ == 1
594           ? shift->$get('$field')
595           : do {
596             my \$caller = caller;
597             my \$class = ref \$_[0] || \$_[0];
598             Carp::croak(\"'\$caller' cannot alter the value of '$field' \".
599                         \"(read-only attributes of class '\$class')\");
600           }
601       "
602     },
603   },
604   wo => {
605     xs_call => 'setters',
606     pp_code => sub {
607       my $set = "set_$_[0]";
608       my $field = $_[1];
609       $field =~ s/'/\\'/g;
610
611       "
612         \@_ != 1
613           ? shift->$set('$field', \@_)
614           : do {
615             my \$caller = caller;
616             my \$class = ref \$_[0] || \$_[0];
617             Carp::croak(\"'\$caller' cannot access the value of '$field' \".
618                         \"(write-only attributes of class '\$class')\");
619           }
620       "
621     },
622   },
623 };
624
625
626 my ($accessor_maker_cache, $no_xsa_warned_classes);
627
628 # can't use pkg_gen to track this stuff, as it doesn't
629 # detect superclass mucking
630 my $original_simple_getter = __PACKAGE__->can ('get_simple');
631 my $original_simple_setter = __PACKAGE__->can ('set_simple');
632
633 # Note!!! Unusual signature
634 $gen_accessor = sub {
635   my ($type, $class, $group, $field, $methname) = @_;
636   if (my $c = Scalar::Util::blessed( $class )) {
637     $class = $c;
638   }
639
640   # When installing an XSA simple accessor, we need to make sure we are not
641   # short-circuiting a (compile or runtime) get_simple/set_simple override.
642   # What we do here is install a lazy first-access check, which will decide
643   # the ultimate coderef being placed in the accessor slot
644   #
645   # Also note that the *original* class will always retain this shim, as
646   # different branches inheriting from it may have different overrides.
647   # Thus the final method (properly labeled and all) is installed in the
648   # calling-package's namespace
649   if ($USE_XS and $group eq 'simple') {
650     die sprintf( "Class::XSAccessor requested but not available:\n%s\n", __CAG_ENV__::NO_CXSA )
651       if __CAG_ENV__::NO_CXSA;
652
653     my ($expected_cref, $cached_implementation);
654     my $ret = $expected_cref = sub {
655       my $current_class = Scalar::Util::blessed( $_[0] ) || $_[0];
656
657       # $cached_implementation will be set only if the shim got
658       # 'around'ed, in which case it is handy to avoid re-running
659       # this block over and over again
660       my $resolved_implementation = $cached_implementation->{$current_class} || do {
661         if (
662           ($current_class->can('get_simple')||0) == $original_simple_getter
663             &&
664           ($current_class->can('set_simple')||0) == $original_simple_setter
665         ) {
666           # nothing has changed, might as well use the XS crefs
667           #
668           # note that by the time this code executes, we already have
669           # *objects* (since XSA works on 'simple' only by definition).
670           # If someone is mucking with the symbol table *after* there
671           # are some objects already - look! many, shiny pieces! :)
672           #
673           # The weird breeder thingy is because XSA does not have an
674           # interface returning *just* a coderef, without installing it
675           # anywhere :(
676           Class::XSAccessor->import(
677             replace => 1,
678             class => '__CAG__XSA__BREEDER__',
679             $maker_templates->{$type}{xs_call} => {
680               $methname => $field,
681             },
682           );
683           __CAG__XSA__BREEDER__->can($methname);
684         }
685         else {
686           if (! $xsa_autodetected and ! $no_xsa_warned_classes->{$current_class}++) {
687             # not using Carp since the line where this happens doesn't mean much
688             warn 'Explicitly requested use of Class::XSAccessor disabled for objects of class '
689               . "'$current_class' inheriting from '$class' due to an overriden get_simple and/or "
690               . "set_simple\n";
691           }
692
693           do {
694             # that's faster than local
695             $USE_XS = 0;
696             my $c = $gen_accessor->($type, $class, 'simple', $field, $methname);
697             $USE_XS = 1;
698             $c;
699           };
700         }
701       };
702
703       # if after this shim was created someone wrapped it with an 'around',
704       # we can not blindly reinstall the method slot - we will destroy the
705       # wrapper. Silently chain execution further...
706       if ( !$expected_cref or $expected_cref != ($current_class->can($methname)||0) ) {
707
708         # there is no point in re-determining it on every subsequent call,
709         # just store for future reference
710         $cached_implementation->{$current_class} ||= $resolved_implementation;
711
712         # older perls segfault if the cref behind the goto throws
713         # http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878
714         return $resolved_implementation->(@_) if __CAG_ENV__::BROKEN_GOTO;
715
716         goto $resolved_implementation;
717       }
718
719       if (__CAG_ENV__::TRACK_UNDEFER_FAIL) {
720         my $deferred_calls_seen = do {
721           no strict 'refs';
722           \%{"${current_class}::__cag_deferred_xs_shim_invocations"}
723         };
724         my @cframe = caller(0);
725         if (my $already_seen = $deferred_calls_seen->{$cframe[3]}) {
726           Carp::carp (
727             "Deferred version of method $cframe[3] invoked more than once (originally "
728           . "invoked at $already_seen). This is a strong indication your code has "
729           . 'cached the original ->can derived method coderef, and is using it instead '
730           . 'of the proper method re-lookup, causing performance regressions'
731           );
732         }
733         else {
734           $deferred_calls_seen->{$cframe[3]} = "$cframe[1] line $cframe[2]";
735         }
736       }
737
738       # install the resolved implementation into the code slot so we do not
739       # come here anymore (hopefully)
740       # since XSAccessor was available - so is Sub::Name
741       {
742         no strict 'refs';
743         no warnings 'redefine';
744
745         my $fq_name = "${current_class}::${methname}";
746         *$fq_name = Sub::Name::subname($fq_name, $resolved_implementation);
747
748         # need to update what the shim expects too *in case* its
749         # ->can was cached for some moronic reason
750         $expected_cref = $resolved_implementation;
751         Scalar::Util::weaken($expected_cref);
752       }
753
754       # older perls segfault if the cref behind the goto throws
755       # http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878
756       return $resolved_implementation->(@_) if __CAG_ENV__::BROKEN_GOTO;
757
758       goto $resolved_implementation;
759     };
760
761     Scalar::Util::weaken($expected_cref); # to break the self-reference
762     $ret;
763   }
764
765   # no Sub::Name - just install the coderefs directly (compiling every time)
766   elsif (__CAG_ENV__::NO_SUBNAME) {
767     my $src = $accessor_maker_cache->{source}{$type}{$group}{$field} ||=
768       $maker_templates->{$type}{pp_code}->($group, $field);
769
770     no warnings 'redefine';
771     local $@ if __CAG_ENV__::UNSTABLE_DOLLARAT;
772     eval "sub ${class}::${methname} { $src }";
773
774     undef;  # so that no further attempt will be made to install anything
775   }
776
777   # a coderef generator with a variable pad (returns a fresh cref on every invocation)
778   else {
779     ($accessor_maker_cache->{pp}{$type}{$group}{$field} ||= do {
780       my $src = $accessor_maker_cache->{source}{$type}{$group}{$field} ||=
781         $maker_templates->{$type}{pp_code}->($group, $field);
782
783       local $@ if __CAG_ENV__::UNSTABLE_DOLLARAT;
784       eval "sub { my \$dummy; sub { \$dummy if 0; $src } }" or die $@;
785     })->()
786   }
787 };
788
789 1;