Re: Draft Spec for Third Preview of Pattern Matching for Switch and Record Patterns (JEP 405) now available

2022-04-26 Thread Gavin Bierman
Dear experts:

The latest draft of a joint spec covering JEP 427 (Third Preview of Pattern 
Matching for switch)  and JEP 405 (Record Patterns) is available at:

https://cr.openjdk.java.net/~gbierman/jep427+405/latest

And, following convention, is also accessible from both of the following:

https://cr.openjdk.java.net/~gbierman/jep405/latest
https://cr.openjdk.java.net/~gbierman/jep427/latest

Thanks,
Gavin

On 7 Apr 2022, at 12:40, Gavin Bierman  wrote:

Dear experts:

The first draft of a spec covering both the third preview of Pattern Matching 
for switch (JEP number coming, but currently available at 
https://openjdk.java.net/jeps/8282272) and JEP 405 (Record Patterns) is now 
available at:

http://cr.openjdk.java.net/~gbierman/PatternSwitchPlusRecordPatterns/PatternSwitchPlusRecordPatterns-20220407/specs/patterns-switch-jls.html

Comments welcome!

Thanks,
Gavin



Re: Draft Spec for Third Preview of Pattern Matching for Switch and Record Patterns (JEP 405) now available

2022-04-20 Thread Gavin Bierman
Thanks for spotting these, Guy. All corrected.

Gavin

On 10 Apr 2022, at 03:45, Guy Steele 
mailto:guy.ste...@oracle.com>> wrote:

Nice work defining new terminology for Chapter 14.  Just a few nits:


14.11.1

A switch label is said to support a default if either it has a default label, 
or it has a case label with a default.

Maybe:

A switch label is said to support a default if either it has a default label, 
or it has a case label with a default case element.



Any variable that is used but not declared in a whenexpression must either be 
final or effectively final 
(4.12.4).

Make that:

Any variable that is used but not declared in a whenexpression must be either 
final or effectively final 
(4.12.4).




The switch block of a switch statement or a switch expression is switch 
compatible with the type of the selector expression, T, if all the switch 
labels in the switch block are switch compatible with T.

I suggest:

The switch block of a switch statement or a switch expression is switch 
compatible with the type of the selector expression, T, if every switch label 
in the switch block is switch compatible with T.

because the following sentence defines the phrase “a switch label is switch 
compatible with T “ rather than “(a set of) switch labels are switch compatible 
with T “.

(These are basic principles of the style of writing I tried to establish for 
JLS: (a) once you define a specific form for a technical phrase, stick as 
closely as possible to that form; (2) where possible, focus on a single item in 
preference to sets of items—this means that “every” is usually a more useful 
quantifier than “all”.)


[more to come? I’m too sleepy to continue reading right now]

—Guy




Re: Draft Spec for Third Preview of Pattern Matching for Switch and Record Patterns (JEP 405) now available

2022-04-20 Thread Gavin Bierman
Thanks Aggelos, all corrected .

Gavin

On 14 Apr 2022, at 22:34, Angelos Bimpoudis 
mailto:angelos.bimpou...@oracle.com>> wrote:

Hello Gavin,

Exceptional work. Some minor proposals from my side...

14.11.1 includes a discussion about executable switch expressions and 
statements. It describes the transformation of default and case labels after 
resolution of patterns. Maybe this deserves a separate subsection.

> A set of case elements is exhaustive for a type T if it contains a pattern 
> that is unconditional at type T (14.30.3)

I think this is a crucial rule since it brings the two worlds of totality and 
exhaustivity together. It deserves a tiny example here. Do you think it would 
be beneficial?

> The set Q is exhaustive from component d at type V, where d is the component 
> following c, V is the type of corresponding component field in T, and Q is 
> the set of patterns containing every record pattern in P whose component 
> pattern corresponding to c covers U.

Instead of using the word "covers" we need to talk about the T <: U subtype 
relation. Covers is a remnant of the previous terminology set IIUC (which was 
good, but here is undefined).

nitpicking:

a instanceof expression -> an
a enum -> an enum
a unrefined -> an unrefined
and that statement can completely normally -> can complete normally
then it is further tranformed -> then it is further *transformed*
or the RelationalExpression of a instanceof -> an

Many thanks,
Aggelos


From: amber-spec-experts 
mailto:amber-spec-experts-r...@openjdk.java.net>>
 on behalf of Gavin Bierman 
mailto:gavin.bier...@oracle.com>>
Sent: 07 April 2022 13:40
To: amber-spec-experts 
mailto:amber-spec-experts@openjdk.java.net>>
Subject: Draft Spec for Third Preview of Pattern Matching for Switch and Record 
Patterns (JEP 405) now available

Dear experts:

The first draft of a spec covering both the third preview of Pattern Matching 
for switch (JEP number coming, but currently available at 
https://openjdk.java.net/jeps/8282272) and JEP 405 (Record Patterns) is now 
available at:

http://cr.openjdk.java.net/~gbierman/PatternSwitchPlusRecordPatterns/PatternSwitchPlusRecordPatterns-20220407/specs/patterns-switch-jls.html

Comments welcome!

Thanks,
Gavin



Re: Draft Spec for Third Preview of Pattern Matching for Switch and Record Patterns (JEP 405) now available

2022-04-20 Thread Gavin Bierman
Thanks Maurizio!

On 8 Apr 2022, at 11:57, Maurizio Cimadamore 
mailto:maurizio.cimadam...@oracle.com>> wrote:


Hi Gavin,
great work - some comments:

* in section 6 on names there's no mention of whether pattern variables are 
matched in the `when` clause.

This is covered in section 6.3.4? But maybe I misunderstand your point?

* section 14.11.1, you say that a case element is "unrefined" if it has `when` 
with constant expression whose value is `true`. This is a bit ambiguous: I 
think what you want here is "evaluates to true", because I think you also want 
to cover "true || true" or "!!true", right? I think that's what you meant, but 
the word "value" is confusing, I think. This ambiguity is also present in the 
rule below when we say that two case label with same "value" are not permitted. 
Maybe all this is pre-existing, but I wonder it it could be worth clarifying.

Point taken, but I followed the language of Chapter of JLS on Definite 
Assignment, e.g. in 16.1.1:

"V  is [un]assigned after any >>> constant expression (§15.29) whose value is 
true <<< when false.”

* we define the concept of what it means for a case label to "support default" 
but we do not define what it means to "support null". The latter is also 
referred to in the list of checks for switch labels in 14.11.1

Yeah - I’m probably trying to be too clever here...let me try to clarify some 
of the language...

* "If a switch label appears at the end of a switch block, it is a compile-time 
error if it consists of more than one case or default label." - not sure I get 
this? I mean, sure I can't have "case default: case default" - but the rest? 
E.g. can't I end a switch with "case 4: case 5: ..." ?

Yikes - mistake! Thanks for spotting.

* this sentence "A switch label that supports a unrefined pattern p dominates 
another switch label supporting a pattern q if p dominates q" is tricky - but I 
think correct; only labels w/o a "when" can dominate other labels, and pattern 
dominance doesn't care about "when", so you shold be good.

* 10.3.2 and also the small example at the end of the definition of "executable 
switch" refer to the notion of "any" pattern - but that pattern is not defined

It is defined at the end of 14.30.1, but it is (currently) a pattern that can’t 
be expressed, so is not in the grammar, but is a pattern that appears in the 
process of resolving a pattern (defined in 14.30.2). This is similar to the JLS 
treatment of intersection types, that don’t appear in the grammar, but are 
defined as types in Chapter 4.

Thanks so much for these comments!

Gavin


Re: Draft Spec for Third Preview of Pattern Matching for Switch and Record Patterns (JEP 405) now available

2022-04-07 Thread Gavin Bierman
Thanks Guy.

All corrected.

Gavin

On 8 Apr 2022, at 03:27, Guy Steele 
mailto:guy.ste...@oracle.com>> wrote:


13.4.26 Evolution of Enum Classes

Adding or reordering enum constants in an enum class will not break 
compatibility with pre-existing binaries.

As with sealed classes 
(13.4.2.1),
 whilst adding an enum constant to an enum class is considered a binary 
compatible change, it may cause the execution of an exhaustive switch 
(14.11.1)
 to fail with a linkage error (an IncompatibleClassChangeError may be thrown) 
if the switch encounters the new enum constant that was not known at compile 
time 
(14.11.3,
 
15.28.2).


Would it be more accurate (or more to the point) to replace “whilst” with 
“although”?

—Guy




Re: Draft Spec for Third Preview of Pattern Matching for Switch and Record Patterns (JEP 405) now available

2022-04-07 Thread Gavin Bierman


On 7 Apr 2022, at 20:41, Brian Goetz 
mailto:brian.go...@oracle.com>> wrote:



http://cr.openjdk.java.net/~gbierman/PatternSwitchPlusRecordPatterns/PatternSwitchPlusRecordPatterns-20220407/specs/patterns-switch-jls.html

Comments welcome!

The execution of an exhaustive switch can fail with a linkage error (an 
IncompatibleClassChangeError is thrown) if it encounters an instance of a 
permitted direct subclass that was not known at compile time 
(14.11.3,
 
15.28.2).
 Strictly speaking, the linkage error is not flagging a binary incompatible 
change of the sealed class, but more accurately a migration incompatible change 
of the sealed class.

I think we should back away from ICCE here as well, and put this in the 
MatchException bucket too.  Then:

 - a switch throws NPE if the operand is null;
 - an _enum switch_ throws ICCE when encountering a novel constant;
 - all other remainder errors are MatchException.

File away for future use, that these clauses will have to be extended to 
include other exhaustive pattern-aware constructs, like let.
14.11.1 Switch Blocks

The grammar for CaseOrDefaultLabel seems like it could be profitably refactored 
to reflect more of the restrictions:

CaseOrDefaultLabel
case (null | CaseConstant) {, CaseConstant }
case [null, ] Pattern { WhenClause }
case [null, ] default
default

and then you don't have to enumerate as many of the restrictions of what can 
combine with what.

Will have a think about that.

It is a compile-time error if a when expression has the value false.

... is a constant expression and has the value false ?

Corrected.


  *   A pattern case element p is switch compatible with T if p is assignable 
to type T 
(14.30.3).

Isn't this cast-convertible?  If the selector is String and the pattern is 
`Object o`, o is not assignable to String, but it is cast-convertible.

Actually it’s a typo, it’s supposed to read “applicable” instead of assignable! 
Corrected


A switch label is said to dominate another switch label

Can we say that in a pattern switch, default dominates everything, which has 
the effect of forcing the default to the bottom?


We could do. I wasn’t sure that we had settled on that design - there was some 
discussion on this list.


 if there are values for which both apply and there is not an obvious preference

Is this really what we mean?  Don't we really mean that the first one matches 
everything the second one does?

Corrected.

A set of case elements is exhaustive

This is a nit, but couldn't this be its own subsection?  This section is 
getting long and varied.

Let me have a think about that.


 T if T is downcast convertible to U

Is this right?  Upcast convertibility is OK too -- you can match `Object o` to 
a target of `String`, and vice versa.

Corrected.


If the type R is a raw type 
(4.8) 
then the type T must be a raw type, or vice versa; otherwise a compile-time 
error occurs.

Is this the right restriction?  What we want here (for this iteration) is that 
if R is generic, we specify the type parameters.  But this is not the same 
thing.  I would think we would want to say here something like "if the class of 
R is a generic class, R cannot be raw".

Corrected.

whose type names R

missing a word

Corrected.



  1.  A switch label that supports a pattern p applies if the value matches p 
(14.30.2).
 If pattern matching completes abruptly then determining which switch label 
applies completes abruptly for the same reason.

I think this is carried over from the previous round?  Or do we not resolve 
total type patterns to any at the top level of a switch?


  1.  If no case label matches but there is a default label, then the default 
label matches. If neither of these rules apply to any of the switch labels in 
the switch block, then a switch label that supports a default applies.

Don't we need a clause that says "if there is no default, a MatchException is 
thrown"?

If pattern matching completes abruptly then the process of determining which 
switch label applies completes abruptly for the same reason.

Doesn't it complete abruptly with MatchException?  Or can PM only complete 
abruptly with ME as well?

I think perhaps you are misreading this section. This is just determining which 
label applies (none app

Draft Spec for Third Preview of Pattern Matching for Switch and Record Patterns (JEP 405) now available

2022-04-07 Thread Gavin Bierman
Dear experts:

The first draft of a spec covering both the third preview of Pattern Matching 
for switch (JEP number coming, but currently available at 
https://openjdk.java.net/jeps/8282272) and JEP 405 (Record Patterns) is now 
available at:

http://cr.openjdk.java.net/~gbierman/PatternSwitchPlusRecordPatterns/PatternSwitchPlusRecordPatterns-20220407/specs/patterns-switch-jls.html

Comments welcome!

Thanks,
Gavin


Re: Record pattern: matching an empty record

2022-03-25 Thread Gavin Bierman
That’s right; with record patterns pattern matching can now initialise **zero 
or more** pattern variables (with type patterns it was always exactly one 
pattern variable to initialise). 

Gavin

> On 13 Mar 2022, at 15:09, Remi Forax  wrote:
> 
> Hi all,
> while writing the prototype of the runtime,
> i found a case i think we never discuss, can we match an empty record ?
> 
> record Empty() { }
> 
> switch(object) {
>  case Empty() -> ...  // no binding here
> 
> I think the answer is yes because i don't see why we should do a special case 
> for that, but i may be wrong.
> 
> Rémi



Re: [18][guarded pattern] conditional-and query - spec clarification

2022-03-10 Thread Gavin Bierman
Hi Manoj,

It’s a slightly moot point, given that we are likely to drop guarded patterns 
in the next preview but I think there has been some confusion here...

On 7 Mar 2022, at 07:08, Manoj Palat 
mailto:manoj.pa...@in.ibm.com>> wrote:

Hi,

Given,
  public void bar(Object o) {
  int i = switch(o) {
case String a && o != null ? true : false -> 1;//ecj flags syntax 
error here
default -> 1;
  };
}

ECJ(eclipse compiler for Java) flags a syntax error on the guarded pattern. 
However, javac accepts.

Ecj translates this into:
case ((String a) && (o != null)) ? true : false
and flags an error instead of
case ((String a) && ((o != null) ? true : false))


The idea of guarded patterns is that we give a secondary role to `&&` to serve 
as an operator for patterns.

After the `case` we parse a pattern. One of the form of a pattern is a guarded 
pattern which is:

GuardedPattern:
PrimaryPattern && ConditionalAndExpression

Given the grammar as per 
http://cr.openjdk.java.net/~gbierman/jep420/jep420-20211208/specs/patterns-switch-jls.html
 I think javac is parsing this correctly.

I don’t know quite what ecj is doing here because the translation you give 
above seems to suggest that it was accepting an expression after the `case` 
which is not correct. Moreover, the inner expression (String a) && (o != null) 
is not an expression but a (guarded) pattern.



And I think the ecj is correct in flagging the error due to:

From https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html 
we see that  Conditional-And Operator “&&”  has higher operator precedence than 
the Conditional Operator “?:” . From 
https://docs.oracle.com/javase/specs/jls/se17/html/jls-15.html#jls-15.23, we 
see that “The conditional-and operator is syntactically left-associative (it 
groups left-to-right).”



Also, I don't see any mention of the precedence changes in spec 420 [latest at 
https://cr.openjdk.java.net/~gbierman/jep420/latest]



I don’t see the connection with precedence - we certainly didn’t make any 
changes.

Am I understanding your issue correctly?

Thanks,
Gavin





Re: [External] : Re: JEP 405 update

2022-02-09 Thread Gavin Bierman
Thanks Remi. Yes, this text could be better (interestingly, it is unchanged 
from nearly a year ago!). I think you’d agree that *pattern matching* with 
nested patterns provides a null-safe approach to data access, right? That’s 
really what I am getting at. In that sense, record patterns are a key, because 
they support nesting of patterns. You are correct that the construct within 
which we surface pattern matching can have a say in the top-level treatment of 
null. Indeed, one of the things we are discussing at the moment is exactly 
whether switch should have a stronger opinion about top-level null! 

Let me see if I can work on the text some more. 

Thanks for the feedback,
Gavin

> On 9 Feb 2022, at 16:40, Remi Forax  wrote:
> 
> Hi Gavin,
> I don't buy the argument that record patterns promote a null-safe style of 
> programming as this is stated several times in the JEP.
> 
> The ""null-safety"" (notice the air quotes) mostly comes from the instanceof 
> or the switch (which semantics is equivalent of a cascade of if instanceof), 
> not from the record pattern by itself.
> 
> You can argue that when a record pattern is nested a nullcheck appears, but 
> it's more than the underlying semantics is a degenerated instanceof when the 
> declared type and the instanceof type are the same.
> 
> The record pattern is about destructuring after the instanceof/nullcheck has 
> been done, so i find that argument counter productive because it does not 
> help to understand the semantics.
> 
> Also, we have talked several times to introduce the record pattern when doing 
> an assignment
>  Point point = ...
>  Point(int x, int y) = point;
>  // can use x and y here !
> 
> This will throw a NPE if point is null, similarly to an unboxing operation.
> 
> The null-safety is not attached to the record pattern per se but by the 
> container that use it (instanceof, case of a switch, enclosing pattern).
> 
> regards,
> Rémi
> 
> - Original Message -
>> From: "Gavin Bierman" 
>> To: "amber-spec-experts" 
>> Sent: Wednesday, February 9, 2022 12:59:02 PM
>> Subject: JEP 405 update
> 
>> Dear experts,
>> 
>> Just to let you know that I have updated JEP 405:
>> 
>> https://openjdk.java.net/jeps/405
>> 
>> You will see that we have removed the array patterns from this JEP (and it 
>> has
>> been retitled accordingly). We're still committed to supporting a direct 
>> pattern
>> form for arrays, but given our tight schedule and a number of queries about 
>> the
>> exact syntactic form for array patterns, we think we'll be better off 
>> decoupling
>> them from JEP 405, and releasing them in a future patterns JEP.
>> 
>> Comments welcomed!
>> Gavin



JEP 405 update

2022-02-09 Thread Gavin Bierman
Dear experts,

Just to let you know that I have updated JEP 405:

https://openjdk.java.net/jeps/405 

You will see that we have removed the array patterns from this JEP (and it has
been retitled accordingly). We're still committed to supporting a direct pattern
form for arrays, but given our tight schedule and a number of queries about the
exact syntactic form for array patterns, we think we'll be better off decoupling
them from JEP 405, and releasing them in a future patterns JEP.

Comments welcomed!
Gavin

Re: Control flow analysis for exhaustive pattern-switch statement

2022-02-07 Thread Gavin Bierman
Thanks Tagir. I’ll take a look at the spec issue and report back.

Gavin

> On 3 Feb 2022, at 05:41, Tagir Valeev  wrote:
> 
> Hello!
> 
> JLS requires (14.11.2) that the new "enhanced" switch statement (not
> expressions) must be exhaustive. In particular, for the switch over
> sealed abstract type, it's required to list all the permitted subtypes
> or provide a total/default branch. This is good. However, this means
> that from CFG point of view exactly one switch branch must always be
> visited. This is indeed so if we take a look at the bytecode: the
> synthetic default branch throws IncompatibleClassChangeError(). But
> compiler ignores this fact and refuses to compile the code like this
> (tried 18-ea+33-2077):
> 
> sealed interface Parent {}
> record A() implements Parent {}
> record B() implements Parent {}
> 
> void test(Parent p) {
>int x;
>switch (p) {
>case A a -> x = 1;
>case B b -> x = 2;
>}
>System.out.println(x); // error: variable x might not have been initialized
> }
> 
> I think this is a mistake that should be corrected: in this code, `x`
> should be considered as definitely assigned.
> 
> I understand that the same reasoning does not apply for switch over
> enums, as for compatibility reasons, default behavior is to do
> nothing. However, for patterns, uninitialized `x` cannot appear after
> the switch, even if we recompile the sealed interface separately
> adding one more inheritor.
> 
> I try to understand what's written in 16.2.9 regarding this [1].
> Unfortunately, its current state looks confusing to me. Sorry if I'm
> missing something, as I'm not very experienced in reading  chapter 16
> of JLS. Nevertheless, it says:
> 
> V is [un]assigned after a switch statement (14.11) iff all of the
> following are true:
> ...
> Original spec:
> - If there is no default label in the switch block, or if the switch
> block ends with a switch label followed by the } separator, then V is
> [un]assigned after the selector expression.
> Preview spec:
> - If the switch block covers the type of the selector expression, or
> if the switch block ends with a switch label followed by the }
> separator, then V is [un]assigned after the selector expression.
> 
> It looks strange that "no default label" (~= non-exhaustive) was
> replaced with "covers the type" (= exhaustive). Was negation lost
> somewhere? In current state it looks like, all exhaustive switches
> (which is almost all switches), including ones with `default` branch
> cannot definitely assign a variable, which contradicts the previous
> state.
> 
> If negation is actually lost, then the sample above should compile, as
> it's exhaustive.
> 
> Sorry if this was already discussed.
> 
> With best regards,
> Tagir Valeev
> 
> [1] 
> https://cr.openjdk.java.net/~gbierman/jep406/jep406-20210608/specs/patterns-switch-jls.html#jls-16.2.9



[patterns-switch] Draft Spec for JEP 420: Pattern Matching for switch (Second Preview)

2021-10-20 Thread Gavin Bierman
Dear experts:

The first draft of the spec for JEP 420 (Pattern Matching for switch - Second 
Preview) is now available at:

http://cr.openjdk.java.net/~gbierman/jep420/latest/

This contains the updates discussed on the list (GADT support, revised 
dominance rules for constant case labels etc). It doesn’t support inference of 
type arguments (yet). More details on that to follow.

Comments welcome!

Thanks,
Gavin

Re: Pattern Matching for switch (Second Preview)

2021-10-01 Thread Gavin Bierman


On 30 Sep 2021, at 23:25, Brian Goetz 
mailto:brian.go...@oracle.com>> wrote:

[ moving to a-s-e ]

I get the concern that a type pattern is no longer "just a variable 
declaration"; that was a nice part of the "patterns aren't really so hard to 
understand" story.  But I think the usability is likely to be not very good.  
Take this example:

sealed interface Node { }
record AddNode(Node left, Node right) extends Node { }
...

Node ni = ...
switch (ni) {
case AddNode(Node left, Node right) -> ...

There's no instantiation of Node possible here *other than* Node.  Which 
means we are forcing users to either redundantly type out the instantiation 
(which can get big), or use casts inside the body when they pull things out of 
left and right.  (And patterns were supposed to make casts go away.)  There's 
almost no case where someone wants a raw type here.

But surely they should write var here?

Gavin


Fwd: Dominance in pattern matching for switch: Spec and Javac inconsistency

2021-09-14 Thread Gavin Bierman


Begin forwarded message:

From: Gavin Bierman mailto:gavin.bier...@oracle.com>>
Subject: Re: Dominance in pattern matching for switch: Spec and Javac 
inconsistency
Date: 14 September 2021 at 17:02:50 BST
To: Ilyas Selimov 
mailto:ilyas.seli...@jetbrains.com>>
Cc: "compiler-...@openjdk.java.net<mailto:compiler-...@openjdk.java.net>" 
mailto:compiler-...@openjdk.java.net>>

Thanks Ilyas,

Yes, this is a small bug in the spec which is causing your confusion. When it 
was first drafted it there was only one pattern case label element - a type 
pattern. By the time we published, there were two more - parenthesised patterns 
and guarded patterns. The rule didn’t get updated :-(

The rule you read only applies to *type* patterns. We need a couple of extra 
rules for parenthesised and guarded patterns.

As it happens the compiler is correct here. We treat a guarded pattern as a 
subset pattern, unless the guard is a constant expression whose value is true 
(a rare case!). So, in your example, we see that the first pattern matches 
*some* integers. We don’t know which ones, so we can’t be sure that it 
dominates the integer value 1. So the code is correct.

We could attempt to look at the guards to see what we can infer statically, but 
I think this unlikely to be a fruitful direction to take.

Thanks,
Gavin

On 3 Sep 2021, at 06:27, Ilyas Selimov 
mailto:ilyas.seli...@jetbrains.com>> wrote:

Hello!

The next code compiles correctly, but it seems to contradict the dominance 
rules:

void test(Integer i) {
 switch (i) {
   case Integer in && in != null:
 break;
   case 1:
 break;
   case default:
 break;
 }
}

A switch label that has a pattern case label element p dominates another switch 
label that has a constant case label element c if either of the following is 
true:
- the type of c is a primitive type and its wrapper class (5.1.7) is a subtype 
of the erasure of the type of p.

Maybe the type of p should also be total for the type of selector expression 
like in the rules for pattern-over-null dominance?

Thanks,
Ilyas




Re: merging cases in between values and types

2021-09-13 Thread Gavin Bierman
Hi Remi,

Sorry for the slow reply:

> On 8 Sep 2021, at 07:42, Remi Forax  wrote:
> 
> Hi all,
> the current spec support merging/fallthrough cases only when there is a case 
> null,
> like
>  case null, case Integer i -> // i can use 'i' here
> 
> First, i'm not sure it's clearly written in the spec, i was not able to 
> pinpoint the rule allowing it.

In 14.11.1 there is a bunch of well-formedness conditions listed for switch 
labels. The paragraph begins “For every switch label in a switch block, all of 
the following must be true, otherwise a compile-time error occurs…” What 
follows is a bunch of rules that spell out which switch labels are correctly 
formed, and which are not. The two rules that cover your question here are:


• If a switch label has a constant case label element then if the switch label 
also has other case element labels they must be either a constant case label 
element, the default case label element, or the null case label element.

and

• If a switch label has a null case label element then if the switch label also 
has any pattern case element labels, they must be type patterns (14.30.1).


So the first rule forbids you from writing case 42, Integer i. The second rule 
allows you to say case null, Integer i (and case Integer i, null actually.) 

So, yes, the null is treated specially. Indeed it’s behaviour is NOT about fall 
through really. When you write case null, Foo f you are not asking for the type 
pattern test to be carried out if the value is null (it might fail!). Nor are 
you asking for it to be ignored (cos then the pattern variable will not be 
initialised). You’re actually saying “if it’s null then it matches AND the 
variable i is initialised to null”. So it’s being treated like a special 
pattern label. If we were to give it an alternative syntax, we might write 
“case Foo? f” instead of “case null, Foo f”. 

Hope this helps,

Gavin


> Then i wonder if this special behavior is special because null is special or 
> if it should work with any values of the type of the type pattern,
> i.e. it works because null is a possible value of Integer, in that case, it 
> should also work with any other values like 42
> 
>  case 42, case Integer i ->  // i can use 'i' here
> 
> So is null a special value or does this rule also work with any values.
> 
> regards,
> Rémi
> 
> 



Re: case null and type pattern

2021-07-19 Thread Gavin Bierman
Hi Manoj,

This is certainly something we can discuss for Preview 2, but…it is intentional 
for now. The `case null, T t` is really a special case of extending a type 
pattern to be null friendly. Remember that the pattern variable `t` is 
initialised with null if this case label applies. 

The problem with what you are suggesting is that we’re going to end up with 
code like:

switch(o) {
…
case null, String s && s != null -> …
}

Now the developer has a guard saying that `s` is not null, and is probably 
going to assume this in the body of the switch rule, but has erroneously 
extended the case label with null. 

So, it’s just an attempt to remove potential puzzlers by design. But we can 
take a look at whether we can capture a more generous definition. An 
alternative would be to define a new null-friendly type pattern. Let’s talk 
about it!

Thanks,
Gavin



> On 14 Jul 2021, at 23:43, Manoj Palat  wrote:
> 
> Hi Gavin, All,
> 
> In 
> http://cr.openjdk.java.net/~gbierman/jep406/jep406-20210608/specs/patterns-switch-jls.html#jls-14.30.1,
>  Section 14.11, I see "If a switch label has a null case label element then 
> if the switch label also has any pattern case element labels, they must be 
> type patterns (14.30.1)." implying that the following code:
> 
> private static void foo(Object o) {
> switch (o) {
> case null, Integer i && i > 10 -> System.out.println(0); // flag error?
> default -> System.out.println(o);
> }
> should have an error flagged for case label with null since the pattern case 
> label element is not a type pattern but a guarded pattern.
> Any reason for excluding guarded patterns here? Or does this requires a 
> modification in spec to include guarded patterns as well?
> 
> Regards,
> Manoj



Re: TypePattern and "var variable"

2021-06-30 Thread Gavin Bierman
Thanks Rémi. It is discussed in the section “Array Patterns”. But I can call it 
out a little more explicitly. 

Gavin

> On 29 Jun 2021, at 14:10, Remi Forax  wrote:
> 
> I was re-reading JEP 405,
> 'var foo' is accepted by the grammar as Type Pattern but
> there is no section explicitly mentioning that.
> 
> Maybe i'm wrong and 'var foo' is already supported in Java 17,
> if it's not the case, i think we should add a section about the Type Pattern 
> being enhanced to support 'var'.
> 
> regards,
> Rémi



Re: Exhaustiveness mixing sealed type and enum

2021-06-09 Thread Gavin Bierman
Ahem,

Actually, now I come to think about it - whilst your example enabled me to 
clean up the notions of coverage and exhaustiveness - I overlooked that your 
example still will not work because of the way that switch deals with case 
constants.

In the Java 16 spec, it says first:

The type of the selector expression must be char, byte, short, int, Character, 
Byte, Short, Integer, String, or an enum type (§8.9), or a compile-time error 
occurs.

And then:

The switch block of a switch statement or a switch expression is compatible 
with the type of the selector expression, T, if both of the following are true:

 *   If T is not an enum type, then every case constant associated with the 
switch block is assignment compatible with T (§5.2).
 *   If T is an enum type, then every case constant associated with the 
switch block is an enum constant of type T.

The important thing to realise is that these rules are driven by the type of 
the selector expression, not the case constant. Whilst these have been 
re-jigged in the draft 17 spec, the semantic content has been preserved for 
compatibility reasons.

Back to a simplified version of your example:

List l = ...
switch(l) {
case Nil.NIL -> ...
default -> ...
}

Using the existing rules, this has to fail as List is not an enum type.

So, what to do? We could add another rule for checking compatibility of a case 
label with the selector expression, along the lines of:

-   If the type of e is not an enum type, char, byte, short, int, Character, 
Byte, Short, Integer, or String, then e is downcast convertible to the type of 
c.

But that is quite a change to Java. We’d now be able to write things like:

Object o = …
switch(o) {
case “Hello” -> ...
case Nil.NIL -> ...
default -> ...
}

And code like:

switch(o) {
case Nil.NIL -> ...
}

would typecheck only if o is downcast compatible to Nil but NOT if it is 
actually of type Nil! Confusing? Potentially!

But I think actually we need a bigger chat about constants, both on this matter 
and how constants and patterns should co-exist more generally. I propose we 
table this for the second preview of this feature. (But the improved 
definitions of coverage and exhaustiveness stay as I stated them yesterday!)

Thanks,
Gavin


On 8 Jun 2021, at 22:38, Gavin Bierman 
mailto:gavin.bier...@oracle.com>> wrote:

Hi Rémi,

On 2 Jun 2021, at 11:42, Remi Forax 
mailto:fo...@univ-mlv.fr>> wrote:

Do we agree that the code below defines an exhaustive switch so no default is 
necessary ?

sealed interface List permits Cons, Nil { }
record Cons(String value, Object next) implements List { }
enum Nil implements List { NIL }

int size(List list) {
 return switch(list) {
   case Cons cons -> 1 + size(cons.next);
   case Nil.NIL -> 0
 };
}


You are quite right, this should work. I have fixed up the spec to address 
this. The new definition looks like this:

A switch block covers a type T if one of the following is true:

  *   T names an enum class E and all of the enum constants of E appear as 
constant switch label elements in the switch block.
  *   T supports a sealed class or interface C, and the switch block covers all 
of the permitted direct subclasses and subinterfaces of C.
  *   A switch label in the switch block has a pattern case label element p 
where the pattern p is total for T (14.30.3).
  *   There is a default switch label in the switch block.

A switch statement or expression is exhaustive if the switch block covers the 
type of the selector expression. (Neat, huh?)

What is this notion of “supports a sealed class or interface” in the second 
bulletpoint I hear you ask? It’s actually to address another problem you raised 
in a different mailing list:

  sealed interface Vehicle {}
  record Car(String owner, String color) implements Vehicle {}
  record Bus(String owner) implements Vehicle {}

  public static void example2() {
var vehicles = List.of(
new Car("Bob", "red"),
new Bus("Ana")
);
for(var vehicle: vehicles) {
  switch(vehicle) {
case Car car -> System.out.println("car !");
case Bus bus -> System.out.println("bus !");
//default -> throw new AssertionError();
  }
}
  }


PatternMatching101.java:25: error: the switch statement does not cover all 
possible input values
  switch(vehicle) {

The reason this doesn’t behave as you expected is is that the inferred type for 
vehicle is not Vehicle but an intersection type! Previously the spec didn’t 
deal with this, it only asked if the type of the selector expression was a 
sealed class/interface on the nose. We need to be a little more flexible. So we 
define the following:

A type T supports a sealed class or interface C if and only if one of the 
following holds:

  *   T is a class type that names C, and the class C is both sealed and 
abstract.
  *   T is an interf

Re: Exhaustiveness mixing sealed type and enum

2021-06-08 Thread Gavin Bierman
Hi Rémi,

On 2 Jun 2021, at 11:42, Remi Forax 
mailto:fo...@univ-mlv.fr>> wrote:

Do we agree that the code below defines an exhaustive switch so no default is 
necessary ?

sealed interface List permits Cons, Nil { }
record Cons(String value, Object next) implements List { }
enum Nil implements List { NIL }

int size(List list) {
 return switch(list) {
   case Cons cons -> 1 + size(cons.next);
   case Nil.NIL -> 0
 };
}


You are quite right, this should work. I have fixed up the spec to address 
this. The new definition looks like this:

A switch block covers a type T if one of the following is true:

  *   T names an enum class E and all of the enum constants of E appear as 
constant switch label elements in the switch block.
  *   T supports a sealed class or interface C, and the switch block covers all 
of the permitted direct subclasses and subinterfaces of C.
  *   A switch label in the switch block has a pattern case label element p 
where the pattern p is total for T (14.30.3).
  *   There is a default switch label in the switch block.

A switch statement or expression is exhaustive if the switch block covers the 
type of the selector expression. (Neat, huh?)

What is this notion of “supports a sealed class or interface” in the second 
bulletpoint I hear you ask? It’s actually to address another problem you raised 
in a different mailing list:

  sealed interface Vehicle {}
  record Car(String owner, String color) implements Vehicle {}
  record Bus(String owner) implements Vehicle {}

  public static void example2() {
var vehicles = List.of(
new Car("Bob", "red"),
new Bus("Ana")
);
for(var vehicle: vehicles) {
  switch(vehicle) {
case Car car -> System.out.println("car !");
case Bus bus -> System.out.println("bus !");
//default -> throw new AssertionError();
  }
}
  }


PatternMatching101.java:25: error: the switch statement does not cover all 
possible input values
  switch(vehicle) {

The reason this doesn’t behave as you expected is is that the inferred type for 
vehicle is not Vehicle but an intersection type! Previously the spec didn’t 
deal with this, it only asked if the type of the selector expression was a 
sealed class/interface on the nose. We need to be a little more flexible. So we 
define the following:

A type T supports a sealed class or interface C if and only if one of the 
following holds:

  *   T is a class type that names C, and the class C is both sealed and 
abstract.
  *   T is an interface type that names C, and the interface C is sealed.
  *   T is a type variable, and its bound supports C.
  *   T is an intersection type T1 & ... & Tn, and a type Ti supports C (1 ≤ i 
≤ n).

This is what the second bulletpoint for the “covers” relation uses. This 
ensures that your vehicle example works as expected as well.

The compiler will be updated to match this spec shortly.

Thanks for the feedback.
Gavin

PS: Latest version of the spec available, as always, at: 
http://cr.openjdk.java.net/~gbierman/jep406/latest



Re: [patterns-switch] Draft JLS spec for JEP 406 (Pattern Matching for Switch)

2021-05-17 Thread Gavin Bierman
Dear experts,

I have amended the spec for JEP 406 (Pattern Matching for Switch) to reflect 
the consensus following the recent lengthy discussions on this list about two 
design changes, specifically:

  1.  treating total type patterns as match-everything switch labels (i.e. 
matching null)
  2.  requiring non-legacy switches to be total like switch expressions

The updated spec is available at:

http://cr.openjdk.java.net/~gbierman/jep406/latest/

Please let us know what you think!

Thanks,
Gavin

PS: The details:

To capture the notion of a total type pattern matching everything, I have not 
followed the idea of extending the notion of pattern matching to be a 
three-place relation, taking a value, a compile-time type, and a pattern. This 
passing of a compile-time type around at *runtime* is not at all how the JLS 
works (which maintains a pretty strict phase distinction), and it doesn’t 
accurately reflect what we do in the compiler either. So, here’s how it has 
been specified:

1. I introduced a new pattern, called an *any pattern*. Right now, it’s a 
pattern that is expressible but not denotable, i.e. it is an error if it 
appears anywhere in the source program. It arises from a process of “resolving” 
a pattern...

2. There is a new notion of "resolving" a pattern with a type. It works like 
this:

A pattern P resolves with a type U as follows:

1. if P is T t where U <: T, P resolves to an any pattern `var t`, where the 
type of t is T; otherwise P resolves to P.

2. if P is var x, P resolves to an any pattern `var x` where the type of x is U;

3. if P is (Q), then P resolves to (Q'), where Q' is the result of resolving Q 
with U

4. if P is Q && e, then
(i)  If Q && e is total for U then P resolves to Q' && e where Q' is the 
result of resolving Q with U;
(ii.) If Q && e is not total for U then P resolves to P.

So the basic idea of resolving a pattern is that it replaces any total patterns 
with an any pattern.

Now, the runtime behaviour of pattern matching is specified to always be with 
respect to a resolved pattern.

In other words, with e instanceof P, we resolve P with the type of e to get a 
resolved pattern Q, and then we pattern match the value of e with the resolved 
pattern Q. With switches we resolve any pattern labels with the type of the 
selector expression before finding a switch label that matches.

Pattern matching can now be more fully specified as follows:

-   A value v (including null) matches `var x` and x is initialized to v.

-   The null reference does not match T t.

-   A non-null value v matches T t if v can be cast to T without raising a 
ClassCastException, and t is initialized to v; and does not match otherwise.

-   A value v matches p && e if (i) v matches p, and (ii) e evaluates to true; 
and does not match otherwise.

-   A value v matches (p) if v matches p; and does not match otherwise.

This means that total type patterns appearing as switch labels will now match 
all values *including null*, as they will be resolved to any patterns.

I have also changed the specification of the runtime semantics of switches by 
breaking it up into two different cases depending on whether the selector 
expression evaluates to `null` or not. If it does evaluate to null then we look 
for either a `case null` or a total pattern case label. If we find none then we 
NPE. Otherwise, we look at all the switch labels as before (including the 
legacy ones involving constants). This simplifies matters with the legacy 
labels so they don't need to explicitly exclude null.

I have added a new condition on switch statements that if it is a non-legacy 
switch then the switch block must be complete (the same condition as for switch 
expressions). The execution of a switch statement now has a new test: if no 
switch label matches in the body, then either (i) if it is a non-legacy switch 
then ICCE is thrown; or (ii) if it is a legacy switch then execution completes 
normally (as before).

Some other minor tweaks were also made.

On 23 Apr 2021, at 16:58, Gavin Bierman 
mailto:gavin.bier...@oracle.com>> wrote:

Dear experts,

Apologies for the delay, but here is the first draft of the spec for JEP 406 
(Pattern Matching for Switch):

http://cr.openjdk.java.net/~gbierman/jep406/latest/

As you will see, the design has evolved a little since we wrote the JEP (which 
I will update shortly). The chief changes are:

1. Instead of enumerating the special case labels, e.g. case null, default, 
case null, T t and so on; the notion of switch label has been made more 
general, with a set of restrictions to cut out the things we don’t want. In 
particular, this means that we get (a) symmetric versions of the compound 
patterns, e.g. case null, default and case default, null: and (b) we get a 
perfect alignment of the old : style with the new , style, e.g. we can write 
both `case null, default: …` and `case

Re: [sealed-types] Draft Spec for JEP 409 Sealed Types (Final)

2021-05-11 Thread Gavin Bierman
Sorry, meant to thank you for pointing this out. You are correct in that (i) 
when writing these I wrote them side-by-side, and (ii) when we fixed up the 
text surrounding top-level/member/local I forgot to put them side-by-side again 
to check there wasn’t any stray old text. Ug.

(It’s also super annoying that the section numbers don’t match to make this 
even better!)

Alex spotting a small issue that will break up this nice symmetry some more: 
the restriction on the canonical name excludes the neat trick that we play 
compiling out enums with constants that have bodies into a sealed hierarchy (as 
we need to have permitted subclasses that are anonymous classes). It’s fixable 
but we have to special case enum classes :-(

Thanks again,
Gavin

> On 23 Apr 2021, at 21:19, John Rose  wrote:
> 
> On Apr 20, 2021, at 2:00 AM, Gavin Bierman  wrote:
>> 
>> 
>> http://cr.openjdk.java.net/~gbierman/jep409/latest/
> 
> Out of curiosity I compared the two large new sections
> on permits, 8.1.4 and 9.1.4, perhaps to find unintentional
> divergences.  Here are the differences I found FYI,
> aside from than the required differences arising
> from section numbering and the parallel terminology
> of interfaces and lists.
> 
>> The optional permits clause in a [C/I] declaration {specifies, lists} the 
>> [C/I]s
> 
>> It is a compile-time error if {the same class, a class or interface} is 
>> {specified, named} more than once in a {, single} permits clause
> 
>> The permitted direct sub[C/I]s of a sealed [C/I] are the [C/I]s listed by 
>> its permits clause, or, if [C/I] lacks a permits clause, each {, top level 
>> or member} [C/I] declared in the same compilation unit as [C/I] (7.3) which 
>> has a canonical name (6.7)
> 
> This last one is especially odd, since “top level or member”
> seems redundant when “has a canonical name” is specified.
> The latter condition is in both places, and is more pertinent.
> 
> Also, this comment was in the class section, but there was no
> parallel comment in the interface section:
> 
>> This means that if a sealed class C lacks a permits clause one will be 
>> inferred that contains all the top-level and member classes in the same 
>> compilation unit that list C as their direct superclass. The requirement of 
>> having a canonical name means that no local classes or anonymous classes 
>> will be considered.
> 
> Perhaps you added the “canonical name” and did not replace
> all of the predecessor language about “top level or member”?
> 
> (As expected, I found no substantive differences.)
> 
> — John



[patterns-switch] Draft JLS spec for JEP 406 (Pattern Matching for Switch)

2021-04-23 Thread Gavin Bierman
Dear experts,

Apologies for the delay, but here is the first draft of the spec for JEP 406 
(Pattern Matching for Switch):

http://cr.openjdk.java.net/~gbierman/jep406/latest/

As you will see, the design has evolved a little since we wrote the JEP (which 
I will update shortly). The chief changes are:

1. Instead of enumerating the special case labels, e.g. case null, default, 
case null, T t and so on; the notion of switch label has been made more 
general, with a set of restrictions to cut out the things we don’t want. In 
particular, this means that we get (a) symmetric versions of the compound 
patterns, e.g. case null, default and case default, null: and (b) we get a 
perfect alignment of the old : style with the new , style, e.g. we can write 
both `case null, default: …` and `case null: default: …` with identical 
treatment.

2.  I figured out a way to remove the restriction from the JEP that switches 
must be all pattern-matching, or all non-pattern-matching. Apart from 
simplifying matters, this allows for some nice new features, e.g.

enum E { F, G, H }

switch(...) {   // A switch block with an enum constant and pattern 
label!
case F -> …
case E e -> …   // Acts like a default but e is in scope!
}

A couple of odd extras come for the ride, just for your information:

switch(o) { /* empty */ } 

is now well-typed for all types of o, as is:

switch(o) { default: … }

[Basically any type restrictions on the selector expression come from the 
switch labels. We still maintain that if you use a constant case label, the 
type of the selector must be char, byte, short, int, Character, Byte, Short, 
Integer, or String as in Java 16.]

As always, your opinions are welcomed!

Thanks,
Gavin



[sealed-types] Draft Spec for JEP 409 Sealed Types (Final)

2021-04-20 Thread Gavin Bierman
Dear experts:

Draft of the specs for JEP 409 (Sealed Types) are available at:

http://cr.openjdk.java.net/~gbierman/jep409/latest/

Comments welcome!

Thanks,
Gavin


Draft JEP: Sealed Classes

2021-03-22 Thread Gavin Bierman
Dear all,

Now JDK 16 is out (yay!) it’s time for us to focus on finalizing Sealed Classes 
in JDK 17.

I have written a draft JEP, which is unchanged (other than some superficial 
editorial changes) from JEP 397.

https://openjdk.java.net/jeps/8260514

(I think Brian’s proposal to consider extending the language in some way to 
support assignment and switch statements being total over sealed hierarchies is 
something that can be considered as a JEP in itself.)

If you have any comments on the draft JEP, please let me know!

Thanks,
Gavin


Re: Type pattern and raw type

2021-03-22 Thread Gavin Bierman
Agreed, Maurizio. Jan has pushed a patch for this. Now if you compile with 
`-Xlint:rawtypes` you’ll get a warning for `o instanceof Foo foo` - this was 
just an oversight. 

Gavin

> On 19 Mar 2021, at 18:52, Maurizio Cimadamore 
>  wrote:
> 
> 
> On 15/03/2021 13:28, Brian Goetz wrote:
>> Unchecked conversions are forbidden because of type pollution, that why you 
>> can not write
>>   if (o instanceof Foo foo) {
>> 
>> Raw type conversions also leads to type pollution, so i think that a type 
>> pattern with a raw type should be forbidden too.
> 
> Note sure I agree here - they are two very different kind of pollutions.
> 
> In the Foo case the issue is that we might any type that converts to 
> Foo to be treated as a Foo. E.g. Foo -> 
> Foo. That is unsound, and the unsoundness happens in the conversion 
> itself.
> 
> But when you say `o instanceof Foo f`, you are not introducing any pollution. 
> The pollution will be introduced when (and if) the raw type will be accessed.
> 
> Honestly, I'm not even sure this deserves a warning (other than the customary 
> "raw-type usage" warning - not an "unchecked" warning, to be clear).
> 
> Maurizio
> 



Re: [External] : Re: Guards redux

2021-03-12 Thread Gavin Bierman


> On 12 Mar 2021, at 11:02, Remi Forax  wrote:
> 
> - Mail original -
>> De: "Gavin Bierman" 
>> À: "John Rose" 
>> Cc: "amber-spec-experts" 
>> Envoyé: Vendredi 12 Mars 2021 11:11:46
>> Objet: Re: Guards redux
> 
>> Thanks everyone for the discussion. I have updated the JEP:
>> 
>> http://openjdk.java.net/jeps/8213076
>> 
>> It proposes *guarded patterns* of the form `p&&e`, as well as parenthesized
>> patterns, written `(p)`.
> 
> 
> Hi Gavin,
> nice, i find this version more appealing.

Yay!

> In the first example that shows && as a guard, the example uses parenthesis 
> which is my opinion should be removed
>case Triangle t && (t.calculateArea() > 100) -> 
>System.out.println("Large Triangle"); 
> 
> if i read the grammar correctly, those parenthesis around the boolean 
> expression are unnecessary
>case Triangle t && t.calculateArea() > 100 -> 

They are unnecessary, but this example comes before the grammar, so I didn’t 
want anyone to get confused. 

> 
> it will be more inline with the example above in the text that is using 'when'
>case Triangle t when t.calculateArea() > 100 ->
> 
> 
> Otherwise, in the document, the words "->-style" and ":-style" are hard to 
> parse, i think array-style and colon-style are better terms.

I’ll take a look.

> In the section "Dominance of pattern label",
> It's not clear to me if there is a dominance in between expressions,
> by example, can we have the following cases in that order ?
> 
>  case Foo(var a, var b) && a == 3:
>  case Foo(var a, var b) && a == 3 && b  == 4:
> 
> for me the answer is yes, the dominance is computed on patterns only, not on 
> expressions.

I agree. I don’t think trying to calculate dominance between expressions is 
viable. 

Thanks Rémi!
Gavin

Re: Guards redux

2021-03-12 Thread Gavin Bierman
Thanks everyone for the discussion. I have updated the JEP:

http://openjdk.java.net/jeps/8213076

It proposes *guarded patterns* of the form `p&&e`, as well as parenthesized 
patterns, written `(p)`.  

I have left out AND and OR patterns, at least for now. Thanks to Guy we now 
know how to add them elegantly to the grammar when the time comes :-) When 
people come to play with this, I’d be especially interested to hear about the 
need for AND and OR patterns. (I have a feeling that OR is more important, but 
that’s another email...)

Comments on the JEP very welcome.

Thanks,
Gavin


> On 11 Mar 2021, at 13:51, Gavin Bierman  wrote:
> 
> Very clever, John. Yes, let’s not add any more puzzlers to the language!
> 
>> On 10 Mar 2021, at 21:59, John Rose  wrote:
>> 
>> Good.  PrimaryPattern is a good concept.
>> 
>> On Mar 10, 2021, at 6:47 AM, Gavin Bierman  wrote:
>>> 
>>> Guard:
>>> : AssignmentExpression
>> 
>> I think it should be this instead:
>> 
>> Guard:
>> : ConditionalAndExpression
>> 
>> The effects of this narrower definition of a guard expression
>> are two:
>> 
>> First, any guard of the form (a || b), (a ? b : c), or (a = b)
>> will require parentheses.
>> 
>> Second, as a result, the following puzzlers will not be legal
>> inputs:
>> 
>> case P && a || b:  // compare x instanceof P && a || b
>> case P && a ? b : c:  // compare x instanceof P && a ? b : c
>> case P && a = b:  // compare x instanceof P && a = b
>> 
>> In all of these puzzlers, the “extremely fortuitous”
>> correspondence between the syntaxes of guarded
>> cases and instanceof’s with following boolean logic
>> are broken.
>> 
>> The fix to align the meanings of the cases with the
>> instanceof’s is to add parentheses:
>> 
>> case P && (a || b):  // compare x instanceof P && (a || b)
>> case P && (a ? b : c):  // compare x instanceof P && (a ? b : c)
>> case P && (a = b):  // compare x instanceof P && (a = b)
>> 
>> Using the modified grammar rule above forces the
>> coder to write the parentheses, I think.
>> 
>> I think we should aim for “perfectly fortuitous”
>> here, not just “well, look how often the syntaxes
>> seem to mean the same thing although sometimes
>> they don’t”.  Indeed, this is my main reason for
>> plumping  for P && g in the first place.
>> 
>> — John
>> 
>> 
> 



Re: Guards redux

2021-03-11 Thread Gavin Bierman
Very clever, John. Yes, let’s not add any more puzzlers to the language!

On 10 Mar 2021, at 21:59, John Rose 
mailto:john.r.r...@oracle.com>> wrote:

Good.  PrimaryPattern is a good concept.

On Mar 10, 2021, at 6:47 AM, Gavin Bierman 
mailto:gavin.bier...@oracle.com>> wrote:

Guard:
: AssignmentExpression

I think it should be this instead:

Guard:
: ConditionalAndExpression

The effects of this narrower definition of a guard expression
are two:

First, any guard of the form (a || b), (a ? b : c), or (a = b)
will require parentheses.

Second, as a result, the following puzzlers will not be legal
inputs:

case P && a || b:  // compare x instanceof P && a || b
case P && a ? b : c:  // compare x instanceof P && a ? b : c
case P && a = b:  // compare x instanceof P && a = b

In all of these puzzlers, the “extremely fortuitous”
correspondence between the syntaxes of guarded
cases and instanceof’s with following boolean logic
are broken.

The fix to align the meanings of the cases with the
instanceof’s is to add parentheses:

case P && (a || b):  // compare x instanceof P && (a || b)
case P && (a ? b : c):  // compare x instanceof P && (a ? b : c)
case P && (a = b):  // compare x instanceof P && (a = b)

Using the modified grammar rule above forces the
coder to write the parentheses, I think.

I think we should aim for “perfectly fortuitous”
here, not just “well, look how often the syntaxes
seem to mean the same thing although sometimes
they don’t”.  Indeed, this is my main reason for
plumping  for P && g in the first place.

— John





Guards redux

2021-03-10 Thread Gavin Bierman
Okay, so it seems like our initial stab at guards and a pattern conjunction
operator needs some finessing. 

Here's another take, inspired by Guy's emails. 

Step 1. Let's use `p && e` as the way to guard a pattern p with a boolean
expression e. 

Step 2. [Now or later] Let's use `&` (and `|`) as the conjunction and
disjunction operators on patterns.

There are a couple of immediate parsing puzzlers:

* e instanceof String s && s.length() > 2

This parses as `(e instanceof String s) && s.length() > 2` today. We need to be
careful that our grammar continues to make this the case (see below). We will
also introduce a parenthesized pattern, which you can use if you want the
dangling `&& s.length() > 2` to parse as a guard for the `String s` type
pattern. (It is extremely fortuitous that the functional behavior of both
expressions is the same, but either way I think this is a simple rule.)

* case p && b -> c -> b

Now we have some ambiguity from the `->` in a lambda expression and in a switch
rule. Fortunately, again I think we can just lean into the grammar to get what
we want. At the moment, the grammar for expressions is:

Expression:
LambdaExpression
AssignmentExpression

As a lambda expression can never be a boolean expression it can never
meaningfully serve as a guard for a pattern. Great!

So, I'd like to suggest this grammar for patterns (including pattern conjunction
and pattern disjunction operators for completeness but we can drop them from the
first release): 

Pattern:
: ConditionalOrPattern
: ConditionalOrPattern `&&` Guard

ConditionalOrPattern:
: ConditionalAndPattern
: ConditionalOrPattern `|` ConditionalAndPattern

ConditionalAndPattern:
: PrimaryPattern
: ConditionalAndPattern `&` PrimaryPattern

PrimaryPattern:
: TypePattern
: RecordPattern
: ArrayPattern
: `(` Pattern `)`

Guard:
: AssignmentExpression

Along with the following change to the grammar for instanceof:

InstanceofExpression:
: RelationalExpression `instanceof` ReferenceType 
: RelationalExpression `instanceof` PrimaryPattern  <-- Note!

Some consequences:

p1 & p2 & p3 && g1 && g2 parses as ((p1 & p2) & p3) && (g1 && g2), yay!

p1 && g1 & p2 && g2 needs to be bracketed as (p1 && g1) & (p2 && g2) to parse
properly. But that's okay, as I think the second is much clearer.

Let me know what you think.

Gavin

Re: [External] : Re: Guards

2021-03-10 Thread Gavin Bierman


On 10 Mar 2021, at 00:55, Guy Steele 
mailto:guy.ste...@oracle.com>> wrote:



On Mar 9, 2021, at 1:47 PM, Brian Goetz 
mailto:brian.go...@oracle.com>> wrote:


Apart from what have said about letting grobble to fully access to the bindings

Except that argument doesn't make sense.  Accessing the bindings is not a 
special behavior of grobble, but a natural consequence of flow scoping.  If I 
have P && g (or P & grobble(g)), then the scoping rules will tell us that the 
true set of P is present in g, and we're done.  Nothing special here.


Well, just to be fair, rules for flow scoping within expressions g && h already 
exist, but rules for P && g and P & Q do not yet exist.  It’s easy to see that 
they probably should exist, and that this can be done in a manner entirely 
analogous to the way flow scoping is already done in expressions, but it has 
been an implicit assumption in some of the past discussion that is worth making 
explicit.  “Consider it done!”  :-)


The draft JEP does try to be reasonably informative on this matter:

A conditional-and pattern p & q introduces the union of the pattern variables 
introduced by the patterns p and q. The scope of any pattern variable 
declaration in p includes the pattern q. (This allows for a pattern such as 
String s & true(s.length() > 1) -- a value matches this pattern if it can be 
cast to a String and that string has a length of two or more characters.)

Gavin


Re: [External] : Pattern assignment statements (extracted from: Primitive type patterns and conversions)

2021-03-04 Thread Gavin Bierman


> On 4 Mar 2021, at 08:44, John Rose  wrote:
> 
> On Mar 3, 2021, at 11:52 PM, fo...@univ-mlv.fr wrote:
>>> 
>>> First, I agree with Brian  that “int data[] = …”
>>> is horrible; we should have only allowed
>>> “int[] data = …” and taken the hit early.
>>> 
>> There is also its big brother
>>  int foo() [] { return null; }
>> which is the epitome of the C-style array declaration allowed in Java.
> 
> Thanks, Remi; that's the stuff of nightmares
> and it's bedtime here.

:-o I had no idea! I see the JLS says "It is very strongly recommended that 
this syntax is not used in new code.”

Gavin

Re: [External] : Re: Two new draft pattern matching JEPs

2021-03-04 Thread Gavin Bierman
Hi Remi,

I know that Brian has already replied, but just to a couple of your points:

> 
> The traditional approach for guards cleanly separate the pattern part from 
> the expression part
>  case Rectangle(Point x, Point y) if x > 0 && y > 0
> which makes far more sense IMO.
> 
> The current proposal allows
>  case Rectangle(Point x & true(x > 0), Point y & true(y > 0))
> which is IMO far least readable because the clean separation between the 
> patterns and the expressions is missing.

Well it is, but that’s because you’ve written it in such a way. You could also 
have written it:

case Rectangle(Point x, Point y) & true(x > 0 && y > 0)

which isn’t so different from the guards solution.

> 
> There is also a mismatch in term of evaluation, an expression is evaluated 
> from left to right, for a pattern, you have bindings and bindings are all 
> populated at the same time by a deconstructor, this may cause issue, by 
> example, this is legal in term of execution
>  case Rectangle(Point x & true(x > 0 && y > 0), Point y)
> because at the point where the pattern true(...) is evaluated, the Rectangle 
> has already been destructured, obviously, we can ban this kind of patterns to 
> try to conserve the left to right evaluation but the it will still leak in a 
> debugger, you have access to the value of 'y' before the expression inside 
> true() is called.

As Brian has pointed out, this pattern is actually ill-formed, as the `y` is 
not in scope in the guard pattern…

But thanks for the feedback. There are two issues here: expressivity and 
syntax. With increased expressivity, of course you get more ways to write 
difficult-to-understand code. Sometimes this is important enough for us to 
reject expressivity, but mostly not. Syntax is, on the other hand, everyone’s 
favourite subject :-) We could use pretty much any symbol as a pattern 
operator. Your experience as an educator will certainly be very useful for us 
to help determine the best choice if we go down this path - do you have any 
suggestions? 

Cheers,
Gavin

PS: I know you left this as a red flag, but just to say that I don’t recognise 
this mission statement :-)

> 
> * Java do not invent things, it merely stole ideas from the other and make 
> them its own in a coherent way



Re: [External] : Re: Two new draft pattern matching JEPs

2021-03-04 Thread Gavin Bierman


> On 3 Mar 2021, at 10:55, Remi Forax  wrote:
> 
> 
> I also found the code of the translation of 
> "printXCoordOfUpperLeftPointBeforePatterns" confusing,
> because the local variable 'c' in this example is not related to the binding 
> 'c' in the pattern matching example.

That’s a good point, thanks. I’ll change that.

Gavin

Re: [External] : Re: Two new draft pattern matching JEPs

2021-02-18 Thread Gavin Bierman
Ha! I’ll change the example.

Thanks,
Gavin

> On 18 Feb 2021, at 12:52, Tagir Valeev  wrote:
> 
> Hello!
> 
> Thank you!
> 
> There's a sample in Nested Record and Array Patterns draft:
> 
> static void printColorOfUpperLeftPoint(Object o) {
>if (o instanceof Rectangle(ColoredPoint ul, ColoredPoint lr)){
>if (ul instanceof ColoredPoint(Point p, Color c)) {
>System.out.println(c);
>}
>}
> }
> 
> It looks like here, the nested pattern "ul instanceof
> ColoredPoint(Point p, Color c)" is total. I thought that there's idea
> to prohibit total patterns with instanceof (at least total type test
> patterns are already prohibited). Please correct me if I'm wrong.
> 
> With best regards,
> Tagir Valeev.
> 
> On Thu, Feb 18, 2021 at 7:33 PM Gavin Bierman  
> wrote:
>> 
>> Dear all,
>> 
>> The next steps in adding pattern matching to Java are coming! I have drafted 
>> two new JEPs:
>> 
>> - Nested Record and Array Patterns: 
>> https://bugs.openjdk.java.net/browse/JDK-8260244
>> 
>> - Pattern Matching for switch: 
>> https://bugs.openjdk.java.net/browse/JDK-8213076
>> 
>> We split them up to try to keep the complexity down, but we might decide to 
>> merge them into a single JEP. Let me know what you think.
>> 
>> Draft language specs are under way - I will announce those as soon as they 
>> are ready.
>> 
>> Comments welcome as always!
>> 
>> Thanks,
>> Gavin



Two new draft pattern matching JEPs

2021-02-18 Thread Gavin Bierman
Dear all,

The next steps in adding pattern matching to Java are coming! I have drafted 
two new JEPs:

- Nested Record and Array Patterns: 
https://bugs.openjdk.java.net/browse/JDK-8260244

- Pattern Matching for switch: https://bugs.openjdk.java.net/browse/JDK-8213076

We split them up to try to keep the complexity down, but we might decide to 
merge them into a single JEP. Let me know what you think. 

Draft language specs are under way - I will announce those as soon as they are 
ready.

Comments welcome as always!

Thanks,
Gavin

Re: Pattern Matching in Python

2021-02-11 Thread Gavin Bierman
Yes, it’s interesting, and it’s a real improvement to the language. Tobias Kohn 
gave a very nice talk at SPLASH last year that’s worth watching. (It’s purely a 
coincidence that Cambridge seems to be a centre for pattern matching!)

https://www.youtube.com/watch?v=pxQZhL2ZHJU

The treatment of a pattern being an expression with named holes is very nice. 
Unfortunately, it’s really not so simple for us - we’d end up with something 
like : e instanceof new R(x, y). The `new` feels like clutter, doesn’t fit so 
well with subtyping, and we don’t allow local variable declarations like `x`, 
etc etc.

That said, we are aiming for a lot more (although I haven’t followed their 
discussions very closely). Once we get to defining instance patterns etc we 
have gone way beyond simple pattern matching of many languages.

Gavin

On 11 Feb 2021, at 09:34, Remi Forax 
mailto:fo...@univ-mlv.fr>> wrote:

Hi all,
in the news, Python have been accepted the PEP 642, Pattern Matching in Python 
[1].

The accepted PEP is https://www.python.org/dev/peps/pep-0642/
And the rational is https://www.python.org/dev/peps/pep-0635/

Compared to us,
- bindings are visually like variables not a special keyword (a previous 
proposal was using 'as')
 so "case foo:" capture the value inside and store it into foo which is 
obviously very controversial
 (it's even worst because "foo" doesn't have to be a fresh variable).
 I'm happy that we have not chosen that way :)

- guards are introduced with "if", which i find more readable than & or &&.
 Using 'if' can be an issue for us because it means that we can not have a 
guard inside the instanceof pattern, but i am not sure this is really a problem.

- constants can be used directly
 I'm still on the fence about that, it's certainly confusing that case 
Point(0,0) means case Point(var x, var y) if x == 0 && y == 0 and not
 equals(new Point(0,0)) but i understand the arguments that people don't care 
because the result is identical and bloating the syntax to make the semantics 
extra clear
 like in C#, case Point(== 0, == 0) doesn't worth the fuss.

- no support for comma separated values because the syntax is too close to the 
tuple syntax,
 we have already chosen to support comma separated values but only at top 
level, not inside a nested pattern.
 They have introduced '|' for OR and it can be used as top level and inside 
nested patterns.
 Note: in Java, using ',' vs '|' in the syntax is not something new, we are 
using '|' for catch and not ','.
 So question, should we introduce a OR pattern ??

- no support for AND and NOT pattern,
 because as i said in an early mail, using tuples is already an implicit AND.

regards,
Rémi

[1] https://lwn.net/Articles/845480/



Re: Patterns vs guards

2021-01-21 Thread Gavin Bierman
Agreed. The “problem” with guards is that they are expressions that hang off on 
to one side. I think we can do better than that by leaning into pattern 
composition, and the elegant idea of a guard pattern that turns a boolean 
expression into a pattern. 

Gavin

> On 18 Jan 2021, at 16:54, Guy Steele  wrote:
> 
> I agree with this analysis, especially the comment about “the One True Source 
> Of Expressiveness: composition”.
> 
> —Guy
> 
>> On Jan 18, 2021, at 10:20 AM, Brian Goetz  wrote:
>> 
>> I think the question here is mostly one of terminology.  Let’s restate the 
>> problem first.  The canonical example is:
>> 
>>   if (p instanceof Point(var x, var y) && x == y) { /* diagonal */ }
>> 
>> Here, the language is fully powerful enough for the pattern to 
>> test-and-extract on Point-ness, and the conjoined clause refines with an 
>> arbitrary predicate.  This comes “for free” because expressions compose.  
>> 
>> The switch analogue is:
>> 
>>switch (p) {
>>   case Point(var x, var y): 
>>  // I want to do one thing for diagonal points, and something else 
>> for other points
>>}
>> 
>> This is where it gets messy, because switch gives you one chance to classify 
>> the target, and you have to live with that.  I think we all agree that 
>> making cases powerful enough to include type / deconstruction patterns has a 
>> “glass half empty” character to it; there will be plenty of “cases” where we 
>> can’t express what we want using a pattern switch, at least not without some 
>> ugly and error-prone contortions.  
>> 
>> There have been three ways proposed out of this mess:
>> 
>> 1.  Have a “continue” statement that lets a case body say “whoops, I fell 
>> into the wrong case, please keep trying to match at the next case.”  
>> 2.  Have an explicit feature of the switch statement to refine the pattern 
>> with a predicate, such as: “case P when(e)”.
>> 3.  Find a way to turn boolean expressions into patterns, and just use 
>> pattern-AND composition.
>> 
>> The confusion over terminology stems from the fact that we could describe 
>> all these as sorts of guards: 1 is an “imperative guard”, 2 is a “switch 
>> guard”, and 3 is a “guard pattern.”  Which underscores we want some kind of 
>> guarding-feature no matter what.  
>> 
>> John has defended #1 as being a good “primitive”.  And from a VM-design 
>> perspective, I agree; it is the sort of “control flow assembly language” we 
>> might want, and it covers 100% of the cases.  Unfortunately, as a user tool, 
>> it has fewer good characteristics; it is like fallthrough squared.  
>> 
>> #2 had seemed like a “tolerable evil.”  From a language design perspective, 
>> it is surely a “bag” of sorts; it is limited in purpose, and doesn’t compose 
>> with other features.  It’s basically a “patch”, but one that users might 
>> find easy enough to reason about.  It is a candidate for a “worse is better” 
>> solution.
>> 
>> #3 is a feature that should make a PL designer happy; it is strictly more 
>> powerful than #2, is more broadly applicable (we can use it in other 
>> contexts where patterns are allowed), and its power derives from the One 
>> True Source Of Expressiveness: composition.  
>> 
>> Even adding constant patterns or relational patterns (>= 0) doesn’t really 
>> remove the need for some sort of guarding.  
>> 
>> The question is how we want to get there.  #3 amounts to “turn a guard into 
>> a pattern”.  We might call it a “guard pattern”, or a “boolean pattern”.  
>> But the terminology has gotten fuzzy, I agree.
>> 
>> For the record, I am now strongly in Camp #3: we want AND pattern 
>> combination anyway, so let’s find some way to turn a boolean expression into 
>> a pattern and call that a win.  
>> 
>>> On Jan 18, 2021, at 3:03 AM, Remi Forax  wrote:
>>> 
>>> Hi everybody,
>>> following the discussion about && / and between guards and patterns,
>>> i don't think i've a clear understanding on what is a pattern and what is a 
>>> guard.
>>> 
>>> When we first discuss of guards, the separation was a kind of clean, a 
>>> pattern match something and a guard provides further refinements.
>>> By example, with a made a syntax,
>>> case Point(var x, var y) && x > 0 && y > 0
>>> Point(var x, var y) is the pattern and x > 0 and y > 0 are the guards.
>>> 
>>> So a pattern asks if something match and a guard uses the binding to add 
>>> restrictions.
>>> 
>>> As Brian said, in C#, you can directly test inside a pattern, using a weird 
>>> syntax chosen by C# like >0,
>>> so the same example can be rewritten
>>> case Point(>0, >0)
>>> and with the bindings, i suppose something like
>>> case Point(var x >0, var y >0)
>>> 
>>> Here the line between a pattern and a guard starts to become blurry, 
>>> because >0 is pattern.
>>> 
>>> So if there a difference between a pattern and a guard ?
>>> 
>>> regards,
>>> Rémi
>>> 
>>> 
>>> 
>>> 
>> 
> 



Re: [records] C-style array declaration of record components - sec 10.2 clarification

2021-01-21 Thread Gavin Bierman
Thanks Manoj. You’re quite correct, the text in the brackets is stale and 
should read as you suggest. 

Alex is currently integrating the text into the JLS, so I shall make sure this 
change is reflected in the final specification.

Best wishes,
Gavin

> On 15 Jan 2021, at 06:52, Manoj Palat  wrote:
> 
> Hi Gavin, all,
> 
> From 
> http://cr.openjdk.java.net/~gbierman/jep395/jep395-20201204/specs/records-jls.html
>  (which is the http://cr.openjdk.java.net/~gbierman/jep395/latest as of 
> writing this),
> from the section before introduction, we see that :
> 
> "The changes are the same as those in the second preview of Records in Java 
> SE 15, except for minor editorial changes and the following:
> ...
> Add text to explicitly rule out using C-style array declaration of record 
> components (10.2)."
> 
> but 10.2 talks about only variable arity record component as reproduced below:
> 
> "the array type of the variable is denoted by:
> ...
> any bracket pairs that follow the variable's Identifier in the declarator 
> (not applicable for a variable arity parameter or variable arity record 
> component); then
> ..."
> 
> Shouldn't the text in the brackets be "(not applicable for a variable arity 
> parameter or record component)" ?
> 
> 
> Regards,
> Manoj
> 
> 



Re: Specs update

2021-01-18 Thread Gavin Bierman
Yes, good spot Tagir. I’ll update.

Thanks,
Gavin

> On 9 Jan 2021, at 11:31, Tagir Valeev  wrote:
> 
> Hello, Gavin!
> 
> Thank you for spec update. A minor nitpick regarding pattern-matching spec:
> http://cr.openjdk.java.net/~gbierman/jep394/jep394-20210108/specs/patterns-instanceof-jls.html#jls-14.20.3
> 
> As resource variable is now a local variable declaration, probably,
> the following statement is redundant and should be removed?
> 
>> It is a compile-time error if final appears more than once as a modifier for 
>> each variable declared in a resource specification.
> 
> With best regards,
> Tagir Valeev.
> 
> On Tue, Dec 22, 2020 at 6:47 PM Gavin Bierman  
> wrote:
>> 
>> As we rampdown to JDK 16, the three spec bundles have been polished up a 
>> little. I’ve updated them all:
>> 
>> * Records: http://cr.openjdk.java.net/~gbierman/jep395/latest/
>> * Pattern matching for instanceof: 
>> http://cr.openjdk.java.net/~gbierman/jep394/latest/
>> * Sealed Classes: http://cr.openjdk.java.net/~gbierman/jep397/latest/
>> 
>> Nearly all of the changes are just polishing up the language.  However, the 
>> pattern matching spec did have a small, significant change: Given that we 
>> had already lifted the restriction that pattern variables were always final, 
>> we have now decided to allow pattern variables to support a `final` 
>> modifier. For example:
>> 
>> if (e instanceof final String s) {
>>  // s is in scope and final here
>>  ...
>> }
>> 
>> You’ll see also in the pattern matching spec that we have taken the 
>> opportunity to tidy up the treatment of local variables in various places; 
>> this is old technical debt that we are paying down, but given that pattern 
>> variables are a subset of local variables we had an opportunity to finally 
>> do this.
>> 
>> As always, further polishing may apply as they get inserted into the actual 
>> specs.
>> 
>> If you have any comments please let me know.
>> 
>> Wishing you all Happy Holidays and a better 2021!
>> 
>> Gavin
>> 



Specs update

2020-12-22 Thread Gavin Bierman
As we rampdown to JDK 16, the three spec bundles have been polished up a 
little. I’ve updated them all:

* Records: http://cr.openjdk.java.net/~gbierman/jep395/latest/
* Pattern matching for instanceof: 
http://cr.openjdk.java.net/~gbierman/jep394/latest/
* Sealed Classes: http://cr.openjdk.java.net/~gbierman/jep397/latest/

Nearly all of the changes are just polishing up the language.  However, the 
pattern matching spec did have a small, significant change: Given that we had 
already lifted the restriction that pattern variables were always final, we 
have now decided to allow pattern variables to support a `final` modifier. For 
example:

if (e instanceof final String s) {
  // s is in scope and final here
  ...
}

You’ll see also in the pattern matching spec that we have taken the opportunity 
to tidy up the treatment of local variables in various places; this is old 
technical debt that we are paying down, but given that pattern variables are a 
subset of local variables we had an opportunity to finally do this. 

As always, further polishing may apply as they get inserted into the actual 
specs. 

If you have any comments please let me know.

Wishing you all Happy Holidays and a better 2021!

Gavin



Re: [sealed-classes] Spec for next version of Sealed Classes

2020-11-04 Thread Gavin Bierman
The permanent location for this spec is now:

http://cr.openjdk.java.net/~gbierman/jep397/latest/ 
<http://cr.openjdk.java.net/~gbierman/jep397/latest/>

(I have fixed the two issues that Chris spotted [1].)

Comments still welcome!

Gavin

[1] 
http://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-October/002624.html

> On 23 Oct 2020, at 16:16, Gavin Bierman  wrote:
> 
> Dear all:
> 
> Drafts of the specs for the Sealed Classes feature that we plan to preview for
> a second time in JDK 16 are now available:
> 
> http://cr.openjdk.java.net/~gbierman/8246775/latest/
> 
> [NB: The URL will change once we have a JEP number, and will be announced.]
> 
> The changes are the same as those in the first preview that was released in 
> Java
> SE 15, except for minor editorial changes and the following:
> 
> - Clarification the use of context when applying the lexical grammar,
>  particularly in the identification of contextual keywords (formerly described
>  as "restricted identifiers" and "restricted keywords"). This is detailed in a
>  companion document entitled “Contextual Keywords". The keywords `sealed`,
>  `non-sealed`, and `permits` are now defined as new instances of contextual
>  keywords (3.9). 
> 
> - This spec now assumes that the changes detailed in companion documents
>  entitled "Consistent Class and Interface Terminology” and "Local and Nested
>  Static Declarations" have been applied (these are being introduced as part of
>  the Records JEP). In particular, this means that Java SE 16 will support
>  static declarations in two new positions:
> 
>1. Local, implicitly-static interfaces and enum classes
>2. Static members of inner classes
> 
>  This requires asserting that local interfaces are not permitted to be
>  `sealed`. (14.3)
> 
> - To enhance narrowing reference conversion to allow for stricter checking of
>  cast conversions with respect to sealed type hierarchies (5.1.6.1). 
> 
> - Local classes are not considered when determining implicitly declared
>  permitted direct subclasses of a `sealed` class or `sealed` interface
>  (8.1.6, 9.1.4).
> 
> 
> Comments welcome!
> 
> Gavin



Re: getPermittedSubclasses() on j.l.rClass returning an array of ClassDesc

2020-10-23 Thread Gavin Bierman
Just to follow this up; we have decided to change the signature of 
permittedSubclasses to the following:

public Class[] permittedSubclasses() {}

Thanks!
Gavin

> On 8 May 2020, at 23:53, Remi Forax  wrote:
> 
> The current draft of the reflection API for the sealed keyword adds a method 
> getPermittedSubclasses() [1] to java.lang.Class.
> 
> I'm not fully sure that returning an array of ClassDesc is the right choice 
> here, mainly for two reasons,
> 
> 1/ it's weird to return an array of ClassDesc when all others similar methods 
> return an array of Class,
>   I know why a ClassDesc might be "better" because it avoid the class loading,
>   but it also means that now to fully understand java.lang.Class, people has 
> to understand how java.lang.constant works.
>   The java.lang.constant API was not designed for that, the first line of the 
> overview of this package talks about descriptors, constant pool and indy, not 
> something beginners should worry about.
> 
> 2/ returning a symbolic view (ClassDesc) instead of a Class is *very* error 
> prone from a user POV, to resolve a ClassDesc to a class, the user as to 
> provide a Lookup
>   and there is a good chance that users will pick the wrong ones. The number 
> of people that understand classloading and how Lookup works is < 10,
>   even experts struggle given the number of time the Lookup API as to be 
> patched in recent years. Returning a ClassDesc in this context is like asking 
> a child
>   to read the serial number of a loaded gun.  
>   Perhaps a way to mitigate that is to provide the code a user should use to 
> get the equivalent classes in the javadoc of getPermittedSubclasses().
> 
> cheers,
> Rémi
> 
> [1] https://bugs.openjdk.java.net/browse/JDK-8244556



[sealed-classes] Spec for next version of Sealed Classes

2020-10-23 Thread Gavin Bierman
Dear all:

Drafts of the specs for the Sealed Classes feature that we plan to preview for
a second time in JDK 16 are now available:

http://cr.openjdk.java.net/~gbierman/8246775/latest/

[NB: The URL will change once we have a JEP number, and will be announced.]

The changes are the same as those in the first preview that was released in Java
SE 15, except for minor editorial changes and the following:

- Clarification the use of context when applying the lexical grammar,
  particularly in the identification of contextual keywords (formerly described
  as "restricted identifiers" and "restricted keywords"). This is detailed in a
  companion document entitled “Contextual Keywords". The keywords `sealed`,
  `non-sealed`, and `permits` are now defined as new instances of contextual
  keywords (3.9). 

- This spec now assumes that the changes detailed in companion documents
  entitled "Consistent Class and Interface Terminology” and "Local and Nested
  Static Declarations" have been applied (these are being introduced as part of
  the Records JEP). In particular, this means that Java SE 16 will support
  static declarations in two new positions:

1. Local, implicitly-static interfaces and enum classes
2. Static members of inner classes
   
  This requires asserting that local interfaces are not permitted to be
  `sealed`. (14.3)
  
- To enhance narrowing reference conversion to allow for stricter checking of
  cast conversions with respect to sealed type hierarchies (5.1.6.1). 

- Local classes are not considered when determining implicitly declared
  permitted direct subclasses of a `sealed` class or `sealed` interface
  (8.1.6, 9.1.4).


Comments welcome!

Gavin

Re: [records] Spec for next version of Record Classes JEP

2020-10-19 Thread Gavin Bierman
Following the announcement of JEP 395 [1] the latest version of the spec is now 
available at:

http://cr.openjdk.java.net/~gbierman/jep395/latest/

This covers the various bugs in an earlier draft that have been reported on 
this list. As per my earlier email this spec does not treat a non-propagating 
annotation in the case where an explicit accessor method has been declared as a 
compile-time error. I still think this is a better design, but if anyone feels 
strongly, please email the list!

Thanks,
Gavin

[1] https://openjdk.java.net/jeps/395

Re: [records] Spec for next version of Record Classes JEP

2020-10-14 Thread Gavin Bierman
Hi Tagir,

Upon reflection I think it’s best that we don’t treat this as a compile-time 
error, but just as the specified behaviour. The warning vs error thing is a 
grey area, especially in Java, but having bounced this around it seems like it 
has fallen (just) in the warning side of the divide. As you say, this is a 
great opportunity for IDEs to be helpful :-)

Just to be clear:

  @Target(ElementType.METHOD)
  @interface A { }
  record R1(@A int x) { // Where did the annotation go?
  int x() { return x; }
  }

In this example, what I am proposing is that there is no compile-time error and 
the A annotation will simply not be propagated anywhere. [I am expecting that 
most developers in this case would have added the RECORD_COMPONENT target, so 
the annotation does not disappear completely.]

Thanks,
Gavin



> On 5 Oct 2020, at 05:47, Tagir Valeev  wrote:
> 
> On Sat, Oct 3, 2020 at 12:09 AM Brian Goetz  wrote:
>> 
>> I think we're reaching diminishing returns here.
> 
> Well, to me, it's not diminishing. It's certainly a piece of code that
> will not have any effect after compilation, so it's a mistake.
> Reporting it is not that hard. Having a class/runtime annotation in
> source code that disappears completely in the compiled class-file
> without any warning sounds confusing and may cause subtle problems.
> Well, of course, we can create an inspection in IntelliJ IDEA to warn
> about these cases, and people will like IntelliJ IDEA even more, but I
> believe it's a compiler job to reject this, like Java already does
> with e.g. unreachable code.
> 
> With best regards,
> Tagir Valeev.



Re: [records] Spec for next version of Record Classes JEP

2020-10-14 Thread Gavin Bierman


> On 29 Sep 2020, at 22:32, Brian Goetz  wrote:
> 
> Should @SafeVarargs be allowed to be applied to a varargs record?  Should it 
> get propagated to the constructor in that case?  Or do we just have people 
> declare a compact constructor with @SafeVarargs?  What is the correct use of 
> @SV for varargs records?

Right now, if you annotate a record component with @SafeVarArgs you are in 
trouble, because @SafeVarArgs is applicable in the method context, and so it 
will be propagated to the accessor method. As the accessor method is a fixed 
arity method, that’s going to be an error. 

We say currently that you should declare a constructor with @SafeVarArgs. That 
seems reasonable to me. 

Unless someone thinks otherwise, I don’t think we should be special-casing this 
annotation. (I guess we can always do this in a later release.)

Gavin



Re: [records] Spec for next version of Record Classes JEP

2020-10-14 Thread Gavin Bierman



> On 29 Sep 2020, at 16:50, Tagir Valeev  wrote:
> 
> The only nit-pick is that it says "if a canonical constructor
> is declared explicitly". However, from 8.10.4 one may derive that
> compact constructor is a canonical constructor, so if compact
> canonical constructor is explicitly declared then, per 8.10.5 it looks
> like annotation should be discarded but it's not. Probably it's better
> to write in 8.10.5 something like "if a non-compact canonical
> constructor is declared explicitly". Well, probably I'm seeing things.

No, you’re right. A compact constructor gets its formal parameter list from the 
record component list, and so you get any annotations that are applicable. I 
have clarified this in 8.10.4. 

If we keep 8.10.5, then it needs wording much as you suggest; but I see that 
Brian is arguing that we shouldn’t treat non-propagating annotations as errors. 

Gavin






Re: [patterns-instanceof] Spec for next version of Patterns in instanceof JEP

2020-10-12 Thread Gavin Bierman
Following the announcement of JEP 394 [1] the latest version of the spec is now 
available at:

http://cr.openjdk.java.net/~gbierman/jep394/latest/

I have fixed the bugs spotted by Brian in the previous draft. I have also 
tidied up the treatment of annotations (See sections 9.6.4.1 and 9.7.4 along 
with the refactored grammar for type test patterns 14.20.1.1)

Still time to pass on comments!
Gavin

[2] https://openjdk.java.net/jeps/394

> On 5 Oct 2020, at 13:53, Gavin Bierman  wrote:
> 
> Dear all:
> 
> A draft of the spec for the Patterns in instanceof feature that we plan to
> finalize in JDK 16 is now available:
> 
> http://cr.openjdk.java.net/~gbierman/8250623/latest/
> 
> [NB: The URL will change once we have a JEP number, and will be announced.]
> 
> The changes are the same as those in the second preview that was released in
> Java SE 16, except for minor editorial changes and the following:
> 
> - To lift the restriction that pattern variables are implicitly final. This
>  allows pattern variables to be considered as a strict subset of local
>  variables. A number of simplifications to the spec result from this change. 
> 
> - To make it a compile-time error for an expression of type _S_ to be matched
>  against a pattern of type _T_, where _S_ is a subtype of _T_. (This pattern
>  match will always succeed and is then pointless. The opposite case, where a
>  pattern match will always fail is already a compile-time error.) 
> 
> Comments welcome!
> 
> Gavin



Re: instanceof and exceptions

2020-10-09 Thread Gavin Bierman


> On 9 Oct 2020, at 11:11, Remi Forax  wrote:
> 
> Following the course on exceptions, where i explain that a catch() is an 
> instanceof,
> two different students ask me why catch() can use '|' in between the 
> exception types but instanceof can not.
> 
> i.e why this code works
>  try {
>...
>  } catch(RuntimeException | Error e) {
>throw e;
>  } catch(Throwable t) {
>...
>  }
> 
> but this one doesn't
>  try {
>...
>  } catch(Throwable t) {
>if (t instanceof RuntimeException | Error e) {
>  throw e;
>}
>...
>  }
> 
> I wonder if people will want to do pattern matching on exceptions ?

I’m sure they will! (We mentioned adding pattern matching to catch in our 
overview document 
https://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html 
) The issue - 
as always - is how we reconcile the syntactic choices that have already been 
made, and the ones that are natural for our more general setting of pattern 
matching.

Gavin

Re: [patterns-instanceof] Spec for next version of Patterns in instanceof JEP

2020-10-08 Thread Gavin Bierman


> On 5 Oct 2020, at 16:20, Brian Goetz  wrote:
> 
> 5.5.  I think of `instanceof` as having two forms:
> 
> o instanceof Type
> o instanceof Pattern
> 
> This phrasing ("converted to the type indicated by the second operand") is 
> consistent with the first, but I think needs a few more words to be 
> consistent with the second?  Every pattern has a "principal type" (making up 
> a term); the principal type of a type pattern `T t` is `T`; the principal 
> type of a deconstruction pattern `D(...)` is `D`.  (The definition for other 
> kinds of patterns like constant patterns or declared patterns are 
> straightforward enough to define as needed.)  

[The spec also thinks there are two forms of instanceof - see second line of 
15.20.2!]

You don’t need to make up a term; it’s there already. In 14.30.1.1.:

The type of a type test pattern is the ReferenceType.

I use this notion of “type of a pattern” elsewhere. I tried to hedge the 
phrasing in 5.5 to spare myself mentioning both forms of instanceof, but 
perhaps it would just be clearer to do so.

Thanks.
Gavin



Re: [patterns-instanceof] Spec for next version of Patterns in instanceof JEP

2020-10-08 Thread Gavin Bierman


> On 5 Oct 2020, at 16:20, Brian Goetz  wrote:
> 
> 
> I have one concern:
> 
>> The second condition eliminates pointless instances of pattern matching 
>> where the expression will always match the pattern. In particular, the null 
>> literal is not compatible with any type test pattern.
> 
> I am not sure I agree with this framing.  We need to separate the semantics 
> of _patterns_ from the semantics of `instanceof`.  A total pattern (var x, 
> Object x, total type pattern) _does_ match null.  We may exclude some 
> patterns from `instanceof`, but that doesn't change their semantics.  I think 
> we should get ahead of this, rather than plan on patching it later.

Yes, I had spotted this. Apologies, I put the error condition in the wrong 
section - in matching rather than in instanceof - although it’s effect right 
now is the same. I shall move it. 


> Even more so:
> 
>> The null reference value does not match any type test pattern.
> 
> According to the discussions surrounding switch, this is not true.  The null 
> reference value matches any type pattern _that is total on the static type of 
> the operand_.  Again, we've got to separate the semantics of the type 
> pattern, from what `instanceof` does with a type pattern.  We get several 
> shots at null before we actually match the pattern: we can eliminate some 
> matches statically at compile time, and we can eliminate others by giving 
> semantics to instanceof before we ask "does it match the pattern."  So we 
> should be careful in which of these three buckets we put our null hostility.

Yes, spotted this also! I have refactored the semantics. In fact, for now we 
don’t need to give a case about null reference value matching, as it is caught 
by the instanceof rules.


> Overall, though, I am super-happy with how this spec has landed.  At the 
> beginning, we we a bit fearful of how intrusive it would be; in the end, 
> there is basically just the obvious set of new sections: pattern syntax, 
> pattern scoping, pattern operational semantics.  That the diffs are almost 
> entirely "adding new sections" looks like winning to me.  Further, 
> looking ahead, adding both new kinds of patterns (e.g., deconstruction 
> patterns) and new places that use patterns (e.g., pattern assignment) will 
> have an obvious place to go.

Thanks. For now section 14.30 looks a little “over-structured”, but it was 
carefully designed to be able to grow gracefully. 

Now this is JEP 394 (yay!), I will build a new version of the spec and put it 
in a more memorable place shortly. I will announce on this list when it is 
available.

Gavin

[patterns-instanceof] Spec for next version of Patterns in instanceof JEP

2020-10-05 Thread Gavin Bierman
Dear all:

A draft of the spec for the Patterns in instanceof feature that we plan to
finalize in JDK 16 is now available:

http://cr.openjdk.java.net/~gbierman/8250623/latest/

[NB: The URL will change once we have a JEP number, and will be announced.]

The changes are the same as those in the second preview that was released in
Java SE 16, except for minor editorial changes and the following:

- To lift the restriction that pattern variables are implicitly final. This
  allows pattern variables to be considered as a strict subset of local
  variables. A number of simplifications to the spec result from this change. 

- To make it a compile-time error for an expression of type _S_ to be matched
  against a pattern of type _T_, where _S_ is a subtype of _T_. (This pattern
  match will always succeed and is then pointless. The opposite case, where a
  pattern match will always fail is already a compile-time error.) 
  
Comments welcome!

Gavin

[records] Spec for next version of Record Classes JEP

2020-09-28 Thread Gavin Bierman
Dear all:

A draft of the specs for the Record Classes feature that we plan to finalize in
JDK 16 is now available:

http://cr.openjdk.java.net/~gbierman/8246771/latest/

[NB: The URL will change once we have a JEP number, and will be announced.]

The changes are the same as those in the second preview that was released in
Java SE 15, except for minor editorial changes and the following:

- To relax the current restriction on an inner class from declaring a member
  that is explicitly or implicitly static. This will now be permitted and, in
  particular, will allow an inner class to declare a record class member. (These
  changes are detailed in the companion document "Local and Nested Static 
Declarations").

- Add text to explicitly rule out using C-style array declaration of record
  components.

- Clarify that any annotations on record components that apply to the implicitly
  declared accessor method must satisfy the existing rules for annotating a
  method declaration.

- A new section (8.10.5) defining new restrictions on annotations of record
  components to ensure that they are not lost.


This last point addresses the case highlighted by Tagir
(http://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-September/002560.html).


There’s one minor corner-case that I bring to your attention. Consider the
following:

@Target(ElementType.METHOD)
@interface A { }

record R(@A int x) {
   int x() { return this.x; }
}

The new rules ensure that this is an error as the annotation on the record
component is not propagated anywhere because of the explicit accessor
declaration. However, what if the accessor was annotated with the same
annotation?

@Target(ElementType.METHOD)
@interface A { }

record R(@A int x) {
   @A int x() { return this.x; }
}

As it stands, the spec rules this out as an error. For simple annotations,
equality is simple to define, but do we want to attempt to define it for all
kinds of annotations? This feels like it’s not worth the complexity, but I’d be
happy to hear opinions. 

Many thanks,
Gavin

Re: [records] Specify use of @Override and @SafeVarargs on record components

2020-09-21 Thread Gavin Bierman


> On 19 Sep 2020, at 10:23, Tagir Valeev  wrote:
> 
> Hello!
> 
> On Fri, Sep 18, 2020 at 10:40 PM Gavin Bierman  
> wrote:
> 
>> - It is annotated with the annotations, if any, that appear on the 
>> corresponding
>>  record component and whose annotation types are applicable in the method
>>  declaration context, or in type contexts, or both. **The rules for these
>>  annotation modifiers, if any, on the accessor method are the same as for a
>>  method declaration, and are specified in [9.7.4] and [9.7.5].**
>> 
>> The last sentence is new, and mirrors what is said about normal method 
>> declarations in §8.4.3.
>> 
>> What do you think?
> 
> I'm not very good in English but I'm fine if this statement
> unambiguously imply that
> if the annotation is not applicable to the method, then this is a
> compilation error to put it on the record accessor.

Well it’s as unambiguous as the existing text around annotations on method 
declarations :-) 

I think to further emphasise this point, I will add the following text after 
the list of properties of the implicitly declared accessor method:

An implicitly declared accessor method must satisfy all the rules for a
method in a normal class declaration ([8.4]).

That makes it crystal clear (I hope). 

> 
> Btw, we allowed Override on explicit accessors, so now it might be
> unclear whether it's allowed on implicit ones.
> 
> Also what if we mark the record component with `@SafeVarargs` and
> define an explicit accessor without this annotation? Like:
> 
> record X(@SafeVarargs int y) {
>  @Override
>  public int y() {
>return y;
>  }
> }
> 
> Is this acceptable? Javac 15 happily compiles this.

Under the current rules this is acceptable; as the @SafeVarargs annotation is 
not propagated to the explicitly declared accessor method. 

> 
> This brings more general question: is it allowed to put an annotation
> that targeted to METHOD only if we define explicit accessor? In this
> case, the annotation is not propagated anywhere and completely
> disappears from the bytecode, even if it has CLASS/RUNTIME retention.
> So probably this code should be rejected as mistaken? 

That’s a very good question - well spotted. I think there is a good case to 
call that out as a compile-time error. Opinions everyone?

Gavin



Re: [records] Specify use of @Override and @SafeVarargs on record components

2020-09-18 Thread Gavin Bierman
Hi Tagir,

Returning to this one:

> On 22 Jan 2020, at 08:03, Tagir Valeev  wrote:
> 
> Hello!
> 
> It appears that it's possible to annotate record component as
> @Override or @SafeVarargs, and spec doesn't explicitly forbid this:
> 
> record Test(@SafeVarargs int x, @Override int y) {}
> 
> In these cases, it's assumed that the annotation propagates to the
> accessor method. However, having @SafeVarargs on the accessor method
> is prohibited, so should be in a record component. So I expect to see
> in 9.6.4.7 something like this:
> 
>> It is a compile-time error if a record component (§8.10.1) is annotated with 
>> the annotation @SafeVarargs.
> 
> Having the @Override is possible on the accessor if accessor overrides
> the interface method (and it's really cool possibility!) Probably it's
> ok to allow this annotation on the record component in this case, but
> it should be definitely disallowed if the accessor doesn't override
> anything. So I expect something like this in 9.6.4.4:
> 
>> If a record component (§8.10.1) of record R is annotated with the annotation 
>> @Override and the accessor method for that component (§8.10.3) does not 
>> override a method declared in a superinterface of R (§8.4.8.1), then a 
>> compile-time error occurs.

I’d like to make sure both of these are covered as erroneous, but I’m not so 
keen on the suggested JLS text. Both of these cases are actually the same, i.e. 
the annotation on the implicitly declared method doesn’t make sense. So, I’d 
prefer to call that out explicitly as a single, catch-all rule. More precisely, 
in the draft spec in §8.10.3 on implicitly declared accessor methods is the 
following bullet-point:

- It is annotated with the annotations, if any, that appear on the corresponding
  record component and whose annotation types are applicable in the method
  declaration context, or in type contexts, or both.

I propose to amend this to the following:

- It is annotated with the annotations, if any, that appear on the corresponding
  record component and whose annotation types are applicable in the method
  declaration context, or in type contexts, or both. **The rules for these
  annotation modifiers, if any, on the accessor method are the same as for a
  method declaration, and are specified in [9.7.4] and [9.7.5].**

The last sentence is new, and mirrors what is said about normal method 
declarations in §8.4.3.

What do you think?
Gavin

Re: [records] Is C-style array declaration in components dropped?

2020-09-18 Thread Gavin Bierman
Hi Tagir,

[Just tidying up the next version of the spec…and going through my list of 
outstanding emails.]

> On 24 Jul 2020, at 05:06, Tagir Valeev  wrote:
> 
> Btw if this change is intended, then it looks like the changes in
> section 10.2 [1] must be dropped as well
> 
> The array type of a variable depends on the bracket pairs that may
> appear as part of the type at the beginning of a variable declaration,
> or as part of the declarator for the variable, or both. Specifically,
> in the declaration of a field, formal parameter, local variable, or
> record component (8.3, 8.4.1, 9.3, 9.4, 14.4.1, 14.14.2, 15.27.1,
> 8.10.1), the array type of the variable is denoted by <...>
> 
> Now, this text is inconsistent with 8.10.1.

Actually it isn’t inconsistent as we need this text to allow for variable arity 
record component declarations. What is needed is to keep this as it is, but 
additionally to amend the three bullet points that follow to:

-   the element type that appears at the beginning of the declaration; then,

-   any bracket pairs that follow the variable's Identifier in the declarator
(not applicable for a variable arity parameter **or variable arity record
component**); then,

-   any bracket pairs that appear in the type at the beginning of the
declaration (where the ellipsis of a variable arity parameter **or variable
arity record component** is treated as a bracket pair).

(Text marked **…** is new).

Thanks,
Gavin

Finalizing in JDK 16 - Records

2020-07-27 Thread Gavin Bierman
[Second email of two, looking to close out features we hope to finalize in JDK
16.]


Records
---

Record classes are a special kind of class that are used primarily to define a
simple aggregate of values. 

Records can be thought of as _nominal tuples_; their declaration commits to a
description of their state and given that their representation, as well as all
of the interesting protocols an object might expose -- construction, property
access, equality, etc -- are derived from that state description.

Because we can derive everything from a common state description, the
declaration can be extremely parsimonious. Here is an example of a record class
declaration: 

record Point(int x, int y){}

The state or, more formally, a record component list, (int x, int y), drives the
implicit declaration of a number of members of the Point class.

- A `private` field is declared for each record component 
- A `public` accessor method is declared for each record component
- A constructor is declared with an argument list matching the record component
list, and whose body assigns the fields with the corresponding argument. This
constructor is called the _canonical constructor_.
- Implementations of the methods: equals, toString and HashCode. 

The body of a record class declaration is often empty, but it can contain method
declarations as usual. Indeed, if it is necessary, the implicitly declared
members - the accessors, canonical constructor, and equals, toString, or
HashCode methods -- can alternatively be explicitly declared in the body.

Often the reason for explicitly providing a canonical constructor for a record
class is to validate and/or normalize the argument values. To
enhance the readability of record class declarations, we provide a new compact
form of canonical constructor declaration, where only this
validation/normalization code is required. Here is an example:

record Rational(int num, int denom) { 
Rational {
int gcd = gcd(num, denom);
num /= gcd;
denom /= gcd;
}
}

The intention of a compact constructor declaration is that only validation
and/or normalization code need be given in the constructor body; the remaining
initialization code is automatically supplied by the compiler. The formal
argument list is not required in a compact constructor declaration as it is
taken from the record component list. In other words, this declaration is
equivalent to the following one that uses the conventional constructor form:

record Rational(int num, int denom) { 
Rational(int num, int demon) {
// Validation/Normalization
int gcd = gcd(num, denom);
num /= gcd;
denom /= gcd;
// Initialization
this.num = num;
this.denom = denom;
}
}

Once we settled on the design of record classes, things have been pretty stable.
Three issues that did arise were:

1. Initially canonical constructors were required to be public. This was changed
in the second preview. Now, if the canonical constructor is implicitly declared
then its access modifier is the same as the record class. If it is explicitly
declared then its access modifier must provide at least as much access as the
record class.

2. We have extended the meaning of the `@Override` annotation to include the
case that the annotated method is an explicitly declared accessor method for a
record component.

3. To enforce the intended use of compact constructors, we made it a
compile-time error to assign to any of the instance fields in the constructor
body. 

One area that has generated a number of questions is annotations. Our intention
is that an annotation on a record component is propagated to the field,
accessor, and/or constructor parameter, according to the applicability of the
annotation. It is not clear what other design choices there are. So we hope this
is just something that has to be learnt, and afterwards it feels natural.

The records JEP also allows for local record declarations. This is important as
records will often be used as containers for intermediate data within method
bodies. Being able to declare these record classes locally is essential to stop
proliferation of classes. We are aware of some small tweaks that will be
required to the specification during the second preview period, but overall this
feature has not generated any controversy. 



Finalizing in JDK 16 - Pattern matching for instanceof

2020-07-27 Thread Gavin Bierman
In JDK 16 we are planning to finalize two JEPs:

  - Pattern matching for `instanceof`
  - Records

Whilst we don't have any major open issues for either of these features, I would
like us to close them out. So I thought it would be useful to quickly summarize
the features and the issues that have arisen over the preview periods so far. In
this email I will discuss pattern matching; a following email will cover the
Records feature.

Pattern matching


Adding conditional pattern matching to an expression form is the main technical
novelty of our design of this feature. There are several advantages that come
from this targeting of an expression form: First, we get to refactor a very
common programming pattern:

if (e instanceof T) {
T t = (T)e; // grr...
...
}

to

if (e instanceof T t) {
// let the pattern matching do the work!
...
}

A second, less obvious advantage is that we can combine the pattern matching
instanceof with other *expressions*. This enables us to compactly express things
with expressions that are unnecessarily complicated using statements. For
example, when implementing a class Point, we might write an equals method as
follows:

public boolean equals(Object o) {
if (!(o instanceof Point))
return false;
Point other = (Point) o;
return x == other.x 
&& y == other.y;
}

Using pattern matching with instanceof instead, we can combine this into a
single expression, eliminating the repetition and simplifying the control flow:

public boolean equals(Object o) {
return (o instanceof Point other)
&& x == other.x
&& y == other.y;
}

The conditionality of pattern matching - if a value does not match a pattern,
then the pattern variable is not bound - means that we have to consider
carefully the scope of the pattern variable. We could do something simple and
say that the scope of the pattern variable is the containing statement and all
subsequent statements in the enclosing block. But this has unfortunate
'poisoning' consequences, e.g.

if (a instanceof Point p) {
...
} 
if (b instanceof Point p) { // ERROR - p is in scope
...
}

In other words in the second statement the pattern variable is in a poisoned
state - it is in scope, but it should not be accessible as it may not be
instantiated with a value. Moreover, as it is in scope, we can't declare it
again. This means that a pattern variable is 'poisoned' after it is declared, so
the pattern-loving programmer will have to think of lots of distinct names for
their pattern variables. 

We have chosen another way: Java already uses flow analysis - both in checking
the access of local variables and blank final fields, and detecting unreachable
statements. We lean on this concept to introduce the new notion of flow scoping.
A pattern variable is only in scope where the compiler can deduce that the
pattern has matched and the variable will be bound. This analysis is flow
sensitive and works in a similar way to the existing analyses. Returning to our
example:

if (a instanceof Point p) {
// p is in scope   
... 
} 
// p not in scope here
if (b instanceof Point p) { // Sure!
...
}

The motto is "a pattern variable is in scope where it has definitely matched".
This is intuitive, allows for the safe reuse of pattern variables, and Java
developers are already used to flow sensitive analyses. 

As pattern variables are treated in all other respects like normal variables
-- and this was an important design principle -- they can shadow fields.
However, their flow scoping nature means that some care must be taken to
determine whether a name refers to a pattern variable declaration shadowing a
field declaration or a field declaration. 

// field p is in scope

if (e instanceof Point p) {
// p refers to the pattern variable
} else {
// p refers to the field
}

We call this unfortunate interaction of flow scoping and shadowing the "Swiss
cheese property". To rule it out would require ad-hoc special cases or more
features, and our sense is that will not be that common, so we have decided to
keep the feature simple. We hope that IDEs will quickly come to help programmers
who have difficulty with flow scoping and shadowing.  

Re: [records] Is C-style array declaration in components dropped?

2020-07-27 Thread Gavin Bierman
Thanks. Yes, we did remove this syntax deliberately - apologies that it didn’t 
make the change list. 

I’ll tidy up the remaining inconsistency in the first version of the next 
records JEP JLS doc.

Gavin

> On 24 Jul 2020, at 05:06, Tagir Valeev  wrote:
> 
> Btw if this change is intended, then it looks like the changes in
> section 10.2 [1] must be dropped as well
> 
> The array type of a variable depends on the bracket pairs that may
> appear as part of the type at the beginning of a variable declaration,
> or as part of the declarator for the variable, or both. Specifically,
> in the declaration of a field, formal parameter, local variable, or
> record component (8.3, 8.4.1, 9.3, 9.4, 14.4.1, 14.14.2, 15.27.1,
> 8.10.1), the array type of the variable is denoted by <...>
> 
> Now, this text is inconsistent with 8.10.1.
> 
> With best regards,
> Tagir Valeev.
> [1] 
> http://cr.openjdk.java.net/~gbierman/jep384/jep384-20200506/specs/records-jls.html#jls-10.2
> 
> 
> 
> On Fri, Jul 24, 2020 at 10:55 AM Tagir Valeev  wrote:
>> 
>> Hello!
>> 
>> The JLS 14 record preview spec allows C-style array declaration in
>> components (like record R(int x[])) [1]:
>> 
>> RecordComponent:
>>  { VariableModifier } UnannType VariableDeclaratorId
>>  VariableArityRecordComponent
>> VariableDeclaratorId:
>>  Identifier [ Dims ]
>> 
>> However, it appears that JLS 15 draft spec doesn't allow it anymore [2]
>> 
>> RecordComponent:
>>  { Annotation } UnannType Identifier
>>  VariableArityRecordComponent
>> 
>> This change is not listed in the draft spec prolog in "The changes are
>> the same as those in the first preview of Records in Java SE 14,
>> except for the following", so I overlooked it when updated the records
>> support in IntelliJ IDEA. Is this intended change? If yes, then
>> probably the changes section should be updated to include it as well.
>> 
>> I must say that I heavily support this change. Supporting C-style
>> array declaration in records adds complexity in many places of our
>> codebase and introduces subtle bugs. It's somewhat depressing to fix
>> all of them, knowing that nobody would use this anyway.
>> 
>> With best regards,
>> Tagir Valeev.
>> 
>> [1] 
>> https://docs.oracle.com/javase/specs/jls/se14/preview/specs/records-jls.html#jls-8.10.1
>> [2] 
>> http://cr.openjdk.java.net/~gbierman/jep384/jep384-20200506/specs/records-jls.html#jls-8.10.1



Re: [sealed-types] Draft Spec for JEP 360 Sealed Types (Preview)

2020-06-03 Thread Gavin Bierman


> On 26 May 2020, at 21:54, Gavin Bierman  wrote:
> 
> I fixed a number of small bugs in the spec. The latest draft is available at:
> 
>
> <http://cr.openjdk.java.net/~gbierman/jep360/latest/>http://cr.openjdk.java.net/~gbierman/jep360/latest/
>  <http://cr.openjdk.java.net/~gbierman/jep360/latest/>
> 
> Thanks,
> Gavin


PS: I should like to mention one aspect of this spec that we intend to change 
in JDK 16 (it was too late in the day for JDK 15). We currently specify in 3.9 
that `non-sealed` is a keyword. We couldn’t simply play the trick that it was a 
restricted identifier, as identifiers cannot contain the `-` character. 
However, this is not where we intend to land. We would prefer to introduce a 
notion of “contextual keyword” and use this to properly deal with not just 
‘non-sealed`, but also `var`, `yield`, and `sealed` (the restricted 
identifiers), as well as the ten restricted keywords (`open`, `module`, 
`requires`, `transitive`, `exports`, `opens`, `to`, `uses`, `provides`, and 
`with`).

We will share details of this once they are ready, but I wanted to share our 
intent here now.

Gavin 




Re: [sealed-types] Draft Spec for JEP 360 Sealed Types (Preview)

2020-05-26 Thread Gavin Bierman
I fixed a number of small bugs in the spec. The latest draft is available at:

 
<http://cr.openjdk.java.net/~gbierman/jep360/latest/>http://cr.openjdk.java.net/~gbierman/jep360/latest/
 <http://cr.openjdk.java.net/~gbierman/jep360/latest/>

Thanks,
Gavin

> On 13 May 2020, at 17:34, Gavin Bierman  wrote:
> 
> There has been a small change to the spec available at:
> 
>   http://cr.openjdk.java.net/~gbierman/jep360/latest/ 
> <http://cr.openjdk.java.net/~gbierman/jep360/latest/>
> 
> [This brings the spec in line with the compiler on the corner-case of an enum 
> class that both implements a sealed interface and contains an enum constant 
> with a class body.]
> 
> Thanks,
> Gavin
> 
>> On 6 May 2020, at 16:13, Gavin Bierman > <mailto:gavin.bier...@oracle.com>> wrote:
>> 
>> We have made some presentational changes to the spec for JEP360 (Sealed 
>> Types), which are available at:
>> 
>>  http://cr.openjdk.java.net/~gbierman/jep360/latest/ 
>> <http://cr.openjdk.java.net/~gbierman/jep360/latest/>
>> 
>> The only semantic change is a new error if the direct superclass or direct 
>> superinterface of a local class is `sealed`. A more complete set of changes 
>> to address all interactions between local and member classes and sealed 
>> types (see [1] for some of these) will come later, although perhaps not 
>> until JDK 16. 
>> 
>> Thanks,
>> Gavin
>> 
>> [1] 
>> http://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-May/002156.html
>> 
>> 
>> 
>>> On 20 Apr 2020, at 22:50, Gavin Bierman  wrote:
>>> 
>>> The latest (and hopefully final) draft of JEP 360 (Sealed Types) is 
>>> available at:
>>> 
>>>   http://cr.openjdk.java.net/~gbierman/jep360/latest
>>> 
>>> The changes since the last draft was circulated in February [1]:
>>> 
>>> * Some minor typos have been corrected, including changing the title of 
>>> 8.1.6.
>>> 
>>> * We have make corrections in a number of places to make it clear that the 
>>> name
>>> in a `permits` clause is not a type (and can not be annotated, for example).
>>> 
>>> * We now require a functional interface to not be `sealed`, rather than 
>>> imposing
>>> checks on target types of lambda expressions. 
>>> 
>>> * We have removed the changes to narrowing reference conversion which 
>>> allowed
>>> for stricter checking of cast conversions wrt sealed type hierarchies. We 
>>> have
>>> decided to defer this feature until a later release to allow us to develop a
>>> broader treatment of "disjoint types" that can be used not just in cast
>>> conversion, but in other places such as bounds checking and pattern 
>>> matching.
>>> 
>>> The refined cast conversion was nice to have, but really only will make a
>>> difference when we get to patterns in switches, so it makes sense to spend 
>>> some
>>> more time now considering our design rather than refining cast conversion 
>>> in a
>>> piecewise manner. 
>>> 
>>> Thanks,
>>> Gavin
>>> 
>>> [1] 
>>> https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-February/002031.html
>>> 
>> 
> 



Re: Switch Expression - complete normally - spec omission?

2020-05-21 Thread Gavin Bierman
Thanks Manoj. I’ve filed this as a bug [1] and we’ll fix it for JDK 15. 

Cheers,
Gavin

[1] https://bugs.openjdk.java.net/browse/JDK-8245546 
 

> On 16 May 2020, at 10:10, Manoj Palat  wrote:
> 
> Thanks Alex for the reply and clarifying that we are discussing Switch 
> Statements with Switch rules.
> My bad for putting the title as Switch Expressions - don't want to correct 
> the title now which
> will break the chain of the mail.
> 
> Regards,
> Manoj
> 
> -"amber-spec-experts"  
> wrote: -
> To: amber-spec-experts@openjdk.java.net
> From: Alex Buckley
> Sent by: "amber-spec-experts"
> Date: 05/15/2020 11:34PM
> Subject: [EXTERNAL] Re: Switch Expression - complete normally - spec omission?
> 
> On 5/14/2020 7:22 PM, Manoj Palat wrote:
>> I think there is a spec omission regarding "complete normally for switch 
>> statements whose switch block consists of switch rules
>> 
>> Ref JLS 14 Sec 14.22
>> ...
>> A switch statement whose switch block consists of switch rules can complete
>> normally iff at least one of the following is true:
>> – One of the switch rules introduces a switch rule expression (which is
>> necessarily a statement expression).
>> – One of the switch rules introduces a switch rule block that can complete
>> normally.
>> – One of the switch rules introduces a switch rule block that contains a 
>> reachable
>> break statement which exits the switch statement.
>> ...
>> Now consider:
>> 
>> switch (b) {
>> case 1 -> {
>> throw new Exception();
>> }
>> }
>> 
>> As per the above definition, this switch statement cannot complete normally;
>> but consider "b" having a value other than 1 and then it completes normally.
> 
> /* -
> To demonstrate the point, the switch statement above uses a switch rule
> block that completes abruptly, but could alternatively have used a
> switch rule `throw` statement:
> 
> switch (b) {
>   case 1 -> throw new Exception();
> }
> 
> Also, to clarify for the many readers of this list, we are discussing
> switch statements, which never require a `default` label. We are not
> discussing switch expressions, which almost always require a `default`
> label.
> - */
> 
>> 
>> Also consider, 14.11.3. which says:
>> "If no switch label matches, the entire switch statement completes normally."
>> 
>> which looks inconsistent. One hand says: "completes normally" the other:
>> "iff at least one of the following ..." not mentioning default.
>> 
>> Hence, shouldn't the item,
>> -> – The switch block does not contain a default label.
>> 
>> also be added in the list in 14.22?
> 
> I agree that without a `default` switch label, 14.11.3 may evaluate "If
> no switch label matches, the entire switch statement completes
> normally."  Since we can see a way for the statement to complete
> normally, 14.22 ought to say that the statement _can_ complete normally.
> So, it looks right to add "– The switch block does not contain a default
> label."
> 
> Alex
> 
> 



[sealed-types] Draft Spec for JEP 360 Sealed Types (Preview)

2020-05-13 Thread Gavin Bierman
There has been a small change to the spec available at:

http://cr.openjdk.java.net/~gbierman/jep360/latest/ 
<http://cr.openjdk.java.net/~gbierman/jep360/latest/>

[This brings the spec in line with the compiler on the corner-case of an enum 
class that both implements a sealed interface and contains an enum constant 
with a class body.]

Thanks,
Gavin

> On 6 May 2020, at 16:13, Gavin Bierman  wrote:
> 
> We have made some presentational changes to the spec for JEP360 (Sealed 
> Types), which are available at:
> 
>   http://cr.openjdk.java.net/~gbierman/jep360/latest/
> 
> The only semantic change is a new error if the direct superclass or direct 
> superinterface of a local class is `sealed`. A more complete set of changes 
> to address all interactions between local and member classes and sealed types 
> (see [1] for some of these) will come later, although perhaps not until JDK 
> 16. 
> 
> Thanks,
> Gavin
> 
> [1] 
> http://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-May/002156.html
> 
> 
> 
>> On 20 Apr 2020, at 22:50, Gavin Bierman  wrote:
>> 
>> The latest (and hopefully final) draft of JEP 360 (Sealed Types) is 
>> available at:
>> 
>>   http://cr.openjdk.java.net/~gbierman/jep360/latest
>> 
>> The changes since the last draft was circulated in February [1]:
>> 
>> * Some minor typos have been corrected, including changing the title of 
>> 8.1.6.
>> 
>> * We have make corrections in a number of places to make it clear that the 
>> name
>> in a `permits` clause is not a type (and can not be annotated, for example).
>> 
>> * We now require a functional interface to not be `sealed`, rather than 
>> imposing
>> checks on target types of lambda expressions. 
>> 
>> * We have removed the changes to narrowing reference conversion which allowed
>> for stricter checking of cast conversions wrt sealed type hierarchies. We 
>> have
>> decided to defer this feature until a later release to allow us to develop a
>> broader treatment of "disjoint types" that can be used not just in cast
>> conversion, but in other places such as bounds checking and pattern matching.
>> 
>> The refined cast conversion was nice to have, but really only will make a
>> difference when we get to patterns in switches, so it makes sense to spend 
>> some
>> more time now considering our design rather than refining cast conversion in 
>> a
>> piecewise manner. 
>> 
>> Thanks,
>> Gavin
>> 
>> [1] 
>> https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-February/002031.html
>> 
> 



Re: [records] Latest spec available

2020-05-07 Thread Gavin Bierman
As Records has now been approved as JEP 384 [1] I have updated and relocated the
spec appropriately:

http://cr.openjdk.java.net/~gbierman/jep384/latest

(The old URL now redirects to this one)

Thanks,
Gavin

[1] https://mail.openjdk.java.net/pipermail/amber-dev/2020-May/005964.html


> On 1 May 2020, at 18:09, Gavin Bierman  wrote:
> 
> I have updated this spec with the new restriction to compact constructors:
> 
>It is a compile-time error if an assignment occurs (16) to a 
>field corresponding to a record component of the record class
>in the body of the compact constructor.
> 
> Latest spec available at:
> 
>
> http://cr.openjdk.java.net/~gbierman/records2/20200501/specs/records-jls.html
> 
> Thanks,
> Gavin
> 
>> On 28 Apr 2020, at 06:48, Gavin Bierman  wrote:
>> 
>> Dear all:
>> 
>> The latest draft of the spec for the second preview of records is available 
>> at:
>> 
>> http://cr.openjdk.java.net/~gbierman/records2/20200428/specs/records-jls.html
>> 
>> The changes from the first preview spec [1] have been discussed on this list 
>> and
>> are listed below for reference. However, with an eye to a better treatment of
>> nesting in Java as discussed by Brian [2] we have taken the opportunity to
>> refactor the spec somewhat to allow for a better treatment of local 
>> declarations
>> including local records. 
>> 
>> We have kept these refactorings as two separate JLS change documents, linked 
>> to
>> from the records spec. The first document clarifies the usage of terms 
>> related
>> to classes and interfaces, and more clearly distinguishes them from types. 
>> The
>> second builds on this and regularizes the treatment of nested and local
>> declarations. In particular, it relaxes previous restrictions and permits 
>> *local
>> interface and enum declarations*. The records spec then builds on top of 
>> these
>> two changes to the JLS to support records (and local record declarations).
>> 
>> Comments welcome!
>> Gavin
>> 
>> PS: The URLs will change once we have a JEP number for the second preview of
>> records.
>> 
>> [1] 
>> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20200115/specs/records-jls.html
>> [2] 
>> https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-January/001904.html
>> 
>> Details: 
>> 
>> The changes are the same as those in the first preview of Records in Java SE 
>> 14,
>> except for the following:
>> 
>> - All text now uses the terminology of "Consistent Class and Interface
>> Terminology" spec change document
>> 
>> - The handling of local records now builds on the changes in "Local Static
>> Interfaces and Enum Classes" spec change document
>> 
>> - Removed unnecessary change to 4.12.4
>> 
>> - 8.10.1: Removed possibility of `final` modifier for record components
>> 
>> - 8.10.1: Clarified that annotations on a record component only remain on the
>> component if its annotation type is applicable in the record component 
>> context
>> 
>> - 8.10.1: Corrected text around use of `@SafeVarArgs` annotation
>> 
>> - 8.10.4: Removed requirement that canonical constructor must be `public`. 
>> Any
>> access modifier must provide at least as much access as the record class. If 
>> a
>> canonical constructor is implicitly declared, then its access modifier is the
>> same as the record class.
>> 
>> - 8.10.4: Added requirement each formal parameter in the formal parameter 
>> list
>> of the constructor must have the same name and type as the corresponding 
>> record
>> component. The formal parameter must be a variable arity parameter if and 
>> only
>> if the corresponding record component is a variable arity record component.
>> 
>> - 8.10.4 Added error condition if a field corresponding to a record 
>> component of
>> a record class is neither DA nor DU in the body of a compact constructor.
>> 
>> - 9.6.4.4 New case for using `@Override` annotation to declare that a method 
>> is
>> an accessor method for a record component.
>> 
> 



[sealed-types] Draft Spec for JEP 360 Sealed Types (Preview)

2020-05-06 Thread Gavin Bierman
We have made some presentational changes to the spec for JEP360 (Sealed Types), 
which are available at:

http://cr.openjdk.java.net/~gbierman/jep360/latest/

The only semantic change is a new error if the direct superclass or direct 
superinterface of a local class is `sealed`. A more complete set of changes to 
address all interactions between local and member classes and sealed types (see 
[1] for some of these) will come later, although perhaps not until JDK 16. 

Thanks,
Gavin

[1] 
http://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-May/002156.html



> On 20 Apr 2020, at 22:50, Gavin Bierman  wrote:
> 
> The latest (and hopefully final) draft of JEP 360 (Sealed Types) is available 
> at:
> 
>http://cr.openjdk.java.net/~gbierman/jep360/latest
> 
> The changes since the last draft was circulated in February [1]:
> 
> * Some minor typos have been corrected, including changing the title of 8.1.6.
> 
> * We have make corrections in a number of places to make it clear that the 
> name
> in a `permits` clause is not a type (and can not be annotated, for example).
> 
> * We now require a functional interface to not be `sealed`, rather than 
> imposing
> checks on target types of lambda expressions. 
> 
> * We have removed the changes to narrowing reference conversion which allowed
> for stricter checking of cast conversions wrt sealed type hierarchies. We have
> decided to defer this feature until a later release to allow us to develop a
> broader treatment of "disjoint types" that can be used not just in cast
> conversion, but in other places such as bounds checking and pattern matching.
> 
> The refined cast conversion was nice to have, but really only will make a
> difference when we get to patterns in switches, so it makes sense to spend 
> some
> more time now considering our design rather than refining cast conversion in a
> piecewise manner. 
> 
> Thanks,
> Gavin
> 
> [1] 
> https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-February/002031.html
> 



Re: [records] Latest spec available

2020-05-01 Thread Gavin Bierman
I have updated this spec with the new restriction to compact constructors:

It is a compile-time error if an assignment occurs (16) to a 
field corresponding to a record component of the record class
in the body of the compact constructor.

Latest spec available at:


http://cr.openjdk.java.net/~gbierman/records2/20200501/specs/records-jls.html

Thanks,
Gavin

> On 28 Apr 2020, at 06:48, Gavin Bierman  wrote:
> 
> Dear all:
> 
> The latest draft of the spec for the second preview of records is available 
> at:
> 
>  http://cr.openjdk.java.net/~gbierman/records2/20200428/specs/records-jls.html
> 
> The changes from the first preview spec [1] have been discussed on this list 
> and
> are listed below for reference. However, with an eye to a better treatment of
> nesting in Java as discussed by Brian [2] we have taken the opportunity to
> refactor the spec somewhat to allow for a better treatment of local 
> declarations
> including local records. 
> 
> We have kept these refactorings as two separate JLS change documents, linked 
> to
> from the records spec. The first document clarifies the usage of terms related
> to classes and interfaces, and more clearly distinguishes them from types. The
> second builds on this and regularizes the treatment of nested and local
> declarations. In particular, it relaxes previous restrictions and permits 
> *local
> interface and enum declarations*. The records spec then builds on top of these
> two changes to the JLS to support records (and local record declarations).
> 
> Comments welcome!
> Gavin
> 
> PS: The URLs will change once we have a JEP number for the second preview of
> records.
> 
> [1] 
> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20200115/specs/records-jls.html
> [2] 
> https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-January/001904.html
> 
> Details: 
> 
> The changes are the same as those in the first preview of Records in Java SE 
> 14,
> except for the following:
> 
> - All text now uses the terminology of "Consistent Class and Interface
> Terminology" spec change document
> 
> - The handling of local records now builds on the changes in "Local Static
> Interfaces and Enum Classes" spec change document
> 
> - Removed unnecessary change to 4.12.4
> 
> - 8.10.1: Removed possibility of `final` modifier for record components
> 
> - 8.10.1: Clarified that annotations on a record component only remain on the
> component if its annotation type is applicable in the record component context
> 
> - 8.10.1: Corrected text around use of `@SafeVarArgs` annotation
> 
> - 8.10.4: Removed requirement that canonical constructor must be `public`. Any
> access modifier must provide at least as much access as the record class. If a
> canonical constructor is implicitly declared, then its access modifier is the
> same as the record class.
> 
> - 8.10.4: Added requirement each formal parameter in the formal parameter list
> of the constructor must have the same name and type as the corresponding 
> record
> component. The formal parameter must be a variable arity parameter if and only
> if the corresponding record component is a variable arity record component.
> 
> - 8.10.4 Added error condition if a field corresponding to a record component 
> of
> a record class is neither DA nor DU in the body of a compact constructor.
> 
> - 9.6.4.4 New case for using `@Override` annotation to declare that a method 
> is
> an accessor method for a record component.
> 



Re: Possible records tweak

2020-04-29 Thread Gavin Bierman
Talking it through with Dan, I think the best thing for the JLS is to avoid 
issues of `this` etc and simply state:

It is a compile-time error to assign to the instance fields of the 
record class in the body of the compact constructor.

Thoughts?
Gavin


> On 27 Apr 2020, at 23:54, Remi Forax  wrote:
> 
> 
> 
> - Mail original -
>> De: "Brian Goetz" 
>> À: "daniel smith" , "John Rose" 
>> 
>> Cc: "amber-spec-experts" 
>> Envoyé: Mardi 28 Avril 2020 00:37:05
>> Objet: Re: Possible records tweak
> 
 So maybe `super` is DA but `this` is DU, just like in the code
 before the super-constructor call.  (I’m abusing the terms DA/DU
 like Brian is, and you call out, but they are close to correct.)
>>> I think this means I can't call inherited method 'getParentWidget()' or some
>>> static utility 'computeWidgetOfParent(this)' method (e.g.,
>>> 'identityHashCode(this)'). I *can* call 'super.getParentWidget()'.
>> 
>> Except records only inherit from Record, which has no non-inherited
>> instance methods.
> 
> super.wait(), etc should work
> 
> Rémi
> 



Re: [sealed] Module & package constraints

2020-04-28 Thread Gavin Bierman



> On 24 Apr 2020, at 22:24, Dan Smith  wrote:
> 
> Sounds like the conclusion is:
> 
>> On Apr 24, 2020, at 1:16 PM, Dan Smith  wrote:
>> 
>> I presented this as an outline of our choices, but to put a stake in the 
>> ground, here are my preferences.
>> 
>>> On Apr 23, 2020, at 12:27 PM, Dan Smith  wrote:
>>> 
>>> 1) Is it legal to have a permitted subclass/subinterface that does not 
>>> actually extend the permitting class or interface?
>> 
>> At compile time, no. Let's prohibit that.
>> 
>> At run time, delay any validation until a particular subclass is loaded.
> 
> Agreement on both of these. (Requires a new rule in the language spec.)

Apologies. That rule was in the Feb spec, but got left out by mistake in the 
last draft. Now reinstated. 

Gavin



[records] Latest spec available

2020-04-27 Thread Gavin Bierman
Dear all:

The latest draft of the spec for the second preview of records is available at:

  http://cr.openjdk.java.net/~gbierman/records2/20200428/specs/records-jls.html

The changes from the first preview spec [1] have been discussed on this list and
are listed below for reference. However, with an eye to a better treatment of
nesting in Java as discussed by Brian [2] we have taken the opportunity to
refactor the spec somewhat to allow for a better treatment of local declarations
including local records. 

We have kept these refactorings as two separate JLS change documents, linked to
from the records spec. The first document clarifies the usage of terms related
to classes and interfaces, and more clearly distinguishes them from types. The
second builds on this and regularizes the treatment of nested and local
declarations. In particular, it relaxes previous restrictions and permits *local
interface and enum declarations*. The records spec then builds on top of these
two changes to the JLS to support records (and local record declarations).

Comments welcome!
Gavin

PS: The URLs will change once we have a JEP number for the second preview of
records.

[1] 
http://cr.openjdk.java.net/~gbierman/jep359/jep359-20200115/specs/records-jls.html
[2] 
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-January/001904.html

Details: 

The changes are the same as those in the first preview of Records in Java SE 14,
except for the following:

- All text now uses the terminology of "Consistent Class and Interface
Terminology" spec change document

- The handling of local records now builds on the changes in "Local Static
Interfaces and Enum Classes" spec change document

- Removed unnecessary change to 4.12.4

- 8.10.1: Removed possibility of `final` modifier for record components

- 8.10.1: Clarified that annotations on a record component only remain on the
component if its annotation type is applicable in the record component context

- 8.10.1: Corrected text around use of `@SafeVarArgs` annotation

- 8.10.4: Removed requirement that canonical constructor must be `public`. Any
access modifier must provide at least as much access as the record class. If a
canonical constructor is implicitly declared, then its access modifier is the
same as the record class.

- 8.10.4: Added requirement each formal parameter in the formal parameter list
of the constructor must have the same name and type as the corresponding record
component. The formal parameter must be a variable arity parameter if and only
if the corresponding record component is a variable arity record component.

- 8.10.4 Added error condition if a field corresponding to a record component of
a record class is neither DA nor DU in the body of a compact constructor.

- 9.6.4.4 New case for using `@Override` annotation to declare that a method is
an accessor method for a record component.



[sealed-types] Draft Spec for JEP 360 Sealed Types (Preview)

2020-04-20 Thread Gavin Bierman
The latest (and hopefully final) draft of JEP 360 (Sealed Types) is available 
at:

http://cr.openjdk.java.net/~gbierman/jep360/latest

The changes since the last draft was circulated in February [1]:

* Some minor typos have been corrected, including changing the title of 8.1.6.

* We have make corrections in a number of places to make it clear that the name
in a `permits` clause is not a type (and can not be annotated, for example).

* We now require a functional interface to not be `sealed`, rather than imposing
checks on target types of lambda expressions. 

* We have removed the changes to narrowing reference conversion which allowed
for stricter checking of cast conversions wrt sealed type hierarchies. We have
decided to defer this feature until a later release to allow us to develop a
broader treatment of "disjoint types" that can be used not just in cast
conversion, but in other places such as bounds checking and pattern matching.

The refined cast conversion was nice to have, but really only will make a
difference when we get to patterns in switches, so it makes sense to spend some
more time now considering our design rather than refining cast conversion in a
piecewise manner. 

Thanks,
Gavin

[1] 
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-February/002031.html



[patterns] Draft Spec for JEP 375 Pattern Matching for instanceof (Preview 2)

2020-04-14 Thread Gavin Bierman
Dear experts:

The latest (and hopefully final) draft of JEP 375 (Pattern matching for
instanceof) is available at:

http://cr.openjdk.java.net/~gbierman/jep375/latest

This spec is now equivalent to the spec for the first preview version (JEP 
305). 
The only changes are:

1. Some minor typos corrected. 

2. Added missing case dealing with parenthesized expressions in the definition
of scope of pattern variables.

3. Added missing case dealing with labeled statements in the definition of scope
of pattern variables.

We have decided to remove the deconstruction patterns for record types from this
preview release. There are some complications surrounding generics and
deconstruction patterns, along with varargs and deconstruction patterns, and
we'd like some more time to consider our design. I'll write separately on these
issues.

Thanks,
Gavin


Re: Record component type can be an inner class of a record

2020-04-13 Thread Gavin Bierman
Thanks for pointing this out Remi. We definitely need to tweak the draft spec 
to deal with this scoping question. 

However, I am of the opinion that this example should not be allowed. I would 
expect the scope of things defined in a record body to be the record body. I 
don’t think the record header should be considered part of the body. 
Analogously:

class Foo {
class Bar { … }
…
}

This doesn’t work as the scope of the Bar declaration is the class body.

What do you think?
Gavin

> On 24 Mar 2020, at 20:57, Remi Forax  wrote:
> 
> Hi all,
> a record component can use as type a type declared inside the record itself,
> in term of scoping it's like if the record component is part of the internal 
> scope of the record.
> 
> record Foo(Bar bar) {
>  class Bar {
> 
>  }
> }
> 
> I think it's the right behaviour but i was not able to find any reference to 
> that in the spec.
> 
> regards,
> Rémi



Final issues regarding records

2020-04-06 Thread Gavin Bierman
Dear Experts:

I’d like to circle back on a couple of issues regarding records. I am finalizing
the draft language spec - would really like to complete this very soon - so it 
would be great to get some EG feedback so we cancomplete the spec (and tweak 
the implementation as necessary). I'm especially keen to hear from anyone who 
has actually been playing with the records prototype already. 


#1. Accessibility of various record members.

In an earlier email, I wrote:

> Currently the mandated members are public regardless of the accessibility of
> the record type. What should be the default accessibility for record
> members? 
> 
> A: Currently the most popular proposal is that mandated members get
> accessibility of the record type. Other members get package level
> accessibility as per a regular class. (Note: it should be legal for explicit
> declarations of mandated members to specify something _more_ accessible
> (same rules as overriding.) )

Just to clarify which members we are talking about; there are actually two
categories to consider: 

1. The implicitly declared accessor methods corresponding to the record
components.  

2. The canonical constructor (including possibly a compact constructor). 

For these members, the current spec and implementation require that they are
`public` regardless of the accessibility of the enclosing record type. 

The question before the house is whether this is the right design. A gut
reaction is that it feels wrong; why insist on a public accessibility regardless
of the enclosing declaration? But after a little thought, it is not so clear
that this is the wrong design.

First, note that enums already have this implicit-members-are-`public` feature -
the implicitly declared `values` and `valueOf` methods are `public` regardless
of the accessibility of the enum type. As far as I am aware, this feature of
enums has not caused any confusion (or much comment).

Second, consider the case where we are using interfaces to specify the behavior
of the record type, including the accessor methods. For example:

interface I {
  int i();
}

record R(int i) implements I {}

If we make R private, then there is no way we can satisfy our contract as
interfaces can’t have private methods. In this example, there’s not a lot we can
do other than explicitly declare the accessor method ourselves. This is a shame
- we can't utilize the implicit declaration of accessor methods because of a
mismatch of accessibility. 

Whilst this example is a little contrived, it asks whether the essence of the
(public) contract that records satisfy, even private ones, is that they support
accessor methods to access the values of the record components. 

Regarding the canonical constructor: it's indeed the case that for normal class
declarations the *default* constructor gets the access modifier from the
enclosing class declaration. But, this is a weak argument for *canonical*
constructors, which are different in a number of ways already. 

I can see 4 options:

1. Keep the everything public option as currently spec-ed and implemented. This
is simple to remember, and not without precedent.

2. Change the current spec and implementation so the accessor methods and
canonical constructor inherit the accessibility from the record type. This is
also simple to remember, but it ignores the issues with interfaces detailed
above.

3. Incorporate both strategies: Perhaps that the canonical constructor inherits
accessibility from the record type, whereas accessor methods are required to be
public. 

4. Some variant of (2) that can deal with the interface example (?)

What are your thoughts?


#2. Annotating explicit accessor methods

> Q10. Special annotation for explicit declaration of accessors. 
> 
>Tagir [6] proposes a new `@RecordAccessor` annotation to mark explicit
>accessors, much as `@Override` is used to mark method overrides.
> 
>A: Rather than introduce a new accessor, we will consider extending the
>meaning of the `@Override` annotation to include this case.

There's been some discussion about this, but we were hoping for more! The
motivation for co-opting @Override is that its purpose already is to allow the
compiler to give us better type checking because we’ve captured a bit of user
intent, so this feels similar. However, Peter has made the excellent point that
extending `@Override` in this way might be confusing in record declarations that
also contain implementations of methods from interfaces. 

Essentially, I think our options are:

1. Do nothing. (We can come back to this at the next release.)

2. Co-op `@Override`

3. Invent a new annotation, as suggested by Tagir.


Any further thoughts?


---

Thanks for your consideration. I look forward to hearing your feedback. 

Best wishes,
Gavin

Re: [patterns] Draft Spec for JEP 375 Pattern Matching for instanceof (Preview 2)

2020-03-17 Thread Gavin Bierman
Thanks. Must have slipped under the radar. Will fix soon. 

Gavin

Sent from my iPhone

> On 17 Mar 2020, at 04:33, Tagir Valeev  wrote:
> 
> 
> Hello!
> 
> Just a reminder that parenthesized expression is still not covered by the 
> spec draft. I expect to see it in chapter 6.3.1. Without this, even some 
> samples listed in the spec draft itself are incorrect. E.g. the sample in 
> 6.3.2: if (!(o instanceof String s)) {...
> 
> With best regards,
> Tagir Valeev
> 
>> On Mon, Mar 16, 2020 at 10:04 PM Gavin Bierman  
>> wrote:
>> Dear experts:
>> 
>> A draft language spec for JEP 375 (Pattern Matching for instanceof) is 
>> available at:
>> 
>> http://cr.openjdk.java.net/~gbierman/jep375/latest
>> 
>> Main change from Preview 1 is, as discussed on this list, support for 
>> deconstruction patterns over record types.
>> 
>> Comments welcome!
>> 
>> Thanks,
>> Gavin


[patterns] Draft Spec for JEP 375 Pattern Matching for instanceof (Preview 2)

2020-03-16 Thread Gavin Bierman
Dear experts:

A draft language spec for JEP 375 (Pattern Matching for instanceof) is 
available at:

http://cr.openjdk.java.net/~gbierman/jep375/latest 


Main change from Preview 1 is, as discussed on this list, support for 
deconstruction patterns over record types.

Comments welcome!

Thanks,
Gavin

Re: [sealed] Draft Language Spec available

2020-03-03 Thread gavin . bierman
Thanks Tagir. I’ll take a look.

Gavin

Sent from my iPad

> On 2 Mar 2020, at 05:01, Tagir Valeev  wrote:
> 
> I see that you added a note to "15.27.3 Type of a Lambda Expression",
> but a similar note is missing in "15.13.2 Type of a Method Reference".
> I think both should be unnecessary if you just restrict the
> "functional interface" definition instead.
> 
> With best regards,
> Tagir Valeev
> 
> 
>> On Mon, Mar 2, 2020 at 11:57 AM Tagir Valeev  wrote:
>> 
>> Hello!
>> 
>> Shouldn't we update a section 9.8 Functional Interfaces? E.g.:
>> 
>> A functional interface is an interface that [is not declared as sealed
>> and] has just one abstract method (aside from the methods of Object),
>> and thus represents a single function contract.
>> 
>> This will also imply that the @FunctionalInterface annotation cannot
>> be applicable to sealed interfaces (9.6.4.9).
>> 
>> With best regards,
>> Tagir Valeev.
>> 
>> 
>>> On Fri, Feb 28, 2020 at 7:25 PM Gavin Bierman  
>>> wrote:
>>> 
>>> The next draft language spec for JEP 360 (Sealed Types) is available at:
>>> 
>>> http://cr.openjdk.java.net/~gbierman/jep360/latest/
>>> 
>>> This version reflects the changes to the type system I mentioned [1], along 
>>> with a number of other changes. We’d appreciate further comments on this in 
>>> particular (along with anything else).
>>> 
>>> Thanks,
>>> Gavin
>>> 
>>> [1] 
>>> https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-February/002018.html



Re: Pattern Matching for instanceof (Preview 2)

2020-02-28 Thread Gavin Bierman



> On 28 Feb 2020, at 11:52, fo...@univ-mlv.fr wrote:
> 
> - Mail original -
>> De: "Brian Goetz" 
>> À: "Remi Forax" , "Gavin Bierman" 
>> 
>> Cc: "amber-spec-experts" , "jan lahoda" 
>> 
>> Envoyé: Mardi 18 Février 2020 16:14:57
>> Objet: Re: Pattern Matching for instanceof (Preview 2)
> 
>>>> I don’t know what you mean here. There are two patterns, a type test 
>>>> pattern and
>>>> a deconstruction pattern. In v2 we propose to support deconstruction 
>>>> patterns
>>>> over record types *only*. A deconstruction pattern looks like this: 
>>>> Point(var
>>>> a, var b), i.e. all the components are either (recursively) deconstruction
>>>> patterns, or `var` , i.e. with no type needed. I added a note 
>>>> to
>>>> the JEP page pointing out that this is a starting point, and eventually we 
>>>> will
>>>> support other patterns in the argument position, specifically 
>>>> ; hopefully in this release.
>>> Currently we don't support mixing var and non var in lambda parameters.
>>> So my question is: does this pattern Point(var x, int y) that mix a 'var' 
>>> and an
>>> explicit type allowed or not ?
>> 
>> Unequivocal "yes".   There is a universe of patterns.  Some might be
>> disallowed in certain contexts (e.g., `instanceof var x` seems kind of
>> silly), but once we decide on the set of patterns allowable in which
>> contexts, any pattern can be nested inside a deconstruction pattern.
>> 
>> The `var x` pattern can equally be thought of as inference for a total
>> type pattern, or an "any" pattern; they are semantically equivalent.
>> 
>> If you're asking "but why can I not mix them in a lambda", the answer
>> is: because we don't support partial inference in lambdas at this time.
>> We could, and we might someday.  (If you're suggesting that the
>> consistency between the two superficially-related forms is the most
>> important consideration here, I would disagree.)
> 
> 
> with a record, there is no real inference, but when you will have several 
> deconstructors, we will need inference, right ?
> 

That’s exactly it! We just want to make sure we don’t bake something in that 
won’t work for more general overloaded deconstructors.

Gavin



[sealed] Draft Language Spec available

2020-02-28 Thread Gavin Bierman
The next draft language spec for JEP 360 (Sealed Types) is available at:

http://cr.openjdk.java.net/~gbierman/jep360/latest/

This version reflects the changes to the type system I mentioned [1], along 
with a number of other changes. We’d appreciate further comments on this in 
particular (along with anything else). 

Thanks,
Gavin

[1] 
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-February/002018.html

Re: Pattern Matching for instanceof (Preview 2)

2020-02-18 Thread Gavin Bierman



> On 18 Feb 2020, at 15:04, fo...@univ-mlv.fr wrote:
> 
> Hi Gavin,
> 
> - Mail original -
>> De: "Gavin Bierman" 
>> À: "Remi Forax" 
>> Cc: "jan lahoda" , "amber-spec-experts" 
>> 
>> Envoyé: Mardi 18 Février 2020 15:32:12
>> Objet: Re: Pattern Matching for instanceof (Preview 2)
> 
>> 
>>> - must the identifier of a pattern argument be the same name as the
>>> corresponding record component ?
>>> To be coherent with the fact that constructors requires the same names.
>> 
>> Absolutely not! Note this does mean that you can write confusing code:
>> 
>> record Point(int x, int y) { }
>> 
>> if (o instanceof Point(var y, var x)) {
>> … // y refers to x component, y refers to x component
>> }
>> 
>> (I’ll get my coat…)
> 
> yes, that's why i ask, it leads to very confusing code, some languages don't 
> allow this kind of code,
> by example destructuring in JavaScript as a special syntax if you want to use 
> different names.

I appreciate this, but requiring you to use the record component name is not 
very friendly if you have repeated nested patterns, e.g.

if (o instanceof Line(Point(int x, int y), Point(int x, int y))) // Error two 
occurrences of x and y!
{ …}

The only way around that would be to have explicit renaming operators, which is 
pretty ugly. 

Gavin

[sealed] Changes to type system

2020-02-18 Thread Gavin Bierman
Dear Experts:

One aspect of sealed types that we have not discussed before, is that it
suggests a change in the type system.

This change regards conversions used in casting contexts. For example, in Java
right now:

   interface I {}
   class C {} // does not implement I

   void test (C c) {
   if (c instanceof I) 
   System.out.println("It's an I");
   }

This compiles even though it is *currently* not possible for a C object to
implement the interface I. Of course, it might be, for example:

   class B extends C implements I {}

   test(new B()); 
   // Prints "It's an I"

So, the conversion rules capture "open extensibility"; i.e. the Java type system
does not assume a closed world, classes and interfaces could be extended, and
casting conversions compile to runtime tests, so we can safely be flexible.

However, at the other end of the spectrum the conversion rules do address
the case where a class can *not* be extended, i.e. when it is a *final* class.

   final class C {}

   void test (C c) {
   if (c instanceof I) 
   System.out.println("It's an I");
   }

The method test fails to compile, as the compiler knows that there can be no
subclass of C, so as C does not implement I then it is never possible for a C
value to implement I. This is a compile-time error.

But what about if C is not final, but *sealed*? Given that its direct subclasses
are explicitly enumerated, and - by the definition of being sealed - in the same
module, we would surely expect the compiler to look to see if it can spot a
similar compile-time error. Consider the following code: 

   interface I {}
   sealed class C permits D {}
   final class D extends C {}
   
   void test (C c) {
   if (c instanceof I) 
   System.out.println("It's an I");
   }

Class C does not implement I, and is not final - so by the old rules we might
conclude that there is a conversion - but it is sealed. There is one permitted
direct subclass of C: D. By definition of sealed types, D must be either final,
sealed or non-sealed. In this example, all the direct subclasses of C are final
and do not implement I, so in fact we can safely reject this program, as there
cannot be a subtype of C that implements I. 

In contrast, consider a similar program where one of the direct subclasses of
the sealed class is non-sealed:

   interface I {}
   sealed class C permits D, E {}
   non-sealed class D extends C {}
   final class E extends C {}

   void test (C c) {
   if (c instanceof I) 
   System.out.println("It's an I");
   }

This is type correct as it is possible for a subtype of the non-sealed type D to
implement I.

The trick is to extend the notion of allowed narrowing reference conversion (JLS
5.1.6.1) to follow the sealed type declarations. I'll spare you the gory details
in this email - they will appear in the JLS draft appearing soon (!) - but I
wanted to check that this extension to the type system seems reasonable.
Obviously it will be putting more strain on the type checker. Is everyone happy
with this extension?

Thanks,
Gavin


PS: Some further examples for your amusement:

Example 1:
--

non-sealed interface I {}
non-sealed interface J {}

I i;
if (i instanceof J) {} // Yes!

Example 2:
--

sealed interface I permits C {}
final class C implements I {}
non-sealed interface J {}

I i;
if (i instanceof J) {} // Error, only instance of I is C
   // Which doesn’t implement J

Example 3:
--

non-sealed interface I {}
sealed interface J permits C {}
final class C implements J {}

I i;
if (i instanceof J) {} // Error, only instance of J is C
   // which doesn’t implement I

Example 4:
--

sealed interface I permits A {}
sealed interface J permits B {}
final class A implements I {}
final class B implements J {}

I i;
if (i instanceof J) {} // Error, similar to above


Example 5:
--

non-sealed class C {}
non-sealed interface I {}

C c;
if (c instanceof I) {} // Yes!

Example 6:
--

non-sealed class C {} 
sealed interface I permits A {}
final class A implements I {}

C c;
if (c instanceof I) {} // Error

Example 7:
--

final class C {}
non-sealed interface I {}

C c;
if (c instanceof I) {} // Error

Example 8:
--

final class C {}
sealed interface I permits D {}
final class D implements I {}

C c;
if (c instanceof I) {} // Error

Example 9:
--

sealed class C permits D {}
final class D extends C {}
non-sealed interface I {}

C c;
if (c instanceof I) {} // Error

Example 10:
---

sealed class C permits D {}
final class D {}
sealed interface I permits E {}
final class E {}

C c;
if (c instanceof I) {} // Error

Example 11:
---

non-sealed interface I {}
non-sealed class C {}

I i;
if (i instanceof C) {} // Yes!

Example 12:
---

non-sealed interface I {}
final class C {}

I i;
if (i instanceof C) {} // Error

Example 13:
---

non-sealed interface I {}
sealed class C perm

[records] Summary so far

2020-02-18 Thread Gavin Bierman
Dear Experts:

In [1] Brian asked for comments on some remaining design decisions concerning
records (and asked for any new ones that you'd like to raise). 

First, thank you for your feedback so far! I have been through the threads, and
tried to summarize the question and the current status below. Of course,
these decisions are not set in stone, but the point of this email is to warn you
that they are hardening :-) So, if you disagree, or would like further
discussion, *now* is the time to speak up!


Q1. Should the distinguished supertype of records java.lang.Record be
renamed?

[Since the original post, it seems that inline types will be able to inherit
from abstract classes.]

Is the name "Record" a good one? It has good clash
potential :-) possible alternatives are RecordClass, or AbstractRecord?

A: No consensus so far. 

Q2. Accessibilty of mandated members.

Currently the mandated members are public regardless of the accessibility of
the record type. What should be the default accessibility for record
members? 

A: Currently the most popular proposal is that mandated members get
accessibility of the record type. Other members get package level
accessibility as per a regular class. (Note: it should be legal for explicit
declarations of mandated members to specify something _more_ accessible
(same rules as overriding.) )

Q3. Nesting.

A: We are working on a new spec that removes a lot of restriction regarding
nested classes/records.

Q4. Abstract records.

Should we allow the declaration of abstract classes, possibly supporting
some form of record subtyping?

A: No support for this.

Q5. Deconstruction patterns.

A: We will be proposing deconstruction patterns in the patterns v2 preview.

Q6. @deprecated

Should we allow record components to be marked as @deprecated? 

A: We don't want to add any additional support for @deprecated beyond the
fact that it is an annotation and it can be inspected via reflection. 

Q7. .equals and .toString are slow.

Remi [2] points out that the current implementations of .equals and
.toString are slow.

A: We will look into this. 

Q8. Translation strategy.

John [3] suggested changing the compilation strategy of records so we can
future-proof the evolution of members from the record supertype. 

A: No change.

Q9. Hashing.

John [4] proposed weakening of the .hashCode spec.

A: Agreed. John has written candidate text [5].

Q10. Special annotation for explicit declaration of accessors. 

Tagir [6] proposes a new `@RecordAccessor` annotation to mark explicit
accessors, much as `@Override` is used to mark method overrides.

A: Rather than introduce a new accessor, we will consider extending the
meaning of the `@Override` annotation to include this case.

Q11. Changing the spec of .toString method

We should weaken the spec of the .toString method so it explicitly states
that the form of the string produced is subject to change and can not be
relied upon.

A: Agreed.

Q12. Transactional methods

Canonical constructors are an instance of a general pattern where a set of
variables are in scope for a given block, and assigned values at the end. 
This could be a useful abstraction to be given first-class representation. 

A: No change. More research needed. 

Q13. Factory methods instead of constructors.

Should "new R(v1, ..., vn)" be compiled to a factory method, to allow
future-proofing with inline types?

A: No change for now.

Thanks for your comments and discussions so far. If you disagree with anything
written here, please reply!

Thanks,
Gavin


[1] 
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-January/001913.html
[2] 
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-January/001943.html
[3] 
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-January/001937.html
[4] 
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-January/001935.html
[5] http://cr.openjdk.java.net/~jrose/draft/record-contract
[6] 
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-January/001931.html




Re: Pattern Matching for instanceof (Preview 2)

2020-02-18 Thread Gavin Bierman


> On 18 Feb 2020, at 15:04, fo...@univ-mlv.fr wrote:
> 
> Hi Gavin,
> 
> - Mail original -
>> De: "Gavin Bierman" 
>> À: "Remi Forax" 
>> Cc: "jan lahoda" , "amber-spec-experts" 
>> 
>> Envoyé: Mardi 18 Février 2020 15:32:12
>> Objet: Re: Pattern Matching for instanceof (Preview 2)
> 
>> [Just circling back to this, as I added a note about the grammar to the JEP
>> page…]
>> 
>>> On 6 Feb 2020, at 20:38, Remi Forax  wrote:
>>> 
>>> [moved to amber-spec]
>>> 
>>> - Mail original -
>>>> De: "jan lahoda" 
>>>> À: "amber-dev" 
>>>> Envoyé: Jeudi 6 Février 2020 21:18:52
>>>> Objet: Pattern Matching for instanceof (Preview 2)
>>> 
>>>> Hi,
>>>> 
>>>> Thanks to Gavin, Brian and Alex, there is a new draft JEP for Pattern
>>>> Matching for instanceof (Preview 2):
>>>> https://bugs.openjdk.java.net/browse/JDK-8235186
>>>> 
>>>> Any feedback on the JEP is more than welcome!
>>>> 
>>>> Thanks,
>>>>Jan
>>> 
>>> so the difference with the previous preview is that deconstruction is added.
>> 
>> That is correct.
>> 
>>> 
>>> I see two questions:
>>> - the grammar allows to mix var and non-var for a given reference type, i 
>>> think
>>> that should only permitted if the non var is a deconstruction itself ?
>> 
>> I don’t know what you mean here. There are two patterns, a type test pattern 
>> and
>> a deconstruction pattern. In v2 we propose to support deconstruction patterns
>> over record types *only*. A deconstruction pattern looks like this: Point(var
>> a, var b), i.e. all the components are either (recursively) deconstruction
>> patterns, or `var` , i.e. with no type needed. I added a note to
>> the JEP page pointing out that this is a starting point, and eventually we 
>> will
>> support other patterns in the argument position, specifically 
>> ; hopefully in this release.
> 
> Currently we don't support mixing var and non var in lambda parameters.
> So my question is: does this pattern Point(var x, int y) that mix a 'var' and 
> an explicit type allowed or not ?

Aha. So, we’re not at that stage yet - this isn’t allowed by the spec as it 
stands. This - and many other issues - is why I’m starting small…

Do you have a preference?

Gavin

Re: Pattern Matching for instanceof (Preview 2)

2020-02-18 Thread Gavin Bierman
[Just circling back to this, as I added a note about the grammar to the JEP 
page…]

> On 6 Feb 2020, at 20:38, Remi Forax  wrote:
> 
> [moved to amber-spec]
> 
> - Mail original -
>> De: "jan lahoda" 
>> À: "amber-dev" 
>> Envoyé: Jeudi 6 Février 2020 21:18:52
>> Objet: Pattern Matching for instanceof (Preview 2)
> 
>> Hi,
>> 
>> Thanks to Gavin, Brian and Alex, there is a new draft JEP for Pattern
>> Matching for instanceof (Preview 2):
>> https://bugs.openjdk.java.net/browse/JDK-8235186
>> 
>> Any feedback on the JEP is more than welcome!
>> 
>> Thanks,
>> Jan
> 
> so the difference with the previous preview is that deconstruction is added.

That is correct.

> 
> I see two questions:
> - the grammar allows to mix var and non-var for a given reference type, i 
> think that should only permitted if the non var is a deconstruction itself ?

I don’t know what you mean here. There are two patterns, a type test pattern 
and a deconstruction pattern. In v2 we propose to support deconstruction 
patterns over record types *only*. A deconstruction pattern looks like this: 
Point(var a, var b), i.e. all the components are either (recursively) 
deconstruction patterns, or `var` , i.e. with no type needed. I 
added a note to the JEP page pointing out that this is a starting point, and 
eventually we will support other patterns in the argument position, 
specifically  ; hopefully in this release.


> - must the identifier of a pattern argument be the same name as the 
> corresponding record component ?
>  To be coherent with the fact that constructors requires the same names.

Absolutely not! Note this does mean that you can write confusing code:

record Point(int x, int y) { }

if (o instanceof Point(var y, var x)) { 
… // y refers to x component, y refers to x component
}

(I’ll get my coat…)

Thanks,
Gavin

Re: [records] New draft spec for JEP 359

2020-01-20 Thread Gavin Bierman
As I mentioned in the original email, some fixes didn’t make it through the JDK 
14 process. So, on this particular issue, the compiler is correct, and the spec 
has a bug, which will be fixed in JDK 15. (I agree that it is a minor detail.)

Gavin

> On 17 Jan 2020, at 11:22, Tagir Valeev  wrote:
> 
> The spec from the previous e-mail [1] allows them, so either spec or
> javac should be updated (or we can ignore it, as this is a minor
> detail).
> 
> With best regards,
> Tagir Valeev.
> 
> [1] 
> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20200115/specs/records-jls.html
> 
> On Fri, Jan 17, 2020 at 5:02 PM Remi Forax  wrote:
>> 
>> - Mail original -
>>> De: "Tagir Valeev" 
>>> À: "Gavin Bierman" 
>>> Cc: "amber-spec-experts" 
>>> Envoyé: Vendredi 17 Janvier 2020 07:32:49
>>> Objet: Re: [records] New draft spec for JEP 359
>> 
>>> So it looks like the `final` modifier on record components is allowed
>>> in 14-preview?
>> 
>> javac using the latest beta of jdk 14 rejects them.
>> so i hope the spec also reject them.
>> 
>>> 
>>> With best regards,
>>> Tagir Valeev.
>> 
>> Rémi
>> 
>>> 
>>> On Thu, Jan 16, 2020 at 10:41 PM Gavin Bierman  
>>> wrote:
>>>> 
>>>> Dear spec-experts,
>>>> 
>>>> I need to make a clarification regarding the earlier email. Since we are so
>>>> close to entering RDP2, it wasn’t possible to get all these changes to the 
>>>> spec
>>>> (and their corresponding compiler patches) into JDK 14. They will have to 
>>>> wait
>>>> until the second preview of records in JDK 15; along with whatever we 
>>>> decide
>>>> regarding the issues that Brian has raised in a recent email:
>>>> https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-January/001913.html
>>>> 
>>>> The records spec for JDK 14 that was approved by the CSR (JDK-8236189) is
>>>> available at:
>>>> 
>>>> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20200115/specs/records-jls.html
>>>> 
>>>> It contains only two of the items listed in my earlier email, viz
>>>> 
>>>> * Forbids capture of local variables in a local record
>>>> * Adding missing annotation target PARAMETER (this was already implemented 
>>>> in
>>>> the compiler, so just a typo in the spec)
>>>> 
>>>> Just to repeat, the others - along with aligning the use of variable arity 
>>>> in
>>>> the record component header and the canonical constructor
>>>> (http://mail.openjdk.java.net/pipermail/amber-spec-experts/2019-December/001885.html)
>>>> - will be dealt with in the second preview of Records in JDK 15.
>>>> 
>>>> Thanks,
>>>> Gavin
>>>> 
>>>> On 10 Jan 2020, at 13:31, Gavin Bierman  wrote:
>>>> 
>>>> Happy new year everyone! An updated version of the records spec is 
>>>> available at:
>>>> 
>>>> http://cr.openjdk.java.net/~gbierman/jep359/latest
>>>> 
>>>> (which currently points to
>>>> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20200110/specs/records-jls.html)
>>>> 
>>>> This addresses:
>>>> 
>>>> * Removes `final` modifier on record components
>>>> * Adding missing annotation target PARAMETER
>>>> * Corrects discussion of @SafeVarargs annotation
>>>> * Forbids capture of local variables in a local record
>>>> * Clarifies implicit formal parameter list in a compact constructor
>>>> 
>>>> Gavin
>>>> 
>>>> 
>>>> 



Re: [records] New draft spec for JEP 359

2020-01-16 Thread Gavin Bierman
Dear spec-experts,

I need to make a clarification regarding the earlier email. Since we are so 
close to entering RDP2, it wasn’t possible to get all these changes to the spec 
(and their corresponding compiler patches) into JDK 14. They will have to wait 
until the second preview of records in JDK 15; along with whatever we decide 
regarding the issues that Brian has raised in a recent email: 
https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-January/001913.html
 
<https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-January/001913.html>
 

The records spec for JDK 14 that was approved by the CSR (JDK-8236189) is 
available at:

http://cr.openjdk.java.net/~gbierman/jep359/jep359-20200115/specs/records-jls.html
 <http://cr.openjdk.java.net/~gbierman/jep359/latest> 

It contains only two of the items listed in my earlier email, viz

* Forbids capture of local variables in a local record 
* Adding missing annotation target PARAMETER (this was already implemented in 
the compiler, so just a typo in the spec)

Just to repeat, the others - along with aligning the use of variable arity in 
the record component header and the canonical constructor 
(http://mail.openjdk.java.net/pipermail/amber-spec-experts/2019-December/001885.html)
 - will be dealt with in the second preview of Records in JDK 15.

Thanks,
Gavin

> On 10 Jan 2020, at 13:31, Gavin Bierman  wrote:
> 
> Happy new year everyone! An updated version of the records spec is available 
> at:
> 
> http://cr.openjdk.java.net/~gbierman/jep359/latest
> 
> (which currently points to 
> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20200110/specs/records-jls.html)
> 
> This addresses:
> 
> * Removes `final` modifier on record components
> * Adding missing annotation target PARAMETER 
> * Corrects discussion of @SafeVarargs annotation
> * Forbids capture of local variables in a local record
> * Clarifies implicit formal parameter list in a compact constructor
> 
> Gavin
> 
> 
> 



Re: [records] SafeVarargs and canonical constructors

2020-01-10 Thread Gavin Bierman
Spec now updated as per this suggestion 
(http://cr.openjdk.java.net/~gbierman/jep359/latest)

> On 29 Dec 2019, at 19:15, Remi Forax  wrote:
> 
> Yes, i agree.
> 
> Rémi
> 
> De: "Brian Goetz" 
> À: "Tagir Valeev" , "amber-spec-experts" 
> 
> Envoyé: Dimanche 29 Décembre 2019 18:35:08
> Objet: Re: [records] SafeVarargs and canonical constructors
> This seems a very practical place to land here.
> 
> On 12/29/2019 12:32 PM, Tagir Valeev wrote:
> I have a proposal on how to solve SafeVarargs problem:
> 
> 1. Do not allow annotating record type with SafeVarargs
> 2. If the record type has explicit canonical/compact constructor, the
> heap pollution warning should be issued on the constructor, rather
> than on record header declaration
> 3. If explicit canonical/compact constructor is annotated with
> SafeVarargs, no warning should be issued.
> 
> So if one has a record declaration with potential heap pollution, and
> want to declare that varargs are safe, they must explicitly add an
> empty compact constructor and annotate it with SafeVarargs. Given that
> this case should be extremely rare in practice, such an amount of
> boilerplate doesn't look too big to me. On the other hand, such
> solution requires less changes in Java (e.g. no need to allow
> SafeVarargs on types).
> 
> What do you think?
> 
> With best regards,
> Tagir Valeev.
> 
> On Sat, Dec 28, 2019 at 1:10 PM Tagir Valeev  
>  wrote:
> Hello!
> 
> More questions about SafeVarargs:
> 
> 1. If we have a compact constructor declared, should the warning be
> issued at record header or at compact constructor declaration? To
> suppress the warning should I annotate a record type or compact
> constructor?
> 
> 2. The same if explicit canonical constructor is declared.
> 
> To me, it seems logical to put SafeVarargs at record type if compact
> constructor is present (because the variable arity parameter is not
> explicitly written in constructor declaration). However, if explicit
> canonical constructor is declared, it seems better to require
> SafeVarargs at constructor declaration, rather than a record
> declaration. Or place it in either place (but not at both).
> 
> What do you think?
> 
> With best regards,
> Tagir Valeev.
> 
> 



Re: Record component annotations with target=PARAMETER

2020-01-10 Thread Gavin Bierman
Now updated. (http://cr.openjdk.java.net/~gbierman/jep359/latest)

> On 19 Dec 2019, at 10:45, Gavin Bierman  wrote:
> 
> Well spotted Tagir. Updated spec on its way...
> 
>> On 17 Dec 2019, at 14:29, Vicente Romero  wrote:
>> 
>> Hi Tagir,
>> 
>> Yes the spec should be updated, you are correct that `parameter` should be 
>> added here,
>> 
>> Thanks,
>> Vicente
>> 
>> On 12/17/19 5:10 AM, Tagir Valeev wrote:
>>> Hello!
>>> 
>>> Current records JLS spec draft [1] says:
>>> 
>>> a record component but T is not applicable to record component
>>> declarations, field declarations, method declarations, or type
>>> contexts.
>>> 
>>> However, javac doesn't fail if the annotation target is parameter:
>>> 
>>> import java.lang.annotation.*;
>>> 
>>> record Foo(@Anno int x) {}
>>> @Target(ElementType.PARAMETER)
>>> @interface Anno {}
>>> 
>>> This code compiles and the canonical constructor is annotated with
>>> Anno. To me, the javac behavior is expected and spec should be updated
>>> to include "parameters":
>>> 
>>> a record component but T is not applicable to record component
>>> declarations, field declarations, method declarations, parameters, or
>>> type contexts.
>>> 
>>> What do you think? I'm implementing error highlighting for records in
>>> IntelliJ now. Should I follow the spec or javac behavior?
>>> 
>>> With best regards,
>>> Tagir Valeev.
>>> 
>>> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191125/specs/records-jls.html#jls-9.7.4
>> 
> 



[records] New draft spec for JEP 359

2020-01-10 Thread Gavin Bierman
Happy new year everyone! An updated version of the records spec is available at:

http://cr.openjdk.java.net/~gbierman/jep359/latest

(which currently points to 
http://cr.openjdk.java.net/~gbierman/jep359/jep359-20200110/specs/records-jls.html)

This addresses:

* Removes `final` modifier on record components
* Adding missing annotation target PARAMETER 
* Corrects discussion of @SafeVarargs annotation
* Forbids capture of local variables in a local record
* Clarifies implicit formal parameter list in a compact constructor

Gavin





Re: Record component annotations with target=PARAMETER

2019-12-19 Thread Gavin Bierman
Well spotted Tagir. Updated spec on its way...

> On 17 Dec 2019, at 14:29, Vicente Romero  wrote:
> 
> Hi Tagir,
> 
> Yes the spec should be updated, you are correct that `parameter` should be 
> added here,
> 
> Thanks,
> Vicente
> 
> On 12/17/19 5:10 AM, Tagir Valeev wrote:
>> Hello!
>> 
>> Current records JLS spec draft [1] says:
>> 
>> a record component but T is not applicable to record component
>> declarations, field declarations, method declarations, or type
>> contexts.
>> 
>> However, javac doesn't fail if the annotation target is parameter:
>> 
>> import java.lang.annotation.*;
>> 
>> record Foo(@Anno int x) {}
>> @Target(ElementType.PARAMETER)
>> @interface Anno {}
>> 
>> This code compiles and the canonical constructor is annotated with
>> Anno. To me, the javac behavior is expected and spec should be updated
>> to include "parameters":
>> 
>> a record component but T is not applicable to record component
>> declarations, field declarations, method declarations, parameters, or
>> type contexts.
>> 
>> What do you think? I'm implementing error highlighting for records in
>> IntelliJ now. Should I follow the spec or javac behavior?
>> 
>> With best regards,
>> Tagir Valeev.
>> 
>> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191125/specs/records-jls.html#jls-9.7.4
> 



Re: Updated Draft specs for JEP 359 (Records)

2019-12-03 Thread Gavin Bierman
I have made a further change to the online version. 

There was a missing case in 8.10.3, as it should be required that an explicitly 
declared accessor method is not static.

Gavin

gbierman$ hg diff -c 30704:012cc50cb363
diff -r 9f5a21334115 -r 012cc50cb363 
closed/src/java.se/share/specs/records-jls.md
--- a/closed/src/java.se/share/specs/records-jls.md Thu Nov 28 14:06:43 
2019 +
+++ b/closed/src/java.se/share/specs/records-jls.md Tue Dec 03 11:27:03 
2019 +
@@ -2433,6 +2433,8 @@
 
   - The accessor method must be declared `public`
 
+  - The accessor method must not be declared `static`
+
   - The accessor method must not have a `throws` clause
 
   - All other rules for a method in a normal class declaration must be


> On 26 Nov 2019, at 14:17, Gavin Bierman  wrote:
> 
> Thanks Alex; have made these changes to the online version.
> 
> Gavin
> 
>> On 26 Nov 2019, at 02:23, Alex Buckley  wrote:
>> 
>> // Cutting amber-dev
>> 
>> On 11/25/2019 3:23 PM, Gavin Bierman wrote:
>>> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191125/specs/records-jls.html
>> 
>> The JLS draft is good. Some technical rewordings:
>> 
>> 1. 8.10.3: "and the type as the declared type" -- missing a "same"
>> 
>> 2. 8.10.3: Say "This field is annotated with the annotations, if any, that 
>> appear on the corresponding record component and whose annotation types are 
>> applicable in the field declaration context or in type contexts or both."  
>> (Later, for implicitly declared accessor methods, the phrase "whose 
>> annotation type is" should be "whose annotation types are". We do not 
>> constrain all the annotations to have the same annotation type, nor all the 
>> annotation types to be applicable in the same way. You could introduce an 
>> existential qualifier if you like -- "For each annotation A that appears on 
>> the corresponding ..." -- but I don't think it's necessary.)
>> 
>> 3. 8.10.3: "A method ***declared*** in a record type R is said to be an 
>> accessor method" -- this raises questions of "explicitly or implicitly". 
>> It's too easy to think it means "explicitly" when that's not always true. 
>> Sidestep the problem by speaking more directly: "In a record type R, an 
>> _accessor method for a record component_ is a method whose name is the same 
>> as the name of the record component, and whose formal parameter list is 
>> empty." Then some refactoring because long list items are hard to follow:
>> 
>> -
>> For each record component appearing in the record component list:
>> 1. An implicitly declared private final field ...
>> 2. An accessor method for the record component. [THAT'S IT. DON'T RULE ON 
>> THE FORM OF EXPLICITLY DECLARED METHODS HERE. JUST MAKE SURE ALL THE METHODS 
>> EXIST:]
>> 
>>  If an accessor method for the record component is not explicitly declared, 
>> then one is implicitly declared with the following properties:
>>  - The name is the same as ...
>>  - ...
>> 
>>  It is a compile-time error if the implicitly declared accessor method is 
>> override-equivalent (8.4.2) with a non-private method of the class Object. 
>> [THIS PARAGRAPH IS TROUBLE. PLEASE MAKE AN EXPLICIT RULE IN 8.10.1 THAT 
>> SPELLS OUT IN CLEAR NORMATIVE TEXT THAT A RECORD COMPONENT MUST NOT HAVE BE 
>> CALLED CLONE, FINALIZE, ETC. RELYING ON A SUBTLE RULE IN A DIFFERENT SECTION 
>> ABOUT IMPLICITLY DECLARED STUFF IS *TOO HARD*. IT SUGGESTS THAT THE COMPILER 
>> SHOULD POSITION THE CARET FOR THE ERROR AT SOME POINT IN THE RECORD'S BODY, 
>> WHERE THE IMP.DECL. METHOD WOULD LIVE, RATHER THAN IN THE RECORD'S HEADER.]
>> 
>> [ITEM 2 ENDS HERE. NON-LIST TEXT FOLLOWS.]
>> 
>> If an accessor method for a record component is declared explicitly, then it 
>> must satisfy the following rules, or else a compile-time error occurs:
>> - The return type of the accessor method ...
>> - ...
>> 
>> [THE FOLLOWING PARAGRAPH IS DISTINCTLY SURE -- "IS NOT ANNOTATED" -- THAT AN 
>> EXPLICIT METHOD HAS NO ANNOTATIONS LIKE THE ONES ON THE RECORD COMPONENT. 
>> WHAT IF THE DEVELOPER WRITES ANNOTATIONS EXPLICITLY? PLEASE CHANGE THE 
>> PARAGRAPH TO AN INFORMATIVE NOTE WHERE YOU CAN SAY: ANNOTATIONS THAT APPEAR 
>> ON THE CORRESPONDING RECORD COMPONENTS ARE NOT CARRIED OVER TO EXPLICITLY 
>> DECLARED ACCESSOR METHODS, IN CONTRAST TO HOW IMPLICITLY DECLARED ACCESSOR 
>> METHODS ARE ANNOTATED ACCORDING TO BLAH BLAH.]
>> An explicitly declared accessor method is

Re: Pattern variable and field shadowing

2019-12-03 Thread Gavin Bierman



> On 2 Dec 2019, at 22:59, Remi Forax  wrote:
> 
> - Mail original -
>> De: "Gavin Bierman" 
>> À: "Tagir Valeev" 
>> Cc: "amber-spec-experts" 
>> Envoyé: Lundi 2 Décembre 2019 13:18:43
>> Objet: Re: Pattern variable and field shadowing
> 
>> Hi Tagir,
>> 
>> No, that’s very much the expected behaviour. The idea of flow scoping is 
>> that a
>> pattern variable is only *in scope* where it has definitely matched. Thus, in
>> places where it is definitely not matched - like your else block - it is not 
>> in
>> scope. Thus it doesn’t exist. Thus if there is field with that name, then 
>> that
>> is the meaning of the name.
>> 
>> We looked long and hard at exactly this example; as Brian mentioned, it is
>> called the “Swiss cheese” problem in the team! The problem is that not doing
>> this also comes at a heavy cost. For example, we could say that the variable
>> str in your example is in scope but not DA, for example. But that means that
>> using a pattern variable poisons it forever more in the statement/block. This
>> forbids very, very common code like:
>> 
>> if (a instanceof Point p) {
>> …
>> } else {
>>   if (b instanceof Point p) { // Can’t use p even though it won’t be bound
>>   …
>>   }
>> }
>> 
>> In other words, you’ll have to find a new pattern variable everytime. [And 
>> this
>> gets even worse in switch.] That’s a real pain, and I think most people will
>> say “why do I have to find a new name, can’t you figure it out?”. Yes, we
>> could, but then we’d have to do something even more special case, like 
>> allowing
>> shadowing of pattern variables with pattern variables. But we’re now
>> unravelling all sorts of aspects of the way Java deals with naming, and that
>> feels like something that most users will never have in their heads. We’re
>> hoping the “only in scope where it is matched” is a simpler rule that is 
>> easier
>> to internalize.
>> 
>> That’s not to say that there couldn’t be tooling to provide warnings in the 
>> case
>> where pattern variables shadow fields (as it inevitably means that there will
>> be some holes in the cheese), hint hint :-)
> 
> why not javac being "the tooling" ?
> I think it will be useful for our users if javac emit such warning (if the 
> linter is activated).

Noted :-)

Gavin




Re: Pattern variable and field shadowing

2019-12-02 Thread Gavin Bierman
Hi Tagir, 

No, that’s very much the expected behaviour. The idea of flow scoping is that a 
pattern variable is only *in scope* where it has definitely matched. Thus, in 
places where it is definitely not matched - like your else block - it is not in 
scope. Thus it doesn’t exist. Thus if there is field with that name, then that 
is the meaning of the name.

We looked long and hard at exactly this example; as Brian mentioned, it is 
called the “Swiss cheese” problem in the team! The problem is that not doing 
this also comes at a heavy cost. For example, we could say that the variable 
str in your example is in scope but not DA, for example. But that means that 
using a pattern variable poisons it forever more in the statement/block. This 
forbids very, very common code like:

if (a instanceof Point p) {
…
} else {
if (b instanceof Point p) { // Can’t use p even though it won’t be bound
…
} 
}

In other words, you’ll have to find a new pattern variable everytime. [And this 
gets even worse in switch.] That’s a real pain, and I think most people will 
say “why do I have to find a new name, can’t you figure it out?”. Yes, we 
could, but then we’d have to do something even more special case, like allowing 
shadowing of pattern variables with pattern variables. But we’re now 
unravelling all sorts of aspects of the way Java deals with naming, and that 
feels like something that most users will never have in their heads. We’re 
hoping the “only in scope where it is matched” is a simpler rule that is easier 
to internalize.

That’s not to say that there couldn’t be tooling to provide warnings in the 
case where pattern variables shadow fields (as it inevitably means that there 
will be some holes in the cheese), hint hint :-)

But please use the preview feature and let us know how you get along so we can 
assess this design decision.

Thanks,
Gavin


> On 28 Nov 2019, at 03:39, Tagir Valeev  wrote:
> 
> Hello!
> 
> Consider the following code:
> 
> public class A {
>private String str;
> 
>public void f(Object obj) {
>if (obj instanceof String str) {
>System.out.println(str.toLowerCase()); // str refers to
> pattern binding
>} else {
>System.out.println(str.toLowerCase()); // str refers to the field
>}
>}
> }
> 
> I thought that such a code should be rejected by the compiler, as it's
> confusing and could be a source of very subtle bugs. However, I
> haven't found any explicit statement regarding this in the latest spec
> draft [1]. Could you please clarify whether such code is acceptable
> and point me to the relevant part of the spec draft. Thank you!
> 
> With best regards,
> Tagir Valeev.
> 
> [1] 
> http://cr.openjdk.java.net/~gbierman/jep305/jep305-20191021/specs/patterns-instanceof-jls.html



Re: Updated Draft specs for JEP 359 (Records)

2019-11-27 Thread Gavin Bierman



> On 26 Nov 2019, at 19:28, Alex Buckley  wrote:
> 
> 
> On 11/26/2019 8:48 AM, Dan Smith wrote:
>> Here's my slightly-tweaked version of this note:
>>> It is a limitation of the `class` file that, while a method parameter or a
>>> module may be marked `ACC_MANDATED` ([4.7.24], [4.7.25]), there is no
>>> equivalent way to flag compiler-generated methods and fields which are not
>>> considered implementation artifacts (JLS 13.1).
>>> This limitation means that reflective APIs may not accurately indicate the
>>> mandated status of such members.
> 
> Thanks. (I note the change from "oversight in the design of" to "limitation 
> of" :-) )
> 
> I don't see any changes to 
> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191125/specs/records-jvms.html
>  ?

Should be there now.

Thanks,
Gavin



Re: Updated Draft specs for JEP 359 (Records)

2019-11-26 Thread Gavin Bierman
Thanks Alex; have made these changes to the online version.

Gavin

> On 26 Nov 2019, at 02:23, Alex Buckley  wrote:
> 
> // Cutting amber-dev
> 
> On 11/25/2019 3:23 PM, Gavin Bierman wrote:
>> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191125/specs/records-jls.html
> 
> The JLS draft is good. Some technical rewordings:
> 
> 1. 8.10.3: "and the type as the declared type" -- missing a "same"
> 
> 2. 8.10.3: Say "This field is annotated with the annotations, if any, that 
> appear on the corresponding record component and whose annotation types are 
> applicable in the field declaration context or in type contexts or both."  
> (Later, for implicitly declared accessor methods, the phrase "whose 
> annotation type is" should be "whose annotation types are". We do not 
> constrain all the annotations to have the same annotation type, nor all the 
> annotation types to be applicable in the same way. You could introduce an 
> existential qualifier if you like -- "For each annotation A that appears on 
> the corresponding ..." -- but I don't think it's necessary.)
> 
> 3. 8.10.3: "A method ***declared*** in a record type R is said to be an 
> accessor method" -- this raises questions of "explicitly or implicitly". It's 
> too easy to think it means "explicitly" when that's not always true. Sidestep 
> the problem by speaking more directly: "In a record type R, an _accessor 
> method for a record component_ is a method whose name is the same as the name 
> of the record component, and whose formal parameter list is empty." Then some 
> refactoring because long list items are hard to follow:
> 
> -
> For each record component appearing in the record component list:
> 1. An implicitly declared private final field ...
> 2. An accessor method for the record component. [THAT'S IT. DON'T RULE ON THE 
> FORM OF EXPLICITLY DECLARED METHODS HERE. JUST MAKE SURE ALL THE METHODS 
> EXIST:]
> 
>   If an accessor method for the record component is not explicitly declared, 
> then one is implicitly declared with the following properties:
>   - The name is the same as ...
>   - ...
> 
>   It is a compile-time error if the implicitly declared accessor method is 
> override-equivalent (8.4.2) with a non-private method of the class Object. 
> [THIS PARAGRAPH IS TROUBLE. PLEASE MAKE AN EXPLICIT RULE IN 8.10.1 THAT 
> SPELLS OUT IN CLEAR NORMATIVE TEXT THAT A RECORD COMPONENT MUST NOT HAVE BE 
> CALLED CLONE, FINALIZE, ETC. RELYING ON A SUBTLE RULE IN A DIFFERENT SECTION 
> ABOUT IMPLICITLY DECLARED STUFF IS *TOO HARD*. IT SUGGESTS THAT THE COMPILER 
> SHOULD POSITION THE CARET FOR THE ERROR AT SOME POINT IN THE RECORD'S BODY, 
> WHERE THE IMP.DECL. METHOD WOULD LIVE, RATHER THAN IN THE RECORD'S HEADER.]
> 
> [ITEM 2 ENDS HERE. NON-LIST TEXT FOLLOWS.]
> 
> If an accessor method for a record component is declared explicitly, then it 
> must satisfy the following rules, or else a compile-time error occurs:
> - The return type of the accessor method ...
> - ...
> 
> [THE FOLLOWING PARAGRAPH IS DISTINCTLY SURE -- "IS NOT ANNOTATED" -- THAT AN 
> EXPLICIT METHOD HAS NO ANNOTATIONS LIKE THE ONES ON THE RECORD COMPONENT. 
> WHAT IF THE DEVELOPER WRITES ANNOTATIONS EXPLICITLY? PLEASE CHANGE THE 
> PARAGRAPH TO AN INFORMATIVE NOTE WHERE YOU CAN SAY: ANNOTATIONS THAT APPEAR 
> ON THE CORRESPONDING RECORD COMPONENTS ARE NOT CARRIED OVER TO EXPLICITLY 
> DECLARED ACCESSOR METHODS, IN CONTRAST TO HOW IMPLICITLY DECLARED ACCESSOR 
> METHODS ARE ANNOTATED ACCORDING TO BLAH BLAH.]
> An explicitly declared accessor method is not annotated with any applicable 
> annotation that appears on the corresponding record component.
> -
> 
> 4. 8.10.4: It's odd to see in "derived constructor signature" that a ctor has 
> a name R, since 8.8 doesn't admit to a ctor having a name. That said, 8.8.2 
> speaks of "two constructors with override-equivalent signatures (§8.4.2) in a 
> class", and the definition of override equivalent implies a name is present, 
> so I'll set my concern aside. Just a minor rewording for flow -- push 
> derivation of formal parameter list down one level, as it's not used by 
> anything else (OK, one place, but I'll get to that) :
> 
> -
> To support proper ... corresponding to the record components.
> 
> A record type R has a derived constructor signature with the name R, with no 
> type parameters, and with a formal parameter list that is derived from the 
> record component list of R as follows:
> 
> - For each record component ...
> -
> 
> 8.10.5: C

Re: Updated Draft specs for JEP 359 (Records)

2019-11-25 Thread Gavin Bierman
A further updated draft language spec for JEP 359 (Records) is available at:

http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191125/specs/records-jls.html

along with an updated JVMS spec:

http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191125/specs/records-jvms.html

(Thanks to Maurizio, Alex, Tagir and others for feedback.)

Main change is around the definition of canonical constructor and accessor 
methods. The text has changed quite a bit, but this is mainly at the surface. 
Hopefully this new definition is easier to understand than before and removes 
some corner cases (most of which were of the “which error should arise from 
this program?”).

The idea for canonical constructors is as follows (it’s very similar for 
accessor methods): You are a constructor. If your signature is 
override-equivalent to the constructor signature derived from the record 
declaration in the obvious way, then you are considered a canonical 
constructor. (This also means that there can’t be more than one canonical 
constructor.) In addition, as you have been identified as a canonical 
constructor, you must satisfy some additional requirements, otherwise there is 
a compile-time error. These are:
The types of the formal parameters in the formal parameter list of the 
canonical constructor must be identical to the declared type of the 
corresponding record component.
A canonical constructor must not be generic (8.8.4).
A canonical constructor must be declared public.
A canonical constructor must not have a throws clause.
The body of a canonical constructor must not contain an explicit constructor 
invocation statement (8.8.7.1).
All the other rules for a constructor in a normal class declaration must be 
satisfied (8.8).
We could relax some of these rules - I know Remi would like to change the third 
one :-) The first one is another candidate. I propose that we try these ones 
out in the preview, and during the preview period you can send us your 
experience kicking the tires with these. [One reason for this refactoring is 
that should we decide to relax some of these restrictions, it is a relatively 
simple change to the spec, which will make our lives easier for subsequent 
JDKs.]

Many thanks,
Gavin



> On 21 Nov 2019, at 15:01, Gavin Bierman  wrote:
> 
> A hopefully final draft language spec for JEP 359 (Records) is available at:
> 
> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191121/specs/records-jls.html
>  
> <http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191121/specs/records-jls.html>
>   
> 
> This incorporates (I hope!) all the very helpful suggestions from everyone on 
> these lists - many thanks. 
> 
> As always - any further comments/thoughts/bugs most welcome!
> 
> Gavin
> 
>> On 31 Oct 2019, at 14:17, Gavin Bierman > <mailto:gavin.bier...@oracle.com>> wrote:
>> 
>> An updated draft language spec for JEP 359 (Records) is available at:
>> 
>> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jls.html
>>  
>> <http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jls.html>
>> 
>> (Alongside is a draft JVM spec for this feature:
>> 
>> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jvms.html
>>  
>> <http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jvms.html>
>> 
>> )
>> 
>> As always, please email me any comments/thoughts/bugs.
>> 
>> Thanks,
>> Gavin
>> 
>> 
>>> On 23 Aug 2019, at 22:25, Gavin Bierman >> <mailto:gavin.bier...@oracle.com>> wrote:
>>> 
>>> A draft language spec for records is available at:
>>> 
>>> http://cr.openjdk.java.net/~gbierman/8222777/8222777-20190823/specs/records-jls.html
>>>  
>>> <http://cr.openjdk.java.net/~gbierman/8222777/8222777-20190823/specs/records-jls.html>
>>> 
>>> This spec doesn’t yet discuss varargs records - to appear in the next draft.
>>> 
>>> All comments welcomed!
>>> 
>>> Thanks,
>>> Gavin
>> 
> 



Re: Updated Draft specs for JEP 359 (Records)

2019-11-21 Thread Gavin Bierman
A hopefully final draft language spec for JEP 359 (Records) is available at:

http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191121/specs/records-jls.html
  

This incorporates (I hope!) all the very helpful suggestions from everyone on 
these lists - many thanks. 

As always - any further comments/thoughts/bugs most welcome!

Gavin

> On 31 Oct 2019, at 14:17, Gavin Bierman  wrote:
> 
> An updated draft language spec for JEP 359 (Records) is available at:
> 
> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jls.html
>  
> <http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jls.html>
> 
> (Alongside is a draft JVM spec for this feature:
> 
> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jvms.html
>  
> <http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jvms.html>
> 
> )
> 
> As always, please email me any comments/thoughts/bugs.
> 
> Thanks,
> Gavin
> 
> 
>> On 23 Aug 2019, at 22:25, Gavin Bierman > <mailto:gavin.bier...@oracle.com>> wrote:
>> 
>> A draft language spec for records is available at:
>> 
>> http://cr.openjdk.java.net/~gbierman/8222777/8222777-20190823/specs/records-jls.html
>>  
>> <http://cr.openjdk.java.net/~gbierman/8222777/8222777-20190823/specs/records-jls.html>
>> 
>> This spec doesn’t yet discuss varargs records - to appear in the next draft.
>> 
>> All comments welcomed!
>> 
>> Thanks,
>> Gavin
> 



Re: Updated Draft specs for JEP 359 (Records)

2019-11-15 Thread Gavin Bierman
Thanks Maurizio

> On 31 Oct 2019, at 14:29, Maurizio Cimadamore 
>  wrote:
> 
> Related to the earlier discussion on forbidden record members - how is this 
> section still relevant?
> 
> "It is a compile-time error for a record declaration to declare a record 
> component with the name clone, finalize, getClass, hashCode, notify, 
> notifyAll, readObjectNoData, readResolve, serialPersistentFields, 
> serialVersionUID, toString, wait, or writeReplace."
> 
> Chris says that the serialization spec ignores all the serialization-related 
> methods if they appear inside a record; should we lift the restrictions?

Yes, we’re going to update this part of the spec. I will write separately about 
this.

> 
> In the grammar for records, I find it odd that we basically say that record 
> members are class members plus compact constructor, but then we revert to say 
> that instance initializer are not allowed.
> I wonder if a more specific production for the record body would be useful 
> and more direct here?

I think this is a style thing, but I’m keen to reuse the class grammar. 

> 
> I note an asymmetry between the rules for canonical constructor and compact 
> constructor; in one we say:
> 
> "Every field corresponding to a record component of R must be definitely 
> assigned and moreover not definitely unassigned (16.9) at the end of the body 
> of the canonical constructor."
> 
> In the other we say:
> 
> "It is a compile-time error if at the end of the body of the compact 
> constructor, any of the fields corresponding to the record components of R 
> are neither definitely assigned nor definitely unassigned.”

Indeed. Although I can remove both as we get this by virtue of the fields being 
blank final instance variables (JLS 8.3.1.2). 

> 
> Moreover, a deeper question: should we leave the magic auto-initialization of 
> fields only for the compact form? That way, you would have a _new_ linguistic 
> form, with _new_ properties, whereas old forms (e.g. a constructor with 
> parameters) will have same rules as before (can have returns, must initialize 
> fields explicitly). I think that, from a pedagogical aspect, that would be 
> preferrable.

That’s what we do.

Thanks,
Gavin



Re: New candidate JEP: 361: Switch Expressions (Standard)

2019-11-15 Thread Gavin Bierman
Great news!

Thanks,
Gavin

> On 11 Nov 2019, at 06:49, Manoj Palat  wrote:
> 
> Hi Gavin,
>  
> For the record, JEP 361 Switch Expressions draft looks fine - we have started 
> to make the preview-to-standard transition of Switch Expressions in Eclipse 
> on the basis of this, already.
>  
> Thanks,
> Manoj
> Eclipse Java Dev, IBM.
>  
> ----- Original message -
> From: Gavin Bierman 
> Sent by: "amber-spec-experts" 
> To: amber-spec-experts 
> Cc: amber-dev , Jan Lahoda 
> Subject: [EXTERNAL] Re: New candidate JEP: 361: Switch Expressions (Standard)
> Date: Mon, Oct 21, 2019 4:54 PM
>  
> Just a gentle reminder if you have any feedback based on your experience with 
> using this feature.
>  
> Gavin
>  
>> 
>> On 27 Sep 2019, at 17:45, Gavin Bierman > <mailto:gavin.bier...@oracle.com>> wrote:
>>  
>> Please note that we are considering making this a permanent feature, so this 
>> is your last chance to provide substantive feedback based on any new 
>> experience you may have had with this feature.
>>  
>> A new, draft language spec for JEP 361 (Switch Expressions) is available at:
>>  
>>  
>> http://cr.openjdk.java.net/~gbierman/jep361/jep361-20190927/specs/switch-expressions-jls.html
>>  
>> <http://cr.openjdk.java.net/~gbierman/jep305/jep305-20190918/specs/patterns-instanceof-jls.html>
>>  
>> This is identical to the version made available for JEP354, apart from some 
>> cosmetic changes around terminology following some feedback. 
>>  
>> [For spec nerds: The primary change is that what was previously called a 
>> "switch labeled rule" is now called, more simply, a "switch rule”. “Switch 
>> labeled expression” is now a “switch rule expression”, “switch labeled 
>> block” is now a “switch rule block” and a “switch labeled throw statement” 
>> is now a “switch rule throw statement”.]
>>  
>> All feedback welcomed!
>> Gavin
>>  
>>> 
>>> On 25 Sep 2019, at 23:32, mark.reinh...@oracle.com 
>>> <mailto:mark.reinh...@oracle.com> wrote:
>>>  
>>> https://openjdk.java.net/jeps/361 <https://openjdk.java.net/jeps/361>
>>> 
>>> - Mark
> 
>  
> 



Re: [records] Compact constructor type parameters

2019-11-15 Thread Gavin Bierman
Sounds good. 

Gavin

> On 9 Nov 2019, at 11:47, Brian Goetz  wrote:
> 
> This is reasonable and probably easy to spec: when we define the canonical 
> ctor, in addition to defining its is defined to have no type parameters.  
> Since the compact ctor is shorthand for a full canonical ctor, no additional 
> spec is needed for that.  
> 
> Sent from my iPad
> 
>> On Nov 9, 2019, at 12:07 PM, Tagir Valeev  wrote:
>> 
>> Hello!
>> 
>> Reading the latest JLS spec draft for records, chapter 8.10.5 [1] I
>> see the following:
>> 
>> A compact constructor declaration provides an alternative, succinct
>> means to declare a canonical constructor for a record type.
>> CompactConstructorDeclaration:{ Annotation } { ConstructorModifier } [
>> TypeParameters ] SimpleTypeName ConstructorBody
>> 
>> Is it really useful to allow type parameters specification for a
>> compact constructor, given that we cannot alter the formal parameters
>> list, thus we cannot use them there? Yes, we could use them to declare
>> local variables but this is an implementation detail, thus it should
>> not leak to the clients (especially given the fact that canonical
>> constructors are always public). Should not we exclude type parameters
>> from the compact constructor declaration?
>> 
>> I think we can go even further and disable type parameters for
>> explicit canonical constructor declaration (not in compact form) as
>> well. WDYT?
>> 
>> With best regards,
>> Tagir Valeev.
>> 
>> [1] 
>> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jls.html#jls-8.10.5
> 



  1   2   >