If you expect this to be changed, the same would be expected e.g. from
?: expression. This also would create some kind of confusion: the
switch expression cannot be inside the expression statement, but the
expression statement is mostly associated with void-type expression.

Btw, there's another place where void-expression is allowed: update
clause in for statement:
for(int i=0; i<10; switch(i) {case 1 ->
System.out.println(i++);default -> i++;}) {}
Should this work?

Your example assumes more changes to the switch expression, not just
the 'void' type. You also assume that the block can omit the yield
statement, and in this case the resulting type of the corresponding
rule is considered to be 'void'. Also, what will be the resulting type
of switch expression in case if different branches have different
void-ness? E.g.:

(i, consumer) -> switch(i) {
case A a -> consumer.accept(a); // void branch
case B b -> myList.add(b); // boolean branch
}

I don't think we already have result type rules for void & boolean
(JLS 15.28.1). Should we set the resulting type as 'void'? This might
be confusing and error-prone. E.g., I have two method overloads (think
of ExecutorService.submit(Runnable) and
ExecutorService.submit(Callable)). I may assume that the result is
used but in fact it's not because I forget yield in one of the
branches, so the rule type is set to void, this changes the type of
the whole switch expression to the 'void', so the results of all other
branches are ignored, lambda becomes void-compatible and we resolve to
submit(Runnable) instead of submit(Callable). Sounds not very good.

With best regards,
Tagir Valeev.

On Mon, Sep 27, 2021 at 2:11 AM Remi Forax <fo...@univ-mlv.fr> wrote:
>
> There is a bad interaction between a lambda and a switch expression,
> a lambda allows its expression to be typed void but a switch expression can 
> not be typed void,
> so the following code does not compile
>
>   sealed interface I permits A, B {}
>   record A() {}
>   record B() {}
>
>   public Optional<A> findOneA(List<I> list) {
>     return list.stream()
>       .<A>mapMulti((i, consumer) -> switch(i) {
>           case A a -> consumer.accept(a);
>           case B b -> {}
>       })
>       .findFirst();
>   }
>
> This bug occurs for with any methods that takes a Consumer has parameter (so 
> stream.forEach/peek, Iterator.forEachRemaining etc).
>
> The workaound is to add a pair of curly braces around the switch to transform 
> it to a switch statement.
>
> For me, it should be possible to have a switch expression typed void. This is 
> a backward compatible change given that the code does not compile otherwise.
>
> regards,
> RĂ©mi

Reply via email to