Re: nest syntax proposal

2019-01-26 Thread forax
> De: "Brian Goetz" 
> À: "Remi Forax" 
> Cc: "amber-spec-experts" 
> Envoyé: Samedi 26 Janvier 2019 17:08:51
> Objet: Re: nest syntax proposal

> Let’s back up and look at the problem, before we jump to solutions.

> The sealed class mechanism, on its own, is fine. I think we have the right 
> knobs
> to express the sorts of types we want.

> People are going to want to express sums of records. And they are going to 
> want
> to do so “conveniently.” There are several inconveniences:

> - Defining a sum of five records in a flat namespace requires six files, all 
> of
> which may frequently be one-liners. This is annoying to write, but it is also
> harder to read — if these classes are so tightly related, we want to declare
> them in one place.
> - The streamlined syntax (inferring the permits clause) is clearly aimed at
> supporting the above (many languages with sealed types don’t even let you
> declare subtypes outside of the same compilation unit.) It is better for
> readers and writers for simple subtypes of simple sealed types to be defined
> together.
> - We could define them as auxiliary classes, and everything would be great,
> except aux classes can’t be public. (Accidental interaction number 1.)
> - We could define them as nested classes, and everything would be great, 
> except
> then clients have to deal with the nesting. (Accidental interaction number 2.)

We can have multiple public classes in case there is a sealed type by lifting 
the restriction, force to have the compilation unit to have the same name as 
the interface and make all subtypes nestmate of the interface. 
For tools, it means that if you want to find the java file from a class file, 
if there is not corresponding java file, then you can look in the java file of 
the nest host of the class file. 

> If we don’t solve this problem at all, what are people most likely going to 
> do?
> Most of the time, I suspect non-API writers will write nested records, and 
> then
> use import static to hide the nesting from the client view.

which is fine with sealed interface not sealed class ... 

> And API writers will bite the bullet and use six files.

> Neither of these are terrible, but they have that whiff of friction that we 
> know
> people will complain about, because they don’t like their choices. But I think
> we could ship the feature with no special support in any case. So we’re in the
> “filing rough edges” department.

I think we can lift the "only one public class" if the compilation unit is the 
sealed type as described above because it's a backward compatible change. 
It doesn't solve the case you want several record classes with no sealed type, 
but at least we cover the most common case. 

Rémi 

>> On Jan 26, 2019, at 8:24 AM, [ mailto:fo...@univ-mlv.fr | fo...@univ-mlv.fr ]
>> wrote:

>> I've slept on that problem this night.

>> Let's focus first on the sealed type, You are proposing to declare the 
>> subtypes
>> inside the sealed type, so you get nesting automatically and you can use 
>> import
>> + a special switch rules to be able to reference a subtype directly.
>> I believe this fell flat with a sealed class, because you are mixing 
>> inheritance
>> and enclosing scopes.

>> Let's take an example
>> sealed class Expr {
>> public void aMethod() { ... }

>> record Value(int value) extends Expr;
>> record Add(Expr left, Expr right) {
>> public void anotherMethod() {
>> aMethod(); // call super.aMethod() or Expr.this.aMethod() ?
>> }
>> }
>> }

>> as you can see, we are mixing inheritance and enclosing scope here, i don't
>> think it's wise to let a user to write this kind of monstrosity.

>> I wish inner classes where never invented (anonymous class are fine) but 
>> it's a
>> too late ...

>> We can say that records are always a static class, but refactoring a class 
>> to a
>> record or vice-versa will create instant puzzler.
>> We can only support sealed interface, not sealed class, it may be not a bad 
>> idea
>> per itself, anyway i think we should no try to mix nesting and subtyping.

>> Rémi

>>> De: "Brian Goetz" < [ mailto:brian.go...@oracle.com | 
>>> brian.go...@oracle.com ] >
>>> À: "Remi Forax" < [ mailto:fo...@univ-mlv.fr | fo...@univ-mlv.fr ] >
>>> Cc: "amber-spec-experts" < [ mailto:amber-spec-experts@openjdk.java.net |
>>> amber-spec-experts@openjdk.java.net ] >
>>> Envoyé: Lundi 21 Janvier 2019 00:07:01
>>> Objet: Re: nest syntax proposal

>>>>> And they understand auxiliary classes. Let’s work with the familiar 
>&g

Re: nest syntax proposal

2019-01-26 Thread Brian Goetz
Let’s back up and look at the problem, before we jump to solutions.  

The sealed class mechanism, on its own, is fine.  I think we have the right 
knobs to express the sorts of types we want.  

People are going to want to express sums of records.  And they are going to 
want to do so “conveniently.”  There are several inconveniences:

 - Defining a sum of five records in a flat namespace requires six files, all 
of which may frequently be one-liners.  This is annoying to write, but it is 
also harder to read — if these classes are so tightly related, we want to 
declare them in one place.  
 - The streamlined syntax (inferring the permits clause) is clearly aimed at 
supporting the above (many languages with sealed types don’t even let you 
declare subtypes outside of the same compilation unit.)  It is better for 
readers and writers for simple subtypes of simple sealed types to be defined 
together.  
 - We could define them as auxiliary classes, and everything would be great, 
except aux classes can’t be public. (Accidental interaction number 1.)
 - We could define them as nested classes, and everything would be great, 
except then clients have to deal with the nesting.  (Accidental interaction 
number 2.)  

If we don’t solve this problem at all, what are people most likely going to do? 
 Most of the time, I suspect non-API writers will write nested records, and 
then use import static to hide the nesting from the client view.  And API 
writers will bite the bullet and use six files.  

Neither of these are terrible, but they have that whiff of friction that we 
know people will complain about, because they don’t like their choices.  But I 
think we could ship the feature with no special support in any case.  So we’re 
in the “filing rough edges” department.  




> On Jan 26, 2019, at 8:24 AM, fo...@univ-mlv.fr wrote:
> 
> I've slept on that problem this night.
> 
> Let's focus first on the sealed type, You are proposing to declare the 
> subtypes inside the sealed type, so you get nesting automatically and you can 
> use import + a special switch rules to be able to reference a subtype 
> directly.
> I believe this fell flat with a sealed class, because you are mixing 
> inheritance and enclosing scopes.
> 
> Let's take an example
>   sealed class Expr {
> public void aMethod() { ... }
> 
> record Value(int value) extends Expr;
> record Add(Expr left, Expr right) {
>   public void anotherMethod() {
> aMethod();  // call super.aMethod() or Expr.this.aMethod() ?
>   }
> }
>   }
> 
> as you can see, we are mixing inheritance and enclosing scope here, i don't 
> think it's wise to let a user to write this kind of monstrosity. 
> 
> I wish inner classes where never invented (anonymous class are fine) but it's 
> a too late ...
> 
> We can say that records are always a static class, but refactoring a class to 
> a record or vice-versa will create instant puzzler.
> We can only support sealed interface, not sealed class, it may be not a bad 
> idea per itself, anyway i think we should no try to mix nesting and subtyping.
> 
> Rémi
> 
> De: "Brian Goetz" 
> À: "Remi Forax" 
> Cc: "amber-spec-experts" 
> Envoyé: Lundi 21 Janvier 2019 00:07:01
> Objet: Re: nest syntax proposal
>  And they understand auxiliary classes.  Let’s work with the familiar 
> concepts.  
> 
> but your solution seems tailored to sealed types, what if i have several 
> record classes with no common abstract type, how it works ?
> and again there is no refactoring between a classical interface and a sealed 
> interface, something we should try offer.
> 
> Indeed, I think there are two things here.  We can choose to address one or 
> both or neither, with the obvious tradeoffs.  
> 
> Issue #1 is that sealed types naturally form a family, you’re going to switch 
> over them, etc, like enums, and we want the same (or more) nice treatment as 
> we currently get with enums in switch.  So it makes sense to define them all 
> in one place; indeed, that should be the common case.  Doing something with 
> import helps here, but as you say, it is more specific to sealed types.  On 
> the other hand, enums and sealed types are related, so mirroring the special 
> treatment that enums get (maybe even giving both a little more) is a 
> low-energy-state solution.  
> 
> Issue #2 is that with records, one line per file starts to seem silly.  This 
> has a lot of overlap with #1, but not entirely.  You could argue its a more 
> general solution, and maybe we like that, but maybe we don’t.  It surely is 
> more intrusive — affecting the existing semantics of auxiliary classes, and 
> dramatically increasing the use of auxiliary classes (which, BTW, we’ve 
> banned from the JDK source base b

Re: nest syntax proposal

2019-01-26 Thread forax
I've slept on that problem this night. 

Let's focus first on the sealed type, You are proposing to declare the subtypes 
inside the sealed type, so you get nesting automatically and you can use import 
+ a special switch rules to be able to reference a subtype directly. 
I believe this fell flat with a sealed class, because you are mixing 
inheritance and enclosing scopes. 

Let's take an example 
sealed class Expr { 
public void aMethod() { ... } 

record Value(int value) extends Expr; 
record Add(Expr left, Expr right) { 
public void anotherMethod() { 
aMethod(); // call super.aMethod() or Expr.this.aMethod() ? 
} 
} 
} 

as you can see, we are mixing inheritance and enclosing scope here, i don't 
think it's wise to let a user to write this kind of monstrosity. 

I wish inner classes where never invented (anonymous class are fine) but it's a 
too late ... 

We can say that records are always a static class, but refactoring a class to a 
record or vice-versa will create instant puzzler. 
We can only support sealed interface, not sealed class, it may be not a bad 
idea per itself, anyway i think we should no try to mix nesting and subtyping. 

Rémi 

> De: "Brian Goetz" 
> À: "Remi Forax" 
> Cc: "amber-spec-experts" 
> Envoyé: Lundi 21 Janvier 2019 00:07:01
> Objet: Re: nest syntax proposal

>>> And they understand auxiliary classes. Let’s work with the familiar 
>>> concepts.

>> but your solution seems tailored to sealed types, what if i have several 
>> record
>> classes with no common abstract type, how it works ?
>> and again there is no refactoring between a classical interface and a sealed
>> interface, something we should try offer.

> Indeed, I think there are two things here. We can choose to address one or 
> both
> or neither, with the obvious tradeoffs.

> Issue #1 is that sealed types naturally form a family, you’re going to switch
> over them, etc, like enums, and we want the same (or more) nice treatment as 
> we
> currently get with enums in switch. So it makes sense to define them all in 
> one
> place; indeed, that should be the common case. Doing something with import
> helps here, but as you say, it is more specific to sealed types. On the other
> hand, enums and sealed types are related, so mirroring the special treatment
> that enums get (maybe even giving both a little more) is a low-energy-state
> solution.

> Issue #2 is that with records, one line per file starts to seem silly. This 
> has
> a lot of overlap with #1, but not entirely. You could argue its a more general
> solution, and maybe we like that, but maybe we don’t. It surely is more
> intrusive — affecting the existing semantics of auxiliary classes, and
> dramatically increasing the use of auxiliary classes (which, BTW, we’ve banned
> from the JDK source base because they make life very hard for build tooling),
> etc. It’s a bigger hammer.

> Its also possible we do nothing here, and let users nest the subtypes and
> clients just say “import static SealedType.*”. That’s the least intrusive, so
> we should compare cost/benefit against that baseline.


Re: nest syntax proposal

2019-01-20 Thread Brian Goetz
>  And they understand auxiliary classes.  Let’s work with the familiar 
> concepts.  
> 
> but your solution seems tailored to sealed types, what if i have several 
> record classes with no common abstract type, how it works ?
> and again there is no refactoring between a classical interface and a sealed 
> interface, something we should try offer.

Indeed, I think there are two things here.  We can choose to address one or 
both or neither, with the obvious tradeoffs.  

Issue #1 is that sealed types naturally form a family, you’re going to switch 
over them, etc, like enums, and we want the same (or more) nice treatment as we 
currently get with enums in switch.  So it makes sense to define them all in 
one place; indeed, that should be the common case.  Doing something with import 
helps here, but as you say, it is more specific to sealed types.  On the other 
hand, enums and sealed types are related, so mirroring the special treatment 
that enums get (maybe even giving both a little more) is a low-energy-state 
solution.  

Issue #2 is that with records, one line per file starts to seem silly.  This 
has a lot of overlap with #1, but not entirely.  You could argue its a more 
general solution, and maybe we like that, but maybe we don’t.  It surely is 
more intrusive — affecting the existing semantics of auxiliary classes, and 
dramatically increasing the use of auxiliary classes (which, BTW, we’ve banned 
from the JDK source base because they make life very hard for build tooling), 
etc.  It’s a bigger hammer.  

Its also possible we do nothing here, and let users nest the subtypes and 
clients just say “import static SealedType.*”.  That’s the least intrusive, so 
we should compare cost/benefit against that baseline. 





Re: nest syntax proposal

2019-01-20 Thread Brian Goetz
So, there are about 100 people in the world who know what “nest mates” means, 
which is a huge black mark against introducing an explicit “nest” concept into 
the language.  Nest mates has been a low-level implementation detail, and the 
fact that it it is hidden from the user model is a feature, not a bug.  This is 
a big new concept to teach to a large audience that doesn’t yet have any 
conception of it.  So far, the benefits do not remotely outweigh the degree to 
which it exposes new complexity to everyone.  

I would much prefer a solution that builds on existing concepts that people 
already understand, than one that requires them to learn a new concept just to 
support a particular use of a new feature.  

People understand import.  And they understand auxiliary classes.  Let’s work 
with the familiar concepts.  

> On Jan 20, 2019, at 4:31 PM, fo...@univ-mlv.fr wrote:
> 
> - Mail original -
>> De: "Brian Goetz" 
>> À: "Remi Forax" 
>> Cc: "amber-spec-experts" 
>> Envoyé: Dimanche 20 Janvier 2019 18:04:00
>> Objet: Re: nest syntax proposal
> 
>> This is a nice example of “today’s problems come from yesterday’s solutions.”
>> In Java 1.1, we did nested classes, and they were pretty cool, but there were
>> some mismatches between the language model and the runtime model, which had
>> some sharp edges.  So, as a solution to that problem, we taught the JVM about
>> the notion of “nest”, to align the two.  The intent, at the time, was that 
>> the
>> natural syntax for nests was — nesting.
>> 
>> Now, you’re saying that it kinds of stinks that we have to take all the
>> properties of nests (shared access control, hierarchical namespace) or none 
>> of
>> them, and you’d like to introduce a way to get the first without the second.
>> It’s a fair idea.
> 
> Yes, i see the fact that in Java the language force classes to be enclosed to 
> have private access as an accidental complexity. The JVM has no such 
> requirement so i propose to reconcile the language and the VM netsmates. 
> 
>> 
>> However, I think I’d solve the problem — which is that it is irritating to 
>> have
>> to say FruitBasket.Apple all the time, rather than Apple — more directly?  
>> Like
>> some sort of more powerful “import”.  For example:
>> 
>>   import enum Foo;
>> 
>> could import the Foo enum class, _plus_ import-static all its constants.  
>> (And
>> something similar for sealed classes, of course).
> 
> In a sense, you are doubling-down on the notion of hierarchy, or at least of 
> enclosing, by saying that you have an "import tree" that can import a set of 
> types that are declared inside another one. 
> 
> The main issue with your solution is that you can not retrofit an existing 
> hierarchy/set of classes to this new scheme because moving a class inside 
> another change its name so it's not a backward compatible change hence the 
> idea to de-couple nestmates access and nested classes.
> 
> Rémi
> 
>> 
>>> On Jan 20, 2019, at 7:49 AM, Remi Forax  wrote:
>>> 
>>> Hi all,
>>> as Brian said recently, we have an issue because we are shortening the class
>>> declaration (with records) or wants to declare in a single compilation unit 
>>> a
>>> hierarchy of types (with sealed types) and currently Java requires that a
>>> compilation unit can only have one public class.
>>> 
>>> One solution is to get ride of this constraint, because it may be a good 
>>> idea in
>>> 1995 but today we are writing programs that have far more classes (the
>>> introduction of modules recently was also driven by that idea). I propose
>>> another way of solving that issue, introducing a mechanism to opt-in to have
>>> more than one public class in a compilation unit.
>>> 
>>> Currently we have the mechanism of nestmates which has a runtime 
>>> representation
>>> (VM + reflection) but no language representation, i propose to introduce a 
>>> new
>>> declaration in the language in between the package declaration and the first
>>> import,
>>> nest NestHostClass;
>>> which define the class that will be used as nest host (obviously it can be
>>> another keyword instead of "nest").
>>> 
>>> So a closed hierarchy can defines like this in one compilation unit:
>>> nest Expr;
>>> 
>>> public sealed Expr permits Variable, Value, Add;
>>> public record Variable(String name) implements Expr;
>>> public record Value(int value) implements Expr;
>>> public record Add

Re: nest syntax proposal

2019-01-20 Thread forax
- Mail original -
> De: "Brian Goetz" 
> À: "Remi Forax" 
> Cc: "amber-spec-experts" 
> Envoyé: Dimanche 20 Janvier 2019 18:04:00
> Objet: Re: nest syntax proposal

> This is a nice example of “today’s problems come from yesterday’s solutions.”
> In Java 1.1, we did nested classes, and they were pretty cool, but there were
> some mismatches between the language model and the runtime model, which had
> some sharp edges.  So, as a solution to that problem, we taught the JVM about
> the notion of “nest”, to align the two.  The intent, at the time, was that the
> natural syntax for nests was — nesting.
> 
> Now, you’re saying that it kinds of stinks that we have to take all the
> properties of nests (shared access control, hierarchical namespace) or none of
> them, and you’d like to introduce a way to get the first without the second.
> It’s a fair idea.

Yes, i see the fact that in Java the language force classes to be enclosed to 
have private access as an accidental complexity. The JVM has no such 
requirement so i propose to reconcile the language and the VM netsmates. 

> 
> However, I think I’d solve the problem — which is that it is irritating to 
> have
> to say FruitBasket.Apple all the time, rather than Apple — more directly?  
> Like
> some sort of more powerful “import”.  For example:
> 
>import enum Foo;
> 
> could import the Foo enum class, _plus_ import-static all its constants.  (And
> something similar for sealed classes, of course).

In a sense, you are doubling-down on the notion of hierarchy, or at least of 
enclosing, by saying that you have an "import tree" that can import a set of 
types that are declared inside another one. 

The main issue with your solution is that you can not retrofit an existing 
hierarchy/set of classes to this new scheme because moving a class inside 
another change its name so it's not a backward compatible change hence the idea 
to de-couple nestmates access and nested classes.

Rémi

> 
>> On Jan 20, 2019, at 7:49 AM, Remi Forax  wrote:
>> 
>> Hi all,
>> as Brian said recently, we have an issue because we are shortening the class
>> declaration (with records) or wants to declare in a single compilation unit a
>> hierarchy of types (with sealed types) and currently Java requires that a
>> compilation unit can only have one public class.
>> 
>> One solution is to get ride of this constraint, because it may be a good 
>> idea in
>> 1995 but today we are writing programs that have far more classes (the
>> introduction of modules recently was also driven by that idea). I propose
>> another way of solving that issue, introducing a mechanism to opt-in to have
>> more than one public class in a compilation unit.
>> 
>> Currently we have the mechanism of nestmates which has a runtime 
>> representation
>> (VM + reflection) but no language representation, i propose to introduce a 
>> new
>> declaration in the language in between the package declaration and the first
>> import,
>>  nest NestHostClass;
>> which define the class that will be used as nest host (obviously it can be
>> another keyword instead of "nest").
>> 
>> So a closed hierarchy can defines like this in one compilation unit:
>>  nest Expr;
>> 
>>  public sealed Expr permits Variable, Value, Add;
>>  public record Variable(String name) implements Expr;
>>  public record Value(int value) implements Expr;
>>  public record Add(Expr left, Expr right) implements Expr;
>> 
>> at runtime, Variable.class.getNestHost() == Expr.class
>> 
>> Another simpler example
>>  nest FruitBasket;
>> 
>>  public record Fruit(String name);
>> 
>>  public class FruitBasket {
>>private final ArrayList fruits = new ArrayList<>();
>> 
>>public void add(Fruit fruit) {
>>  Objects.requireNonNull(fruit);
>>  fruits.add(fruit);
>>}
>>  }
>> 
>> at runtime, Fruit.class.getNestHost() == FruitBasket.class
>> 
>> I believe that the nest host class defined by the keyword "nest", doesn't 
>> have
>> to be public, but it's not a qualified name (obviously) and the class has to 
>> be
>> defined in the compilation unit.
>> 
>> Defining a nest can be seen as an extension of the case with only one class, 
>> if
>> there is only one class in the compilation unit, the class is it's own nest
>> host.
>> If there is more than one class in the compilation unit, but only one class 
>> is
>> public, currently, they are not nestmates, i think we should not do anything 
>> to
>> try to retcon that compilation unit because this case is rare (one may 
>> argument
>> that if we introduce the nest syntax, it can be more frequent). Also the
>> compiler message should be tweaked if there are more than one public classes 
>> to
>> say that a nest can be defined.
>> 
> > Rémi


Re: nest syntax proposal

2019-01-20 Thread Brian Goetz
This is a nice example of “today’s problems come from yesterday’s solutions.”   
In Java 1.1, we did nested classes, and they were pretty cool, but there were 
some mismatches between the language model and the runtime model, which had 
some sharp edges.  So, as a solution to that problem, we taught the JVM about 
the notion of “nest”, to align the two.  The intent, at the time, was that the 
natural syntax for nests was — nesting.  

Now, you’re saying that it kinds of stinks that we have to take all the 
properties of nests (shared access control, hierarchical namespace) or none of 
them, and you’d like to introduce a way to get the first without the second.  
It’s a fair idea.

However, I think I’d solve the problem — which is that it is irritating to have 
to say FruitBasket.Apple all the time, rather than Apple — more directly?  Like 
some sort of more powerful “import”.  For example:

import enum Foo;

could import the Foo enum class, _plus_ import-static all its constants.  (And 
something similar for sealed classes, of course).  

> On Jan 20, 2019, at 7:49 AM, Remi Forax  wrote:
> 
> Hi all,
> as Brian said recently, we have an issue because we are shortening the class 
> declaration (with records) or wants to declare in a single compilation unit a 
> hierarchy of types (with sealed types) and currently Java requires that a 
> compilation unit can only have one public class.
> 
> One solution is to get ride of this constraint, because it may be a good idea 
> in 1995 but today we are writing programs that have far more classes (the 
> introduction of modules recently was also driven by that idea). I propose 
> another way of solving that issue, introducing a mechanism to opt-in to have 
> more than one public class in a compilation unit.
> 
> Currently we have the mechanism of nestmates which has a runtime 
> representation (VM + reflection) but no language representation, i propose to 
> introduce a new declaration in the language in between the package 
> declaration and the first import,
>  nest NestHostClass;
> which define the class that will be used as nest host (obviously it can be 
> another keyword instead of "nest").
> 
> So a closed hierarchy can defines like this in one compilation unit:
>  nest Expr;
> 
>  public sealed Expr permits Variable, Value, Add;
>  public record Variable(String name) implements Expr;
>  public record Value(int value) implements Expr;
>  public record Add(Expr left, Expr right) implements Expr;
> 
> at runtime, Variable.class.getNestHost() == Expr.class
> 
> Another simpler example
>  nest FruitBasket;
> 
>  public record Fruit(String name);
> 
>  public class FruitBasket {
>private final ArrayList fruits = new ArrayList<>();
> 
>public void add(Fruit fruit) {
>  Objects.requireNonNull(fruit);
>  fruits.add(fruit);
>}
>  }
> 
> at runtime, Fruit.class.getNestHost() == FruitBasket.class
> 
> I believe that the nest host class defined by the keyword "nest", doesn't 
> have to be public, but it's not a qualified name (obviously) and the class 
> has to be defined in the compilation unit.
> 
> Defining a nest can be seen as an extension of the case with only one class, 
> if there is only one class in the compilation unit, the class is it's own 
> nest host.
> If there is more than one class in the compilation unit, but only one class 
> is public, currently, they are not nestmates, i think we should not do 
> anything to try to retcon that compilation unit because this case is rare 
> (one may argument that if we introduce the nest syntax, it can be more 
> frequent). Also the compiler message should be tweaked if there are more than 
> one public classes to say that a nest can be defined.
> 
> Rémi



nest syntax proposal

2019-01-20 Thread Remi Forax
Hi all,
as Brian said recently, we have an issue because we are shortening the class 
declaration (with records) or wants to declare in a single compilation unit a 
hierarchy of types (with sealed types) and currently Java requires that a 
compilation unit can only have one public class.

One solution is to get ride of this constraint, because it may be a good idea 
in 1995 but today we are writing programs that have far more classes (the 
introduction of modules recently was also driven by that idea). I propose 
another way of solving that issue, introducing a mechanism to opt-in to have 
more than one public class in a compilation unit.

Currently we have the mechanism of nestmates which has a runtime representation 
(VM + reflection) but no language representation, i propose to introduce a new 
declaration in the language in between the package declaration and the first 
import,
  nest NestHostClass;
which define the class that will be used as nest host (obviously it can be 
another keyword instead of "nest").

So a closed hierarchy can defines like this in one compilation unit:
  nest Expr;

  public sealed Expr permits Variable, Value, Add;
  public record Variable(String name) implements Expr;
  public record Value(int value) implements Expr;
  public record Add(Expr left, Expr right) implements Expr;

at runtime, Variable.class.getNestHost() == Expr.class

Another simpler example
  nest FruitBasket;

  public record Fruit(String name);

  public class FruitBasket {
private final ArrayList fruits = new ArrayList<>();

public void add(Fruit fruit) {
  Objects.requireNonNull(fruit);
  fruits.add(fruit);
}
  }

at runtime, Fruit.class.getNestHost() == FruitBasket.class

I believe that the nest host class defined by the keyword "nest", doesn't have 
to be public, but it's not a qualified name (obviously) and the class has to be 
defined in the compilation unit.

Defining a nest can be seen as an extension of the case with only one class, if 
there is only one class in the compilation unit, the class is it's own nest 
host.
If there is more than one class in the compilation unit, but only one class is 
public, currently, they are not nestmates, i think we should not do anything to 
try to retcon that compilation unit because this case is rare (one may argument 
that if we introduce the nest syntax, it can be more frequent). Also the 
compiler message should be tweaked if there are more than one public classes to 
say that a nest can be defined.

Rémi