diff --git a/gv.c b/gv.c index 2f75f25c7d..89bd964776 100644 --- a/gv.c +++ b/gv.c @@ -1212,13 +1212,7 @@ Perl_gv_fetchmethod_pvn_flags(pTHX_ HV *stash, const char *name, const STRLEN le gv = gv_fetchmeth_pvn(stash, name, name_end - name, 0, flags); if (!gv) { - /* This is the special case that exempts Foo->import and - Foo->unimport from being an error even if there's no - import/unimport subroutine */ - if (strEQ(name,"import") || strEQ(name,"unimport")) { - gv = (GV*)sv_2mortal((SV*)newCONSTSUB_flags(NULL, - NULL, 0, 0, NULL)); - } else if (autoload) + if (autoload) gv = gv_autoload_pvn( ostash, name, name_end - name, GV_AUTOLOAD_ISMETHOD|flags ); diff --git a/lib/UNIVERSAL.pm b/lib/UNIVERSAL.pm index 96ecfe6e43..5e9537daae 100644 --- a/lib/UNIVERSAL.pm +++ b/lib/UNIVERSAL.pm @@ -1,19 +1,9 @@ package UNIVERSAL; -our $VERSION = '1.15'; +our $VERSION = '1.16'; -# UNIVERSAL should not contain any extra subs/methods beyond those -# that it exists to define. The existence of import() below is a historical -# accident that can't be fixed without breaking code. - -# Make sure that even though the import method is called, it doesn't do -# anything unless called on UNIVERSAL. -sub import { - return unless $_[0] eq __PACKAGE__; - return unless @_ > 1; - require Carp; - Carp::croak("UNIVERSAL does not export anything"); -} +# UNIVERSAL.pm should not contain any methods/subs, they +# are all defined in universal.c 1; __END__ diff --git a/pod/perldiag.pod b/pod/perldiag.pod index 38aa9c550a..698817d5d6 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -1256,6 +1256,14 @@ 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 import method defined in its inheritance graph. This is very +often the sign of a mispelled package name in a use or require statement +that has silently succeded due to a case insensitive file system. + =item Can't locate package %s for @%s::ISA (W syntax) The @ISA array contained the name of another package that diff --git a/t/op/universal.t b/t/op/universal.t index 4c277c3e39..cbd2b79ef0 100644 --- a/t/op/universal.t +++ b/t/op/universal.t @@ -139,9 +139,9 @@ like $@, qr/^Invalid version format/; my $subs = join ' ', sort grep { defined &{"UNIVERSAL::$_"} } keys %UNIVERSAL::; if ('a' lt 'A') { - is $subs, "can isa DOES VERSION"; + is $subs, "can import isa unimport DOES VERSION"; } else { - is $subs, "DOES VERSION can isa"; + is $subs, "DOES VERSION can import isa unimport"; } ok $a->isa("UNIVERSAL"); @@ -160,11 +160,10 @@ eval "use UNIVERSAL"; ok $a->isa("UNIVERSAL"); my $sub2 = join ' ', sort grep { defined &{"UNIVERSAL::$_"} } keys %UNIVERSAL::; -# XXX import being here is really a bug if ('a' lt 'A') { - is $sub2, "can import isa DOES VERSION"; + is $sub2, "can import isa unimport DOES VERSION"; } else { - is $sub2, "DOES VERSION can import isa"; + is $sub2, "DOES VERSION can import isa unimport"; } eval 'sub UNIVERSAL::sleep {}'; @@ -198,10 +197,12 @@ ok $x->isa('UNIVERSAL'); ok $x->isa('UNIVERSAL'); -# Check that the "historical accident" of UNIVERSAL having an import() -# method doesn't effect anyone else. eval { Some::Package->import("bar") }; -is $@, ''; +my $err= $@; +$err=~s!t/op!op!; +is $err, "Attempt to call undefined import method with arguments" + . " via package \"Some::Package\" (Perhaps you forgot to load" + . " the package?) at op/universal.t line 200.\n"; # This segfaulted in a blead. diff --git a/universal.c b/universal.c index 20a36fae85..fd654f4920 100644 --- a/universal.c +++ b/universal.c @@ -454,6 +454,29 @@ XS(XS_UNIVERSAL_isa) } } +XS(XS_UNIVERSAL_import_unimport); /* prototype to pass -Wmissing-prototypes */ +XS(XS_UNIVERSAL_import_unimport) +{ + dXSARGS; + dXSI32; + + if (items > 1) { + char *class_pv= SvPV_nolen(ST(0)); + if (strEQ(class_pv,"UNIVERSAL")) + Perl_croak(aTHX_ "UNIVERSAL does not export anything"); + /* _charnames is special - ignore it for now as the code that + * 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))); + } + XSRETURN_EMPTY; +} + + XS(XS_UNIVERSAL_can); /* prototype to pass -Wmissing-prototypes */ XS(XS_UNIVERSAL_can) { @@ -1287,6 +1310,8 @@ static const struct xsub_details these_details[] = { {"UNIVERSAL::isa", XS_UNIVERSAL_isa, NULL, 0 }, {"UNIVERSAL::can", XS_UNIVERSAL_can, NULL, 0 }, {"UNIVERSAL::DOES", XS_UNIVERSAL_DOES, NULL, 0 }, + {"UNIVERSAL::import", XS_UNIVERSAL_import_unimport, NULL, 0}, + {"UNIVERSAL::unimport", XS_UNIVERSAL_import_unimport, NULL, 1}, #define VXS_XSUB_DETAILS #include "vxs.inc" #undef VXS_XSUB_DETAILS