Re: Meeting today: IdentityClass

2021-05-06 Thread Dan Smith

> On May 5, 2021, at 8:39 AM, Remi Forax  wrote:
> 
> If it's possible, i would like to discuss about IdentityClass again.
> 
> As noted in the last draft, adding IdentityClass automatically at runtime is 
> not a compatible change if tests that uses Class::getInterfaces() are not 
> written correctly,
> and sadly, a lot of tests are written that way. I'm guilty to having written 
> those tests too.
> I don't believe that the solution is to tweak the reflection because adding 
> IdentityClass at runtime is already a hack and introducing a hack² (hack 
> square hack) is usually where we should stop before anyone sanity goes under 
> the bus.

You're correct that this is a risk. I don't think it's a deal-breaker—there 
aren't that many use cases for using 'getInterfaces', and those that do should 
ideally be writing code that isn't hostile to new supers—but I agree it's 
something to watch out for. The current plan is to release a preview feature 
and get some feedback on how disruptive this is.

> Apart the result of Class::getInterfaces() being hardcoded, IdentityClass has 
> to other issues, as javadoc container, given that IdentityClass is inserted 
> by the VM, it means there is no place in the Java code where someone can 
> click to see the javadoc in an IDE, we have the same issue with 
> java.lang.Record currently, the class is added by javac automatically and 
> unlike java.lang.Enum, there is no method useful on java.lang.Record 
> (equals/hashCode and toString are defined directly on the record) so very few 
> of my student where able to understand why a record with a NaN value was 
> equals to itself.

That's interesting. In this case, less of a concern because IdentityObject 
doesn't specify any behaviors at all. It's just a marker. If you're confused 
about, say, 'equals' behavior for primitive objects, you can go to the 
Object.equals documentation to get an explanation.

Object also has this property—you extend it even if you don't mention it in 
source. And I think that works just because "everybody knows" that's how it 
works. Understanding which class declarations implicitly implement 
IdentityObject and what class declarations implicitly implement PrimitiveObject 
will similarly be something that people just need to understand as part of 
their language fluency.

(If you're browsing javadoc, we'll be sure to make this obvious, just like it's 
obvious in javadoc that everything extends Object.)

> But there is a more serious issue, using IdentityClass is not backward 
> compatible with Object.
> When we have introduced IdentityClass, one scenario was to be able to declare 
> that the type parameter corresponding to the keys (K) to only support 
> identity class.
> This is not possible using IdentityClass because the erasure of K will be 
> IdentityClass instead of Object (IdentityClass also appears when the compiler 
> will to a lub, so the common class of String and URI will be computed as 
> IdentityClass instead of Object leading to source compatibility issues).

As John mentioned yesterday: the simplest solution is to make sure erasure 
treats 'K extends Object & IdentityObject' differently than 'K extends 
IdentityObject'. A bit awkward, but workable for authors who need to preserve 
binary compatibility.

> 
> I think at that point, we should go back to our blackboard and see if there 
> is no other solution.
> 
> I see two, one is to do *nothing* and do not add a type saying that only 
> identity class is a corner case after all,
> the other is to piggyback on erasure not unlike Scala does, i.e. 
> IdentityClass is a fake class that is erased to Object at runtime.

There are a few different pieces any solution should support (unless we're 
changing our requirements):

- Dynamic test for "is this object an identity object?" or "is this class an 
identity class?"
- Static type for a variable ('void m(IdentityObject o)')
- Type variable bound ('T extends IdentityObject')
- Concise way to constrain a class's subtypes to primitive/identity classes 
(both compile-time and runtime)

If you say IdentityObject is only a compile-time type, you've lost the dynamic 
tests, runtime guarantees about variable types, and runtime class subtyping 
restrictions. You haven't improved anything about javadoc discoverability.

Of course we could come up with other solutions for those problems, but that's 
a lot of complexity just to make life easier for 'getInterfaces' clients and 
library authors who want to compatibly apply IdentityObject as a bound. Doesn't 
seem like a good trade-off.



Re: Meeting today: IdentityClass

2021-05-05 Thread forax
> De: "Brian Goetz" 
> À: "Remi Forax" , "valhalla-spec-experts"
> 
> Envoyé: Mercredi 5 Mai 2021 20:20:07
> Objet: Re: Meeting today: IdentityClass

> Here are some idioms I can imagine a use for with IdentityObject:

> // parameter type
> void withLock(IdentityObject monitor, Runnable task)

> // type bound
> Map map = ... // gonna lock on keys

> // dynamic check
> if (x instanceof IdentityObject) {
> sync (x) { task(); }
> }
> else {
> sync (GLOBAL_LOCK) { task(); }
> }

> // reflective check against class
> Class c = ...
> if (IdentityObject.class.isAssignableFrom(c)) { ... }

> The "fake type" approach handles the first two cases well enough. But it 
> doesn't
> address the latter two cases; for that we'd need to expose a
> Class::isIdentityClass (x.getClass().isIdentityClass()), which seems workable,
> though might feel gratuitously different from the first two.
Erasure in the generic sense (sorry for the pun) is the way to retcon types as 
if they were present since the beginning in Java. 
So it fit well with the idea of IdentityObject/PrimitiveObject. 

Now, i think there are two kind of erasures, we have classic erasure by the 
compiler only like with generics and we have erasure with TypeRestriction which 
involve the VM. 
Note that the erasure using TypeRestriction does not necessarily implies any 
parametric type, this is a separate mechanism. 

As you said, classic erasure only supports the first two scenarios, while i 
believe that erasure by TypeRestriction support all of them. 

> Erasing to Object means that we don't get to do things like overloading:

> m(IdentityObject o) { ... }
> m(PrimitiveObject o) { ... }

> or

> m(IdentityObject o) { ... }
> m(Object o) { ... }
Sadly, this scenario is not supported by both kinds of erasure. 

And as i said two weeks ago, erasure by TypeRestriction is also something 
interesting for value based classes, at least some of them, the ones that do 
not allow null, by example for Optional. 
Optional the Q-type can be erased as Optional the L-type everywhere in the 
existing method signatures so we have binary backward compatibility at the 
price of 
- having the VM to lightweight box/unbox at the inlining horizons and 
- spurious NPEs where a null is sent as an Optional. 

Obviously, this is an incomplete proposal, but i think it's worth to take a 
look into that direction. 

Rémi 

> On 5/5/2021 10:39 AM, Remi Forax wrote:

>> If it's possible, i would like to discuss about IdentityClass again.

>> As noted in the last draft, adding IdentityClass automatically at runtime is 
>> not
>> a compatible change if tests that uses Class::getInterfaces() are not written
>> correctly,
>> and sadly, a lot of tests are written that way. I'm guilty to having written
>> those tests too.
>> I don't believe that the solution is to tweak the reflection because adding
>> IdentityClass at runtime is already a hack and introducing a hack² (hack 
>> square
>> hack) is usually where we should stop before anyone sanity goes under the 
>> bus.

>> The purpose of IdentityClass is
>> - to have a classfile for the javadoc describing the behavior of all identity
>> class
>> - to be used as type or bound of type parameter.

>> Apart the result of Class::getInterfaces() being hardcoded, IdentityClass 
>> has to
>> other issues, as javadoc container, given that IdentityClass is inserted by 
>> the
>> VM, it means there is no place in the Java code where someone can click to 
>> see
>> the javadoc in an IDE, we have the same issue with java.lang.Record 
>> currently,
>> the class is added by javac automatically and unlike java.lang.Enum, there is
>> no method useful on java.lang.Record (equals/hashCode and toString are 
>> defined
>> directly on the record) so very few of my student where able to understand 
>> why
>> a record with a NaN value was equals to itself.
>> But there is a more serious issue, using IdentityClass is not backward
>> compatible with Object.
>> When we have introduced IdentityClass, one scenario was to be able to declare
>> that the type parameter corresponding to the keys (K) to only support 
>> identity
>> class.
>> This is not possible using IdentityClass because the erasure of K will be
>> IdentityClass instead of Object (IdentityClass also appears when the compiler
>> will to a lub, so the common class of String and URI will be computed as
>> IdentityClass instead of Object leading to source compatibility issues).

>> I think at that point, we should go back to our blackboard and see if there 
>> is
>> no other solution.

>> I see two, one is to do *nothing* and do not add a type saying that only
>> identity class is a corner case after all,
>> the other is to piggyback on erasure not unlike Scala does, i.e. 
>> IdentityClass
>> is a fake class that is erased to Object at runtime.

>> regards,
>> Rémi


Re: Meeting today: IdentityClass

2021-05-05 Thread Brian Goetz

Here are some idioms I can imagine a use for with IdentityObject:

    // parameter type
    void withLock(IdentityObject monitor, Runnable task)

    // type bound
    Map map = ...  // gonna lock on keys

    // dynamic check
    if (x instanceof IdentityObject) {
    sync (x) { task(); }
    }
    else {
    sync (GLOBAL_LOCK) { task(); }
    }

    // reflective check against class
    Class c = ...
    if (IdentityObject.class.isAssignableFrom(c)) { ... }

The "fake type" approach handles the first two cases well enough.  But 
it doesn't address the latter two cases; for that we'd need to expose a 
Class::isIdentityClass (x.getClass().isIdentityClass()), which seems 
workable, though might feel gratuitously different from the first two.


Erasing to Object means that we don't get to do things like overloading:

    m(IdentityObject o) { ... }
    m(PrimitiveObject o) { ... }

or

    m(IdentityObject o) { ... }
    m(Object o) { ... }




On 5/5/2021 10:39 AM, Remi Forax wrote:

If it's possible, i would like to discuss about IdentityClass again.

As noted in the last draft, adding IdentityClass automatically at runtime is 
not a compatible change if tests that uses Class::getInterfaces() are not 
written correctly,
and sadly, a lot of tests are written that way. I'm guilty to having written 
those tests too.
I don't believe that the solution is to tweak the reflection because adding 
IdentityClass at runtime is already a hack and introducing a hack² (hack square 
hack) is usually where we should stop before anyone sanity goes under the bus.

The purpose of IdentityClass is
- to have a classfile for the javadoc describing the behavior of all identity 
class
- to be used as type or bound of type parameter.

Apart the result of Class::getInterfaces() being hardcoded, IdentityClass has 
to other issues, as javadoc container, given that IdentityClass is inserted by 
the VM, it means there is no place in the Java code where someone can click to 
see the javadoc in an IDE, we have the same issue with java.lang.Record 
currently, the class is added by javac automatically and unlike java.lang.Enum, 
there is no method useful on java.lang.Record (equals/hashCode and toString are 
defined directly on the record) so very few of my student where able to 
understand why a record with a NaN value was equals to itself.
But there is a more serious issue, using IdentityClass is not backward 
compatible with Object.
When we have introduced IdentityClass, one scenario was to be able to declare 
that the type parameter corresponding to the keys (K) to only support identity 
class.
This is not possible using IdentityClass because the erasure of K will be 
IdentityClass instead of Object (IdentityClass also appears when the compiler 
will to a lub, so the common class of String and URI will be computed as 
IdentityClass instead of Object leading to source compatibility issues).

I think at that point, we should go back to our blackboard and see if there is 
no other solution.

I see two, one is to do *nothing* and do not add a type saying that only 
identity class is a corner case after all,
the other is to piggyback on erasure not unlike Scala does, i.e. IdentityClass 
is a fake class that is erased to Object at runtime.

regards,
Rémi





Re: Meeting today: IdentityObject

2021-05-05 Thread Remi Forax
There is a 3rd way, uses the TypeRestriction attribute to still be binary 
backward compatible.

Let suppose that we have a way to say that javac needs to use TypeRestriction 
when generating a specific type in the class file
like
  import ...

  __restrict__ java.lang.IdentityObject __to__ java.lang.Object;

Rémi

- Mail original -
> De: "Remi Forax" 
> À: "valhalla-spec-experts" 
> Envoyé: Mercredi 5 Mai 2021 16:39:01
> Objet: Meeting today: IdentityClass

> If it's possible, i would like to discuss about IdentityClass again.
> 
> As noted in the last draft, adding IdentityClass automatically at runtime is 
> not
> a compatible change if tests that uses Class::getInterfaces() are not written
> correctly,
> and sadly, a lot of tests are written that way. I'm guilty to having written
> those tests too.
> I don't believe that the solution is to tweak the reflection because adding
> IdentityClass at runtime is already a hack and introducing a hack² (hack 
> square
> hack) is usually where we should stop before anyone sanity goes under the bus.
> 
> The purpose of IdentityClass is
> - to have a classfile for the javadoc describing the behavior of all identity
> class
> - to be used as type or bound of type parameter.
> 
> Apart the result of Class::getInterfaces() being hardcoded, IdentityClass has 
> to
> other issues, as javadoc container, given that IdentityClass is inserted by 
> the
> VM, it means there is no place in the Java code where someone can click to see
> the javadoc in an IDE, we have the same issue with java.lang.Record currently,
> the class is added by javac automatically and unlike java.lang.Enum, there is
> no method useful on java.lang.Record (equals/hashCode and toString are defined
> directly on the record) so very few of my student where able to understand why
> a record with a NaN value was equals to itself.
> But there is a more serious issue, using IdentityClass is not backward
> compatible with Object.
> When we have introduced IdentityClass, one scenario was to be able to declare
> that the type parameter corresponding to the keys (K) to only support identity
> class.
> This is not possible using IdentityClass because the erasure of K will be
> IdentityClass instead of Object (IdentityClass also appears when the compiler
> will to a lub, so the common class of String and URI will be computed as
> IdentityClass instead of Object leading to source compatibility issues).
> 
> I think at that point, we should go back to our blackboard and see if there is
> no other solution.
> 
> I see two, one is to do *nothing* and do not add a type saying that only
> identity class is a corner case after all,
> the other is to piggyback on erasure not unlike Scala does, i.e. IdentityClass
> is a fake class that is erased to Object at runtime.
> 
> regards,
> Rémi


Re: Meeting today ?

2017-06-21 Thread Karen Kinnear
https://oracle.zoom.us/j/251372518

> On Jun 21, 2017, at 11:00 AM, Remi Forax  wrote:
> 
> Hi all,
> does somebody can send me the correct URL for the meeting today ?
> 
> cheers,
> Rémi