Unexpected use of "ConditionalExpression" in JLS grammars

Alex Buckley alex.buckley at oracle.com
Thu Mar 9 17:45:20 UTC 2023


This is a good and interesting question.

The ConstantExpression production in JLS 15.29 uses the Expression 
nonterminal. This is good for giving a lightning-fast intro to the 
topic, but also bad because Expression is extremely general. Expression 
allows LambdaExpression and AssignmentExpression, neither of which are 
usually desirable in constant-like places.

Thus, 15.29 does not define "constant expression" syntactically as 
"Anything that matches ConstantExpression". Rather, 15.29 defines it 
_semantically_, as an expression that meets various criteria.

ConditionalExpression is the highest nonterminal under Expression that 
syntactically precludes lambda expressions and assignment expressions. 
This makes ConditionalExpression the "go to" nonterminal in many places, 
as it lets wholly invalid code be ruled out _syntactically_, during 
parsing, early on in compilation. This is not some artifact of compiler 
implementation, but rather an artifact of how the Java language 
generally prefers to reject invalid code sooner rather than later.

We still need to _semantically_ constrain the conditional expression to 
be a "constant expression" (or else compile-time error), but we would 
have to do that even if using ConstantExpression instead of 
ConditionalExpression.

(`BASE + 1` is an AdditiveExpression, so a ConditionalExpression, and an 
Expression, and a ConstantExpression.)

Alex

On 3/9/2023 4:15 AM, Leon Linhart wrote:
> Hi,
> Initially, I believed to have found a mistake in the JLS (Java 19 
> Edition) that
> was introduced with JEP 361. However, while further looking into the 
> spec, this
> has developed into more of a question than a report.
> 
> In several places in the grammar where I'd expect to find 
> `ConstantExpression`,
> `ConditionalExpression` is used instead. Specifically, in §14.11.1 [1], the
> grammar for a `CaseConstant` is defined through a 
> `ConditionalExpression`. I'd
> tend to think this should at least be a `ConstantExpression` instead as 
> this
> would be more in line with the textual description of a case constant:
> 
>  > Every case constant must be either a constant expression (§15.29) or 
> the name
>    of an enum constant (§8.9.1), or a compile-time error occurs.
> 
> Although, from a quick reading of the JLS, I'm not sure if 
> `ConstantExpression`
> covers names of enum constants. However, neither does the current 
> definition.
> Interestingly, the same production is used for the definition of 
> `ElementValue`
> for annotations in §9.7.1 [2], which seems similarly out-of-place to me.
> 
> My opinion is further reinforced by the fact that the following snippet
> compiles despite using a constant expression for a case label that is not a
> conditional expression:
> 
>      public static final int BASE = 42;
> 
>      public void printForBasePlusOne(int i) {
>          switch (i) {
>              case BASE + 1 -> System.out.println("Test");
>              default -> {}
>          }
>      }
> 
> Now, I'm curious about the reasoning behind using 
> `ConditionalExpression` in
> these places in the JLS and if this might actually be a mistake. If this 
> is not
> the right place to ask about this, please point me in the right direction.
> 
> 
> Regards
> Leon Linhart
> 
> 
> [1] 
> https://docs.oracle.com/javase/specs/jls/se19/html/jls-14.html#jls-14.11.1
> [2] https://docs.oracle.com/javase/specs/jls/se19/html/jls-9.html#jls-9.7.1


More information about the amber-dev mailing list