diff --git a/lib/warnings.pm b/lib/warnings.pm index cb2c92cbadee..64dee569a1b7 100644 --- a/lib/warnings.pm +++ b/lib/warnings.pm @@ -5,7 +5,7 @@ package warnings; -our $VERSION = "1.76"; +our $VERSION = "1.77"; # Verify that we're called correctly so that warnings will work. # Can't use Carp, since Carp uses us! @@ -132,6 +132,7 @@ our %Offsets = ( # Warnings Categories added in Perl 5.043 'experimental::signature_named_parameters'=> 156, + 'undef_import' => 158, ); our %Bits = ( @@ -208,6 +209,7 @@ our %Bits = ( 'syscalls' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00", # [54] 'taint' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [39] 'threads' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [40] + 'undef_import' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40", # [79] 'uninitialized' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [41] 'unopened' => "\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [11] 'unpack' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [42] @@ -290,6 +292,7 @@ our %DeadBits = ( 'syscalls' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00", # [54] 'taint' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [39] 'threads' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [40] + 'undef_import' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80", # [79] 'uninitialized' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [41] 'unopened' => "\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [11] 'unpack' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [42] @@ -316,8 +319,8 @@ our %NoOp = ( # These are used by various things, including our own tests our $NONE = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; -our $DEFAULT = "\x10\x01\x00\x00\x00\x50\x04\x00\x00\x00\x00\x00\x01\x40\x05\x45\x55\x15\x55\x15"; # [2,4,22,23,25,48,55..57,60,61,63..70,72..78] -our $LAST_BIT = 158 ; +our $DEFAULT = "\x10\x01\x00\x00\x00\x50\x04\x00\x00\x00\x00\x00\x01\x40\x05\x45\x55\x15\x55\x55"; # [2,4,22,23,25,48,55..57,60,61,63..70,72..79] +our $LAST_BIT = 160 ; our $BYTES = 20 ; sub Croaker @@ -1056,6 +1059,8 @@ The current hierarchy is: | +- threads | + +- undef_import + | +- uninitialized | +- unpack diff --git a/pod/perldeprecation.pod b/pod/perldeprecation.pod index 6d2857cdf7ef..a35cc5d814e8 100644 --- a/pod/perldeprecation.pod +++ b/pod/perldeprecation.pod @@ -45,19 +45,6 @@ Category: "deprecated::unicode_property_name" =head2 Perl 5.44 -=head3 Calling a missing C or C method with an argument - -Historically calling C or C on any class which did not -define such a method would be silently ignored. Effectively Perl behaved as -though there was an empty method defined in the C package (even -when there was no such method actually defined). Beginning with Perl version -5.39.2 (production version 5.40), calling such a method I an argument -triggered a warning, and in Perl version 5.44 this warning became upgraded to -an error. (Calling such a method with no arguments at all will always be -safe.) - -Category: "deprecated::missing_import_called_with_args" - =head3 Changing C while another C is in scope A C declaration has many implicit effects on the surrounding @@ -632,7 +619,6 @@ So now C will always tie the scalar, not the handle it holds. To tie the handle, use C (with an explicit asterisk). The same applies to C and C. - =head1 SEE ALSO L, L. diff --git a/pod/perldiag.pod b/pod/perldiag.pod index a9730ee4eab5..9bf45d742345 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -1339,15 +1339,20 @@ a string overload and is also not a blessed CODE reference. In short the C function does not know what to do with the object. See also L. -=item Attempt to call undefined %s method with arguments via package -"%s" (Perhaps you forgot to load the package?) - -(F) You called the C or C method of a class that has no -such method defined in its inheritance graph, and passed an argument to the -method. This is very often the sign of a misspelled package name in a C -or C statement that has silently succeeded due to a case insensitive +=item Attempt to call undefined %s method with arguments ("%s"%s) +via package "%s" (Perhaps you forgot to load the package?) + +(S undef_import) You called the +C or C method of a class that has no import method +defined in its inheritance graph, and passed an argument to the method. +This is very often the sign of a misspelled package name in a use or +require statement that has silently succeeded due to a case insensitive file system. +Another common reason this may happen is mistakenly attempting to +import or unimport a symbol from a package which does not use +C or otherwise define its own C or C method. + =item Can't locate package %s for @%s::ISA (W syntax) The @ISA array contained the name of another package that diff --git a/regen/warnings.pl b/regen/warnings.pl index 099eac70449d..97a583667b0c 100644 --- a/regen/warnings.pl +++ b/regen/warnings.pl @@ -16,7 +16,7 @@ # # This script is normally invoked from regen.pl. -$VERSION = '1.76'; +$VERSION = '1.77'; BEGIN { require './regen/regen_lib.pl'; @@ -80,8 +80,6 @@ BEGIN 'deprecated::dot_in_inc' => [ 5.025011, DEFAULT_ON], 'deprecated::version_downgrade' => [ 5.035009, DEFAULT_ON], 'deprecated::delimiter_will_be_paired' => [ 5.035010, DEFAULT_ON], - 'deprecated::missing_import_called_with_args' - => [ 5.039002, DEFAULT_ON], 'deprecated::subsequent_use_version' => [ 5.039008, DEFAULT_ON], }], 'void' => [ 5.008, DEFAULT_OFF], @@ -170,6 +168,7 @@ BEGIN 'locale' => [ 5.021, DEFAULT_ON], 'shadow' => [ 5.027, DEFAULT_OFF], 'scalar' => [ 5.035, DEFAULT_OFF], + 'undef_import' => [ 5.043, DEFAULT_ON ], #'default' => [ 5.008, DEFAULT_ON ], }]}; diff --git a/t/lib/warnings/universal b/t/lib/warnings/universal index fc21973a4832..3d2ec7506ee8 100644 --- a/t/lib/warnings/universal +++ b/t/lib/warnings/universal @@ -25,3 +25,26 @@ my $a = bless [] ; UNIVERSAL::isa $a, Jim ; EXPECT Can't locate package Joe for @Y::ISA at - line 8. +######## +use warnings 'undef_import'; +Some::Package->import; +EXPECT +######## +Some::Package->import("bar"); +EXPECT +Attempt to call undefined import method with arguments ("bar") via package "Some::Package" (Perhaps you forgot to load the package?) at - line 1. +######## +use warnings 'undef_import'; +Some::Package->import("bar", "guff"); +EXPECT +Attempt to call undefined import method with arguments ("bar" ...) via package "Some::Package" (Perhaps you forgot to load the package?) at - line 2. +######## +use warnings; +no warnings 'undef_import'; +Some::Package->import("bar", "guff"); +EXPECT +######## +use warnings 'undef_import'; +Some::Package->unimport(1.234); +EXPECT +Attempt to call undefined unimport method with arguments ("1.234") via package "Some::Package" (Perhaps you forgot to load the package?) at - line 2. diff --git a/t/op/universal.t b/t/op/universal.t index 4343f7ac9852..810a35510292 100644 --- a/t/op/universal.t +++ b/t/op/universal.t @@ -11,7 +11,7 @@ BEGIN { require "./test.pl"; } -plan tests => 144; +plan tests => 142; $a = {}; bless $a, "Bob"; @@ -196,26 +196,6 @@ my $x = {}; bless $x, 'X'; ok $x->isa('UNIVERSAL'); ok $x->isa('UNIVERSAL'); -sub test_undefined_method { - my $method = shift; - my @message_components = ( - q|Attempt to call undefined|, - q|method with arguments via package "Some::Package"|, - q|(Perhaps you forgot to load the package?)|, - ); - my $message = join ' ' => ( - $message_components[0], - $method, - @message_components[1,2], - ); - my $pattern = qr/\Q$message\E/; - - eval { Some::Package->$method("bar") }; - like $@, $pattern, "Got expected pattern for undefined $method"; -} - -test_undefined_method($_) for (qw| import unimport |); - # This segfaulted in a blead. fresh_perl_is('package Foo; Foo->VERSION; print "ok"', 'ok'); diff --git a/universal.c b/universal.c index 25ca0d170f04..9c237391536d 100644 --- a/universal.c +++ b/universal.c @@ -451,10 +451,14 @@ XS(XS_UNIVERSAL_import_unimport) * depends on it has its own "no import" logic that produces better * warnings than this does. */ if (strNE(class_pv,"_charnames")) - Perl_croak(aTHX_ - "Attempt to call undefined %s method with arguments via package " - "%" SVf_QUOTEDPREFIX " (Perhaps you forgot to load the package?)", - ix ? "unimport" : "import", SVfARG(ST(0))); + ck_warner_d(packWARN(WARN_UNDEF_IMPORT), + "Attempt to call undefined %s method with arguments " + "(%" SVf_QUOTEDPREFIX "%s) via package " + "%" SVf_QUOTEDPREFIX " (Perhaps you forgot to load the package?)", + ix ? "unimport" : "import", + SVfARG(ST(1)), + (items > 2 ? " ..." : ""), + SVfARG(ST(0))); } XSRETURN_EMPTY; } diff --git a/warnings.h b/warnings.h index e48789ca21dc..f16b5d332dba 100644 --- a/warnings.h +++ b/warnings.h @@ -161,10 +161,11 @@ /* Warnings Categories added in Perl 5.043 */ #define WARN_EXPERIMENTAL__SIGNATURE_NAMED_PARAMETERS 78 +#define WARN_UNDEF_IMPORT 79 #define WARNsize 20 #define WARN_ALLstring "\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125" #define WARN_NONEstring "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" -#define WARN_DEFAULTstring "\x10\x01\x00\x00\x00\x50\x04\x00\x00\x00\x00\x00\x01\x40\x05\x45\x55\x15\x55\x15" +#define WARN_DEFAULTstring "\x10\x01\x00\x00\x00\x50\x04\x00\x00\x00\x00\x00\x01\x40\x05\x45\x55\x15\x55\x55" #define isLEXWARN_on \ cBOOL(PL_curcop && PL_curcop->cop_warnings != pWARN_STD) @@ -355,6 +356,7 @@ category parameters passed. =for apidoc Amnh||WARN_EXPERIMENTAL__KEYWORD_ALL =for apidoc Amnh||WARN_EXPERIMENTAL__KEYWORD_ANY =for apidoc Amnh||WARN_EXPERIMENTAL__SIGNATURE_NAMED_PARAMETERS +=for apidoc Amnh||WARN_UNDEF_IMPORT =cut */