if (!(x instanceof String y)) syntax - better syntax?

Tagir Valeev amaembo at gmail.com
Fri Feb 14 01:00:25 UTC 2020


Please note that it's not just about a compiler patch. It requires
significant rewrite of the specification and full CSR process. Also, this
would be effectively a new preview feature so you would need to support
parsing in old and new way, depending on the compilation options. Finally,
probably some JCK tests may fail and this should be addressed as well. So I
believe, it will still take a fair amount of time for Oracle folks. Not
sure whether they'll agree to spend their time this way :-)

With best regards,
Tagir Valeev.


пт, 14 февр. 2020 г., 5:00 Reinier Zwitserloot <reinier at zwitserloot.com>:

> Did some research; this is not a bad idea!
>
> Right now, this:
>
> if (!<ANY EXPR HERE> instanceof <ANYTHING>) {}
>
> is necessarily a compile time error. The type of !<EXPR> is necessarily
> `boolean` (or !<EXPR> itself is already a compile-time error) - even if the
> type of <EXPR> is `Boolean` (that expression itself is legal; javac will
> auto-unbox, making !Boolean of type boolean). And instanceof, explicitly,
> does not autobox. This:
>
> boolean z = true;
> if (z instanceof Boolean) {}
>
> does not compile (javac: types incompatible. Expected: reference, found:
> boolean. ecj: boolean is not compatible with Boolean).
>
> So, that hacky way to cook up an example of backwards incompatibility won't
> lead us to any problems, leaving Tagir's string concat example.
>
> I agree the string concat break is probably an acceptable break, given that
> the code is so meaningless already (insofar that it does 'break' any code,
> that code was likely to be buggy in the first place), but I've gone on
> record as having no good grasp on what core openjdk contributors consider
> 'unacceptably backwards incompatible' already, so perhaps I'm not the best
> judge on this one :)
>
> Note that this:
>
> if ("a" + "b" instanceof X) {}
>
> is a compile-time error unless X is either java.lang.String or one of its
> supertypes (Serializable, CharSequence, Comparable, or Object). Therefore,
> if it is not a compile-time error, then the whole expression necessarily
> resolves to 'true', though it does not count as a compile time constant.
> Surely this does not occur in real life java code and if it does, it's
> already a buggy line.
>
> I can try to contribute a patch for either form. I assume supporting both
> is not desired? I'm honestly not sure which version I prefer. I guess I
> prefer !instanceof but that is a very light precedence and I've clearly
> arrived at the bikeshed painting phase of syntax debate here.
>
> if (!x instanceof String) {}
>
> or
>
> if (x !instanceof String) {}
>
> assuming the string concat case can justifiably be considered as acceptable
> collateral damage, which one is more intuitive?
>
>  --Reinier Zwitserloot
>
>
> On Sat, 8 Feb 2020 at 04:40, Tagir Valeev <amaembo at gmail.com> wrote:
>
> > This discussion motivated me to implement a very small feature in
> > IntelliJ IDEA: adding parentheses automatically:
> > https://twitter.com/tagir_valeev/status/1225979390330314752
> > Hopefully, now this problem will be less frustrating, at least during
> > the typing.
> >
> > I thought about making `instanceof` priority higher than logical
> > complement operator priority. However, this will also make
> > `instanceof` priority higher than binary plus, changing the semantics
> > of this expression:
> >
> > System.out.println("a" + "b" instanceof String) // now prints 'true",
> > will print "atrue" after the change
> >
> > However, such kind of expression is completely silly, so probably such
> > a semantics change is acceptable. Other binary operators never accept
> > boolean (result of instanceof) or produce reference type (argument of
> > instanceof), so this change should not affect them.
> >
> > For reference, here's the proposed grammar change.
> >
> > 1. Exclude RelationalExpression instanceof ReferenceType from
> > RelationalExpression productions
> > 2. Update MultiplicativeExpression productions:
> > MultiplicativeExpression:
> >   InstanceOfOrUnaryExpression
> >   MultiplicativeExpression * UnaryExpression
> >   MultiplicativeExpression / UnaryExpression
> >   MultiplicativeExpression % UnaryExpression
> >
> > 3. Add more productions:
> > InstanceOfOrUnaryExpression:
> >   InstanceOfOrUnaryExpressionNotLogicalComplement
> >   ! InstanceOfOrUnaryExpression
> >
> > InstanceOfOrUnaryExpressionNotLogicalComplement:
> >   UnaryExpressionNotLogicalComplement
> >   InstanceOfOrUnaryExpressionNotLogicalComplement instanceof
> ReferenceType
> >
> > UnaryExpressionNotLogicalComplement:
> >   PreIncrementExpression
> >   PreDecrementExpression
> >   + UnaryExpression
> >   - UnaryExpression
> >   UnaryExpressionNotPlusMinusLogicalComplement
> >
> > UnaryExpressionNotPlusMinusLogicalComplement:
> >   PostfixExpression
> >   ~ InstanceOfOrUnaryExpression
> >   CastExpression
> >
> > 4. Remove UnaryExpression and UnaryExpressionNotPlusMinus productions.
> >
> > With best regards,
> > Tagir Valeev.
> >
> > On Fri, Feb 7, 2020 at 7:53 AM Reinier Zwitserloot
> > <reinier at zwitserloot.com> wrote:
> > >
> > > I'm not sure if now is an appropriate time (or how one should bring up
> > > something like this), but I noticed a bit of friction in regards to
> this
> > > particular style of code:
> > >
> > >     if (!(x instanceof String y)) return;
> > >     // carry on, with y available of type Strin.
> > >
> > > This is a stated goal of why the instanceof patternmatch feature's
> rules
> > on
> > > where the declared 'y' variable is available ('binding variables')
> works
> > as
> > > it does.
> > >
> > > That's great; we've debated it at length before.
> > >
> > > However, the syntax of this particular construct is a bit unfortunate;
> I
> > > see newbies write if (!x instanceof String) or if (x !instanceof
> String)
> > > relatively often; the second one gives a straight up syntax error, but
> > the
> > > first is a bit more convoluted ('x is not boolean'). Even disregarding
> > the
> > > anecdotal evidence that those new to java fairly consistently misjudge
> > how
> > > to do an if-not-an-instance-of check, the correct syntax is rather
> > > unwieldy. Maybe it's comfortable to any LISP fans in the audience, but
> > it's
> > > a few too many parentheses for my tastes.
> > >
> > > Given that a new language feature is being introduced which is catering
> > > rather explicitly to this particular 'if not an instance of, then'
> style,
> > > is there room to add a small, entirely backwards compatible syntax
> > feature
> > > [1]?
> > >
> > > Something like:
> > >
> > >     if (x !instanceof String y) return;
> > >
> > > Any form of the *ReferenceType* AST node accepts this form, so also the
> > > older form:
> > >
> > >     boolean z = x !instanceof String; // valid. equivalent to z = !(x
> > > instanceof String).
> > >
> > > I'm not sure if it would be appropriate to debate here if this should
> be
> > > tagged onto the aims for e.g. JDK15's expanded instanceof support (
> > > Preview-2 [2] ), or if this should be its own proposal, or if this is
> > even
> > > the appropriate channel for such ideas.
> > >
> > > [1] I'm jumping the gun a little bit on how backwards compatible this
> > is. I
> > > _think_ so, as it's a straight up syntax error right now, but before I
> > > write a PoC patch to javac, I thought I'd check if the idea itself is
> > sound
> > > before delving that deep.
> > > [2] https://bugs.openjdk.java.net/browse/JDK-8235186
> > >
> > >
> > >  --Reinier Zwitserloot
> >
>


More information about the amber-dev mailing list