In perl.git, the branch blead has been updated

<https://perl5.git.perl.org/perl.git/commitdiff/4efd247d4c712a390e5c79db522ef527f439ad6b?hp=cb3fd6ac9362413a80d297fb7708846bd904102b>

- Log -----------------------------------------------------------------
commit 4efd247d4c712a390e5c79db522ef527f439ad6b
Author: Father Chrysostomos <spr...@cpan.org>
Date:   Sun Feb 25 18:19:54 2018 -0800

    [perl #132910] Carp: Avoid ->can
    
    If a module has its own ‘can’ (or even UNIVERSAL::can) implementation,
    it may impede Carp’s use of ->can to detect overloading.  Instead,
    use UNIVERSAL::can directly, or, in the presence of an override,
    use overload::mycan.  Don’t use overload::Overloaded, since old
    versions of overload call ->can.

-----------------------------------------------------------------------

Summary of changes:
 MANIFEST                      |  2 ++
 dist/Carp/lib/Carp.pm         | 50 +++++++++++++++++++++++++------------------
 dist/Carp/t/broken_can.t      | 15 +++++++++++++
 dist/Carp/t/broken_univ_can.t | 24 +++++++++++++++++++++
 4 files changed, 70 insertions(+), 21 deletions(-)
 create mode 100644 dist/Carp/t/broken_can.t
 create mode 100644 dist/Carp/t/broken_univ_can.t

diff --git a/MANIFEST b/MANIFEST
index 4794817c5f..acc1bcba7f 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -2966,6 +2966,8 @@ dist/Carp/t/arg_regexp.t          See if Carp formats 
regexp args OK in stack traces
 dist/Carp/t/arg_string.t               See if Carp formats string args OK in 
stack traces
 dist/Carp/t/baduni.t           See if Carp handles non-char Unicode
 dist/Carp/t/baduni_warnings.t          See if Carp handles non-char Unicode 
when loaded via warnings.pm
+dist/Carp/t/broken_can.t       Test Carp with bad can implementations
+dist/Carp/t/broken_univ_can.t  Test Carp with bad UNIVERSAL::can
 dist/Carp/t/Carp.t             See if Carp works
 dist/Carp/t/Carp_overload.t            See if Carp handles overloads
 dist/Carp/t/Carp_overloadless.t                See if Carp handles overloads 
that dont use overload.pm
diff --git a/dist/Carp/lib/Carp.pm b/dist/Carp/lib/Carp.pm
index 1aa16c9d24..d5443ba676 100644
--- a/dist/Carp/lib/Carp.pm
+++ b/dist/Carp/lib/Carp.pm
@@ -116,6 +116,29 @@ BEGIN {
        ;
 }
 
+sub _univ_mod_loaded {
+    return 0 unless exists($::{"UNIVERSAL::"});
+    for ($::{"UNIVERSAL::"}) {
+       return 0 unless ref \$_ eq "GLOB" && *$_{HASH} && exists $$_{"$_[0]::"};
+       for ($$_{"$_[0]::"}) {
+           return 0 unless ref \$_ eq "GLOB" && *$_{HASH} && exists 
$$_{"VERSION"};
+           for ($$_{"VERSION"}) {
+               return 0 unless ref \$_ eq "GLOB";
+               return ${*$_{SCALAR}};
+           }
+       }
+    }
+}
+
+# _mycan is either UNIVERSAL::can, or, in the presence of an override,
+# overload::mycan.
+BEGIN {
+    *_mycan = _univ_mod_loaded('can')
+        ? do { require "overload.pm"; _fetch_sub overload => 'mycan' }
+        : \&UNIVERSAL::can
+}
+
+
 our $VERSION = '1.49';
 $VERSION =~ tr/_//d;
 
@@ -298,20 +321,6 @@ sub caller_info {
     return wantarray() ? %call_info : \%call_info;
 }
 
-sub _univisa_loaded {
-    return 0 unless exists($::{"UNIVERSAL::"});
-    for ($::{"UNIVERSAL::"}) {
-       return 0 unless ref \$_ eq "GLOB" && *$_{HASH} && exists $$_{"isa::"};
-       for ($$_{"isa::"}) {
-           return 0 unless ref \$_ eq "GLOB" && *$_{HASH} && exists 
$$_{"VERSION"};
-           for ($$_{"VERSION"}) {
-               return 0 unless ref \$_ eq "GLOB";
-               return ${*$_{SCALAR}};
-           }
-       }
-    }
-}
-
 # Transform an argument to a function into a string.
 our $in_recurse;
 sub format_arg {
@@ -321,7 +330,9 @@ sub format_arg {
 
         # lazy check if the CPAN module UNIVERSAL::isa is used or not
         #   if we use a rogue version of UNIVERSAL this would lead to infinite 
loop
-        my $isa = _univisa_loaded() ? sub { 1 } : _fetch_sub(UNIVERSAL => 
"isa");
+        my $isa = _univ_mod_loaded('isa')
+            ? sub { 1 }
+            : _fetch_sub(UNIVERSAL => "isa");
 
          # legitimate, let's not leak it.
         if (!$in_recurse && $isa->( $arg, 'UNIVERSAL' ) &&
@@ -347,13 +358,10 @@ sub format_arg {
         }
         else
         {
-            # overload uses the presence of a special "method" name "((" to 
signal
+            # overload uses the presence of a special
+            # "method" named "((" or "()" to signal
             # it is in effect.  This test seeks to see if it has been set up.
-            # In theory we should be able to use 'can' without the $in_recurse 
guard,
-            # but this breaks modules that call overloads or croak during 
can(), for
-            # instance Class::Std v0.013, so if we end up here twice, we will 
just
-            # load overload outright.
-            if ($in_recurse || do{ local $in_recurse = 1; $pack->can("((") || 
$pack->can("()") }) {
+            if (_mycan($pack, "((") || _mycan($pack, "()")) {
                 # Argument is blessed into a class with overloading, and
                 # so might have an overloaded stringification.  We don't
                 # want to risk getting the overloaded stringification,
diff --git a/dist/Carp/t/broken_can.t b/dist/Carp/t/broken_can.t
new file mode 100644
index 0000000000..c32fa1909d
--- /dev/null
+++ b/dist/Carp/t/broken_can.t
@@ -0,0 +1,15 @@
+use Test::More tests => 1;
+
+# [perl #132910]
+
+package Foo;
+sub can { die }
+
+package main;
+
+use Carp;
+
+eval {
+    sub { confess-sins }->(bless[], Foo);
+};
+like $@, qr/^-sins at /;
diff --git a/dist/Carp/t/broken_univ_can.t b/dist/Carp/t/broken_univ_can.t
new file mode 100644
index 0000000000..0ec19d7aa3
--- /dev/null
+++ b/dist/Carp/t/broken_univ_can.t
@@ -0,0 +1,24 @@
+# [perl #132910]
+# This mock-up breaks Test::More.  Don’t use Test::More.
+
+sub UNIVERSAL::can { die; }
+
+# Carp depends on this to detect the override:
+BEGIN { $UNIVERSAL::can::VERSION = 0xbaff1ed_bee; }
+
+use Carp;
+
+eval {
+    sub { confess-sins }->(bless[], Foo);
+};
+print "1..1\n";
+if ($@ !~ qr/^-sins at /) {
+  print "not ok 1\n";
+  print "# Expected -sins at blah blah blah...\n";
+  print "# Instead, we got:\n";
+  $@ =~ s/^/#   /mg;
+  print $@;
+}
+else {
+  print "ok 1\n";
+}

-- 
Perl5 Master Repository

Reply via email to