2 package Moose::Meta::Class;
9 use Carp qw( confess );
11 use List::Util qw( first );
12 use List::MoreUtils qw( any all uniq first_index );
13 use Scalar::Util 'blessed';
15 use Moose::Meta::Method::Overridden;
16 use Moose::Meta::Method::Augmented;
17 use Moose::Error::Default;
18 use Moose::Meta::Class::Immutable::Trait;
19 use Moose::Meta::Method::Constructor;
20 use Moose::Meta::Method::Destructor;
21 use Moose::Meta::Method::Meta;
23 use Class::MOP::MiniTrait;
25 use base 'Class::MOP::Class';
27 Class::MOP::MiniTrait::apply(__PACKAGE__, 'Moose::Meta::Object::Trait');
29 __PACKAGE__->meta->add_attribute('roles' => (
31 default => sub { [] },
32 Class::MOP::_definition_context(),
35 __PACKAGE__->meta->add_attribute('role_applications' => (
36 reader => '_get_role_applications',
37 default => sub { [] },
38 Class::MOP::_definition_context(),
41 __PACKAGE__->meta->add_attribute(
42 Class::MOP::Attribute->new('immutable_trait' => (
43 accessor => "immutable_trait",
44 default => 'Moose::Meta::Class::Immutable::Trait',
45 Class::MOP::_definition_context(),
49 __PACKAGE__->meta->add_attribute('constructor_class' => (
50 accessor => 'constructor_class',
51 default => 'Moose::Meta::Method::Constructor',
52 Class::MOP::_definition_context(),
55 __PACKAGE__->meta->add_attribute('destructor_class' => (
56 accessor => 'destructor_class',
57 default => 'Moose::Meta::Method::Destructor',
58 Class::MOP::_definition_context(),
61 __PACKAGE__->meta->add_attribute('error_class' => (
62 accessor => 'error_class',
63 default => 'Moose::Error::Default',
64 Class::MOP::_definition_context(),
70 unshift @args, 'package' if @args % 2;
72 my $package = delete $opts{package};
73 return Class::MOP::get_metaclass_by_name($package)
74 || $class->SUPER::initialize($package,
75 'attribute_metaclass' => 'Moose::Meta::Attribute',
76 'method_metaclass' => 'Moose::Meta::Method',
77 'instance_metaclass' => 'Moose::Meta::Instance',
86 unshift @args, 'package' if @args % 2 == 1;
89 (ref $options{roles} eq 'ARRAY')
90 || $class->throw_error("You must pass an ARRAY ref of roles", data => $options{roles})
91 if exists $options{roles};
93 my $package = delete $options{package};
94 my $roles = delete $options{roles};
96 my $new_meta = $class->SUPER::create($package, %options);
99 Moose::Util::apply_all_roles( $new_meta, @$roles );
105 sub _meta_method_class { 'Moose::Meta::Method::Meta' }
107 sub _anon_package_prefix { 'Moose::Meta::Class::__ANON__::SERIAL::' }
109 sub _anon_cache_key {
113 my $superclass_key = join('|',
114 map { $_->[0] } @{ Data::OptList::mkopt($options{superclasses} || []) }
117 my $roles = Data::OptList::mkopt(($options{roles} || []), {
119 val_test => sub { ref($_[0]) eq 'HASH' },
123 for my $role_spec (@$roles) {
124 my ($role, $params) = @$role_spec;
125 $params = { %$params } if $params;
127 my $key = blessed($role) ? $role->name : $role;
129 if ($params && %$params) {
130 my $alias = delete $params->{'-alias'}
131 || delete $params->{'alias'}
133 my $excludes = delete $params->{'-excludes'}
134 || delete $params->{'excludes'}
136 $excludes = [$excludes] unless ref($excludes) eq 'ARRAY';
139 warn "Roles with parameters cannot be cached. Consider "
140 . "applying the parameters before calling "
141 . "create_anon_class, or using 'weaken => 0' instead";
145 my $alias_key = join('%',
146 map { $_ => $alias->{$_} } sort keys %$alias
148 my $excludes_key = join('%',
151 $key .= '<' . join('+', 'a', $alias_key, 'e', $excludes_key) . '>';
154 push @role_keys, $key;
157 my $role_key = join('|', sort @role_keys);
159 # Makes something like Super::Class|Super::Class::2=Role|Role::1
160 return join('=', $superclass_key, $role_key);
167 my $meta = blessed $pkg ? $pkg : Class::MOP::class_of($pkg);
169 my %existing_classes;
171 %existing_classes = map { $_ => $meta->$_() } qw(
174 wrapped_method_metaclass
182 return $self->SUPER::reinitialize(
190 my ($self, $role) = @_;
191 (blessed($role) && $role->isa('Moose::Meta::Role'))
192 || $self->throw_error("Roles must be instances of Moose::Meta::Role", data => $role);
193 push @{$self->roles} => $role;
196 sub role_applications {
199 return @{$self->_get_role_applications};
202 sub add_role_application {
203 my ($self, $application) = @_;
204 (blessed($application) && $application->isa('Moose::Meta::Role::Application::ToClass'))
205 || $self->throw_error("Role applications must be instances of Moose::Meta::Role::Application::ToClass", data => $application);
206 push @{$self->_get_role_applications} => $application;
209 sub calculate_all_roles {
212 grep { !$seen{$_->name}++ } map { $_->calculate_all_roles } @{ $self->roles };
215 sub calculate_all_roles_with_inheritance {
218 grep { !$seen{$_->name}++ }
219 map { Class::MOP::class_of($_)->can('calculate_all_roles')
220 ? Class::MOP::class_of($_)->calculate_all_roles
222 $self->linearized_isa;
226 my ($self, $role_name) = @_;
229 || $self->throw_error("You must supply a role name to look for");
231 foreach my $class ($self->class_precedence_list) {
232 my $meta = Class::MOP::class_of($class);
233 # when a Moose metaclass is itself extended with a role,
234 # this check needs to be done since some items in the
235 # class_precedence_list might in fact be Class::MOP
237 next unless $meta && $meta->can('roles');
238 foreach my $role (@{$meta->roles}) {
239 return 1 if $role->does_role($role_name);
246 my ($self, $role_name) = @_;
249 || $self->throw_error("You must supply a role name to look for");
251 foreach my $class ($self->class_precedence_list) {
252 my $meta = Class::MOP::class_of($class);
253 # when a Moose metaclass is itself extended with a role,
254 # this check needs to be done since some items in the
255 # class_precedence_list might in fact be Class::MOP
257 next unless $meta && $meta->can('roles');
258 foreach my $role (@{$meta->roles}) {
259 return 1 if $role->excludes_role($role_name);
267 my $params = @_ == 1 ? $_[0] : {@_};
268 my $object = $self->SUPER::new_object($params);
270 foreach my $attr ( $self->get_all_attributes() ) {
272 next unless $attr->can('has_trigger') && $attr->has_trigger;
274 my $init_arg = $attr->init_arg;
276 next unless defined $init_arg;
278 next unless exists $params->{$init_arg};
284 ? $attr->get_read_method_ref->($object)
285 : $params->{$init_arg}
290 $object->BUILDALL($params) if $object->can('BUILDALL');
295 sub _generate_fallback_constructor {
298 return $class . '->Moose::Object::new(@_)'
303 my ($params, $class) = @_;
305 'my ' . $params . ' = ',
306 $self->_inline_BUILDARGS($class, '@_'),
311 sub _inline_BUILDARGS {
313 my ($class, $args) = @_;
315 my $buildargs = $self->find_method_by_name("BUILDARGS");
318 && (!$buildargs or $buildargs->body == \&Moose::Object::BUILDARGS)) {
322 'if (scalar @_ == 1) {',
323 'if (!defined($_[0]) || ref($_[0]) ne \'HASH\') {',
324 $self->_inline_throw_error(
325 '"Single parameters to new() must be a HASH ref"',
329 '$params = { %{ $_[0] } };',
333 '"The new() method for ' . $class . ' expects a '
334 . 'hash reference or a key/value list. You passed an '
335 . 'odd number of arguments"',
337 '$params = {@_, undef};',
347 return $class . '->BUILDARGS(' . $args . ')';
351 sub _inline_slot_initializer {
353 my ($attr, $idx) = @_;
357 $self->_inline_check_required_attr($attr),
358 $self->SUPER::_inline_slot_initializer(@_),
362 sub _inline_check_required_attr {
366 return unless defined $attr->init_arg;
367 return unless $attr->can('is_required') && $attr->is_required;
368 return if $attr->has_default || $attr->has_builder;
371 'if (!exists $params->{\'' . $attr->init_arg . '\'}) {',
372 $self->_inline_throw_error(
373 '"Attribute (' . quotemeta($attr->name) . ') is required"'
379 # XXX: these two are duplicated from cmop, because we have to pass the tc stuff
380 # through to _inline_set_value - this should probably be fixed, but i'm not
381 # quite sure how. -doy
382 sub _inline_init_attr_from_constructor {
384 my ($attr, $idx) = @_;
386 my @initial_value = $attr->_inline_set_value(
388 '$params->{\'' . $attr->init_arg . '\'}',
389 '$type_constraint_bodies[' . $idx . ']',
390 '$type_coercions[' . $idx . ']',
391 '$type_constraint_messages[' . $idx . ']',
395 push @initial_value, (
396 '$attrs->[' . $idx . ']->set_initial_value(',
398 $attr->_inline_instance_get('$instance'),
400 ) if $attr->has_initializer;
402 return @initial_value;
405 sub _inline_init_attr_from_default {
407 my ($attr, $idx) = @_;
409 return if $attr->can('is_lazy') && $attr->is_lazy;
410 my $default = $self->_inline_default_value($attr, $idx);
411 return unless $default;
413 my @initial_value = (
414 'my $default = ' . $default . ';',
415 $attr->_inline_set_value(
418 '$type_constraint_bodies[' . $idx . ']',
419 '$type_coercions[' . $idx . ']',
420 '$type_constraint_messages[' . $idx . ']',
425 push @initial_value, (
426 '$attrs->[' . $idx . ']->set_initial_value(',
428 $attr->_inline_instance_get('$instance'),
430 ) if $attr->has_initializer;
432 return @initial_value;
435 sub _inline_extra_init {
438 $self->_inline_triggers,
439 $self->_inline_BUILDALL,
443 sub _inline_triggers {
447 my @attrs = sort { $a->name cmp $b->name } $self->get_all_attributes;
448 for my $i (0 .. $#attrs) {
449 my $attr = $attrs[$i];
451 next unless $attr->can('has_trigger') && $attr->has_trigger;
453 my $init_arg = $attr->init_arg;
454 next unless defined $init_arg;
457 'if (exists $params->{\'' . $init_arg . '\'}) {',
458 '$triggers->[' . $i . ']->(',
460 $attr->_inline_instance_get('$instance') . ',',
465 return @trigger_calls;
468 sub _inline_BUILDALL {
471 my @methods = reverse $self->find_all_methods_by_name('BUILD');
474 foreach my $method (@methods) {
476 '$instance->' . $method->{class} . '::BUILD($params);';
482 sub _eval_environment {
485 my @attrs = sort { $a->name cmp $b->name } $self->get_all_attributes;
488 map { $_->can('has_trigger') && $_->has_trigger ? $_->trigger : undef }
492 # We need to check if the attribute ->can('type_constraint')
493 # since we may be trying to immutabilize a Moose meta class,
494 # which in turn has attributes which are Class::MOP::Attribute
495 # objects, rather than Moose::Meta::Attribute. And
496 # Class::MOP::Attribute attributes have no type constraints.
497 # However we need to make sure we leave an undef value there
498 # because the inlined code is using the index of the attributes
499 # to determine where to find the type constraint
501 my @type_constraints = map {
502 $_->can('type_constraint') ? $_->type_constraint : undef
505 my @type_constraint_bodies = map {
506 defined $_ ? $_->_compiled_type_constraint : undef;
509 my @type_coercions = map {
510 defined $_ && $_->has_coercion
511 ? $_->coercion->_compiled_type_coercion
515 my @type_constraint_messages = map {
517 ? ($_->has_message ? $_->message : $_->_default_message)
522 %{ $self->SUPER::_eval_environment },
523 ((any { defined && $_->has_initializer } @attrs)
524 ? ('$attrs' => \[@attrs])
526 '$triggers' => \$triggers,
527 '@type_coercions' => \@type_coercions,
528 '@type_constraint_bodies' => \@type_constraint_bodies,
529 '@type_constraint_messages' => \@type_constraint_messages,
530 ( map { defined($_) ? %{ $_->inline_environment } : () }
532 # pretty sure this is only going to be closed over if you use a custom
533 # error class at this point, but we should still get rid of this
541 my $supers = Data::OptList::mkopt(\@_);
542 foreach my $super (@{ $supers }) {
543 my ($name, $opts) = @{ $super };
544 Class::MOP::load_class($name, $opts);
545 my $meta = Class::MOP::class_of($name);
546 $self->throw_error("You cannot inherit from a Moose Role ($name)")
547 if $meta && $meta->isa('Moose::Meta::Role')
549 return $self->SUPER::superclasses(map { $_->[0] } @{ $supers });
552 ### ---------------------------------------------
557 (blessed $_[0] && $_[0]->isa('Class::MOP::Attribute')
559 : $self->_process_attribute(@_));
560 $self->SUPER::add_attribute($attr);
561 # it may be a Class::MOP::Attribute, theoretically, which doesn't have
562 # 'bare' and doesn't implement this method
563 if ($attr->can('_check_associated_methods')) {
564 $attr->_check_associated_methods;
569 sub add_override_method_modifier {
570 my ($self, $name, $method, $_super_package) = @_;
572 (!$self->has_method($name))
573 || $self->throw_error("Cannot add an override method if a local method is already present");
575 $self->add_method($name => Moose::Meta::Method::Overridden->new(
578 package => $_super_package, # need this for roles
583 sub add_augment_method_modifier {
584 my ($self, $name, $method) = @_;
585 (!$self->has_method($name))
586 || $self->throw_error("Cannot add an augment method if a local method is already present");
588 $self->add_method($name => Moose::Meta::Method::Augmented->new(
595 ## Private Utility methods ...
597 sub _find_next_method_by_name_which_is_not_overridden {
598 my ($self, $name) = @_;
599 foreach my $method ($self->find_all_methods_by_name($name)) {
600 return $method->{code}
601 if blessed($method->{code}) && !$method->{code}->isa('Moose::Meta::Method::Overridden');
606 ## Metaclass compatibility
608 sub _base_metaclasses {
610 my %metaclasses = $self->SUPER::_base_metaclasses;
611 for my $class (keys %metaclasses) {
612 $metaclasses{$class} =~ s/^Class::MOP/Moose::Meta/;
616 error_class => 'Moose::Error::Default',
620 sub _fix_class_metaclass_incompatibility {
622 my ($super_meta) = @_;
624 $self->SUPER::_fix_class_metaclass_incompatibility(@_);
626 if ($self->_class_metaclass_can_be_made_compatible($super_meta)) {
628 || confess "Can't fix metaclass incompatibility for "
630 . " because it is not pristine.";
631 my $super_meta_name = $super_meta->_real_ref_name;
632 my $class_meta_subclass_meta_name = Moose::Util::_reconcile_roles_for_metaclass(blessed($self), $super_meta_name);
633 my $new_self = $class_meta_subclass_meta_name->reinitialize(
637 $self->_replace_self( $new_self, $class_meta_subclass_meta_name );
641 sub _fix_single_metaclass_incompatibility {
643 my ($metaclass_type, $super_meta) = @_;
645 $self->SUPER::_fix_single_metaclass_incompatibility(@_);
647 if ($self->_single_metaclass_can_be_made_compatible($super_meta, $metaclass_type)) {
649 || confess "Can't fix metaclass incompatibility for "
651 . " because it is not pristine.";
652 my $super_meta_name = $super_meta->_real_ref_name;
653 my $class_specific_meta_subclass_meta_name = Moose::Util::_reconcile_roles_for_metaclass($self->$metaclass_type, $super_meta->$metaclass_type);
654 my $new_self = $super_meta->reinitialize(
656 $metaclass_type => $class_specific_meta_subclass_meta_name,
659 $self->_replace_self( $new_self, $super_meta_name );
665 my ( $new_self, $new_class) = @_;
668 bless $self, $new_class;
670 # We need to replace the cached metaclass instance or else when it goes
671 # out of scope Class::MOP::Class destroy's the namespace for the
672 # metaclass's class, causing much havoc.
673 my $weaken = Class::MOP::metaclass_is_weak( $self->name );
674 Class::MOP::store_metaclass_by_name( $self->name, $self );
675 Class::MOP::weaken_metaclass( $self->name ) if $weaken;
678 sub _process_attribute {
679 my ( $self, $name, @args ) = @_;
681 @args = %{$args[0]} if scalar @args == 1 && ref($args[0]) eq 'HASH';
683 if (($name || '') =~ /^\+(.*)/) {
684 return $self->_process_inherited_attribute($1, @args);
687 return $self->_process_new_attribute($name, @args);
691 sub _process_new_attribute {
692 my ( $self, $name, @args ) = @_;
694 $self->attribute_metaclass->interpolate_class_and_new($name, @args);
697 sub _process_inherited_attribute {
698 my ($self, $attr_name, %options) = @_;
699 my $inherited_attr = $self->find_attribute_by_name($attr_name);
700 (defined $inherited_attr)
701 || $self->throw_error("Could not find an attribute by the name of '$attr_name' to inherit from in ${\$self->name}", data => $attr_name);
702 if ($inherited_attr->isa('Moose::Meta::Attribute')) {
703 return $inherited_attr->clone_and_inherit_options(%options);
707 # kind of a kludge to handle Class::MOP::Attributes
708 return $inherited_attr->Moose::Meta::Attribute::clone_and_inherit_options(%options);
712 # reinitialization support
714 sub _restore_metaobjects_from {
718 $self->SUPER::_restore_metaobjects_from($old_meta);
720 for my $role ( @{ $old_meta->roles } ) {
721 $self->add_role($role);
724 for my $application ( @{ $old_meta->_get_role_applications } ) {
725 $application->class($self);
726 $self->add_role_application ($application);
732 sub _immutable_options {
733 my ( $self, @args ) = @_;
735 $self->SUPER::_immutable_options(
736 inline_destructor => 1,
738 # Moose always does this when an attribute is created
739 inline_accessors => 0,
745 ## -------------------------------------------------
750 my ( $self, @args ) = @_;
751 local $error_level = ($error_level || 0) + 1;
752 $self->raise_error($self->create_error(@args));
755 sub _inline_throw_error {
756 my ( $self, @args ) = @_;
757 $self->_inline_raise_error($self->_inline_create_error(@args));
761 my ( $self, @args ) = @_;
765 sub _inline_raise_error {
766 my ( $self, $message ) = @_;
769 'die ' . $message . ';',
774 my ( $self, @args ) = @_;
778 local $error_level = ($error_level || 0 ) + 1;
780 if ( @args % 2 == 1 ) {
781 unshift @args, "message";
784 my %args = ( metaclass => $self, last_error => $@, @args );
786 $args{depth} += $error_level;
788 my $class = ref $self ? $self->error_class : "Moose::Error::Default";
790 Class::MOP::load_class($class);
793 Carp::caller_info($args{depth}),
798 sub _inline_create_error {
799 my ( $self, $msg, $args ) = @_;
800 # XXX ignore $args for now, nothing currently uses it anyway
810 my $class = ref $self ? $self->error_class : "Moose::Error::Default";
812 Class::MOP::load_class($class);
814 # don't check inheritance here - the intention is that the class needs
815 # to provide a non-inherited inlining method, because falling back to
816 # the default inlining method is most likely going to be wrong
817 # yes, this is a huge hack, but so is the entire error system, so.
818 return '$meta->create_error(' . $msg . ', ' . $args . ');'
819 unless $class->meta->has_method('_inline_new');
822 # XXX ignore this for now too
823 # Carp::caller_info($args{depth}),
830 # ABSTRACT: The Moose metaclass
838 This class is a subclass of L<Class::MOP::Class> that provides
839 additional Moose-specific functionality.
841 To really understand this class, you will need to start with the
842 L<Class::MOP::Class> documentation. This class can be understood as a
843 set of additional features on top of the basic feature provided by
848 C<Moose::Meta::Class> is a subclass of L<Class::MOP::Class>.
854 =item B<< Moose::Meta::Class->initialize($package_name, %options) >>
856 This overrides the parent's method in order to provide its own
857 defaults for the C<attribute_metaclass>, C<instance_metaclass>, and
858 C<method_metaclass> options.
860 These all default to the appropriate Moose class.
862 =item B<< Moose::Meta::Class->create($package_name, %options) >>
864 This overrides the parent's method in order to accept a C<roles>
865 option. This should be an array reference containing roles
866 that the class does, each optionally followed by a hashref of options
867 (C<-excludes> and C<-alias>).
869 my $metaclass = Moose::Meta::Class->create( 'New::Class', roles => [...] );
871 =item B<< Moose::Meta::Class->create_anon_class >>
873 This overrides the parent's method to accept a C<roles> option, just
876 It also accepts a C<cache> option. If this is true, then the anonymous
877 class will be cached based on its superclasses and roles. If an
878 existing anonymous class in the cache has the same superclasses and
879 roles, it will be reused.
881 my $metaclass = Moose::Meta::Class->create_anon_class(
882 superclasses => ['Foo'],
883 roles => [qw/Some Roles Go Here/],
887 Each entry in both the C<superclasses> and the C<roles> option can be
888 followed by a hash reference with arguments. The C<superclasses>
889 option can be supplied with a L<-version|Class::MOP/Class Loading
890 Options> option that ensures the loaded superclass satisfies the
891 required version. The C<role> option also takes the C<-version> as an
892 argument, but the option hash reference can also contain any other
893 role relevant values like exclusions or parameterized role arguments.
895 =item B<< $metaclass->make_immutable(%options) >>
897 This overrides the parent's method to add a few options. Specifically,
898 it uses the Moose-specific constructor and destructor classes, and
899 enables inlining the destructor.
901 Since Moose always inlines attributes, it sets the C<inline_accessors> option
904 =item B<< $metaclass->new_object(%params) >>
906 This overrides the parent's method in order to add support for
909 =item B<< $metaclass->superclasses(@superclasses) >>
911 This is the accessor allowing you to read or change the parents of
914 Each superclass can be followed by a hash reference containing a
915 L<-version|Class::MOP/Class Loading Options> value. If the version
916 requirement is not satisfied an error will be thrown.
918 =item B<< $metaclass->add_override_method_modifier($name, $sub) >>
920 This adds an C<override> method modifier to the package.
922 =item B<< $metaclass->add_augment_method_modifier($name, $sub) >>
924 This adds an C<augment> method modifier to the package.
926 =item B<< $metaclass->calculate_all_roles >>
928 This will return a unique array of C<Moose::Meta::Role> instances
929 which are attached to this class.
931 =item B<< $metaclass->calculate_all_roles_with_inheritance >>
933 This will return a unique array of C<Moose::Meta::Role> instances
934 which are attached to this class, and each of this class's ancestors.
936 =item B<< $metaclass->add_role($role) >>
938 This takes a L<Moose::Meta::Role> object, and adds it to the class's
939 list of roles. This I<does not> actually apply the role to the class.
941 =item B<< $metaclass->role_applications >>
943 Returns a list of L<Moose::Meta::Role::Application::ToClass>
944 objects, which contain the arguments to role application.
946 =item B<< $metaclass->add_role_application($application) >>
948 This takes a L<Moose::Meta::Role::Application::ToClass> object, and
949 adds it to the class's list of role applications. This I<does not>
950 actually apply any role to the class; it is only for tracking role
953 =item B<< $metaclass->does_role($role) >>
955 This returns a boolean indicating whether or not the class does the specified
956 role. The role provided can be either a role name or a L<Moose::Meta::Role>
957 object. This tests both the class and its parents.
959 =item B<< $metaclass->excludes_role($role_name) >>
961 A class excludes a role if it has already composed a role which
962 excludes the named role. This tests both the class and its parents.
964 =item B<< $metaclass->add_attribute($attr_name, %params|$params) >>
966 This overrides the parent's method in order to allow the parameters to
967 be provided as a hash reference.
969 =item B<< $metaclass->constructor_class($class_name) >>
971 =item B<< $metaclass->destructor_class($class_name) >>
973 These are the names of classes used when making a class immutable. These
974 default to L<Moose::Meta::Method::Constructor> and
975 L<Moose::Meta::Method::Destructor> respectively. These accessors are
976 read-write, so you can use them to change the class name.
978 =item B<< $metaclass->error_class($class_name) >>
980 The name of the class used to throw errors. This defaults to
981 L<Moose::Error::Default>, which generates an error with a stacktrace
982 just like C<Carp::confess>.
984 =item B<< $metaclass->throw_error($message, %extra) >>
986 Throws the error created by C<create_error> using C<raise_error>
992 See L<Moose/BUGS> for details on reporting bugs.