From forax at univ-mlv.fr Wed Dec 2 10:53:55 2020 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 2 Dec 2020 11:53:55 +0100 (CET) Subject: Using a Condy instead of a Constant_Utf8 Message-ID: <1989096518.1942673.1606906435023.JavaMail.zimbra@u-pem.fr> Using a condy that returns a String instead of a method descriptor in the bytecode ? I'm currently trying to remove the uses of Unsafe.defineAnonymousClass to use Lookup.defineHiddenClass instead. There is one case where i dynamically patch a method descriptor so I can select how many arguments will be sent to a closure, i.e. in the bytecode i put all arguments on the stack but because i've patched the callee descriptor, only some of them will be used. I see defineAnonymousClass has a way to push data to a template class file and defineHiddenClass has a way to pull the data from the template class file. But i can not currently pull data that will be used by a NameAndType info because the descriptor_index has to be a Constant_Utf8 index and can not be a condy with a String as descriptor. This is related to Lazy static final field [1] and also to class templating in general because it equivalent to seeing all the template holes as condy even if it"s less efficient because you need to duplicate the whole constant pool. R?mi [1] https://bugs.openjdk.java.net/browse/JDK-8209964 From forax at univ-mlv.fr Wed Dec 2 11:03:39 2020 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 2 Dec 2020 12:03:39 +0100 (CET) Subject: Use of Class.getSimpleName() in java.lang.invoke and InnerClass attribute verification Message-ID: <1191366945.1952972.1606907019194.JavaMail.zimbra@u-pem.fr> Most of the error message form the error that can be thrown by classes of java.lang.invoke are using Class.getSimpleName() which makes debugging hidden classes painful because getSimpleName() scrubs the hexadecimal number part of a hidden class name. It also seems that the VM has a zealot stance on the InnerClass attribute verification, which i think is wrong. see https://mail.openjdk.java.net/pipermail/core-libs-dev/2020-November/071813.html R?mi From forax at univ-mlv.fr Wed Dec 2 12:09:45 2020 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 2 Dec 2020 13:09:45 +0100 (CET) Subject: Inline Record vs JLS / Reflection Message-ID: <1438116307.2000871.1606910985956.JavaMail.zimbra@u-pem.fr> Hi all, currently an inline record like this public @__inline__ record IntBox(int value) { } generates two classes, IntBox and IntBox$ref, IntBox being the record itself and IntBox$ref being the abstract class representing the nullable version of an inline that inherits from java.lang.Record. This doesn't works well with the JLS view / the reflection API because for them a record class is a direct super class of java.lang.Record while in this case java.lang.Record is not a direct super type. I believe the reflection should be changed to say that a record is a subtype of java.lang.Record. R?mi From daniel.smith at oracle.com Wed Dec 2 15:25:44 2020 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 2 Dec 2020 08:25:44 -0700 Subject: EG meeting *canceled*, 2020-12-02 Message-ID: <21AB83E3-4105-43CF-81B5-B00939F5F5A6@oracle.com> All quiet on the list the last couple of weeks. Let's cancel today's meeting. We'll also want to cancel the meeting at the end of the month. So the upcoming schedule is: December 16 January 13 January 27 Remi has posted a few miscellaneous questions this morning, which I think are best addressed by getting the right people to discuss over email. If that leads to something of general interest, we can touch on it next time. Please note that JEP 390, Warnings for Value-based Classes, has been Proposed to Target JDK 16: https://mail.openjdk.java.net/pipermail/jdk-dev/2020-November/004977.html From daniel.smith at oracle.com Wed Dec 2 15:35:06 2020 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 2 Dec 2020 08:35:06 -0700 Subject: Using a Condy instead of a Constant_Utf8 In-Reply-To: <1989096518.1942673.1606906435023.JavaMail.zimbra@u-pem.fr> References: <1989096518.1942673.1606906435023.JavaMail.zimbra@u-pem.fr> Message-ID: <745067D0-0BBB-4135-956A-C63BE1A833BF@oracle.com> > On Dec 2, 2020, at 3:53 AM, Remi Forax wrote: > > Using a condy that returns a String instead of a method descriptor in the bytecode ? > I'm currently trying to remove the uses of Unsafe.defineAnonymousClass to use Lookup.defineHiddenClass instead. > There is one case where i dynamically patch a method descriptor so I can select how many arguments will be sent to a closure, > i.e. in the bytecode i put all arguments on the stack but because i've patched the callee descriptor, only some of them will be used. > > I see defineAnonymousClass has a way to push data to a template class file and defineHiddenClass has a way to pull the data from the template class file. > But i can not currently pull data that will be used by a NameAndType info because the descriptor_index has to be a Constant_Utf8 index and can not be a condy with a String as descriptor. The trouble I see with changing NameAndType is that verification needs a static string. At that stage, it's too early to be resolving condys. > This is related to Lazy static final field [1] and also to class templating in general because it equivalent to seeing all the template holes as condy even if it"s less efficient because you need to duplicate the whole constant pool. Lazy static fields, if I understand the proposal correctly, use a condy to determine the _value_ of the field, but not its _type_. Linkage behavior is unchanged. Similarly, our preferred story for templating right now is to use normal Utf8 strings for descriptors, and give each species different side-channel type information, computed via condy. This side information is needed fairly early, but verification is entirely descriptor-string-based. From john.r.rose at oracle.com Wed Dec 2 18:56:14 2020 From: john.r.rose at oracle.com (John Rose) Date: Wed, 2 Dec 2020 10:56:14 -0800 Subject: Using a Condy instead of a Constant_Utf8 In-Reply-To: <1989096518.1942673.1606906435023.JavaMail.zimbra@u-pem.fr> References: <1989096518.1942673.1606906435023.JavaMail.zimbra@u-pem.fr> Message-ID: On Dec 2, 2020, at 2:53 AM, Remi Forax wrote: > > There is one case where i dynamically patch a method descriptor so I can select how many arguments will be sent to a closure, > i.e. in the bytecode i put all arguments on the stack but because i've patched the callee descriptor, only some of them will be used. One workaround out of many: Put a switch in your class template, one case per supported arity (limited by the number of stacked items). Then use a fixed descriptor for the call on each arm. Drive the switch from a condy. BTW, if you need to down-cast from Object, use Class::cast on a dynamic Class constant. In the JIT those fold up the same as checkcast. Or just use asType. I?m guessing you are calling MH::invokeExact or some other low-level ?erased? API point, so casting is not strictly necessary but it may help the JIT. ? John From forax at univ-mlv.fr Thu Dec 3 09:41:03 2020 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 3 Dec 2020 10:41:03 +0100 (CET) Subject: Using a Condy instead of a Constant_Utf8 In-Reply-To: <745067D0-0BBB-4135-956A-C63BE1A833BF@oracle.com> References: <1989096518.1942673.1606906435023.JavaMail.zimbra@u-pem.fr> <745067D0-0BBB-4135-956A-C63BE1A833BF@oracle.com> Message-ID: <671755820.194390.1606988463069.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "daniel smith" > ?: "Remi Forax" > Cc: "valhalla-spec-experts" > Envoy?: Mercredi 2 D?cembre 2020 16:35:06 > Objet: Re: Using a Condy instead of a Constant_Utf8 >> On Dec 2, 2020, at 3:53 AM, Remi Forax wrote: >> >> Using a condy that returns a String instead of a method descriptor in the >> bytecode ? >> I'm currently trying to remove the uses of Unsafe.defineAnonymousClass to use >> Lookup.defineHiddenClass instead. >> There is one case where i dynamically patch a method descriptor so I can select >> how many arguments will be sent to a closure, >> i.e. in the bytecode i put all arguments on the stack but because i've patched >> the callee descriptor, only some of them will be used. >> >> I see defineAnonymousClass has a way to push data to a template class file and >> defineHiddenClass has a way to pull the data from the template class file. >> But i can not currently pull data that will be used by a NameAndType info >> because the descriptor_index has to be a Constant_Utf8 index and can not be a >> condy with a String as descriptor. > > The trouble I see with changing NameAndType is that verification needs a static > string. At that stage, it's too early to be resolving condys. yes, thanks, I think the other Dan (Hedinga) already said that but i've a hard time to remember it. > >> This is related to Lazy static final field [1] and also to class templating in >> general because it equivalent to seeing all the template holes as condy even if >> it"s less efficient because you need to duplicate the whole constant pool. > > Lazy static fields, if I understand the proposal correctly, use a condy to > determine the _value_ of the field, but not its _type_. Linkage behavior is > unchanged. > > Similarly, our preferred story for templating right now is to use normal Utf8 > strings for descriptors, and give each species different side-channel type > information, computed via condy. This side information is needed fairly early, > but verification is entirely descriptor-string-based. good to know. R?mi From brian.goetz at oracle.com Fri Dec 4 18:27:55 2020 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 4 Dec 2020 13:27:55 -0500 Subject: Updated State of Valhalla docs Message-ID: <171610da-1500-3cc6-5d5f-0600a5738af0@oracle.com> I've updated the first two State of Valhalla docs to the latest design, and staged them in their new repo.? They can be viewed here: https://github.com/openjdk/valhalla-docs/blob/main/site/design-notes/state-of-valhalla/01-background.md https://github.com/openjdk/valhalla-docs/blob/main/site/design-notes/state-of-valhalla/02-object-model.md Though, these are not their permanent homes, and there are several what appear to be formatting errors, which are artifacts of the skew between pandoc markdown and github markdown.? Still working on infra to properly format and push to the OpenJDK website, which will be the real home for these docs. From daniel.smith at oracle.com Tue Dec 15 23:05:47 2020 From: daniel.smith at oracle.com (Dan Smith) Date: Tue, 15 Dec 2020 16:05:47 -0700 Subject: EG meeting, 2020-12-16 Message-ID: <4946029E-5463-4A81-89B1-B4A8FD882464@oracle.com> The next EG Zoom meeting is Wednesday at 4pm UTC (9am PDT, 12pm EDT). This seems like a good opportunity to take stock of where we're at, including any discussion about "Updated State of Valhalla docs". I can add some structure on the anticipated JEPs as we move forward. Something like: Preparatory tasks - Additional wrapper class migration tooling - JLS revisions to facilitate type system enhancements - JVMS revisions, including improvements to the spec of class file validation Core features - Primitive objects (JVM & language features) - Migrate the wrapper classes (mostly language) - Universal type variables (language feature) Specialization - Specialized classes & methods (mostly JVM) (might become multiple finer-grained pieces) --- Remi also had a couple of unresolved threads that we can discuss as needed: - "Use of Class.getSimpleName() in java.lang.invoke and InnerClass attribute verification" - "Inline Record vs JLS / Reflection" From daniel.smith at oracle.com Wed Dec 16 17:02:12 2020 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 16 Dec 2020 10:02:12 -0700 Subject: EG meeting, 2020-12-16 In-Reply-To: <4946029E-5463-4A81-89B1-B4A8FD882464@oracle.com> References: <4946029E-5463-4A81-89B1-B4A8FD882464@oracle.com> Message-ID: > On Dec 15, 2020, at 4:05 PM, Dan Smith wrote: > > The next EG Zoom meeting is Wednesday at 4pm UTC (9am PDT, 12pm EDT). Err, looks like my meeting ID doesn't work anymore. Stand by, I'll update the calendar... From daniel.smith at oracle.com Wed Dec 16 17:06:23 2020 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 16 Dec 2020 10:06:23 -0700 Subject: EG meeting, 2020-12-16 In-Reply-To: References: <4946029E-5463-4A81-89B1-B4A8FD882464@oracle.com> Message-ID: <775BA911-4696-4468-BE78-781A85EEA15B@oracle.com> > On Dec 16, 2020, at 10:02 AM, Dan Smith wrote: > >> On Dec 15, 2020, at 4:05 PM, Dan Smith wrote: >> >> The next EG Zoom meeting is Wednesday at 4pm UTC (9am PDT, 12pm EDT). > > Err, looks like my meeting ID doesn't work anymore. Stand by, I'll update the calendar... Had to update my password, sorry about that. See invitation, or email me directly if you don't have it. (Quite possible everybody's on vacation today anyway, we'll see who shows up.) From daniel.smith at oracle.com Wed Dec 16 18:00:57 2020 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 16 Dec 2020 11:00:57 -0700 Subject: EG meeting, 2020-12-16 In-Reply-To: <4946029E-5463-4A81-89B1-B4A8FD882464@oracle.com> References: <4946029E-5463-4A81-89B1-B4A8FD882464@oracle.com> Message-ID: > On Dec 15, 2020, at 4:05 PM, Dan Smith wrote: > > The next EG Zoom meeting is Wednesday at 4pm UTC (9am PDT, 12pm EDT). > > This seems like a good opportunity to take stock of where we're at, including any discussion about "Updated State of Valhalla docs". R?mi raised some questions about our story for int vs. Integer vs. legacy uses of 'new Integer'?how many implementation classes are there? (should we use species?); what does reflection look like? We agreed it still needs some polishing. Dan says it looks good, matches previous discussions and what he expected. > Remi also had a couple of unresolved threads that we can discuss as needed: > > - "Use of Class.getSimpleName() in java.lang.invoke and InnerClass attribute verification" He'll raise this in another list at the implementation level. > - "Inline Record vs JLS / Reflection" There is an open issue here. I'll reply to the email. From daniel.smith at oracle.com Wed Dec 16 18:07:44 2020 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 16 Dec 2020 11:07:44 -0700 Subject: Inline Record vs JLS / Reflection In-Reply-To: <1438116307.2000871.1606910985956.JavaMail.zimbra@u-pem.fr> References: <1438116307.2000871.1606910985956.JavaMail.zimbra@u-pem.fr> Message-ID: > On Dec 2, 2020, at 5:09 AM, Remi Forax wrote: > > Hi all, > currently an inline record like this > public @__inline__ record IntBox(int value) { > } > > generates two classes, IntBox and IntBox$ref, IntBox being the record itself and IntBox$ref being the abstract class representing the nullable version of an inline that inherits from java.lang.Record. > > This doesn't works well with the JLS view / the reflection API because for them a record class is a direct super class of java.lang.Record while in this case java.lang.Record is not a direct super type. > I believe the reflection should be changed to say that a record is a subtype of java.lang.Record. Yes, the fact that the superclass of a primitive record class is *not* java.lang.Record is surprising and potentially breaks some things. This is one manifestation of the problem, but more generally it will be surprising to reflection clients that a class that 'extends Foo' (where Foo is a primitive-compatible abstract class) doesn't have 'Foo' as its superclass. I don't think we have a good answer right now, but it's something we will want to address at some point. A solution would have to look like one of: - Ask clients (e.g., "is this a record?" code) to adapt to the presence of the '$ref' class - Modify reflection to hide the '$ref' superclass somehow - Change the translation strategy to not disrupt the superclass hierarchy From john.r.rose at oracle.com Wed Dec 16 19:09:44 2020 From: john.r.rose at oracle.com (John Rose) Date: Wed, 16 Dec 2020 12:09:44 -0700 Subject: Inline Record vs JLS / Reflection In-Reply-To: References: <1438116307.2000871.1606910985956.JavaMail.zimbra@u-pem.fr> Message-ID: <7E96A4BC-94AB-4ADC-8851-22201B5B724C@oracle.com> On Dec 16, 2020, at 11:07 AM, Dan Smith wrote: > > I don't think we have a good answer right now, but it's something we will want to address at some point. A solution would have to look like one of: > > - Ask clients (e.g., "is this a record?" code) to adapt to the presence of the '$ref' class > - Modify reflection to hide the '$ref' superclass somehow > - Change the translation strategy to not disrupt the superclass hierarchy The last is cleanest; the cost is resolving some technical debt in Valhalla, which is allowing more kinds of supers for primitive classes. There?s no firm reason, IMO, why Record could not be a super of both primitive and identity classes, all of which are proper records. Basically we need to make interfaces and abstract classes look a little more similar, with respect to the requirements of primitive classes. Spoiler alert: I think the final solution will endow abstract classes with *both* abstract and concrete constructors. The former will serve primitive classes and the latter will serve identity classes. Record will be such an abstract class. (Alternatively, and more clumsily, Record could be refactored as a proper interface, but sealed to PrimitiveRecord and IdentityRecord, and javac would translate to one or the other. The methods on JLO would not be defaults on record but would be duplicated on the two sealed subtypes.) ? John From forax at univ-mlv.fr Wed Dec 16 19:39:30 2020 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Wed, 16 Dec 2020 20:39:30 +0100 (CET) Subject: Inline Record vs JLS / Reflection In-Reply-To: <7E96A4BC-94AB-4ADC-8851-22201B5B724C@oracle.com> References: <1438116307.2000871.1606910985956.JavaMail.zimbra@u-pem.fr> <7E96A4BC-94AB-4ADC-8851-22201B5B724C@oracle.com> Message-ID: <314918929.2563976.1608147570529.JavaMail.zimbra@u-pem.fr> > De: "John Rose" > ?: "daniel smith" > Cc: "Remi Forax" , "valhalla-spec-experts" > > Envoy?: Mercredi 16 D?cembre 2020 20:09:44 > Objet: Re: Inline Record vs JLS / Reflection > On Dec 16, 2020, at 11:07 AM, Dan Smith < [ mailto:daniel.smith at oracle.com | > daniel.smith at oracle.com ] > wrote: >> I don't think we have a good answer right now, but it's something we will want >> to address at some point. A solution would have to look like one of: >> - Ask clients (e.g., "is this a record?" code) to adapt to the presence of the >> '$ref' class >> - Modify reflection to hide the '$ref' superclass somehow >> - Change the translation strategy to not disrupt the superclass hierarchy I will add that we also have the same issue with enums, should a primitive enum extends java.lang.Enum ? > The last is cleanest; the cost is resolving some technical > debt in Valhalla, which is allowing more kinds of supers > for primitive classes. There?s no firm reason, IMO, why > Record could not be a super of both primitive and identity > classes, all of which are proper records. Basically we need > to make interfaces and abstract classes look a little more > similar, with respect to the requirements of primitive > classes. yes, in the case of enum it's more difficult because ordinal and name are fields in java.lang.Enum. > Spoiler alert: I think the final solution will endow > abstract classes with *both* abstract and concrete > constructors. The former will serve primitive > classes and the latter will serve identity classes. > Record will be such an abstract class. By abstract constructors, i suppose you mean empty constructors so they can be bypassed when creating a primitive type. It will not work with java.lang.Enum. For enums, we need have both constructors and factory methods and a way to ensure that they are semantically equivalent. One possibility is to have the VM generating the factory methods code only inside the primitive type from the chain of superclasses, doing the transformation that is currently done by the compiler at runtime. It can works that way, if i want a primitive enum, the constructor of java.lang.Enum has to be marked as transformable to a factory method, same thing for the constructor of the primitive enum itself. For java.lang.Enum an for any classes of a primitive enum, an empty factory method is generated with a descriptor, an empty body, and an attribute pointing to the corresponding constructor. At runtime, when the class is loaded, the VM insert the correct code in the factory method of the non abstract class. If the VM generates the code, we are sure that the constructor and the factory method are both equivalent. Another solution is to have a special verifying pass that verify that the constructor and the factory method are both equivalent, but it seems harder to me. [...] > ? John R?mi From john.r.rose at oracle.com Wed Dec 16 19:58:06 2020 From: john.r.rose at oracle.com (John Rose) Date: Wed, 16 Dec 2020 12:58:06 -0700 Subject: Inline Record vs JLS / Reflection In-Reply-To: <314918929.2563976.1608147570529.JavaMail.zimbra@u-pem.fr> References: <1438116307.2000871.1606910985956.JavaMail.zimbra@u-pem.fr> <7E96A4BC-94AB-4ADC-8851-22201B5B724C@oracle.com> <314918929.2563976.1608147570529.JavaMail.zimbra@u-pem.fr> Message-ID: <1587932D-EA8E-4101-9486-DDEEA965103B@oracle.com> On Dec 16, 2020, at 12:39 PM, forax at univ-mlv.fr wrote: > > De: "John Rose" > > The last is cleanest; the cost is resolving some technical > debt in Valhalla, which is allowing more kinds of supers > for primitive classes. There?s no firm reason, IMO, why > Record could not be a super of both primitive and identity > classes, all of which are proper records. Basically we need > to make interfaces and abstract classes look a little more > similar, with respect to the requirements of primitive > classes. > >> yes, in the case of enum it's more difficult because ordinal and name are fields in java.lang.Enum. I have a trick up my sleeve for that: Migrate Enum to be a parametric class, and parameterize the fields. The effect of this will be to re-allocate them in every subtype that asserts the parameter. The ?raw? version would continue to behave as today, for compatibility reasons. > Spoiler alert: I think the final solution will endow > abstract classes with *both* abstract and concrete > constructors. The former will serve primitive > classes and the latter will serve identity classes. > Record will be such an abstract class. > >> By abstract constructors, i suppose you mean empty constructors so they can be bypassed when creating a primitive type. I mean constructors ( methods) which are ACC_ABSTRACT. (Or some equivalent.) The point is they are not only empty but have no Code attribute. >> It will not work with java.lang.Enum. >> For enums, we need have both constructors and factory methods and a way to ensure that they are semantically equivalent. You are right about the argument-taking constructors. Something more is needed there than I have outlined. But I think even that difficulty is not a blocker. For example, if a primitive class that inherits from Enum can (somehow) decouple from the name and ordinal fields of Enum (say, using a specialization trick as above) then it can probably also assume responsibility for managing its own name and ordinal values. They could be wired up using method overrides replacing Enum methods. (Hands waving?) >> One possibility is to have the VM generating the factory methods code only inside the primitive type from the chain of superclasses, doing the transformation that is currently done by the compiler at runtime. Yes. A good question is how to formalize such a transformation using as little ?special pleading? as possible, preferably none at all. >> It can works that way, if i want a primitive enum, the constructor of java.lang.Enum has to be marked as transformable to a factory method, same thing for the constructor of the primitive enum itself. Marked as transformable, or simply marked as irrelevant. This is related to a ?wish list? item for specialized generics, which is optional fields and methods. (The ?isPresent? field of an Optional is needed, but not for Optional.) Today?s Enum constructor could be made optional (using one pretext or another), and simply ignored for p-Enums. >> For java.lang.Enum an for any classes of a primitive enum, an empty factory method is generated with a descriptor, an empty body, and an attribute pointing to the corresponding constructor. >> At runtime, when the class is loaded, the VM insert the correct code in the factory method of the non abstract class. Or have *both* the factory method *and* classic constructor, with suitable gating logic about which may be used when. (This would be a doubling down on the tactic of making abstract classes supers of *both* p-classes and i-classes.) >> If the VM generates the code, we are sure that the constructor and the factory method are both equivalent. We could also trust the author of Enum to certify this. >> Another solution is to have a special verifying pass that verify that the constructor and the factory method are both equivalent, but it seems harder to me. At some point, you have to trust a human author. ? John From john.r.rose at oracle.com Wed Dec 16 20:08:36 2020 From: john.r.rose at oracle.com (John Rose) Date: Wed, 16 Dec 2020 13:08:36 -0700 Subject: EG meeting, 2020-12-16 In-Reply-To: References: <4946029E-5463-4A81-89B1-B4A8FD882464@oracle.com> Message-ID: On Dec 16, 2020, at 11:00 AM, Dan Smith wrote: > > R?mi raised some questions about our story for int vs. Integer vs. legacy uses of 'new Integer'?how many implementation classes are there? (should we use species?); what does reflection look like? We agreed it still needs some polishing. Here?s what I *hope* we can do, if/when we figure out how to make an abstract class a super of *both* p-class and i-class. And, then, if/when we figure out how to endow a class with both p-class factories and i-class constructors. (See discussion about Enum, which has a similar problem.) (Caveat: I think these are technically feasible but they might turn out to be too expensive to carry out, compared with other technical goals. We might back off to some less elegant solution with sealed hierarchies and multiple types. But I can hope.) At that point we can give jl.Integer both kinds of constructors, and allow it to instantiate both kinds of instances. How could that be possible? Well, suppose specialization is not a purely VM-level activity, but (as seems likely) defers partially to a user-supplied bootstrap method, which decides what?s in any given species of a class. Next, suppose that the BSM is given the choice (for a suitably declared specializable class) to make species *of both kinds*. Finally, declare Integer that way, and make its BSM choose a legacy i-species along some paths, and a new p-species along the preferred paths. At least as a formal possibility, this tactic suggests that the extra degrees of freedom required could be confined into *one class* (Integer) and managed using species distinctions. Being able to do this is clearly not a primary goal of any reasonable specialization story, but it could turn out to be low-hanging fruit, if we are lucky. Hence my hope. ? John