Front page | perl.perl5.porters |
Postings from February 2009
method names clash by importing
Thread Next
From:
Dmitry Karasik
Date:
February 13, 2009 16:22
Subject:
method names clash by importing
Message ID:
20090213182526.GA18087@tetsuo.karasik.eu.org
Hello,
I've just been bitten by an inhertitance case, as described here:
http://perlmonks.org/?node_id=743606
But in short, the problem is such that if you import names into a class that
derives from a parent class, then you risk to silently override parent class
methods without being aware of it. For example, a code like
package MyCGI;
use base qw(CGI);
use POSIX qw(access);
MyCGI-> new()
may break if next version of CGI.pm may have an important internal "sub access",
that is supposed to be called from new() but mysteriously wouldn't.
I wonder, if solution to this problem is desired for the language.
I investigated a bit and found that a very crude patch (see below)
would do a more "proper" inheritance, so I guess that such a behavior
can be triggered by setting some internal flag, $^H or something similar
that can be made local to a package (I'm unsure if $^H has this feature).
My proposition is twofold: first, I'd like to create means to protect against
blind inheritance problem. Second, I'll also need to ask for help with the
patch, not much, but still, I could easily overlook something or do a plain
wrong. Finally, I'd like to ask for opinions what UI would be appropriate for
this feature, I though that possibly "use base" syntax can be extended for this
purpose, something like use base ':only ParentClass' possibly.
Anyway, please tell me what do you think.
Thanks,
Dmitry Karasik
diff --git a/gv.c b/gv.c
index 65419bd..561cc8f 100644
--- a/gv.c
+++ b/gv.c
@@ -409,7 +409,7 @@ Perl_gv_fetchmeth(pTHX_ HV *stash, const char *name, STRLEN len, I32 level)
gv_init(topgv, stash, name, len, TRUE);
if ((cand_cv = GvCV(topgv))) {
/* If genuine method or valid cache entry, use it */
- if (!GvCVGEN(topgv) || GvCVGEN(topgv) == topgen_cmp) {
+ if ((!GvCVGEN(topgv) || GvCVGEN(topgv) == topgen_cmp) && !GvIMPORTED(topgv)) {
return topgv;
}
else {
@@ -457,7 +457,12 @@ Perl_gv_fetchmeth(pTHX_ HV *stash, const char *name, STRLEN len, I32 level)
candidate = *gvp;
assert(candidate);
if (SvTYPE(candidate) != SVt_PVGV) gv_init(candidate, cstash, name, len, TRUE);
- if (SvTYPE(candidate) == SVt_PVGV && (cand_cv = GvCV(candidate)) && !GvCVGEN(candidate)) {
+ if (
+ SvTYPE(candidate) == SVt_PVGV &&
+ (cand_cv = GvCV(candidate)) &&
+ !GvCVGEN(candidate) &&
+ !GvIMPORTED(cand_cv)
+ ) {
/*
* Found real method, cache method in topgv if:
* 1. topgv has no synonyms (else inheritance crosses wires)
diff --git a/pp_hot.c b/pp_hot.c
index c52a0d6..3b247a5 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -3125,6 +3125,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
if (he) {
gv = MUTABLE_GV(HeVAL(he));
if (isGV(gv) && GvCV(gv) &&
+ !GvIMPORTED(gv) &&
(!GvCVGEN(gv) || GvCVGEN(gv)
== (PL_sub_generation + HvMROMETA(stash)->cache_gen)))
return MUTABLE_SV(GvCV(gv));
--
Sincerely,
Dmitry Karasik
Thread Next
-
method names clash by importing
by Dmitry Karasik