Skip to content

fix: delete $::{'Pkg::'} now properly removes namespace symbols#427

Merged
fglock merged 1 commit into
masterfrom
feature/txn-scope-guard-fix
Apr 3, 2026
Merged

fix: delete $::{'Pkg::'} now properly removes namespace symbols#427
fglock merged 1 commit into
masterfrom
feature/txn-scope-guard-fix

Conversation

@fglock
Copy link
Copy Markdown
Owner

@fglock fglock commented Apr 3, 2026

Summary

  • Fix stash namespace deletion: delete $::{'Foo::'} was a complete no-op because RuntimeStash.deleteGlob() computed fullKey = "main::Foo::" but symbols are stored as "Foo::bar" (without the main:: prefix). The exact-key lookup found nothing and returned early.
  • Add deleteNamespace() method in RuntimeStash: When the key ends with ::, performs prefix-based removal from all 6 global maps (globalCodeRefs, globalVariables, globalArrays, globalHashes, globalIORefs, globalFormatRefs)
  • Add clearPinnedCodeRefsForNamespace() in GlobalVariable: Prevents deleted subs from being resurrected by getGlobalCodeRef() lookups (which re-inserts from pinnedCodeRefs)
  • Invalidate caches after namespace deletion (method resolution + package existence)

Before

$ ./jperl -w -e 'package Foo; sub bar { 42 } package main; delete $::{"Foo::"}; print Foo->can("bar") ? "yes" : "no"'
yes    # WRONG - stash delete was a no-op

After

$ ./jperl -w -e 'package Foo; sub bar { 42 } package main; delete $::{"Foo::"}; print Foo->can("bar") ? "yes" : "no"'
no     # Correct - namespace symbols removed

This fixes spurious Subroutine ACTION_foo redefined warnings in Module::Build's t/help.t test, which calls delete($::{'MyModuleBuilder::'}) between test blocks to clean up the namespace.

Test plan

  • Reproducer: Foo->can('bar') returns false after delete $::{'Foo::'}
  • No 'Subroutine redefined' warning after stash delete + redefine
  • Module::Build t/help.t: 23/23 pass, zero warnings
  • Module::Build full suite: 53/53 test files, 1155/1155 subtests pass
  • make passes (all unit tests)

Generated with Devin

When deleting a stash namespace entry (key ending with '::'),
RuntimeStash.deleteGlob() was a no-op because it computed
fullKey = 'main::Foo::' but symbols are stored as 'Foo::bar'.
The exact-key lookup found nothing and returned early.

Fix: detect namespace keys and perform prefix-based removal from
all global maps (globalCodeRefs, globalVariables, globalArrays,
globalHashes, globalIORefs, globalFormatRefs) plus pinnedCodeRefs.

This fixes spurious 'Subroutine ACTION_foo redefined' warnings in
Module::Build t/help.t, and makes Foo->can('bar') correctly
return false after delete $::{'Foo::'}.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@fglock fglock force-pushed the feature/txn-scope-guard-fix branch from de47b68 to 045f7ec Compare April 3, 2026 12:01
@fglock fglock merged commit 2034066 into master Apr 3, 2026
2 checks passed
@fglock fglock deleted the feature/txn-scope-guard-fix branch April 3, 2026 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant