Re: [External] : Re: SoV-2: weak references
> * For WeakHashMap use cases, I would expect that any attempts to actually > design something "good" that does what users really "want" would end up at > some different library entirely. This is something that Caffeine probably > does well (disclosure, I worked on the thing that became that). > > > Yes, probably. We're worried about existing applications that are built > around WHM, and trying to give them something reasonable that will keep them > going, since many of these are legacy applications with limited room for > rearchitecting. So we're asking "what's the least we have to do", and the > simple set of policies I outlined for WHM is a candidate. I think Kevin's hit on the key point here - WHM as a cache is often used incorrectly and we'd be better off designing something different entirely to solve that use case. This matches the feedback I've gotten when polling Red Hat developers. Breaking the "values as WHM keys" issue into use cases: Single maintenance domain: (A) Migrates its own classes to values and uses them as WHM keys (B) Uses value-based classes as WHM keys and breaks in Valhalla when these become values Cross maintenance domain: (C) Other library changes its classes to be values, our library uses them as WHM keys (D) Our library changes its classes to be values, Other library uses them as WHM keys Both (A) and (D) are very similar and are essentially a consequence of not understanding how users (self, others) are using your classes. This is a consequence of migrating existing classes, and just like with synchronization, users should expect it to fail with an exception. Don't like the exception? Don't migrate the class to be a value. Cases (B) and (C) are very similar if we treat the JDK as "another library". And this is probably the hardest case as it intersects with supported JDK versions. Running on a JDK that supports Valhalla doesn't guarantee that all the maintenance domains were compiled on new enough JDKs. If the library is supported on both pre-Valhalla JDK and Valhalla-JDK, then it can't easily take advantage of the new WHM models being proposed. (caveats: MR jars, reflection related workarounds, ...) And if the domain is only on post-Valhalla JDKs, then the user is in a place to put explicit checks for values into their code (or better, stop using WHM all together). Trying to keep WHM working for values is encouraging the ecosystem to throw good money (effort) after bad. The "keep it working" attempts just shift the problem from a clear exception to an on-call nightmare when the leaking WHM causes the service to go down. I know which I'd prefer. --Dan
Re: JEP update: Classes for the Basic Primitives
* Could the doc make a clearer distinction (throughout) between which facts about int/Integer are happening because we expect *all* bucket-3 classes to work that way, vs. which are special one-off tweaks for the 8 predefined types? A "how are int/Integer special" section would indeed be useful. And I think we haven't finished enumerating what goes in it; in the discussions over inference, for example, several folks have been heard mumbling "maybe we're trying to push the int/Integer analogy too far." * I'm curious whether it would be /possible/ to make `int` no longer a keyword, just a special kind of type alias that normal people don't get to declare. I'm /not/ claiming that'd be worth actually doing; just wanting to understand what forces would act to prevent it, as part of understanding everything that makes the 8 builtin types "irredeemably special". In a previous world, `int` could have been an alias for `Integer.val`. But we (happily) have banished .val from the world. I think this is a useful exercise anyway, though; we have stumbled over type-vs-class in a lot of places already with respect to B3, and int has similar problems; most uses of `int` are types, but there's also `int.class`, which means ... something. What exactly? And how does that differ from Point.class / Point.ref.class / Point.class.noNotThatClassTheOtherClass() ? * I assume the reason "the JVM type Qjava/lang/Double cannot be encoded with a Class object" is because the distinction between it and D is intentional implementation detail. Worse :( The J and D carriers use two slots, so even if we wanted to abstract over the primitive carriers, this is kind of a dead end. The java/lang/Double class allows us to encode List with a class that carries a double but fits in one slot. * Since I think/hope it is /not/ true that `int` will be a subtype of `Integer`, it's not 100% clear whether the phrase "array covariance" in the doc is referring to the (desirable) property that `int[] <: Integer[]`. I think it is. int will not be a subtype of Integer, nor will Point be a subtype of Point.ref. (It was this way in a previous iteration; the VM still believes the latter, but we're probably going to disabuse it of same.) Traditional array covariance is tied to subtyping: T <: U -- T-Cov T[] <: U[] But, we're going to modify this rule somewhat. We define a relation between types, called "extends". A extends B = A <: B if A is a reference type A.ref <: B otherwise (We could write this more concisely as "A extends B == A.ref <: B", since the .ref operator is idempotent.) We use "extends" for things like bounds conformance; if we have Foo, we treat Foo as being in bounds. So our modified covariance is: T extends U -- T-Cov-Ext T[] <: U[] which gives us int[] <: Integer[], even though we don't have int <: Integer. This is no mere flourish; without it, erased generics don't work: class Box { T value(); T[] asArray(); } This erases to returning Object[], and if we want to specialize Box, asArray() should return int[], but to be compatible with erasure, we need int[] <: Object[]. * I said in the meeting that "I don't think anyone cares" what kind of exception gets thrown if trying to store null in an `Integer[]` which is secretly an `int[]`. Well, I'm sure that's not at all true. :-) Sorry. You're lucky they didn't show you their scars. * Re: "a basic primitive class may declare an instance field of its own primitive" -- does it really need that field, or can we nuke it and just s/value/this/g throughout the file? If that could work, it would be so much less confusing -- nothing circular! The only magic would be "where are the actual bits??" but you don't see the bits of an object header in `Object.java` either and the number of people this bothers is a very round number. Seems plausible :)
Re: Abstract class with fields implementing ValueObject
- Original Message - > From: "John Rose" > To: "Frederic Parain" > Cc: "valhalla-spec-experts" > Sent: Thursday, February 10, 2022 12:02:53 AM > Subject: Re: Abstract class with fields implementing ValueObject > That could be one of very many edge conditions in the JVMS that are not > diagnosed directly by a validation, but that will eventually cause an error > when the broken classfile is further used. > > I don’t think there needs to be a special rule for this. We don’t try to > comprehensively diagnose all “impossible-to-use” classfiles. or better we ditch ValueObject and IdentityObject ... Rémi > > On 9 Feb 2022, at 13:50, Frederic Parain wrote: > >> There's a weird case that seems to be allowed by the Value Objects JVMS >> draft: >> >> An abstract class can declare non-static fields, which means it won't >> have the ACC_PERMITS_VALUE flag set, but also declare that it implements >> the ValueObject interface. >> >> The combination looks just wrong, because no class can subclass such class: >> - identity classes are not allowed because of the presence of >> the ValueObject interface >> - value classes are not allowed because of the absence of >> ACC_PERMITS_VALUE >> >> I've looked for a rule that would prohibit such combination in the >> JVMS draft but couldn't find one. >> >> Did I miss something? >> > > Fred
Re: EG meeting, 2022-02-09 [SoV-3: constructor questions]
> From: "John Rose" > To: "daniel smith" > Cc: "valhalla-spec-experts" > Sent: Wednesday, February 9, 2022 7:32:07 PM > Subject: Re: EG meeting, 2022-02-09 [SoV-3: constructor questions] > On 8 Feb 2022, at 19:04, Dan Smith wrote: >> "SoV-3: constructor questions": Dan asked about validation for and >> >> methods. Answer: JVM doesn't care about methods in abstract classes, >> the >> rules about methods still uncertain. > On the question of JVM validation of methods, I’m in favor of as few > rules > as possible, ideally treating as just another name. It’s super-power is > not in its restrictions but in its conventionality: It’s the obvious choice > for > constructor factory methods. But it is not necessarily limited to that use. > Maximal limitation would be that a method can only occur as the > translation of a value-class constructor. Any evidence in the classfile that > it > was not such a translation would be grounds for failing a validation check. > We’d make as many such rules as we can think of. > Arguments against: >* Having a special method identifier in the JVMs without other restrictions > would be a new thing, and hence suspicious. >* Limiting the use of as much as possible makes it clear, to higher > layers >of the code (javac and reflection) what is going on in the class file, as a > “reflection” of the source file. >* Reflection of an irregular (non-source-conforming) method has to be > messy. (Is it really a constructor? Or is it just a method named ?) > Arguments in favor: >* It is a new thing in the JVM for any descriptor to be constrained to > mention >the same name as is the name of the constant pool item referred to by > ClassFile.this_class item (JVMS 4.1). (It is suspicious.) >* A maximal limitation would break hidden classes. (They must sometimes > return a >supertype from their factories, since the HC is not always name-able in a > descriptor. HCs only work because the previous point.) >* A limitation might preclude a perhaps-desirable future translation > strategy >that used factories uniformly to translate new source code > expressions > (identity or value objects, uniformly). >* A limitation could remove a natural translation strategy for “canonical >factory methods” in non-concrete types. This is a hypothetical language > feature >for Java or some other language. (E.g., new List(a,b,c) instead of >List.of(a,b,c) , removing the need of the user to remember whether the > word was > of or make or build or some other designer choice.) >* Most any limitation would preclude ad hoc use of factories by >translation strategies of other languages, such as Scala and Clojure, which >surely have their own uses of JVM object life cycles. We want to be > friendly to > non-Java languages. > Compromise positions: >* Require a method to be ACC_STATIC but allow for any purpose (i.e., > any > access and any descriptor). >* Require a method to return either the class named by this_class or > some > super type (TBD how this should be checked). > I would prefer the first compromise: It’s static but otherwise the JVM asks no > questions. > Regarding reflection, I think it would be OK to surface all of the > methods > (of whatever signature) on the getConstructors list, even if they return > “something odd”. Alternatively, to prevent a sharp edge we could have a new > list Class::getFactories , and copy (not move) entries from that list onto > getConstructors exactly when the return type matches the enclosing class. That > is a more natural move for reflection (which operates on runtime types) than > for class file structuring (which is more static). > The reason I prefer to require static marking is that it would prevent the > funny > name from appearing on the list of regular methods, via reflection. I agree with static being the only requirement for the VM side. For reflection,i prefer the first alternative, surface the method whatever the return type given that the return type is a declared type, not a runtime class. Dynamically typed languages like Groovy or JRuby may want to declare that the return type of is java.lang.Object (it's the default type if no type is provided in Groovy), if reflection filter out those methods, it will be bad for the interropt between Java and those dynamically typed languages. Rémi