Yield as contextual keyword (was: Call for bikeshed -- break replacement in expression switch)
Tagir Valeev
amaembo at gmail.com
Tue May 21 05:31:06 UTC 2019
For the record: I checked IDEA Ultimate source code (>100000 of Java
files, total size is about 400Mb). It appears that an unqualified call
of the method called 'yield' as an expression statement is used only
once accross our sources:
https://github.com/JetBrains/intellij-community/blob/34e0721dca3700bd14081cfb0da115b367e84a84/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java#L305
With best regards,
Tagir Valeev.
On Tue, May 21, 2019 at 3:10 AM Guy Steele <guy.steele at oracle.com> wrote:
>
> Okay, with this more detailed explanation and understanding, I am back in the `yield` camp. But I’m glad to have explored that side path just a bit.
>
> On May 20, 2019, at 3:51 PM, Brian Goetz <brian.goetz at oracle.com> wrote:
>
> Clarification on Option (B): the rational thing to do is probably not to restrict this behavior to switchy blocks, because there are other kinds of statement contexts that will be embedded in switchy blocks, such as:
>
> case L -> {
> if (cond)
> yield e;
> }
>
> And surely we want to treat this as a yield (in fact, the inability to do this in loops was one of the reasons we rejected `break` in the first place.). Which means we always parse `yield <expr>` as a yield statement, and if someone happens to call an _unqualified_ unary method called yield, they get an error (with a helpful suggestion that they might want to try a qualified yield.).
>
> So, to quantify the cost of a conditional keyword here: invocations of the form yield(e) will be parsed as statements, though qualified invocations (this.yield(e), Thread.yield(e), etc) will be parsed as method invocations. The cost-benefit analysis rests on the assumption that this will bite exceedingly rarely, and when it does, the workaround will be clear and easy.
>
>
> OPTION B: DISALLOW UNQUALIFIED INVOCATION
> -----------------------------------------
>
> From a parser perspective, this is similarly straightforward: inside a switchy block, give the rule `yield <expr>` a higher priority than method invocation. The compiler can warn on this ambiguity, if we like.
>
> From a user perspective, users wanting to invoke yield() methods inside switchy blocks will need to qualify the receiver (Foo.yield(), this.yield(), etc).
>
> The cost is that a statement “yield (e)” parses to different things in different contexts; in a switchy block, it is a yield statement, the rest of the time, it is a method invocation.
>
> I think this is much less likely to cause user distress than Option A, because it is rare that there is an unqualified yield(x) method in scope. (And, given every yield() method I can think of, you’d likely never call one from a switchy block anyway, as they are side-effectful and blocking.). And in the case of collision, there is a clear workaround if the user really wanted a method invocation, and the compiler can deliver a warning when there is actual ambiguity.
>
>
>
More information about the amber-spec-experts
mailing list