On Thu, 28 Mar 2024 14:08:44 GMT, Jan Lahoda <jlah...@openjdk.org> wrote:
>> This is a patch for javac, that adds the Derived Record Creation >> expressions. The current draft specification for the feature is: >> https://cr.openjdk.org/~gbierman/jep468/jep468-20240326/specs/derived-record-creation-jls.html >> >> The current CSR is here: >> https://bugs.openjdk.org/browse/JDK-8328637 >> >> The patch is mostly straightforward, with two notable changes: >> - there is a new `ElementKind.COMPONENT_LOCAL_VARIABLE`, as the >> specification introduces this term, and it seems consistent with >> `ElementKind.BINDING_VARIABLE` that was introduced some time ago. >> - there are a bit broader changes in `Flow`, to facilitate the introduction >> of variables without an explicit declaration for definite assignment and >> effectively final computation. > > Jan Lahoda has updated the pull request incrementally with one additional > commit since the last revision: > > Fixing tests. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java line 1415: > 1413: > canonicalConstructorTypes, > 1414: List.nil()); > 1415: createNew.constructor = init; Maybe instead of hardcoding the constructor that is canonical at compile time (in case new components get added), it might be better to go through some sort of `indy` callsite like (at least when not in the same compilation unit): DynamicCallSiteDesc[java.lang.runtime.RecordSupport::derivedConstructor(modified component names...):(T extends Record, Class<?>... /* modified component types */)T] with the `derivedConstructor` bootstrap method: public static MethodHandle derivedConstructor(MethodHandles.Lookup lookup, String unused, MethodType type, String... modifiedComponents) throws ReflectiveOperationException { requireNonNull(lookup); requireNonNull(type); // implicit null-check: List<String> modifiedComponentNames = List.of(modifiedComponents); Class<?> rtype = type.returnType(); if ( !rtype.isRecord() || type.parameterCount() != modifiedComponents.length + 1 || type.parameterType(0) != rtype ) { throw new IllegalArgumentException("..."); } Set<String> remainingComponentNames = new HashSet(modifiedComponentNames); if (remainingComponentNames.size() != modifiedComponentNames.size()) { throw new IllegalArgumentException("Duplicate component names in modifiedComponents"); } RecordComponent[] recordComponents = rtype.getRecordComponents(); var componentTypes = new Class<?>[recordComponents.length]; var filters = new MethodHandle[recordComponents.length]; var reorder = new int[recordComponents.length]; for (int i = 0, j = 1; i < recordComponents.length; i++) { var component = recordComponents[i]; componentTypes[i] = component.getType(); var getter = lookup.findVirtual(rtype, component.getName(), MethodType.methodType(component.getType())); if (modifiedComponentNames.contains(component.getName())) { remainingComponentNames.remove(component.getName()); filters[i] = null; reorder[i] = j++; } else { filters[i] = getter; reorder[i] = 0; } } if (!remainingComponentNames.isEmpty()) { throw new IllegalArgumentException("Components " + remainingComponentNames + " are not present in the record " + rtype); } var canonicalConstructor = lookup.findConstructor(rtype, MethodType.methodType(rtype, componentTypes); var filteredConstructor = MethodHandles.filterArguments(canonicalConstructor, 0, filters); // implicitly verifies that type's parameter types match the actual component types var permutedConstructor = MethodHandles.permuteArguments(filterArguments, type, reorder); return permutedConstructor; } ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/18509#discussion_r1547819538