Skip to content

Commit d381fe8

Browse files
committed
universal.c - handle version style imports as a version check
if someone does use Thing 1.234; it is interpreted as BEGIN { require Thing; Thing->import(); Thing->VERSION(1.234); } however in the case of use Thing "1.234"; we treat it as BEGIN { require Thing; Thing->import("1.234"); } however if people use Exporter::import() as their importer then its import will turn such cases silently into Thing->VERSION("1.234") anyway. With the new logic to detect if someone has called into UNIVERSAL::import() with an argument we were not discriminating between the two cases. This patch basically does the same thing that Exporter would. This patch also special cases the class Test::SubExport::SETUPALT so that Sub::Exporter does not break, as it is very high in the CPAN river, and when it is broken we have problems with test reporting.
1 parent d88da08 commit d381fe8

File tree

1 file changed

+57
-8
lines changed

1 file changed

+57
-8
lines changed

universal.c

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -461,17 +461,66 @@ XS(XS_UNIVERSAL_import_unimport)
461461
dXSI32;
462462

463463
if (items > 1) {
464-
char *class_pv= SvPV_nolen(ST(0));
464+
SV *class_sv = ST(0);
465+
char *class_pv = SvPV_nolen(class_sv);
465466
if (strEQ(class_pv,"UNIVERSAL"))
466467
Perl_croak(aTHX_ "UNIVERSAL does not export anything");
467468
/* _charnames is special - ignore it for now as the code that
468-
* depends on it has its own "no import" logic that produces better
469-
* warnings than this does. */
470-
if (strNE(class_pv,"_charnames"))
471-
Perl_croak(aTHX_
472-
"Attempt to call undefined %s method with arguments via package "
473-
"%" SVf_QUOTEDPREFIX " (Perhaps you forgot to load the package?)",
474-
ix ? "unimport" : "import", SVfARG(ST(0)));
469+
* depends on it has its own "no import" logic that produces
470+
* better warnings than this does. We special case
471+
* Test::SubExport::SETUPALT as Sub::Export is high in the CPAN
472+
* river, and is owned by rjbs, who will fix it soon. For now
473+
* special case it. */
474+
if (strNE(class_pv,"_charnames") &&
475+
strNE(class_pv,"Test::SubExport::SETUPALT"))
476+
{
477+
/* !ix means "import was called" */
478+
IV cmp_items = 1;
479+
480+
if (!ix && Perl_looks_like_number(aTHX_ ST(1))) {
481+
SV *want_version = ST(1);
482+
cmp_items = 2;
483+
484+
/* it looks like the caller has done one of the following:
485+
*
486+
* use Thing '1234';
487+
* Thing->import('1234');
488+
*
489+
* But Thing doesn't define its own import() method.
490+
* So we convert this call into
491+
*
492+
* Thing->VERSION('1234')
493+
*
494+
* which does the version check. VERSION will throw
495+
* an exception if the Thing package isn't defined.
496+
*/
497+
498+
/* note it would be nice if we could do the
499+
* equivalent of 'goto &UNIVERSAL::VERSION'
500+
* here and avoid having to repush items onto the
501+
* stack.
502+
*/
503+
ENTER_with_name("call_VERSION_from_import");
504+
SAVETMPS;
505+
EXTEND(SP, 2);
506+
PUSHMARK(SP);
507+
PUSHs(class_sv);
508+
PUSHs(want_version);
509+
PUTBACK;
510+
(void)call_method("VERSION", G_VOID);
511+
SPAGAIN;
512+
PUTBACK;
513+
FREETMPS;
514+
LEAVE_with_name("call_VERSION_from_import");
515+
}
516+
517+
if ( items > cmp_items ) {
518+
Perl_croak(aTHX_
519+
"Attempt to call undefined %s method with arguments via package "
520+
"%" SVf_QUOTEDPREFIX " (Perhaps you forgot to load the package?)",
521+
ix ? "unimport" : "import", SVfARG(ST(0)));
522+
}
523+
}
475524
}
476525
XSRETURN_EMPTY;
477526
}

0 commit comments

Comments
 (0)