Skip to content

Commit

Permalink
Erase pattern signature for records
Browse files Browse the repository at this point in the history
  • Loading branch information
biboudis committed Feb 10, 2025
1 parent 3466195 commit 03c90dc
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,19 @@ public static CallSite invokePattern(MethodHandles.Lookup lookup,
return new ConstantCallSite(target);
} catch (Throwable t) {
// Attempt 2: synthesize the pattern declaration from the record components
if (!selectorType.isRecord()) {
throw new IllegalArgumentException("Cannot find a pattern");
}

String expectedMangledName = PatternBytecodeName.mangle(selectorType,
Arrays.stream(selectorType.getRecordComponents())
.map(RecordComponent::getType)
.toArray(Class<?>[]::new));

if (!expectedMangledName.equals(mangledName)) {
throw new IllegalArgumentException("\nUnexpected pattern at use site: " + mangledName + "\nWas expecting: " + expectedMangledName);
}

target = MethodHandles.insertArguments(StaticHolders.SYNTHETIC_PATTERN, 0, selectorType).asType(invocationType);

return new ConstantCallSite(target);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2089,9 +2089,15 @@ public Name externalName(Types types) {
}

private Name mangledBytecodePatternName(Types types) {
List<String> parts = bindings().map(param -> {
List<Type> bindingTypes = ((PatternType) this.type).erasedBindingTypes;

if (bindingTypes == null) {
bindingTypes = bindings().map(b -> b.erasure(types));
}

List<String> parts = bindingTypes.map(type -> {
var g = new UnSharedSignatureGenerator(types);
g.assembleSig(param.erasure(types));
g.assembleSig(type);
String mangled = name.table.names.fromString(BytecodeName.toBytecodeName(g.toName(name.table.names).toString())).toString();
mangled = mangled.toString().replaceFirst("\\\\=", "");
return mangled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1934,11 +1934,13 @@ public <R, P> R accept(TypeVisitor<R, P> v, P p) {

public static class PatternType extends Type implements ExecutableType {
public List<Type> bindingtypes;
public List<Type> erasedBindingTypes;

public Type restype;

public PatternType(List<Type> bindingtypes,
Type restype, //TODO:
TypeSymbol methodClass) {
TypeSymbol methodClass) {
super(methodClass, List.nil());
this.bindingtypes = bindingtypes;
this.restype = restype;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4659,6 +4659,12 @@ private List<MethodSymbol> candidatesWithArity(Type site, int nestedPatternCount
.collect(List.collector());

PatternType pt = new PatternType(recordComponents, syms.voidType, syms.methodClass);

pt.erasedBindingTypes = ((ClassSymbol) record.type.tsym).getRecordComponents()
.stream()
.map(rc -> types.erasure(rc.type))
.collect(List.collector());

MethodSymbol synthetized = new MethodSymbol(PUBLIC | SYNTHETIC | PATTERN, ((ClassSymbol) site.tsym).name, pt, site.tsym);

synthetized.patternFlags.add(PatternFlags.DECONSTRUCTOR);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
/**
* @test
* @enablePreview
* @compile -parameters InstanceOfStatementInPatternsTest.java
* @compile InstanceOfStatementInPatternsTest.java
* @run main InstanceOfStatementInPatternsTest
*/
public class InstanceOfStatementInPatternsTest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,236 @@ public List<? extends String> convert(Object o) {
.getOutput(Task.OutputKind.DIRECT);
}

@Test
public void testIncompatibleChange(Path base) throws Exception {
Path current = base.resolve(".");
Path lib = current.resolve("lib");
Path libSrc = lib.resolve("src");
Path libClasses = lib.resolve("classes");

tb.writeJavaFiles(libSrc,
"""
package lib;
import java.util.List;
public class Lib {
public pattern Lib(int a, int b) {
match Lib(1, 2);
}
}
""");

Files.createDirectories(libClasses);

new JavacTask(tb)
.options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
.outdir(libClasses)
.files(tb.findJavaFiles(libSrc))
.run()
.writeAll()
.getOutput(Task.OutputKind.DIRECT);

Path test = current.resolve("test");
Path testSrc = test.resolve("src");
Path testClasses = test.resolve("classes");

tb.writeJavaFiles(testSrc,
"""
package test;
import java.util.List;
import lib.Lib;
public class Test {
public static void main(String... args) {
Lib l = new Lib();
switch (l) {
case Lib(int x, int y) -> { System.out.println(x + y); }
default -> {}
}
}
}
""");

Files.createDirectories(testClasses);

new JavacTask(tb)
.options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
.classpath(libClasses)
.outdir(testClasses)
.files(tb.findJavaFiles(testSrc))
.run()
.writeAll()
.getOutput(Task.OutputKind.DIRECT);

String javaOut = new JavaTask(tb)
.vmOptions("--enable-preview")
.classpath(testClasses.toString() + System.getProperty("path.separator") + libClasses.toString())
.className("test.Test")
.run()
.writeAll()
.getOutput(Task.OutputKind.STDOUT);

// edit Lib
tb.writeJavaFiles(libSrc,
"""
package lib;
import java.util.List;
public class Lib {
public pattern Lib(int a) {
match Lib(1);
}
}
""");

new JavacTask(tb)
.options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
.outdir(libClasses)
.files(tb.findJavaFiles(libSrc))
.run()
.writeAll()
.getOutput(Task.OutputKind.DIRECT);

String javaOut2 = new JavaTask(tb)
.vmOptions("--enable-preview")
.classpath(testClasses.toString() + System.getProperty("path.separator") + libClasses.toString())
.className("test.Test")
.run(Task.Expect.FAIL)
.writeAll()
.getOutput(Task.OutputKind.STDOUT);
}
//
// @Test
// public void testGenericClass(Path base) throws Exception { // TODO: inference issue
// Path current = base.resolve(".");
// Path lib = current.resolve("lib");
// Path libSrc = lib.resolve("src");
// Path libClasses = lib.resolve("classes");
//
// tb.writeJavaFiles(libSrc,
// """
// package lib;
// import java.util.List;
// public class Box<T extends Integer> {
// public pattern Box(List<T> o) {
// match Box(List.of(1, 2));
// }
// }
// """);
//
// Files.createDirectories(libClasses);
//
// new JavacTask(tb)
// .options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
// .outdir(libClasses)
// .files(tb.findJavaFiles(libSrc))
// .run()
// .writeAll()
// .getOutput(Task.OutputKind.DIRECT);
//
// Path test = current.resolve("test");
// Path testSrc = test.resolve("src");
// Path testClasses = test.resolve("classes");
//
// tb.writeJavaFiles(testSrc,
// """
// package test;
// import java.util.List;
// import lib.Box;
//
// public class Test {
// public static void main(String... args) {
// Box<Integer> l = new Box<>();
//
// switch (l) {
// case Box<Integer>(List<Integer> l) -> { System.out.println(l.get(0)); }
// default -> {}
// }
// }
// }
// """);
//
// Files.createDirectories(testClasses);
//
// new JavacTask(tb)
// .options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
// .classpath(libClasses)
// .outdir(testClasses)
// .files(tb.findJavaFiles(testSrc))
// .run()
// .writeAll()
// .getOutput(Task.OutputKind.DIRECT);
//
// String javaOut = new JavaTask(tb)
// .vmOptions("--enable-preview")
// .classpath(testClasses.toString() + System.getProperty("path.separator") + libClasses.toString())
// .className("test.Test")
// .run()
// .writeAll()
// .getOutput(Task.OutputKind.STDOUT);
// }

@Test
public void testGenericRecord(Path base) throws Exception {
Path current = base.resolve(".");
Path lib = current.resolve("lib");
Path libSrc = lib.resolve("src");
Path libClasses = lib.resolve("classes");

tb.writeJavaFiles(libSrc,
"""
package lib;
public record Box<T> (T data){ }
""");

Files.createDirectories(libClasses);

new JavacTask(tb)
.options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
.outdir(libClasses)
.files(tb.findJavaFiles(libSrc))
.run()
.writeAll()
.getOutput(Task.OutputKind.DIRECT);

Path test = current.resolve("test");
Path testSrc = test.resolve("src");
Path testClasses = test.resolve("classes");

tb.writeJavaFiles(testSrc,
"""
package test;
import java.util.List;
import lib.Box;
public class Test {
public static void main(String... args) {
Box<Integer> l = new Box<>(42);
switch (l) {
case Box<Integer>(Integer i) -> { System.out.println(i); }
default -> {}
}
}
}
""");

Files.createDirectories(testClasses);

new JavacTask(tb)
.options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
.classpath(libClasses)
.outdir(testClasses)
.files(tb.findJavaFiles(testSrc))
.run()
.writeAll()
.getOutput(Task.OutputKind.DIRECT);

String javaOut = new JavaTask(tb)
.vmOptions("--enable-preview")
.classpath(testClasses.toString() + System.getProperty("path.separator") + libClasses.toString())
.className("test.Test")
.run()
.writeAll()
.getOutput(Task.OutputKind.STDOUT);
}
}

0 comments on commit 03c90dc

Please sign in to comment.