[patterns] Redefinition of pattern variable is allowed by javac in some cases

Mark Mahieu markmahieu at gmail.com
Sun Jan 5 06:15:28 UTC 2020


Hi.

I just bumped into a variant of that one with 14-ea-29, whilst musing on how the ? : operator might take further advantage of pattern matching.  My example actually used the pattern variable inside a branch, but I expect it’s the same apparent discrepancy between javac and the draft spec.

That draft also suggests that more sophisticated rules may be considered in future for some conditional statements (e.g. the last sentence in 6.3.1.4).  I imagine this was discussed at some point (and I guess, parked for now) but I’ve had no luck searching the archives - any pointers would be gratefully received :)

Mark


> On 26 Dec 2019, at 11:34, Tagir Valeev <amaembo at gmail.com> wrote:
> 
> Another shadowing case:
> 
> class Test {
>  static void test(Object o1, Object o2, Object o3) {
>    boolean b1 = o1 instanceof String s ? o2 instanceof String s : o3
> instanceof String s;
>  }
> }
> 
> Also happily compiled by javac. If I understand correctly the spec
> draft, 6.3.1.4 [1], this should be rejected:
> 
> The following rules apply to a conditional expression a ? b : c:
> ...
> A pattern variable is introduced both by a when true, and by c when true.
> ...
> A pattern variable is introduced both by b when true, and by c when true.
> 
> Am I missing something?
> 
> With best regards,
> Tagir Valeev.
> 
> [1] http://cr.openjdk.java.net/~gbierman/jep305/jep305-20191021/specs/patterns-instanceof-jls.html#jls-6.3.1.4
> 
> On Thu, Dec 26, 2019 at 5:10 PM Tagir Valeev <amaembo at gmail.com> wrote:
>> 
>> Hello!
>> 
>> Playing with javac 14-ea+28-1366. This code can be successfully compiled:
>> 
>> class Test {
>>  static void test(Object o1, Object o2) {
>>      boolean b = o1 instanceof String s && (!(o2 instanceof String s)
>> || consume(s));
>>  }
>> 
>>  static boolean consume(String s) {
>>     System.out.println(s);
>>     return true;
>>  }
>> 
>>  public static void main(String[] args) {
>>    test("x", "y"); // prints y
>>  }
>> }
>> 
>> Spec draft says for `a || b`:
>> It is a compile-time error if any pattern variable introduced by a
>> when false is already in scope at b.
>> 
>> If I understand correctly, assuming a = !(o2 instanceof String s) and
>> b = consume(s), we already have `s` (from `o1 instanceof String s`) in
>> the scope at b, and a introduces new `s` when false, so this code
>> should be rejected. Please correct me if I am wrong.
>> 
>> With best regards,
>> Tagir Valeev.
> 



More information about the amber-dev mailing list