Skip to content

Commit bf00f44

Browse files
fix(B,Sub::Name): honor Sub::Name-assigned CV names in B::GV->NAME
B::svref_2object($cv)->GV->NAME previously returned "__ANON__" for CVs renamed via Sub::Name::subname or Sub::Util::set_subname, because B.pm required `defined &{$fqn}` to trust the name. Real-Perl XS Sub::Name updates the CV's CvGV/CvNAME_HEK directly and B reads those fields without consulting any stash entry, so the name is honored even when the sub was never installed as a glob. The `defined &{$fqn}` check was originally added to handle stash deletion/clearing (op/stash.t, uni/stash.t), so it cannot be removed outright. Instead, track an explicit `explicitlyRenamed` flag on RuntimeCode that is set by Sub::Name::subname and Sub::Util::set_subname, and have B.pm trust the name whenever that flag is set. - RuntimeCode: add `explicitlyRenamed` field - SubName.java / SubUtil.java: set the flag when renaming - SubName: expose private helper `Sub::Name::_is_renamed($cv)` - B.pm: consult the flag before falling back to the stash check Impact on Sub-Name-0.28 t/exotic_names.t: 1038 more tests now pass (0 -> 1038 pass out of 1560). Remaining 522 failures are unrelated to Sub::Name and stem from stash-aliasing semantics (`*palatable:: = *{"aliased::native::..."}`). No regressions in op/stash.t / uni/stash.t (75/105 before and after). Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent a97176f commit bf00f44

5 files changed

Lines changed: 47 additions & 3 deletions

File tree

src/main/java/org/perlonjava/core/Configuration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public final class Configuration {
3333
* Automatically populated by Gradle/Maven during build.
3434
* DO NOT EDIT MANUALLY - this value is replaced at build time.
3535
*/
36-
public static final String gitCommitId = "687b74120";
36+
public static final String gitCommitId = "a97176ff7";
3737

3838
/**
3939
* Git commit date of the build (ISO format: YYYY-MM-DD).
@@ -48,7 +48,7 @@ public final class Configuration {
4848
* Parsed by App::perlbrew and other tools via: perl -V | grep "Compiled at"
4949
* DO NOT EDIT MANUALLY - this value is replaced at build time.
5050
*/
51-
public static final String buildTimestamp = "Apr 22 2026 14:52:02";
51+
public static final String buildTimestamp = "Apr 22 2026 16:01:34";
5252

5353
// Prevent instantiation
5454
private Configuration() {

src/main/java/org/perlonjava/runtime/perlmodule/SubName.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import org.perlonjava.runtime.runtimetypes.*;
44

5+
import static org.perlonjava.runtime.runtimetypes.RuntimeScalarCache.scalarFalse;
6+
import static org.perlonjava.runtime.runtimetypes.RuntimeScalarCache.scalarTrue;
57
import static org.perlonjava.runtime.runtimetypes.RuntimeScalarType.*;
68

79
/**
@@ -35,6 +37,8 @@ public static void initialize() {
3537
subName.defineExport("EXPORT_OK", "subname");
3638
try {
3739
subName.registerMethod("subname", null); // No prototype to allow flexible args
40+
// Private helper used by B.pm to detect CVs renamed via Sub::Name::subname.
41+
subName.registerMethod("_is_renamed", null);
3842
} catch (NoSuchMethodException e) {
3943
System.err.println("Warning: Missing Sub::Name method: " + e.getMessage());
4044
}
@@ -81,6 +85,29 @@ public static RuntimeList subname(RuntimeArray args, int ctx) {
8185
}
8286
code.subName = fullName;
8387
}
88+
// Mark the CV as explicitly renamed so B::svref_2object()->GV->NAME
89+
// honors the assigned name even when no matching stash entry exists.
90+
code.explicitlyRenamed = true;
8491
return codeRef.getList();
8592
}
93+
94+
/**
95+
* _is_renamed CODEREF
96+
*
97+
* Private helper for B.pm. Returns a true scalar if the given code
98+
* reference has been explicitly renamed via Sub::Name::subname (or
99+
* Sub::Util::set_subname), otherwise an empty/false scalar. Non-CODE
100+
* arguments yield false.
101+
*/
102+
public static RuntimeList _is_renamed(RuntimeArray args, int ctx) {
103+
if (args.size() != 1) {
104+
return scalarFalse.getList();
105+
}
106+
RuntimeScalar ref = args.get(0);
107+
if (ref.type != CODE) {
108+
return scalarFalse.getList();
109+
}
110+
RuntimeCode code = (RuntimeCode) ref.value;
111+
return (code.explicitlyRenamed ? scalarTrue : scalarFalse).getList();
112+
}
86113
}

src/main/java/org/perlonjava/runtime/perlmodule/SubUtil.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ public static RuntimeList set_subname(RuntimeArray args, int ctx) {
142142
} else {
143143
code.subName = fullName;
144144
}
145+
// Mark the CV as explicitly renamed so B::svref_2object()->GV->NAME
146+
// honors the assigned name even when no matching stash entry exists.
147+
code.explicitlyRenamed = true;
145148
return codeRef.getList();
146149
}
147150
}

src/main/java/org/perlonjava/runtime/runtimetypes/RuntimeCode.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,12 @@ public static void clearInlineMethodCache() {
343343
public boolean isMapGrepBlock = false;
344344
// Flag to indicate this code is an eval BLOCK - non-local return should propagate through it
345345
public boolean isEvalBlock = false;
346+
// Flag to indicate this CV has been explicitly renamed via Sub::Name::subname
347+
// (or Sub::Util::set_subname). When set, B::svref_2object($cv)->GV->NAME should
348+
// return the assigned name even if the resulting fully-qualified name does not
349+
// correspond to an installed stash entry — matching real-Perl XS Sub::Name
350+
// behaviour, where the CV's CvGV points to a free-floating GV with the name.
351+
public boolean explicitlyRenamed = false;
346352

347353
// Depth of active recursive calls to this subroutine, used by the
348354
// "Deep recursion on subroutine" warning. Incremented on entry and

src/main/perl/lib/B.pm

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,16 @@ package B::CV {
139139
# Verify the sub still exists in the stash. Stubs whose
140140
# stash entry has been deleted/cleared/undefined should be
141141
# treated as anonymous (matching Perl 5's GV anonymization).
142+
# Exception: CVs explicitly renamed via Sub::Name::subname
143+
# (or Sub::Util::set_subname) carry a private flag; in
144+
# real Perl their CvGV points to a free-floating GV with
145+
# the assigned name, and NAME should always reflect that.
142146
no strict 'refs';
143-
if (defined &{"$fqn"}) {
147+
my $renamed = 0;
148+
if (exists $Sub::Name::{_is_renamed}) {
149+
$renamed = Sub::Name::_is_renamed($self->{ref}) ? 1 : 0;
150+
}
151+
if ($renamed || defined &{"$fqn"}) {
144152
$self->{_pkg_name} = $pkg;
145153
$self->{_sub_name} = $name;
146154
$self->{_is_anon} = 0;

0 commit comments

Comments
 (0)