Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

Having an issue with one of the best modules: L. Before Perl 5.28 it warns about "Use of inherited AUTOLOAD for non-method" when calling subs but in 5.28 it's "no longer allowed". Is there a way to fix L? Or another module with the same feature?

perl -ML -e 'Data::Dump::dd(HTTP::Tiny->new->get("https://www.perlmonk +s.org")->{headers})'

5.26

Use of inherited AUTOLOAD for non-method Data::Dump::dd() is deprecated. This will be fatal in Perl 5.28 { "accept-ranges" => "bytes", "content-length" => 61983, "content-type" => "text/html", "date" => "Mon, 28 Oct 2019 01:11:46 GMT", "etag" => "\"f21f-595ee257cedca\"", "last-modified" => "Mon, 28 Oct 2019 01:09:07 GMT", "server" => "Apache/2.4.41", }

5.28

Use of inherited AUTOLOAD for non-method Data::Dump::dd() is no longer allowed
Thank you!

Replies are listed 'Best First'.
Re: Perl 28 broke L: How to fix?
by haukex (Archbishop) on Oct 28, 2019 at 09:11 UTC

    It seems your usage of L depends on a "feature" that was deprecated over 20 years ago: It's setting up an AUTOLOAD function in the UNIVERSAL package, so that function calls such as Data::Dump::pp are sent to AUTOLOAD.

    The module's tests only test a method call, and its synopsis only shows a method call. In fact, the breakage of the module was reported in #131571, and in the module's repository as #2. If I interpret the fix correctly, I think the module was never intended to work for regular function calls.

    At the moment, I don't have any good ideas for a replacement. It's still possible to call Data::Dump->pp(), but that will pass the package as the first argument:

    $ perl -wMstrict -ML -e 'Data::Dump->pp("x")' ("Data::Dump", "x")

    Note that using -M actually doesn't necessarily make the one-liners longer:

    $ perl -wMstrict -ML -e 'Data::Dump::pp("x")' $ perl -wMstrict -MData::Dump=pp -e 'pp("x")'
      Note that using -M actually doesn't necessarily make the one-liners longer

      Not for this example but the real win is not having to worry about -M at all once you have -ML.

      breakage of the module was reported in #131571

      Thanks for the history lesson. So Perl's appearance of backward compatability was an illusion due to not fatalizing deprecated bugs for 20 years? Bugs were mistaken for features: "So, this is something we're likely to see many times in this annual development cycle​: code that breaks because we're fatalizing a behavior we've tolerated for twenty years (+ 1 month)."

      I see a lot of messages from recent versions of Perl about code that is "no longer allowed" and "forbidden" and even "illegal"! The code police have made easy things impossible. If you guys can't figure this out my chances are slim:

      haukex: At the moment, I don't have any good ideas for a replacement.
      Corion: I'm not sure how to best implement the functionality of L.
      
        I see a lot of messages from recent versions of Perl about code that is "no longer allowed" and "forbidden" and even "illegal"! The code police have made easy things impossible.

        I dunno about that, deprecations are usually made with a good amount of consideration, watching all of CPAN for breakage (as in this case) as a canary for how Perl is used by devs in production, and there is usually a workaround or fix possible for code that is affected by this. Personally, I don't remember really being affected by any surprising deprecations. So I'd be curious what problems specifically you've run into.

        As I said, in this case, I doubt that this module was ever supposed to work with plain function calls, and only methods. If you look at the really early and unreleased version of the module, that's all it supported. And the tests specifically test for the failure of a function call.

        If you guys can't figure this out my chances are slim

        There are probably some hacks that would make it possible, but I think chances are that they'd be pretty ugly hacks. Note that using UNIVERSAL::AUTOLOAD is not so great to begin with - anything that installs things into UNIVERSAL risks having other modules break in mysterious ways.

Re: Perl 28 broke L: How to fix?
by davido (Cardinal) on Oct 28, 2019 at 03:36 UTC

    It's interesting that it doesn't exhibit failing tests on newer versions of Perl. I can confirm that it doesn't behave correctly on 5.30, if correct is to work both for OO modules AND for function modules. Here's the tester's matrix, showing that it is still passing: http://matrix.cpantesters.org/?dist=L+v1.0.1. So clearly the tests are inadequate. You might submit a patch that includes a test. If you feel up to fixing the problem itself, include that in the patch too. Otherwise, just the test so that the author can incorporate it, and have something to work with in fixing it. The module was most recently uploaded in December 2018, so it's possible the author is still open to maintaining it.

    Fortunately it's really just saving a few keystrokes; one-liners will survive without it. Also worth noting, perhaps: Object/Class-method calls do work. It's functions (non-methods) that trip up the error.


    Dave

      Fortunately it's really just saving a few keystrokes; one-liners will survive without it. Also worth noting, perhaps: Object/Class-method calls do work. It's functions (non-methods) that trip up the error.

      I find it very valuable and wish to retain the ability to use modules on the command line without having to refer to them twice and tinker with -M! As for the second point, you would think so, but check this out:

      perl -ML -e 'print Data::Dumper->Dump([HTTP::Tiny->new->get(q(https:// +www.perlmonks.org))->{headers}])'

      5.26

      $VAR1 = {
                'server' => 'Apache/2.4.41',
                'etag' => '"f059-595f109c01e50"',
                'date' => 'Mon, 28 Oct 2019 04:38:47 GMT',
                'last-modified' => 'Mon, 28 Oct 2019 04:36:06 GMT',
                'content-length' => '61529',
                'accept-ranges' => 'bytes',
                'content-type' => 'text/html'
              };
      

      5.28

      $VAR1 = {
                'content-type' => 'text/plain',
                'content-length' => 110
              };
      


      <Twilight Zone Music>

        Don’t know what went wrong for you, but it’s working fine for me:

        17:17 >perl -ML -e "print Data::Dumper->Dump([HTTP::Tiny->new->get(q(h +ttps://www.perlmonks.org))->{headers}]);" $VAR1 = { 'content-type' => 'text/html', 'server' => 'Apache/2.4.41', 'etag' => '"e57e-595f34244bafb"', 'content-length' => '58750', 'last-modified' => 'Mon, 28 Oct 2019 07:15:04 GMT', 'accept-ranges' => 'bytes', 'date' => 'Mon, 28 Oct 2019 07:18:01 GMT' }; 17:18 >mversion -f L Data::Dumper HTTP::Tiny L v1.0.1 Data::Dumper 2.173 HTTP::Tiny 0.070 17:18 >perl -v This is perl 5, version 28, subversion 0 (v5.28.0) built for MSWin32-x +64-multi-thread

        Strawberry Perl v5.28.0 under Windows 8.1, 64-bit. Same (correct) result using Perl v5.30.0.

        Cheers,

        Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Perl 28 broke L: How to fix?
by Corion (Patriarch) on Oct 28, 2019 at 09:17 UTC

    You're calling dd as a function, but still expect AUTOLOAD to kick in. This doesn't work anymore, since Perl 5.28.

    I'm not sure how to best implement the functionality of L. For real method calls, (ab)using UNIVERSAL::AUTOLOAD will continue to work I think, but for functions called by absolute name, I'm not aware of any approach where you can find the package name soon enough and then inject AUTOLOAD there.

    Maybe you can work with a tie'd main:: or maybe you can add an INIT block to inject your AUTOLOAD into all packages that exist at that time.

      I'm not sure how to best implement the functionality of L. For real method calls, (ab)using UNIVERSAL::AUTOLOAD will continue to work I think, but for functions called by absolute name, I'm not aware of any approach where you can find the package name soon enough and then inject AUTOLOAD there.

      I found this but don't know how to implement it:

      The simple fix for old code is: In any module that used to depend on inheriting AUTOLOAD for non-methods from a base class named BaseClass, execute *AUTOLOAD = \&BaseClass::AUTOLOAD during startup. 
      
      http://www.rocketaware.com/perl/perldelta/Deprecated_Inherited_C_AUTOLOAD.htm
      

        Yes. That's what I meant when mentioning the INIT block.

Re: Perl 28 broke L: How to fix?
by tobyink (Canon) on Oct 29, 2019 at 00:16 UTC

    Not perfect, but it will fix the majority of cases, including your example...

    # add this to L.pm use Filter::Simple; FILTER { while (/((?:[\w]+::)+)[\w]+\(/g) { substr(my $module = $1, -2) = ''; eval { Module::Load::load($module) }; } };
      I added warn after every significant step in L.pm and read the docs for Filter::Simple to understand what your patch is doing. Nice work and thank you! I also learned that the eval doesn't seem necessary. I thought it was killing the warning about autoloading non-methods but I get no warnings for using functions!
      perl -ML -e 'Data::Dump::dd(File::Spec::Functions::splitpath($^X))'

        The eval is because the regexp might match a package name but you don't have a module with that name available to be loaded. For example, if "lib/Foo.pm" defines a function called "Foo::Bar::baz", then you run this:

        perl -Ilib -MFoo -ML -e'Foo::Bar::baz(42)'

        … without the eval it will die because "lib/Foo/Bar.pm" doesn't exist, even though "lib/Foo/Bar.pm" is unnecessary because "Foo::Bar::baz" is defined elsewhere in a module that successfully loaded.

Re: Perl 28 broke L: How to fix?
by 1nickt (Canon) on Oct 28, 2019 at 13:34 UTC

    It works fine if you use the core module Data::Dumper for your dumping. Easiest solution?

    $ perlbrew use perl-5.28.1
    $ perl -ML -E 'say Data::Dumper->Dump([HTTP::Tiny->new->get("https://w +ww.perlmonks.org")->{headers}])' $VAR1 = { 'etag' => '"e96f-595f85f776cd3"', 'content-length' => '59759', 'last-modified' => 'Mon, 28 Oct 2019 13:21:09 GMT', 'content-type' => 'text/html', 'date' => 'Mon, 28 Oct 2019 13:22:14 GMT', 'server' => 'Apache/2.4.41', 'accept-ranges' => 'bytes' };
    $ perlbrew use perl-5.30.0
    $ perl -ML -E 'say Data::Dumper->Dump([HTTP::Tiny->new->get("https://w +ww.perlmonks.org")->{headers}])' $VAR1 = { 'last-modified' => 'Mon, 28 Oct 2019 13:21:09 GMT', 'content-type' => 'text/html', 'content-length' => '59759', 'etag' => '"e96f-595f85f776cd3"', 'date' => 'Mon, 28 Oct 2019 13:22:23 GMT', 'accept-ranges' => 'bytes', 'server' => 'Apache/2.4.41' };

    Hope this helps!


    The way forward always starts with a minimal test.
Re: Perl 28 broke L: How to fix?
by Anonymous Monk on Oct 28, 2019 at 10:49 UTC
      Or add a l($) to -Mojo -e " l Data::Dump; dd g(q(example.com))->headers->to_hash "
      perl -Mojo -E 'say r g("example.com")->headers->to_hash'

Re: Perl 28 broke L: How to fix?
by Anonymous Monk on Oct 28, 2019 at 02:59 UTC
    file a bug report with author, wait :)
      file a bug report with author

      I considered that and checked the CPAN Testers Matrix but don't see any failures for L! I figured maybe L was doing something unintentional by loading non-methods that a perlbug allowed to happen all this time? L docs are sparse. Why else would Perl remove a way to do it? Since L is maintained it doesn't seem to be considered a bug.

      Anyway I just saw davido's reply too and must say L is black magic to me. I don't even know what it's doing, nor if this is a bug in L, let alone how to fix it or anything. I just love L and want to keep up with new Perl versions and hope someone will post a patch so my local L will autoload non-methods again, without any warnings! 🙏 Thanx 😇