Casts & conditionals

Dan Smith daniel.smith at oracle.com
Wed Oct 10 16:12:18 PDT 2012


I'm exploring the interaction of casts and conditional expressions.  Here's an example:

Object r = ...;
((Runnable) (cond ? r : ()->System.gc())).run();

The EDR spec treats the cast as a "cast to Runnable" context that gets pushed down to each arm of the conditional. As a result, the first arm interprets it as a checkcast and the second as a lambda target.

This might seem kind of strange.  An alternative is to treat the cast not as a general poly-expression context, but rather as a construct with special meaning for lambdas (and method references).  So in the above example, the conditional is treated as a standalone expression, and an error occurs because the lambda doesn't have a target.

Other illustrations:

List<? super String> l1 = ..., l2 = ...;
(ArrayList<? super String>) (cond ? l1 : l2);
// EDR: checkcast for each arm
// alternative: unchecked (because the standalone type is ArrayList<?>)

((Runnable) (cond ? System::gc : System::runFinalization)).run();
// EDR: each arm is a Runnable
// alternative: error -- no target type

(cond ? (Runnable) r : (Runnable) ()->System.gc()).run();
// both strategies: ok

Any preferences?  I think this will be somewhat driven by what's easy to spec and implement, but I'm open to general language design opinions, too.

One thing to think about: lambdas are unique right now as poly expressions that can use target information from casts.  (Method invocations, on the other hand, cannot.)  If, in the future, we add other kinds of poly expressions, would we also want to support cast targets?  That decision may influence whether it's best to treat lambda casts as a special-case feature or a general poly expression feature.

((Set<Integer>) (cond ? {} : {1, 2, 3})).isEmpty() // legal?

—Dan


More information about the lambda-spec-experts mailing list