<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-text-flowed" style="font-family: -moz-fixed;
      font-size: 14px;" lang="x-unicode">
      <br>
      We had a long meeting regarding scoping and shadowing of pattern
      variables.  We ended up in a good place, and we were all a bit
      surprised at where it seems to be pointing.<br>
      <br>
      We started with two use cases that we thought were important:
      <br>
      <br>
      Re-use of binding variables:
      <br>
      <br>
          switch (x) {
      <br>
              case Foo(var a): ...  break;
      <br>
              case Bar(var a): ...
      <br>
          }
      <br>
      <br>
      Short-circuiting tests:
      <br>
      <br>
          if (!(x matches Foo(var a))
      <br>
              throw new NotFooException();
      <br>
          // use a here
      <br>
      <br>
      We had a few nice-to-haves:
      <br>
       - that binding variables should be ordinary variables, not
      something new;
      <br>
       - that binding, when assigned, be final
      <br>
      <br>
      Where we expected to land was something like:
      <br>
       - binding variables are treated as blank finals
      <br>
       - binding variables are hoisted into a synthetic block, which
      starts right before the statement containing the expression
      defining the binding
      <br>
       - it is permitted for locals to shadow other locals that are DU
      at the point of shadowing.  (This, as a bonus, would rescue the
      existing unfortunate scoping of local variables defined in switch
      blocks.)
      <br>
      <br>
      We thought this was a sensible place to land because it built on
      the existing notion of scoping and local variables.  The remaining
      question, it seemed, was: "where does this synthetic scope end."
      <br>
      <br>
      First, a note about where the scope starts.  Consider:
      <br>
      <br>
          if (e1 && x matches Foo(var a)) {
      <br>
              ...
      <br>
          }
      <br>
      <br>
      Logically, we'd like to start the scope for `a` right where it is
      first declared; this is how locals work.  But, if we want to
      maintain the existing concept of local variable scope, it has to
      start earlier.  The latest candidate is right before the if
      starts; we act as if there is an invisible { ... } containing the
      entirety of the if statement, and declare `a` there.
      <br>
      <br>
      This means, though, that the scope of `a` includes `e1`, even
      though `a` is declared later.  This is confusing, but maybe we can
      ignore this, and provide a clear diagnostic if the user stumbles
      across it.
      <br>
      <br>
      So, where does the scope end?  The obvious candidate is right
      after the if statement.  This means `a` is in scope for the entire
      if-else, but, because it is DU in the else-blocks, can be reused
      if we adopt the "shadowing OK if DU" rule.
      <br>
      <br>
      FWIW, the "shadowing ok if DU" rule is clever, and gives us the
      behavior we want for switch / if-else chains with patterns, but
      has some collateral damage.  For example, the following would
      become valid code:
      <br>
      <br>
          int x;  // declared but never used
      <br>
          float x = 1.0f;  // acceptable shadowing of int x
      <br>
      <br>
      Again, maybe we can ignore this.  But where things really blew up
      was attempting to handle the short-circuiting if case:
      <br>
      <br>
          if (!(x matches Foo(var a))
      <br>
              throw new NotFooException();
      <br>
          // use a here
      <br>
      <br>
      For this to work, we'd have to extend the scope to the end of the
      block containing the if statement.  Now, given our "shadowing is
      OK if DU rule", this is fine, right?  Not so fast.  In this
      simpler case:
      <br>
      <br>
          if (x matches Foo(var b)) { }
      <br>
          // try to reuse b here, I dare you
      <br>
      <br>
      we find that
      <br>
       - B is neither DU nor DA after the if, so we can't shadow it;
      <br>
       - B is final and not DU, so we can't write to it;
      <br>
       - B is not DA, so we can't use it.
      <br>
      <br>
      In other words, B is a permanent toxic waste zone, we can neither
      use, nor redeclare, nor assign it.  Urk.
      <br>
      <br>
      Note too that our scoping rule is not really about unbalanced ifs;
      it's about abrupt completion.  This is reasonable too:
      <br>
      <br>
          if (x matches Foo(var a)) {
      <br>
              println("Matched!");
      <br>
          }
      <br>
          else
      <br>
              throw new NotFooException();
      <br>
          // reasonable to use a here too!
      <br>
      <br>
      Taking stock: our goal here was to try and use normal scopes and
      blank final semantics to describe binding variables, out of a
      desire to not introduce new concepts.  But it's a bad fit; the
      scope may be unnaturally large on the beginning side, and wherever
      we set the end of the scope, we end up in a choice of bad
      situations (either something we want in scope is not, or something
      we don't want in scope is.)  So traditional scopes are just a bad
      approximation, and what we gain in "reusing familiar concepts", we
      lose in the mismatch.
      <br>
      <br>
      <br>
      STEPPING BACK
      <br>
      <br>
      What we realized at this point is that the essence of binding
      variables is their <span class="moz-txt-underscore"><span
          class="moz-txt-tag">_</span>conditionality<span
          class="moz-txt-tag">_</span></span>.  There is not a single
      logical old-style scope that describes the right set of places for
      a binding to be in scope, but there is a well-defined control-flow
      analysis that tells us exactly where we can use the binding, and
      where we can't.  This is the flow-scoping construct we initially
      worried was too "new and different."  But, after some further
      thought, and a few tweaks, this seems exactly what we want, and I
      think can be made understandable.
      <br>
      <br>
      The basic idea behind flow-scoping is: a binding variable is in
      scope where it is well-defined, and not in scope when it is not. 
      We'll provide a complete calculus, but the key thing to understand
      is that the rules of flow scoping are just plain old DA/DU; if a
      binding is DA, then it is well-defined.
      <br>
      <br>
      In particular, flow-scoping can handle abrupt termination
      naturally; for a statement:
      <br>
      <br>
          if (x matches Foo(var a)) { A }
      <br>
          else { B }
      <br>
          C
      <br>
      <br>
      the scope of `a` includes A, and also includes C iff B completes
      abruptly.  We can easily explain this as:
      <br>
       - if x matches Foo(var a), we execute the A block, and in this
      case `a` is clearly well-defined (as we'd not execute A if the
      match failed);
      <br>
       - The only way to reach C, if B completes abruptly, is if the
      match succeeds, so `a` is well defined during C in this case too.
      <br>
      <br>
      Because the scope of a binding variable is precisely the cases in
      which it is well defined, there is no need to tinker with
      shadowing.
      <br>
      <br>
      Conditional variables can now always be final, because they will
      never be in scope and not DA.
      <br>
      <br>
      Similarly, folding reachability into scoping for conditional
      variables also means that fallthrough has a well-defined meaning. 
      If we have:<br>
      <br>
          case Foo(int x): ... break;<br>
          case Bar(int x): ....<br>
      <br>
      then the Bar case is not reachable from where x would be
      initialized, so the first x is not in scope when the second x is
      declared, and everything is great.  On the other hand:<br>
      <br>
          case Foo(int x): ... no break ...<br>
          case Bar(int x): ... A ...<br>
      <br>
      now x is well-defined in A, no matter how we got there.  (The
      merging of the two xs is the same merging we have to do anyway for
      "if (x matches Foo(int a) || x matches Bar(int a)".)  <br>
      <br>
      <br>
      People had originally expressed concern that flow-scoping leaves a
      scope "with holes", and allows puzzlers with shadowing of fields.
      (This is the "swiss cheese" problem.) For example:
      <br>
      <br>
          // Field
      <br>
          String s
      <br>
      <br>
          if (!(x matches String s)) {
      <br>
              a(s);
      <br>
          }
      <br>
          else {
      <br>
              b(s);
      <br>
          }
      <br>
      <br>
      This would be confusing because the `s` passed to a() is the
      field, but the `s` passed to b() is the binding.  But, there's a
      really simple way to prevent this: do not allow conditional
      variables to shadow fields or locals.  Now, there is no chance of
      this confusion, and this is not a big constraint, because the
      names of conditional variables are strictly local.  (Further, we
      can disallow shadowing of in-scope conditional variables by locals
      (or other conditional variables.))
      <br>
      <br>
      <br>
      Scorecard:
      <br>
       - Relatively straightforward to spec, as we have a clean calculus
      for flow-scoped conditional variables;
      <br>
       - Relatively straightforward to implement (our prototype already
      does this);
      <br>
       - One new concept: conditional variables;
      <br>
       - Conditional vars are scope where they make sense, and not in
      scope where they do not, cannot be assigned to (always DA and
      final when in scope), and are never in scope when not DA;
      <br>
       - No changes to shadowing;
      <br>
       - Meets all the target use cases.
      <br>
      <br>
      <br>
    </div>
    <br>
    <br>
    <div class="moz-cite-prefix">On 11/3/2017 6:44 AM, Gavin Bierman
      wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:27805597-0665-41D9-996D-6BEBA77B8ADA@oracle.com">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <h2 id="scopes" style="box-sizing: border-box; margin-bottom:
        16px; line-height: 1.225; padding-bottom: 0.3em; color: rgb(51,
        51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',
        Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI
        Emoji', 'Segoe UI Symbol'; margin-top: 0px !important;" class="">Scopes</h2>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class="">Java has five constructs that introduce fresh variables
        into scope: the local variable declaration statement, the for
        statement, the try-with-resources statement, the catch block,
        and lambda expressions. The first, local variable declaration
        statements, introduce variables that are in scope for the rest
        of the block that it is declared in. The others introduce
        variables that are limited in their scope.</p>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class="">The addition of pattern matching brings a new
        expression, <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">matches</code>,
        and extends the <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">switch</code> statement.
        Both these constructs can now introduce fresh (and, if the
        pattern match succeeds, definitely assigned (DA)) variables. But
        the question is <em style="box-sizing: border-box;" class="">what
          is the scope of these ‘pattern’ variables</em>?</p>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class="">Let us consider the pattern matching constructs in
        turn. First the <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">switch</code> statement:</p>
      <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">switch (o) {
    case int i: ...
    case ..
}</code></pre>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class="">What is the scope of the pattern variable <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">i</code>?
        There are a range of options.</p>
      <ol style="box-sizing: border-box; padding: 0px 0px 0px 2em;
        margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51);
        font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial,
        freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
        'Segoe UI Symbol'; font-size: 16px;" class="" type="1">
        <li style="box-sizing: border-box;" class="">
          <p style="box-sizing: border-box; margin-top: 16px;
            margin-bottom: 16px;" class="">The scope of the pattern
            variable is from the start of the switch statement until the
            end of the enclosing block.</p>
          <p style="box-sizing: border-box; margin-top: 16px;
            margin-bottom: 16px;" class="">In this case the pattern
            variable is in scope but would be definitely unassigned (DU)
            immediately after the switch statement.</p>
          <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">switch (o) {
    case int i : ... // DA
                 ... // DA
    case T t :       // i is in scope 
}
... // i in still in scope and DU</code></pre>
        </li>
      </ol>
      <ul style="box-sizing: border-box; padding: 0px 0px 0px 2em;
        margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51);
        font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial,
        freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
        'Segoe UI Symbol'; font-size: 16px;" class="">
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">+ve</strong> Simple</li>
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">-ve</strong> Can’t
          simply reuse a pattern variable in the same switch statement
          (without some form of shadowing)</li>
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">-ve</strong> Pattern
          variable poisons the rest of the block</li>
      </ul>
      <ol start="2" style="box-sizing: border-box; padding: 0px 0px 0px
        2em; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51,
        51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',
        Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI
        Emoji', 'Segoe UI Symbol'; font-size: 16px;" class="" type="1">
        <li style="box-sizing: border-box;" class="">
          <p style="box-sizing: border-box; margin-top: 16px;
            margin-bottom: 16px;" class="">The scope of the pattern
            variable extends only to the end of the switch block.</p>
          <p style="box-sizing: border-box; margin-top: 16px;
            margin-bottom: 16px;" class="">In this case the pattern
            variable would be considered DA only for the statements
            between the current case label and the subsequent case
            labeled statement. For example:</p>
          <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">switch (o) {
    case int i : ... // DA
                 ... // DA
    case T t :       // i is in scope but not DA
}
... // i not in scope</code></pre>
        </li>
      </ol>
      <ul style="box-sizing: border-box; padding: 0px 0px 0px 2em;
        margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51);
        font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial,
        freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
        'Segoe UI Symbol'; font-size: 16px;" class="">
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">+ve</strong> Simple</li>
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">+ve</strong> Pattern
          variables not poisoned in subsequent statements in the rest of
          the block</li>
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">+ve</strong> Similar
          technique to <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">for</code> identifiers
          (not a new idea)</li>
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">-ve</strong> Can’t
          simply reuse a pattern variable in the same switch statement
          (without some form of shadowing)</li>
      </ul>
      <ol start="3" style="box-sizing: border-box; padding: 0px 0px 0px
        2em; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51,
        51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',
        Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI
        Emoji', 'Segoe UI Symbol'; font-size: 16px;" class="" type="1">
        <li style="box-sizing: border-box;" class="">
          <p style="box-sizing: border-box; margin-top: 16px;
            margin-bottom: 16px;" class="">The scope of the pattern
            variable extends only to the next case label.</p>
          <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">switch (o) {
    case int i : ... // in scope and DA
                 ... // in scope and DA
    case T i :       // int i not in scope, so can re-use
}
... // i not in scope</code></pre>
        </li>
      </ol>
      <ul style="box-sizing: border-box; padding: 0px 0px 0px 2em;
        margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51);
        font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial,
        freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
        'Segoe UI Symbol'; font-size: 16px;" class="">
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">+ve</strong> Simple
          syntactic rule</li>
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">+ve</strong> Allows
          reuse of pattern variable in the same switch statement.</li>
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">-ve</strong> Doesn’t
          make sense for fallthrough</li>
      </ul>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class=""><strong style="box-sizing: border-box;" class="">NOTE</strong> This
        final point is important - supporting fallthrough impacts on
        what solution we might choose for scoping of pattern variables.
        (We could not support fallthrough and instead support OR
        patterns - a further design dimension.)</p>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class=""><strong style="box-sizing: border-box;" class="">ASIDE</strong> Should
        we support a <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">switch</code> <em
          style="box-sizing: border-box;" class="">expression</em>; it
        seems clear that scoping should be treated in the same way as it
        is for lambda expressions.</p>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class="">The <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">matches</code> expression
        is unusual in that it is an <em style="box-sizing: border-box;"
          class="">expression</em> that introduces a fresh variable.
        What is the scope of this variable? We want it to be more than
        the expression itself, as we want the following example code to
        be correct:</p>
      <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">if (e matches String s) {
    System.out.println("It's a string - " + s);
}</code></pre>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class="">In other words, the variable introduced by the pattern
        needs to be in scope for an enclosing IfThen statement.</p>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class="">However, a <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">match</code> expression
        could be nested within another expression. It seems reasonable
        that the patterns variables are in scope for at least the rest
        of the expression. For example:</p>
      <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">(e matches String s || s.length() > 0) </code></pre>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class="">Here the <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">s</code> should
        be in scope for the subexpression <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">s.length</code> (although
        it is not DA). In contrast:</p>
      <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">(e matches String s && s.length() > 0)</code></pre>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class="">Here the <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">s</code> is
        both in scope and DA for the subexpression <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">s.length</code>.</p>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class="">However, what about the following:</p>
      <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">if (s.length() > 0 && e matches String s) {
    System.out.println(s);
}</code></pre>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class="">Given the idea that a pattern variable flows from the
        inside-out to the enclosing statement, it would appear that <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">s</code> is
        in scope for the subexpression <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">s.length</code>;
        although it is not DA. Unless we want scopes to be
        non-contiguous, we will have to accept this rather odd situation
        (consider where <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">s</code> shadows
        a field). [This appears to be what happens in the current C#
        compiler.]</p>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class="">Now let’s consider how far a pattern variable flows wrt
        its enclosing statement. We have a range of options:</p>
      <ol style="box-sizing: border-box; padding: 0px 0px 0px 2em;
        margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51);
        font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial,
        freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
        'Segoe UI Symbol'; font-size: 16px;" class="" type="a">
        <li style="box-sizing: border-box;" class="">
          <p style="box-sizing: border-box; margin-top: 16px;
            margin-bottom: 16px;" class="">The scope is both the
            statement that the match expression occurs in and the rest
            of the block. In this scenario,</p>
          <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">if (o matches T t) {
    ... 
} else {
    ...
}</code></pre>
          <p style="box-sizing: border-box; margin-top: 16px;
            margin-bottom: 16px;" class="">is treated as equivalent to
            the following pseudo-code (where <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">match-and-bind</code> is
            a fictional pattern matching construct that pattern-matches
            and binds to a variable that has already been declared)</p>
          <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">T t;
if (o match-and-bind t) {
    // t in scope and DA
} else {
    // t in scope and DU
}
// t in scope and DU</code></pre>
          <p style="box-sizing: border-box; margin-top: 16px;
            margin-bottom: 16px;" class="">This is how the current C#
            compiler works (although the spec describes the next option;
            so perhaps this is a bug).</p>
        </li>
        <li style="box-sizing: border-box;" class="">
          <p style="box-sizing: border-box; margin-top: 16px;
            margin-bottom: 16px;" class="">The scope is just the
            statement that the match expression occurs in. In this
            scenario,</p>
          <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">if (o matches T t) {
... 
} else {

}
...</code></pre>
          <p style="box-sizing: border-box; margin-top: 16px;
            margin-bottom: 16px;" class="">is treated as equivalent to
            the pseudo-code</p>
          <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">{ T t;
  if (o match-and-bind t) {
      // t in scope and DA
  } else {
      // t in scope and DU
      // thus declaration int t = 42; is not allowed.
  }
}
// t not in scope
...</code></pre>
        </li>
      </ol>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class="">This restricted scope allows reuse of pattern
        variables, e.g.</p>
      <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">if (o matches T x) { ... }
if (o matches S x) { ... }</code></pre>
      <ol start="3" style="box-sizing: border-box; padding: 0px 0px 0px
        2em; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51,
        51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',
        Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI
        Emoji', 'Segoe UI Symbol'; font-size: 16px;" class="" type="a">
        <li style="box-sizing: border-box;" class="">
          <p style="box-sizing: border-box; margin-top: 16px;
            margin-bottom: 16px;" class="">The scope of the pattern
            variable is determined by a flow analysis of the enclosing
            statement. (It could be thought of as a refinement of option
            b.) This is currently implemented in the prototype compiler.
            For example:</p>
          <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">if (!!(o matches T t)) {
     // t in scope
} else {
     // t not in scope
}</code></pre>
        </li>
      </ol>
      <ul style="box-sizing: border-box; padding: 0px 0px 0px 2em;
        margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51);
        font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial,
        freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
        'Segoe UI Symbol'; font-size: 16px;" class="">
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">+ve</strong> Code
          will work in the presence of most refactorings</li>
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">+ve</strong> We
          have this code working already :-)</li>
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">-ve</strong> This
          is a break to the existant notion of scope as a contiguous
          program fragment. A scope can now have holes in it. Will users
          ever understand this? (Although they are <em
            style="box-sizing: border-box;" class="">very</em> similar
          to the flow-based rules for DA/DU.)</li>
      </ul>
      <p style="box-sizing: border-box; margin-top: 0px; margin-bottom:
        16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue',
        Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color
        Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px;"
        class=""><strong style="box-sizing: border-box;" class="">ASIDE</strong> Regardless
        of whether we opt for (b) or (c) we may consider a further
        extension where we allow the scope to extend beyond the current
        statement for the case of an unbalanced <code style="white-space: pre; box-sizing: border-box; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">if</code> statement.
        For example</p>
      <pre style="box-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 16px; font-stretch: normal; line-height: 1.45; padding: 16px; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51);" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">```
if (!(o matches T t)) {
    return;
}
// t in scope 
...
return;
```</code></pre>
      <ul style="box-sizing: border-box; padding: 0px 0px 0px 2em;
        margin-top: 0px; color: rgb(51, 51, 51); font-family: 'Helvetica
        Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif,
        'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
        font-size: 16px; margin-bottom: 0px !important;" class="">
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">+ve</strong> Supports
          a common idiom where else blocks are not needed</li>
        <li style="box-sizing: border-box;" class=""><strong
            style="box-sizing: border-box;" class="">-ve</strong> Yet
          further complication of notion of scope.</li>
      </ul>
      <div class=""><br class="">
      </div>
    </blockquote>
    <br>
  </body>
</html>