Skip to content

fix(tie,MakeMaker): AUTOLOAD fallback + INST_ARCHLIBDIR expansion#530

Merged
fglock merged 1 commit intomasterfrom
fix/tie-autoload-fallback
Apr 21, 2026
Merged

fix(tie,MakeMaker): AUTOLOAD fallback + INST_ARCHLIBDIR expansion#530
fglock merged 1 commit intomasterfrom
fix/tie-autoload-fallback

Conversation

@fglock
Copy link
Copy Markdown
Owner

@fglock fglock commented Apr 21, 2026

Summary

Two bugs surfaced while running jcpan -t AI::Prolog. Before: 14 of 19 test files failed to load at all. After: 460/460 tests pass.

1. Tie — Do not fall through to AUTOLOAD for UNTIE/DESTROY

Retying an already-tied hash (as Regexp::Common does in its import when loading sub-modules that themselves use Regexp::Common) triggers an implicit untie. TiedVariableBase::tieCallIfExists, TieHash::tieCallIfExists, TieArray::tieCallIfExists, and TieHandle::tieCallIfExists used InheritanceResolver.findMethodInHierarchy, which transparently falls back to AUTOLOAD when the method doesn't exist.

That invoked Regexp::Common's sub AUTOLOAD { _croak "Can't $AUTOLOAD" } with an unset $AUTOLOAD, producing the cryptic error Can't at .../balanced.pm line 9. and breaking every module that depends on Regexp::Common.

Per Perl semantics, UNTIE/DESTROY on tied variables are "if exists" only and must not trigger AUTOLOAD dispatch. Fix: reject AUTOLOAD-resolved matches (detected via code.autoloadVariableName != null) in all four tieCallIfExists helpers.

Minimal repro:

package Foo;
our %RE;
sub TIEHASH { bless {}, shift }
sub AUTOLOAD { our $AUTOLOAD; die "Can't $AUTOLOAD" }
tie %RE, __PACKAGE__;
tie %RE, __PACKAGE__;  # was: Can't     now: ok

2. MakeMaker — Expand $(INST_ARCHLIBDIR) / $(INST_AUTODIR) + tolerate missing generated sources

Term::ReadKey's Makefile.PL uses PM => { 'ReadKey.pm' => '$(INST_ARCHLIBDIR)/ReadKey.pm' }. PerlOnJava's MakeMaker only expanded INST_LIB / INST_ARCHLIB / INST_LIBDIR, leaving INST_ARCHLIBDIR literal → mkdir: : No such file or directory.

  • Derive <parent> / <full> paths from NAME and expand INST_LIBDIR, INST_ARCHLIBDIR, INST_AUTODIR, INST_ARCHAUTODIR (both $(...) and ${...} forms) per standard EUMM conventions.
  • Make _shell_cp tolerant of missing source files. Some distributions (like Term::ReadKey) generate .pm from a .pm.PL that requires XS bootstrap; PerlOnJava can't run that, but the install should still succeed so dependent modules can proceed.

Test plan

  • make — all unit tests pass
  • jcpan -t AI::Prolog — 460/460 tests pass (was 14/19 files failing)
  • jcpan -i Term::ReadKey — installs (with graceful skip of the missing generated .pm)
  • Minimal tie; tie repro now matches perl behavior (TIEHASH runs on re-tie; DESTROY is dispatched via AUTOLOAD with $AUTOLOAD correctly set)

Generated with Devin

Two fixes surfaced while running `jcpan -t AI::Prolog`:

1. tie: Do not fall through to AUTOLOAD for UNTIE/DESTROY.

   Retying an already-tied hash (as Regexp::Common does when its
   import loads sub-modules that themselves `use Regexp::Common`)
   triggers an implicit untie. The untie path calls tiedUntie()
   which, via tieCallIfExists("UNTIE"), was using
   InheritanceResolver.findMethodInHierarchy — which transparently
   falls back to AUTOLOAD. That invoked Regexp::Common's AUTOLOAD
   with an unset $AUTOLOAD, producing the cryptic error
   `Can't  at .../balanced.pm line 9.` and breaking loading of
   Regexp::Common entirely.

   tie special methods (UNTIE, DESTROY) are "if exists" only: they
   should not trigger AUTOLOAD dispatch. Reject AUTOLOAD-resolved
   matches (detected via code.autoloadVariableName != null) in all
   four tieCallIfExists helpers: TiedVariableBase, TieHash,
   TieArray, TieHandle.

2. MakeMaker: Expand $(INST_ARCHLIBDIR)/$(INST_AUTODIR) and tolerate
   missing generated sources.

   Term::ReadKey's Makefile.PL sets
   `PM => { 'ReadKey.pm' => '$(INST_ARCHLIBDIR)/ReadKey.pm' }`.
   PerlOnJava's MakeMaker only expanded INST_LIB/INST_ARCHLIB/
   INST_LIBDIR, leaving INST_ARCHLIBDIR literal which produced
   `mkdir: : No such file or directory`.

   - Derive <parent> and <full> paths from NAME and expand
     INST_LIBDIR, INST_ARCHLIBDIR, INST_AUTODIR, INST_ARCHAUTODIR
     (both $(...) and ${...} forms).
   - Make `_shell_cp` tolerant of missing source files. Some
     distributions (Term::ReadKey) generate .pm via a .pm.PL that
     requires XS bootstrap; we cannot run that, but the install
     should still succeed so dependent modules can proceed.

Result:
  `jcpan -t AI::Prolog`: 460/460 tests pass (previously 14/19 test
  files failed to load at all).

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@fglock fglock merged commit 8108fc7 into master Apr 21, 2026
2 checks passed
@fglock fglock deleted the fix/tie-autoload-fallback branch April 21, 2026 18:48
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