Skip to content

Inconsistent block scoping #22204

@richardleach

Description

@richardleach

Description
Given an if/else branch, such as the example below, it seems like a reasonable expectation that both branches behave identically with regard to entering a new scope - or not doing so.

sub foo {
    my $x = $_[0];
    if ($x) {
        return 1
    } else {
        return 0
    }
} 

But they don't. The else branch is wrapped in an ENTER/LEAVE pair, but the if branch is not.

5        <;> nextstate(main 3 -e:1) v ->6
-        <1> null K/1 ->-
7           <|> cond_expr(other->8) K/1 ->c
6              <0> padsv[$x:2,9] s ->7
-              <@> scope K ->-
-                 <;> ex-nextstate(main 5 -e:1) v ->8
a                 <@> return K ->b
8                    <0> pushmark s ->9
9                    <$> const[IV 1] s ->a
h              <@> leave KP ->b
c                 <0> enter ->d
d                 <;> nextstate(main 7 -e:1) v ->e
g                 <@> return K ->h
e                    <0> pushmark s ->f
f                    <$> const[IV 0] s ->g

That's not always the behaviour. In the following example, both branches are wrapped in an ENTER/LEAVE pair:

$ perl -MO=Concise,foo -e 'sub foo { $x = $_[0]; if ($x) { local $x = 2 } else { local $x = 3 }}'
main::foo:
...
5        <;> nextstate(main 2 -e:1) v:{ ->6
-        <1> null KP/1 ->-
7           <|> cond_expr(other->8) K/1 ->f
-              <1> ex-rv2sv sK/1 ->7
6                 <#> gvsv[*x] s ->7
d              <@> leave KP ->e
8                 <0> enter ->9
9                 <;> nextstate(main 4 -e:1) v:{ ->a
c                 <2> sassign sKS/2 ->d
a                    <$> const[IV 2] s ->b
-                    <1> ex-rv2sv sKRM*/LVINTRO,1 ->c
b                       <#> gvsv[*x] s/LVINTRO ->c
k              <@> leave KP ->e
f                 <0> enter ->g
g                 <;> nextstate(main 6 -e:1) v:{ ->h
j                 <2> sassign sKS/2 ->k
h                    <$> const[IV 3] s ->i
-                    <1> ex-rv2sv sKRM*/LVINTRO,1 ->j
i                       <#> gvsv[*x] s/LVINTRO ->j
-e syntax OK

The inconsistency seems undesirable because:

  • If a branch should enter a new scope but does not, buggy behaviour may result
  • If a branch needlessly enters a new scope, that harms performance

Steps to Reproduce

perl -MO=Concise,foo -e 'sub foo { my $x = $_[0]; if ($x) { return 1 } else { return 0 }}'

Expected behavior
Both branches have consistent scope behaviour.

Perl configuration
Standard blead, v5.36

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions