Skip to content

Commit 67db825

Browse files
MetadataStorage is mutable - structural equals in copy isn't enough (#11513)
`MetadataStorage` is mutable. Using `Object.equals` in `IR.copy` methods to check whether a _copy is needed_ isn't enough. The fact that two storages are `Object.equal` may be just temporary. Replacing the checks in 69 `IR.copy` methods with identity check - e.g. `ne` in Scala which is `==` in Java. Using proper structural check inside of `MetadataStorage` fixes #11171. # Important Notes I [used this regex](#11171 (comment)) to find out 69 instances of `IR.copy`: ![69 copy methods](https://github.com/user-attachments/assets/257580b9-54fc-4199-88ad-a22103b0041f) and I modified all 69 of them.
1 parent f2037ee commit 67db825

File tree

36 files changed

+95
-145
lines changed

36 files changed

+95
-145
lines changed

engine/runtime-integration-tests/src/test/scala/org/enso/compiler/test/core/ir/MetadataStorageTest.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ class MetadataStorageTest extends CompilerTest {
159159
meta1.update(TestPass1, meta)
160160
meta2.update(TestPass1, meta)
161161

162-
meta1 shouldNot equal(meta2)
162+
meta1 shouldEqual meta2
163163
}
164164

165165
def newMetadataStorage(init: Seq[MetadataPair[_]]): MetadataStorage = {
@@ -201,8 +201,8 @@ class MetadataStorageTest extends CompilerTest {
201201
)
202202
)
203203

204-
meta.duplicate shouldNot equal(meta)
205-
meta.duplicate shouldNot equal(expected)
204+
meta.duplicate shouldEqual meta
205+
meta.duplicate shouldEqual expected
206206
}
207207

208208
"enforce safe construction" in {

engine/runtime-parser/src/main/java/org/enso/compiler/core/IR.java

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.enso.compiler.core;
22

3-
import java.util.Comparator;
43
import java.util.UUID;
54
import java.util.function.Consumer;
65
import java.util.function.Function;
@@ -29,24 +28,6 @@
2928
* <p>See also: Note [IR Equality and hashing]
3029
*/
3130
public interface IR {
32-
/**
33-
* Compares IR structure, but not metadata neither diagnostics. A special comparator used by
34-
* <em>Persistance API</em> to perform some rare consistency checks.
35-
*/
36-
public static final Comparator<IR> STRUCTURE_COMPARATOR =
37-
(aIr, bIr) -> {
38-
if (aIr == bIr) {
39-
return 0;
40-
}
41-
var aCopy = aIr.duplicate(true, false, false, true);
42-
var bCopy = bIr.duplicate(true, false, false, true);
43-
44-
if (aCopy.equals(bCopy)) {
45-
return 0;
46-
}
47-
return System.identityHashCode(aIr) - System.identityHashCode(bIr);
48-
};
49-
5031
/**
5132
* Storage for metadata that the node has been tagged with as the result of various compiler
5233
* passes.

engine/runtime-parser/src/main/java/org/enso/compiler/core/ir/IrPersistance.java

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import java.io.IOException;
44
import java.util.AbstractList;
55
import java.util.ArrayList;
6-
import java.util.LinkedHashMap;
76
import java.util.Map;
87
import java.util.UUID;
98
import org.enso.compiler.core.ir.expression.Application;
@@ -445,33 +444,6 @@ protected Seq readObject(Input in) throws IOException, ClassNotFoundException {
445444
}
446445
}
447446

448-
@ServiceProvider(service = Persistance.class)
449-
public static final class PersistMetadataStorage extends Persistance<MetadataStorage> {
450-
public PersistMetadataStorage() {
451-
super(MetadataStorage.class, false, 389);
452-
}
453-
454-
@Override
455-
@SuppressWarnings("unchecked")
456-
protected void writeObject(MetadataStorage obj, Output out) throws IOException {
457-
var map = new LinkedHashMap<ProcessingPass, ProcessingPass.Metadata>();
458-
obj.map(
459-
(processingPass, data) -> {
460-
map.put(processingPass, data);
461-
return null;
462-
});
463-
out.writeInline(java.util.Map.class, map);
464-
}
465-
466-
@Override
467-
@SuppressWarnings("unchecked")
468-
protected MetadataStorage readObject(Input in) throws IOException, ClassNotFoundException {
469-
var map = in.readInline(java.util.Map.class);
470-
var storage = new MetadataStorage(map);
471-
return storage;
472-
}
473-
}
474-
475447
@ServiceProvider(service = Persistance.class)
476448
public static final class PersistDiagnosticStorage extends Persistance<DiagnosticStorage> {
477449
public PersistDiagnosticStorage() {

engine/runtime-parser/src/main/java/org/enso/compiler/core/ir/MetadataStorage.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,25 @@
1111
import java.util.function.BiFunction;
1212
import java.util.stream.Collectors;
1313
import org.enso.compiler.core.CompilerStub;
14+
import org.enso.persist.Persistable;
1415
import scala.Option;
1516

1617
/** Stores metadata for the various passes. */
18+
@Persistable(id = 398)
1719
public final class MetadataStorage {
1820
private Map<ProcessingPass, ProcessingPass.Metadata> metadata;
1921

22+
/** Constructs empty, ready to be populated metadata. */
2023
public MetadataStorage() {
2124
this(Collections.emptyMap());
2225
}
2326

24-
public MetadataStorage(Map<ProcessingPass, ProcessingPass.Metadata> init) {
25-
this.metadata = init;
27+
MetadataStorage(Map<ProcessingPass, ProcessingPass.Metadata> metaValues) {
28+
this.metadata = metaValues;
29+
}
30+
31+
final Map<ProcessingPass, ProcessingPass.Metadata> metaValues() {
32+
return this.metadata;
2633
}
2734

2835
/**
@@ -82,6 +89,15 @@ public Option<ProcessingPass.Metadata> get(ProcessingPass pass) {
8289
return Option.apply(prev);
8390
}
8491

92+
/**
93+
* Creates a shallow copy of `this`. Use when re-assigning metadata from one IR to another.
94+
*
95+
* @return a shallow copy of `this`
96+
*/
97+
public MetadataStorage copy() {
98+
return new MetadataStorage(metadata);
99+
}
100+
85101
/**
86102
* Creates a deep copy of `this`.
87103
*
@@ -214,7 +230,7 @@ public boolean equals(Object obj) {
214230
return true;
215231
}
216232
if (obj instanceof MetadataStorage other) {
217-
return this.metadata == other.metadata;
233+
return this.metadata.equals(other.metadata);
218234
}
219235
return false;
220236
}

engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/CallArgument.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ object CallArgument {
7272
name != this.name
7373
|| value != this.value
7474
|| location != this.location
75-
|| passData != this.passData
75+
|| (passData ne this.passData)
7676
|| diagnostics != this.diagnostics
7777
|| id != this.id
7878
) {

engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/DefinitionArgument.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ object DefinitionArgument {
123123
|| defaultValue != this.defaultValue
124124
|| suspended != this.suspended
125125
|| location != this.location
126-
|| passData != this.passData
126+
|| (passData ne this.passData)
127127
|| diagnostics != this.diagnostics
128128
|| id != this.id
129129
) {

engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Empty.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ sealed case class Empty(
3535
): Empty = {
3636
if (
3737
location != this.location
38-
|| passData != this.passData
38+
|| (passData ne this.passData)
3939
|| diagnostics != this.diagnostics
4040
|| id != this.id
4141
) {

engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Expression.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ object Expression {
9090
|| returnValue != this.returnValue
9191
|| suspended != this.suspended
9292
|| location != this.location
93-
|| passData != this.passData
93+
|| (passData ne this.passData)
9494
|| diagnostics != this.diagnostics
9595
|| id != this.id
9696
) {
@@ -231,7 +231,7 @@ object Expression {
231231
name != this.name
232232
|| expression != this.expression
233233
|| location != this.location
234-
|| passData != this.passData
234+
|| (passData ne this.passData)
235235
|| diagnostics != this.diagnostics
236236
|| id != this.id
237237
) {

engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Function.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ object Function {
117117
|| body != this.body
118118
|| location != this.location
119119
|| canBeTCO != this.canBeTCO
120-
|| passData != this.passData
120+
|| (passData ne this.passData)
121121
|| diagnostics != this.diagnostics
122122
|| id != this.id
123123
) {
@@ -283,7 +283,7 @@ object Function {
283283
|| isPrivate != this.isPrivate
284284
|| location != this.location
285285
|| canBeTCO != this.canBeTCO
286-
|| passData != this.passData
286+
|| (passData ne this.passData)
287287
|| diagnostics != this.diagnostics
288288
|| id != this.id
289289
) {

engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Literal.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ object Literal {
6565
base != this.base
6666
|| value != this.value
6767
|| location != this.location
68-
|| passData != this.passData
68+
|| (passData ne this.passData)
6969
|| diagnostics != this.diagnostics
7070
|| id != this.id
7171
) {
@@ -197,7 +197,7 @@ object Literal {
197197
if (
198198
text != this.text
199199
|| location != this.location
200-
|| passData != this.passData
200+
|| (passData ne this.passData)
201201
|| diagnostics != this.diagnostics
202202
|| id != this.id
203203
) {

engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Module.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ final case class Module(
8080
|| bindings != this.bindings
8181
|| isPrivate != this.isPrivate
8282
|| location != this.location
83-
|| passData != this.passData
83+
|| (passData ne this.passData)
8484
|| diagnostics != this.diagnostics
8585
|| id != this.id
8686
) {

engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Name.scala

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ object Name {
7676
typePointer != this.typePointer
7777
|| methodName != this.methodName
7878
|| location != this.location
79-
|| passData != this.passData
79+
|| (passData ne this.passData)
8080
|| diagnostics != this.diagnostics
8181
|| id != this.id
8282
) {
@@ -246,7 +246,7 @@ object Name {
246246
if (
247247
parts != this.parts
248248
|| location != this.location
249-
|| passData != this.passData
249+
|| (passData ne this.passData)
250250
|| diagnostics != this.diagnostics
251251
|| id != this.id
252252
) {
@@ -318,7 +318,7 @@ object Name {
318318
): Blank = {
319319
if (
320320
location != this.location
321-
|| passData != this.passData
321+
|| (passData ne this.passData)
322322
|| diagnostics != this.diagnostics
323323
|| id != this.id
324324
) {
@@ -400,7 +400,7 @@ object Name {
400400
if (
401401
specialName != this.specialName
402402
|| location != this.location
403-
|| passData != this.passData
403+
|| (passData ne this.passData)
404404
|| diagnostics != this.diagnostics
405405
|| id != this.id
406406
) {
@@ -506,7 +506,7 @@ object Name {
506506
|| isMethod != this.isMethod
507507
|| location != this.location
508508
|| originalName != this.originalName
509-
|| passData != this.passData
509+
|| (passData ne this.passData)
510510
|| diagnostics != this.diagnostics
511511
|| id != this.id
512512
) {
@@ -616,7 +616,7 @@ object Name {
616616
if (
617617
name != this.name
618618
|| location != this.location
619-
|| passData != this.passData
619+
|| (passData ne this.passData)
620620
|| diagnostics != this.diagnostics
621621
|| id != this.id
622622
) {
@@ -711,7 +711,7 @@ object Name {
711711
name != this.name
712712
|| expression != this.expression
713713
|| location != this.location
714-
|| passData != this.passData
714+
|| (passData ne this.passData)
715715
|| diagnostics != this.diagnostics
716716
|| id != this.id
717717
) {
@@ -822,7 +822,7 @@ object Name {
822822
if (
823823
synthetic != this.synthetic
824824
|| location != this.location
825-
|| passData != this.passData
825+
|| (passData ne this.passData)
826826
|| diagnostics != this.diagnostics
827827
|| id != this.id
828828
) {
@@ -921,7 +921,7 @@ object Name {
921921
): SelfType = {
922922
if (
923923
location != this.location
924-
|| passData != this.passData
924+
|| (passData ne this.passData)
925925
|| diagnostics != this.diagnostics
926926
|| id != this.id
927927
) {

engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Pattern.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ object Pattern {
6666
if (
6767
name != this.name
6868
|| location != this.location
69-
|| passData != this.passData
69+
|| (passData ne this.passData)
7070
|| diagnostics != this.diagnostics
7171
|| id != this.id
7272
) {
@@ -169,7 +169,7 @@ object Pattern {
169169
constructor != this.constructor
170170
|| fields != this.fields
171171
|| location != this.location
172-
|| passData != this.passData
172+
|| (passData ne this.passData)
173173
|| diagnostics != this.diagnostics
174174
|| id != this.id
175175
) {
@@ -324,7 +324,7 @@ object Pattern {
324324
if (
325325
literal != this.literal
326326
|| location != this.location
327-
|| passData != this.passData
327+
|| (passData ne this.passData)
328328
|| diagnostics != this.diagnostics
329329
|| id != this.id
330330
) {
@@ -429,7 +429,7 @@ object Pattern {
429429
name != this.name
430430
|| tpe != this.tpe
431431
|| location != this.location
432-
|| passData != this.passData
432+
|| (passData ne this.passData)
433433
|| diagnostics != this.diagnostics
434434
|| id != this.id
435435
) {
@@ -549,7 +549,7 @@ object Pattern {
549549
if (
550550
doc != this.doc
551551
|| location != this.location
552-
|| passData != this.passData
552+
|| (passData ne this.passData)
553553
|| diagnostics != this.diagnostics
554554
|| id != this.id
555555
) {

engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Type.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ object Type {
5454
args != this.args
5555
|| result != this.result
5656
|| location != this.location
57-
|| passData != this.passData
57+
|| (passData ne this.passData)
5858
|| diagnostics != this.diagnostics
5959
|| id != this.id
6060
) {
@@ -171,7 +171,7 @@ object Type {
171171
|| signature != this.signature
172172
|| comment != this.comment
173173
|| location != this.location
174-
|| passData != this.passData
174+
|| (passData ne this.passData)
175175
|| diagnostics != this.diagnostics
176176
|| id != this.id
177177
) {
@@ -287,7 +287,7 @@ object Type {
287287
typed != this.typed
288288
|| context != this.context
289289
|| location != this.location
290-
|| passData != this.passData
290+
|| (passData ne this.passData)
291291
|| diagnostics != this.diagnostics
292292
|| id != this.id
293293
) {
@@ -399,7 +399,7 @@ object Type {
399399
typed != this.typed
400400
|| error != this.error
401401
|| location != this.location
402-
|| passData != this.passData
402+
|| (passData ne this.passData)
403403
|| diagnostics != this.diagnostics
404404
|| id != this.id
405405
) {

0 commit comments

Comments
 (0)