Skip to content

Commit a0fb99f

Browse files
authored
Erase pattern signature for deconstructors (implicit or explicit) (openjdk#19)
* Erase pattern signature for records * Erase pattern signature for deconstructors
1 parent 3466195 commit a0fb99f

File tree

8 files changed

+277
-9
lines changed

8 files changed

+277
-9
lines changed

src/java.base/share/classes/java/lang/runtime/PatternBootstraps.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,19 @@ public static CallSite invokePattern(MethodHandles.Lookup lookup,
124124
return new ConstantCallSite(target);
125125
} catch (Throwable t) {
126126
// Attempt 2: synthesize the pattern declaration from the record components
127+
if (!selectorType.isRecord()) {
128+
throw new IllegalArgumentException("Cannot find a pattern");
129+
}
130+
131+
String expectedMangledName = PatternBytecodeName.mangle(selectorType,
132+
Arrays.stream(selectorType.getRecordComponents())
133+
.map(RecordComponent::getType)
134+
.toArray(Class<?>[]::new));
135+
136+
if (!expectedMangledName.equals(mangledName)) {
137+
throw new IllegalArgumentException("\nUnexpected pattern at use site: " + mangledName + "\nWas expecting: " + expectedMangledName);
138+
}
139+
127140
target = MethodHandles.insertArguments(StaticHolders.SYNTHETIC_PATTERN, 0, selectorType).asType(invocationType);
128141

129142
return new ConstantCallSite(target);

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,9 +2089,11 @@ public Name externalName(Types types) {
20892089
}
20902090

20912091
private Name mangledBytecodePatternName(Types types) {
2092-
List<String> parts = bindings().map(param -> {
2092+
List<Type> erasedBindingTypes = ((PatternType) this.type).erasedBindingTypes;
2093+
2094+
List<String> parts = erasedBindingTypes.map(type -> {
20932095
var g = new UnSharedSignatureGenerator(types);
2094-
g.assembleSig(param.erasure(types));
2096+
g.assembleSig(type);
20952097
String mangled = name.table.names.fromString(BytecodeName.toBytecodeName(g.toName(name.table.names).toString())).toString();
20962098
mangled = mangled.toString().replaceFirst("\\\\=", "");
20972099
return mangled;

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,9 +313,11 @@ public Type visitForAll(ForAll t, S s) {
313313
public Type visitPatternType(PatternType t, S s) {
314314
List<Type> bindingtypes = t.bindingtypes;
315315
List<Type> bindingtypes1 = visit(bindingtypes, s);
316+
List<Type> erasedBindingTypes1 = visit(t.erasedBindingTypes, s);
317+
316318
if (bindingtypes1 == bindingtypes) return t;
317319
else {
318-
PatternType patternType = new PatternType(bindingtypes1, /*XXX*/t.restype, t.tsym) {
320+
PatternType patternType = new PatternType(bindingtypes1, erasedBindingTypes1, /*XXX*/t.restype, t.tsym) {
319321
@Override
320322
protected boolean needsStripping() {
321323
return true;
@@ -1934,13 +1936,17 @@ public <R, P> R accept(TypeVisitor<R, P> v, P p) {
19341936

19351937
public static class PatternType extends Type implements ExecutableType {
19361938
public List<Type> bindingtypes;
1939+
public List<Type> erasedBindingTypes;
1940+
19371941
public Type restype;
19381942

19391943
public PatternType(List<Type> bindingtypes,
1944+
List<Type> erasedBindingTypes,
19401945
Type restype, //TODO:
1941-
TypeSymbol methodClass) {
1946+
TypeSymbol methodClass) {
19421947
super(methodClass, List.nil());
19431948
this.bindingtypes = bindingtypes;
1949+
this.erasedBindingTypes = erasedBindingTypes;
19441950
this.restype = restype;
19451951
}
19461952

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4658,7 +4658,13 @@ private List<MethodSymbol> candidatesWithArity(Type site, int nestedPatternCount
46584658
.map(rc -> types.memberType(site, rc))
46594659
.collect(List.collector());
46604660

4661-
PatternType pt = new PatternType(recordComponents, syms.voidType, syms.methodClass);
4661+
List<Type> erasedComponents = ((ClassSymbol) record.type.tsym).getRecordComponents()
4662+
.stream()
4663+
.map(rc -> types.erasure(rc.type))
4664+
.collect(List.collector());
4665+
4666+
PatternType pt = new PatternType(recordComponents, erasedComponents, syms.voidType, syms.methodClass);
4667+
46624668
MethodSymbol synthetized = new MethodSymbol(PUBLIC | SYNTHETIC | PATTERN, ((ClassSymbol) site.tsym).name, pt, site.tsym);
46634669

46644670
synthetized.patternFlags.add(PatternFlags.DECONSTRUCTOR);

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,14 @@ Type signature(MethodSymbol msym,
158158
}
159159
if (msym.isPattern()) {
160160
Assert.check(params.isEmpty());
161-
return new PatternType(bindingsbuf.toList(), restype, syms.methodClass);
161+
var erasedBindingTypes = bindingsbuf.toList()
162+
.stream()
163+
.map(b -> types.erasure(b))
164+
.collect(List.collector());
165+
166+
PatternType patternType = new PatternType(bindingsbuf.toList(), erasedBindingTypes, restype, syms.methodClass);
167+
168+
return patternType;
162169
} else {
163170
Assert.check(bindings == null);
164171
MethodType mtype = new MethodType(argbuf.toList(),

src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,7 +1070,9 @@ protected void read(Symbol sym, int attrLen) {
10701070
}
10711071
} else if (sym.type.hasTag(TypeTag.PATTERN)){
10721072
Type mtype = poolReader.getType(nextChar());
1073-
sym.type = new PatternType(mtype.getParameterTypes(), syms.voidType, syms.methodClass);
1073+
PatternType patternType = new PatternType(mtype.getParameterTypes(), mtype.getParameterTypes(), syms.voidType, syms.methodClass);
1074+
1075+
sym.type = patternType;
10741076
//TODO: no thrown types for PatternType
10751077
} else {
10761078
List<Type> thrown = sym.type.getThrownTypes();
@@ -1382,7 +1384,7 @@ protected void read(Symbol sym, int attrLen) {
13821384
parameterAccessFlags = null;
13831385

13841386
MethodSymbol msym = (MethodSymbol) sym;
1385-
msym.type = new PatternType(patternType.getParameterTypes(), syms.voidType, syms.methodClass);
1387+
msym.type = new PatternType(patternType.getParameterTypes(), patternType.getParameterTypes(), syms.voidType, syms.methodClass);
13861388

13871389
readMemberAttrs(sym);
13881390

test/langtools/tools/javac/patterns/declarations/InstanceOfStatementInPatternsTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
/**
2727
* @test
2828
* @enablePreview
29-
* @compile -parameters InstanceOfStatementInPatternsTest.java
29+
* @compile InstanceOfStatementInPatternsTest.java
3030
* @run main InstanceOfStatementInPatternsTest
3131
*/
3232
public class InstanceOfStatementInPatternsTest {

test/langtools/tools/javac/patterns/declarations/SeparateCompilation.java

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,236 @@ public List<? extends String> convert(Object o) {
110110
.getOutput(Task.OutputKind.DIRECT);
111111
}
112112

113+
@Test
114+
public void testIncompatibleChange(Path base) throws Exception {
115+
Path current = base.resolve(".");
116+
Path lib = current.resolve("lib");
117+
Path libSrc = lib.resolve("src");
118+
Path libClasses = lib.resolve("classes");
119+
120+
tb.writeJavaFiles(libSrc,
121+
"""
122+
package lib;
123+
import java.util.List;
124+
public class Lib {
125+
public pattern Lib(int a, int b) {
126+
match Lib(1, 2);
127+
}
128+
}
129+
""");
130+
131+
Files.createDirectories(libClasses);
132+
133+
new JavacTask(tb)
134+
.options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
135+
.outdir(libClasses)
136+
.files(tb.findJavaFiles(libSrc))
137+
.run()
138+
.writeAll()
139+
.getOutput(Task.OutputKind.DIRECT);
140+
141+
Path test = current.resolve("test");
142+
Path testSrc = test.resolve("src");
143+
Path testClasses = test.resolve("classes");
144+
145+
tb.writeJavaFiles(testSrc,
146+
"""
147+
package test;
148+
import java.util.List;
149+
import lib.Lib;
150+
151+
public class Test {
152+
public static void main(String... args) {
153+
Lib l = new Lib();
154+
155+
switch (l) {
156+
case Lib(int x, int y) -> { System.out.println(x + y); }
157+
default -> {}
158+
}
159+
}
160+
}
161+
""");
162+
163+
Files.createDirectories(testClasses);
164+
165+
new JavacTask(tb)
166+
.options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
167+
.classpath(libClasses)
168+
.outdir(testClasses)
169+
.files(tb.findJavaFiles(testSrc))
170+
.run()
171+
.writeAll()
172+
.getOutput(Task.OutputKind.DIRECT);
173+
174+
String javaOut = new JavaTask(tb)
175+
.vmOptions("--enable-preview")
176+
.classpath(testClasses.toString() + System.getProperty("path.separator") + libClasses.toString())
177+
.className("test.Test")
178+
.run()
179+
.writeAll()
180+
.getOutput(Task.OutputKind.STDOUT);
181+
182+
// edit Lib
183+
tb.writeJavaFiles(libSrc,
184+
"""
185+
package lib;
186+
import java.util.List;
187+
public class Lib {
188+
public pattern Lib(int a) {
189+
match Lib(1);
190+
}
191+
}
192+
""");
193+
194+
new JavacTask(tb)
195+
.options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
196+
.outdir(libClasses)
197+
.files(tb.findJavaFiles(libSrc))
198+
.run()
199+
.writeAll()
200+
.getOutput(Task.OutputKind.DIRECT);
201+
202+
String javaOut2 = new JavaTask(tb)
203+
.vmOptions("--enable-preview")
204+
.classpath(testClasses.toString() + System.getProperty("path.separator") + libClasses.toString())
205+
.className("test.Test")
206+
.run(Task.Expect.FAIL)
207+
.writeAll()
208+
.getOutput(Task.OutputKind.STDOUT);
209+
}
210+
//
211+
// @Test
212+
// public void testGenericClass(Path base) throws Exception { // TODO: inference issue
213+
// Path current = base.resolve(".");
214+
// Path lib = current.resolve("lib");
215+
// Path libSrc = lib.resolve("src");
216+
// Path libClasses = lib.resolve("classes");
217+
//
218+
// tb.writeJavaFiles(libSrc,
219+
// """
220+
// package lib;
221+
// import java.util.List;
222+
// public class Box<T extends Integer> {
223+
// public pattern Box(List<T> o) {
224+
// match Box(List.of(1, 2));
225+
// }
226+
// }
227+
// """);
228+
//
229+
// Files.createDirectories(libClasses);
230+
//
231+
// new JavacTask(tb)
232+
// .options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
233+
// .outdir(libClasses)
234+
// .files(tb.findJavaFiles(libSrc))
235+
// .run()
236+
// .writeAll()
237+
// .getOutput(Task.OutputKind.DIRECT);
238+
//
239+
// Path test = current.resolve("test");
240+
// Path testSrc = test.resolve("src");
241+
// Path testClasses = test.resolve("classes");
242+
//
243+
// tb.writeJavaFiles(testSrc,
244+
// """
245+
// package test;
246+
// import java.util.List;
247+
// import lib.Box;
248+
//
249+
// public class Test {
250+
// public static void main(String... args) {
251+
// Box<Integer> l = new Box<>();
252+
//
253+
// switch (l) {
254+
// case Box<Integer>(List<Integer> l) -> { System.out.println(l.get(0)); }
255+
// default -> {}
256+
// }
257+
// }
258+
// }
259+
// """);
260+
//
261+
// Files.createDirectories(testClasses);
262+
//
263+
// new JavacTask(tb)
264+
// .options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
265+
// .classpath(libClasses)
266+
// .outdir(testClasses)
267+
// .files(tb.findJavaFiles(testSrc))
268+
// .run()
269+
// .writeAll()
270+
// .getOutput(Task.OutputKind.DIRECT);
271+
//
272+
// String javaOut = new JavaTask(tb)
273+
// .vmOptions("--enable-preview")
274+
// .classpath(testClasses.toString() + System.getProperty("path.separator") + libClasses.toString())
275+
// .className("test.Test")
276+
// .run()
277+
// .writeAll()
278+
// .getOutput(Task.OutputKind.STDOUT);
279+
// }
280+
281+
@Test
282+
public void testGenericRecord(Path base) throws Exception {
283+
Path current = base.resolve(".");
284+
Path lib = current.resolve("lib");
285+
Path libSrc = lib.resolve("src");
286+
Path libClasses = lib.resolve("classes");
287+
288+
tb.writeJavaFiles(libSrc,
289+
"""
290+
package lib;
291+
public record Box<T> (T data){ }
292+
""");
293+
294+
Files.createDirectories(libClasses);
295+
296+
new JavacTask(tb)
297+
.options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
298+
.outdir(libClasses)
299+
.files(tb.findJavaFiles(libSrc))
300+
.run()
301+
.writeAll()
302+
.getOutput(Task.OutputKind.DIRECT);
303+
304+
Path test = current.resolve("test");
305+
Path testSrc = test.resolve("src");
306+
Path testClasses = test.resolve("classes");
307+
308+
tb.writeJavaFiles(testSrc,
309+
"""
310+
package test;
311+
import java.util.List;
312+
import lib.Box;
313+
314+
public class Test {
315+
public static void main(String... args) {
316+
Box<Integer> l = new Box<>(42);
317+
318+
switch (l) {
319+
case Box<Integer>(Integer i) -> { System.out.println(i); }
320+
default -> {}
321+
}
322+
}
323+
}
324+
""");
325+
326+
Files.createDirectories(testClasses);
327+
328+
new JavacTask(tb)
329+
.options("-XDrawDiagnostics", "--enable-preview", "--release", SOURCE_VERSION)
330+
.classpath(libClasses)
331+
.outdir(testClasses)
332+
.files(tb.findJavaFiles(testSrc))
333+
.run()
334+
.writeAll()
335+
.getOutput(Task.OutputKind.DIRECT);
336+
337+
String javaOut = new JavaTask(tb)
338+
.vmOptions("--enable-preview")
339+
.classpath(testClasses.toString() + System.getProperty("path.separator") + libClasses.toString())
340+
.className("test.Test")
341+
.run()
342+
.writeAll()
343+
.getOutput(Task.OutputKind.STDOUT);
344+
}
113345
}

0 commit comments

Comments
 (0)