Thanks Tagir. I’ll take a look at the spec issue and report back. Gavin
> On 3 Feb 2022, at 05:41, Tagir Valeev <amae...@gmail.com> 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