JEP325: Switch expressions spec

Gavin Bierman gavin.bierman at oracle.com
Thu May 10 12:28:10 UTC 2018


> On 9 May 2018, at 00:08, Dan Smith <daniel.smith at oracle.com> wrote:
> 
> Here are my notes from a pass over the spec.
> 
> Significant items:
> 
> ---
> 
> SwitchStatementClause is probably too general. I don't think we want to allow arbitrary statements to occur on the RHS without braces. It's unweildy (think about a chain of if-else, for example), inconsistent with others uses of "->", and ambiguous: does "case foo -> switch (expr) { ... }" describe a switch statement or a switch expression?

Actually the opposite was argued for - that requiring braces would be too much clutter. It is inconsistent with statement lambda though, as you point out.

> 
> I also have concerns about the heavy duplication between the specs for switch statements and switch expressions. Wasn't this design motivated by wanting to have a single, unified construct packaged in expression and statement forms?

At the time it was felt that the symmetry was not what was wanted. The new forms of case labels would strongly push the user to the comma separated form, rather than the multiple case label form. Allowing both forms seems messy. But I think it’s a matter of taste. [You will have read Guy’s emails on this elsewhere also.]

> 
> Proposed fix: rename SwitchStatementBlock and SwitchExpressionBlock to a single SwitchBlock. Merge the two grammars, with SwitchClause being defined like SwitchExpressionClause, not SwitchStatementClause. Follow lambda expressions in stating a semantic rule that, in the statement form, the Expression be a StatementExpression.
> 
> Discuss switch blocks in a subsection of 14.11 (maybe two subsections, for arrow and colon bodies, with a certain amount of sharing). Define matching, compile-time checks, and runtime behavior. (Like lambda expressions, the treatment of Expression clauses will be context-dependent.) The remaining spec for switch statements and switch expressions should be small.

This makes sense if we go for the symmetry approach. 


> While we're at it, add 'throw' to the set of legal bodies for lambda expressions. (Or we can spin this off into a separate RFE, but I'd like to ship it in parallel.)

I’ll ask about this. At least to me it seems a little odd to throw in a tweak to lambdas in a JEP concerning switch. But maybe it’s acceptable; I’ll find out.

> 
> ---
> 
> After previous discussion about enum names, I think we should relax the requirement that an enum-typed switch must use (unqualified) enum constant names. The behavior I'd like is: if the type of the selector expression is an enum type, and the pattern is an unqualified name, resolve it as a member of the enum type; otherwise, handle a ConstantExpression pattern just like any other.
> 
> (I might also drop the grammar's distinction between EnumConstantName and ConstantExpression, which is ambiguous. And I might also push this special-case logic about name resolution into Chapter 6.)
> 
> ---
> 
> I have concerns about the 'break' rules; see separate thread.


ok

> 
> With or without 'null', there's a good argument that the arrow clauses need a way to syntactically combine specific cases and 'default'. Where are we at on this?

We’ve dropped null patterns for now. 

> 
> ---
> 
> Missing stuff (not necessarily a comprehensive list):
> 
> - 15.6, evaluation of a switch expression may throw (I hate maintaining these lists, but it's here, so we must maintain it)
> - 15.12.2.1, define "potentially compatible"
> - 15.12.2.5, define "more specific"
> - 15.25, categorization of conditionals with switch expression operands (ugh, one more motivation to abandon the categorization scheme)
> - 16, definite assignment (including how does a boolean selector/result get treated?)
> - 18.2.1, inference reduction
> - 18.5.2.2, searching for additional inference constraints
> - 18.5.4, "more specific” inference
> 

Thanks. (Amazing how big this small feature is!)

> ---
> 
> And some notes about presentational issues:
> 
> Throughout: for other specs, people have expressed interest in seeing a complete before-and-after diff. No shortcuts. (And they're probably right—it's a lot easier to see what's going on that way.) So any words that have been removed should be indicated explicitly as deletions, rather than just leaving the old words out and highlighting the new words as additions.

I started with doing just the diff, but as so many changes were being made it started looking rather unhelpful, so I went with the “here’s what the section will look like” with the additions and deletions there. I tried to flag all deletions - but sounds like I might have missed a few. 

> 
> 5.6.3 needs a better title than "numeric promotion", which is a broad term introduced in 5.6; and it needs to be properly introduced in 5.6.
> 
> The conditional expression spec should be updated to re-use the new flavor of numeric promotion.

Agreed.

> 
> 14.11: somewhat arbitrarily, '->' is considered an "operator" while ':' is considered a "separator". Should match that terminology.

Where is ‘:’ called a separator? I used the word ‘operator’ which is the terminology from JLS§3.12. I’d be happy to use other terminology (I wanted to avoid saying token.)


> 
> 14.11: "consists of zero or more statements" is not quite right in either case. A clause block consists of clauses, which are pattern/clause body pairs. A group block consists of statement groups, which are lists of statements prefixed by a list of labels.

Yes, some of this text is still out of date. Will re-work.


> 14.11: "It should be clear from that grammar ..." should be green

Thanks.

> 
> 14.11: Use of the term "pattern" is premature. These are really just ConstantExpressions (plus, maybe, null). As is, we have lots of undefined concepts: When is a pattern "assignment compatible with" a type? When does a pattern "have the same value" as another?

Yes, I wanted to start weaving in pattern terminology ahead of time. On reflection maybe it’s not the right thing to do. [As an aside, I think it’s pretty obvious what the definition of the “undefined” concepts are. Don’t we do a similar pun with constant expressions and expressions? For example, do we define a notion of value for constant expressions distinct from expressions?]

> 
> 14.11: The discussion explaining why we don't silently complete a switch when the selector is null is worth keeping, as an explanation for why, in the absense of an explicit 'case null', the statement will throw. (Better than just saying "historical reasons" or "compatibility”.)

It’s going back in anyhow!

> 
> 14.11 "A Java compiler is encouraged": after much discussion about exhaustiveness, I think the consensus is that we would very much not like for a Java compiler to do this. Silently doing nothing for some inputs is a feature of switch statements.

Hmm…That’s old text that predates this JEP. 

> 
> 14.11: I'm pretty down on explaining features via translation to other features. It's often unclear exactly what this pseudo-code means (which JLS rules apply to it?), and there tends to be a lot of tedious work to make the pseudo-code valid (what if the statement can't complete normally?). Here it would be much clearer to just describe the run-time behavior of 'switch' in terms of clauses.

Ah, thanks for reminding me about this. Actually, this translation was necessary to avoid opening a can of worms to spec out the “can return” for switch. However, much of that pain was dealing with mixed -> and : case labels. In our new world of not mixing them we can take another look at this. Thanks!

> 
> 14.11 "If multiple statements are needed then a block (14.2) should be used": this is a useful illustration, but in the context of Chapter 14, probably too chatty. It's a given that a Block can be used wherever you want multiple statements. Compare the spec for the 'while' loop (14.12).

Ok. That was an explicit request but I’ll take another look.

> 
> 14.11: discussion about unboxing would be clearer if it were limited to a bullet defining the rule for matching a constant expression. (I might separate "constant expression of a primitive type" as a distinct case in the definition.)

ack.

> 
> 14.11: "evaluates to the null”

Thanks.

> 
> 14.11 "A case label can contain multiple patterns, and is said to match if": again, I want to push this down into a definition of "match" somewhere.
> 
> Example 14.11-1: Some further illustration is good here, but this sequencing feels very much like it was tacked on. Something like "what's the difference between two forms of switch blocks?" might be a better way to approach the discussion.

I’ll take another look.

> 14.15, 14.16, 14.17 "immediately enclosing method, constructor, or initializer": this list should consistently include lambda bodies and switch expression blocks as well. (In the 'return' case, switch expression blocks should also be included in the rule about illegal containers.)
> 
> 14.15, 14.16, 14.17 "not permitted to transfer control through a switch expression": with the change to include switch expression blocks in the other rule, there's no need for a special rule that applies to switch expressions. In fact, calling them out suggests that they are somehow treated differently than lambda bodies, when they are not. These paragraphs can be deleted.

I’ll take another look at this text.


> 15.15 "and the switch expression": should be green

Thanks.

> 
> 15.29: this is probably the wrong section number; we'll have to ask Alex how much disruption he wants to tolerate.

Will do.

> 
> 15.29 "In contrast to a switch statement": I think the right thing to say about the contrast is this: it's impossible for the expression to complete normally without a value, so the expression must not leave out some cases.

Thanks, I’ll take another look at this text.

> 
> 15.29 "The rules for the selector expression": I approve of reuse, but I think this is small enough that it would be better to copy/paste the rule here.

Ok.

> 
> 15.29 "Can return": I don't think this requires so much discussion. Just a couple of sentences: "It is a compile-time error if the Block of a SwitchExpressionClause can complete normally. It is a compile-time error if statements of the last SwitchBlockStatementGroup can complete normally.”

Yes, you might be right. Although it is a big difference between switch statement and switch expressions. The thing I don’t like is the rather awkward double-negative definition, so I’d be happy to simply this.

> 
> 15.29 "the switch expression completes normally": More conventionally, "the value of the switch expression is …"

That phrase occurs in several places, so you’ll have to tell me which one you don’t like. 



More information about the amber-spec-experts mailing list