diff --git a/lib/Moose/Object.pm b/lib/Moose/Object.pm index a15005d82..69c471bf4 100644 --- a/lib/Moose/Object.pm +++ b/lib/Moose/Object.pm @@ -78,7 +78,12 @@ sub DEMOLISHALL { foreach my $class (@isa) { no strict 'refs'; - my $demolish = *{"${class}::DEMOLISH"}{CODE}; + # If a child module implements DEMOLISH and its parent does not + # then the access below can be the only reference to that parent's sub + my $demolish = do { + no warnings 'once'; + *{"${class}::DEMOLISH"}{CODE}; + }; $self->$demolish($in_global_destruction) if defined $demolish; } diff --git a/t/bugs/DEMOLISH_warnings.t b/t/bugs/DEMOLISH_warnings.t new file mode 100644 index 000000000..bcb63cdf8 --- /dev/null +++ b/t/bugs/DEMOLISH_warnings.t @@ -0,0 +1,15 @@ +use strict; +use warnings; + +use lib 't/lib'; +use Test::More; +use Test::Requires qw(Test::Warnings); +Test::Warnings->import(':no_end_test'); + +# Demolition::OnceRemoved has a variable only in scope during the initial `use` +# As it leaves scope, Perl will call DESTROY on it +# (and Moose::Object will then go through its DEMOLISHALL method) +use Demolition::OnceRemoved; +Test::Warnings::had_no_warnings("No DEMOLISH warnings"); + +done_testing(); diff --git a/t/lib/Demolition/Demolisher.pm b/t/lib/Demolition/Demolisher.pm new file mode 100644 index 000000000..f1a7c1118 --- /dev/null +++ b/t/lib/Demolition/Demolisher.pm @@ -0,0 +1,6 @@ +package Demolition::Demolisher; +use Moose; + +sub DEMOLISH { } + +1; diff --git a/t/lib/Demolition/OnceRemoved.pm b/t/lib/Demolition/OnceRemoved.pm new file mode 100644 index 000000000..8b52d126b --- /dev/null +++ b/t/lib/Demolition/OnceRemoved.pm @@ -0,0 +1,8 @@ +package Demolition::OnceRemoved; +use strict; +use warnings; +use Demolition::Demolisher; + +my $d = Demolition::Demolisher->new; + +1;