This is part of a larger problem, and I don't think point fixes are really the answer here.  For this reason (and others), any sort of "type more things as void" is on hold for now.  Here's a sketch of the motivation, which comes from Valhalla.

A big part of Valhalla is unifying primitives and references. This means (yay) that we can say goodbye to IntPredicate and friends, since we can have:

    interface IntPredicate extends Predicate<int> { ... }

In turn, we can also start to unify Predicate into Function:

    interface Predicate<T> extends Function<T, boolean> { ... }

But Consumer is a roadblock, because void is not a type.  We'd like to have a path to getting to this unification; tinkering with treating more statements as void expressions could make this harder.

On 9/26/2021 3:11 PM, Remi Forax 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