Skip to content

Commit

Permalink
Forbid any downgrade of use VERSION once at least v5.39 on account of…
Browse files Browse the repository at this point in the history
… imported builtin lexicals
  • Loading branch information
leonerd committed Jan 17, 2024
1 parent 669c2a2 commit 042cb98
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 1 deletion.
8 changes: 8 additions & 0 deletions op.c
Original file line number Diff line number Diff line change
Expand Up @@ -8046,6 +8046,14 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg)
PL_hints &= ~HINT_STRICT_VARS;
}

/* Forbid any VERSION downgrade when already above 5.39 because doing
* so risks disabling an imported builtin, and we don't (currently)
* have an ability to do this.
*/
if (PL_prevailing_version >= SHORTVER(5, 39) && shortver < PL_prevailing_version) {
croak("Downgrading a use VERSION declaration when above v5.39 is not permitted");
}

if (shortver >= SHORTVER(5, 39)) {
prepare_export_lexical();
import_builtin_bundle(shortver);
Expand Down
19 changes: 19 additions & 0 deletions pod/perldiag.pod
Original file line number Diff line number Diff line change
Expand Up @@ -2234,6 +2234,25 @@ declaration of one having a larger number (which would have enabled
these effects). Because of a change to the way that C<use VERSION>
interacts with the strictness flags, this is no longer supported.

=item Downgrading a use VERSION declaration when above v5.39 is not permitted

(F) An attempt was made to back-pedal the prevailing C<use VERSION> to a
lower number, while the version is at least v5.39. Because any version at
least v5.39 imports new lexical symbols from L<builtin>, such imports would
need removing from the scope. At present there is no facility for doing
this, so such version downgrades are not permitted.

Instead, if you need to use a specifically later version only in a small
scope, use a nested block. Upon leaving the block afterwards, all of the
lexical state will be restored - including removing the extra imported
symbols.

use v5.20;
{
use v5.39;
# extra symbols can be used in here
}

=item (Do you need to predeclare %s?)

(S syntax) This is an educated guess made in conjunction with the message
Expand Down
15 changes: 15 additions & 0 deletions pod/perlfunc.pod
Original file line number Diff line number Diff line change
Expand Up @@ -10183,6 +10183,21 @@ file (possibly after a C<package> statement or any amount of whitespace or
comment), so that its effects happen first, and other pragmata are applied
after it.

Furthermore, once the version is 5.39.0 or higher, no later C<use VERSION>
declaration within the same scope is permitted to lower the version again.
This is because any imported functions from C<builtin> would need to be made
invisible again. If you wish to use a higher version only in a small
section of a file, enclose that section in its own lexical scope. Once
outside the scope again afterwards, any imported effects are no longer
visible.

use v5.20;
{
use v5.39;
# imported builtins are now visible
}
# any effects of the block above have now been removed

Specifying VERSION as a numeric argument of the form 5.024001 should
generally be avoided as older less readable syntax compared to
v5.24.1. Before perl 5.8.0 released in 2002 the more verbose numeric
Expand Down
8 changes: 7 additions & 1 deletion t/comp/use.t
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ BEGIN {
$INC{"feature.pm"} = 1; # so we don't attempt to load feature.pm
}

print "1..87\n";
print "1..89\n";

# Can't require test.pl, as we're testing the use/require mechanism here.

Expand Down Expand Up @@ -157,6 +157,12 @@ like $@, qr/^Can't use string/,
like $warnings, qr/^Downgrading a use VERSION declaration to below v5.11 is deprecated, and will become fatal in Perl 5.40 at /,
'use 5.01 after use 5.012 provokes deprecation warning';
}
eval 'use 5.039; use 5.020;';
like $@, qr/^Downgrading a use VERSION declaration when above v5\.39 is not permitted at /,
'downgrading prevailing version in same scope is not permitted';
eval '{ use 5.039; } use 5.020;';
ok !$@, 'downgrading prevailing version by falling out of scope is permitted';

eval 'no strict "subs"; use 5.012; ${"foo"} = "bar"';
ok $@, 'no strict subs allows ver decl to enable refs';
eval 'no strict "subs"; use 5.012; $nonexistent_pack_var';
Expand Down

0 comments on commit 042cb98

Please sign in to comment.