Skip to content

Commit 245c086

Browse files
author
Vicente Romero
committedJul 18, 2024
8332600: javac uses record components source position during compilation
Reviewed-by: jlahoda
1 parent 5f7b007 commit 245c086

File tree

3 files changed

+31
-24
lines changed

3 files changed

+31
-24
lines changed
 

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

+10-18
Original file line numberDiff line numberDiff line change
@@ -1564,29 +1564,21 @@ public RecordComponent getRecordComponent(VarSymbol field) {
15641564
return null;
15651565
}
15661566

1567-
public RecordComponent findRecordComponentToRemove(JCVariableDecl var) {
1568-
RecordComponent toRemove = null;
1569-
for (RecordComponent rc : recordComponents) {
1570-
/* it could be that a record erroneously declares two record components with the same name, in that
1571-
* case we need to use the position to disambiguate, but if we loaded the record from a class file
1572-
* all positions will be -1, in that case we have to ignore the position and match only based on the
1573-
* name
1574-
*/
1575-
if (rc.name == var.name && (var.pos == rc.pos || rc.pos == -1)) {
1576-
toRemove = rc;
1577-
}
1578-
}
1579-
return toRemove;
1580-
}
1581-
15821567
/* creates a record component if non is related to the given variable and recreates a brand new one
15831568
* in other case
15841569
*/
15851570
public RecordComponent createRecordComponent(RecordComponent existing, JCVariableDecl rcDecl, VarSymbol varSym) {
15861571
RecordComponent rc = null;
1587-
if (existing != null) {
1588-
recordComponents = List.filter(recordComponents, existing);
1589-
recordComponents = recordComponents.append(rc = new RecordComponent(varSym, existing.ast, existing.isVarargs));
1572+
if (existing != null && !recordComponents.isEmpty()) {
1573+
ListBuffer<RecordComponent> newRComps = new ListBuffer<>();
1574+
for (RecordComponent rcomp : recordComponents) {
1575+
if (existing == rcomp) {
1576+
newRComps.add(rc = new RecordComponent(varSym, existing.ast, existing.isVarargs));
1577+
} else {
1578+
newRComps.add(rcomp);
1579+
}
1580+
}
1581+
recordComponents = newRComps.toList();
15901582
} else {
15911583
// Didn't find the record component: create one.
15921584
recordComponents = recordComponents.append(rc = new RecordComponent(varSym, rcDecl));

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

+18-5
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,7 @@ protected void runPhase(Env<AttrContext> env) {
10481048
if ((sym.flags_field & RECORD) != 0) {
10491049
List<JCVariableDecl> fields = TreeInfo.recordFields(tree);
10501050

1051+
int fieldPos = 0;
10511052
for (JCVariableDecl field : fields) {
10521053
/** Some notes regarding the code below. Annotations applied to elements of a record header are propagated
10531054
* to other elements which, when applicable, not explicitly declared by the user: the canonical constructor,
@@ -1063,24 +1064,24 @@ protected void runPhase(Env<AttrContext> env) {
10631064
* copying the original annotations from the record component to the corresponding field, again this applies
10641065
* only if APs are present.
10651066
*
1066-
* First, we find the record component by comparing its name and position with current field,
1067-
* if any, and we mark it. Then we copy the annotations to the field so that annotations applicable only to the record component
1067+
* First, we get the record component matching the field position. Then we copy the annotations
1068+
* to the field so that annotations applicable only to the record component
10681069
* can be attributed, as if declared in the field, and then stored in the metadata associated to the record
10691070
* component. The invariance we need to keep here is that record components must be scheduled for
10701071
* annotation only once during this process.
10711072
*/
1072-
RecordComponent rc = sym.findRecordComponentToRemove(field);
1073+
RecordComponent rc = getRecordComponentAt(sym, fieldPos);
10731074

10741075
if (rc != null && (rc.getOriginalAnnos().length() != field.mods.annotations.length())) {
10751076
TreeCopier<JCTree> tc = new TreeCopier<>(make.at(field.pos));
1076-
List<JCAnnotation> originalAnnos = tc.copy(rc.getOriginalAnnos());
1077-
field.mods.annotations = originalAnnos;
1077+
field.mods.annotations = tc.copy(rc.getOriginalAnnos());
10781078
}
10791079

10801080
memberEnter.memberEnter(field, env);
10811081

10821082
JCVariableDecl rcDecl = new TreeCopier<JCTree>(make.at(field.pos)).copy(field);
10831083
sym.createRecordComponent(rc, rcDecl, field.sym);
1084+
fieldPos++;
10841085
}
10851086

10861087
enterThisAndSuper(sym, env);
@@ -1095,6 +1096,18 @@ protected void runPhase(Env<AttrContext> env) {
10951096
}
10961097
}
10971098

1099+
// where
1100+
private RecordComponent getRecordComponentAt(ClassSymbol sym, int componentPos) {
1101+
int i = 0;
1102+
for (RecordComponent rc : sym.getRecordComponents()) {
1103+
if (i == componentPos) {
1104+
return rc;
1105+
}
1106+
i++;
1107+
}
1108+
return null;
1109+
}
1110+
10981111
/** Enter member fields and methods of a class
10991112
*/
11001113
private final class MembersPhase extends AbstractMembersPhase {

‎test/langtools/tools/javac/records/RecordCompilationTests.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
2626
*
2727
* @test
2828
* @bug 8250629 8252307 8247352 8241151 8246774 8259025 8288130 8282714 8289647 8294020
29+
* 8332600
2930
* @summary Negative compilation tests, and positive compilation (smoke) tests for records
3031
* @library /lib/combo /tools/lib /tools/javac/lib
3132
* @enablePreview
@@ -136,6 +137,7 @@ void testMalformedDeclarations() {
136137
assertFail("compiler.err.repeated.modifier", "public public record R(String foo) { }");
137138
assertFail("compiler.err.repeated.modifier", "private private record R(String foo) { }");
138139
assertFail("compiler.err.already.defined", "record R(int x, int x) {}");
140+
assertFail("compiler.err.already.defined", "record R(int x, int x, int x) {}");
139141
for (String s : List.of("var", "record"))
140142
assertFail("compiler.err.restricted.type.not.allowed.here", "record R(# x) { }", s);
141143
for (String s : List.of("public", "protected", "private", "static", "final", "transient", "volatile",

0 commit comments

Comments
 (0)
Please sign in to comment.