Skip to content

Commit fcbd46d

Browse files
committed
ArC: fix hash code of TypeAndQualifiers
The `TypeAndQualifiers` compound is used as a key in hash maps, which means its equality and hash code must be consistent. Unfortunately, the implementation of `equals()` is completely custom, because it needs to ignore `AnnotationInstance.target`, yet the `hashCode()` implementation blindly delegates to `AnnotationInstance`. That used to work, because `AnnotationInstance.hashCode()` ignored the `target` before, but that has never been a stated contract. A completely custom implementation of equality should always be accompanied by a custom implementation of hash code. That's what this commit does.
1 parent 9d27563 commit fcbd46d

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InjectionPointInfo.java

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,8 @@ public TypeAndQualifiers(Type type, Set<AnnotationInstance> qualifiers) {
388388
public int hashCode() {
389389
final int prime = 31;
390390
int result = 1;
391-
result = prime * result + ((qualifiers == null) ? 0 : qualifiers.hashCode());
391+
// We cannot use AnnotationInstance#hashCode() as it includes the AnnotationTarget
392+
result = prime * result + annotationSetHashCode(qualifiers);
392393
result = prime * result + ((type == null) ? 0 : type.hashCode());
393394
return result;
394395
}
@@ -409,8 +410,8 @@ public boolean equals(Object obj) {
409410
if (other.qualifiers != null) {
410411
return false;
411412
}
412-
} else if (!qualifiersAreEqual(qualifiers, other.qualifiers)) {
413-
// We cannot use AnnotationInstance#equals() as it requires the exact same annotationTarget instance
413+
} else if (!annotationSetEquals(qualifiers, other.qualifiers)) {
414+
// We cannot use AnnotationInstance#equals() as it requires the exact same AnnotationTarget instance
414415
return false;
415416
}
416417
if (type == null) {
@@ -423,30 +424,44 @@ public boolean equals(Object obj) {
423424
return true;
424425
}
425426

426-
private boolean qualifiersAreEqual(Set<AnnotationInstance> q1, Set<AnnotationInstance> q2) {
427-
if (q1 == q2) {
427+
private static boolean annotationSetEquals(Set<AnnotationInstance> s1, Set<AnnotationInstance> s2) {
428+
if (s1 == s2) {
428429
return true;
429430
}
430-
if (q1.size() != q2.size()) {
431+
if (s1.size() != s2.size()) {
431432
return false;
432433
}
433-
for (AnnotationInstance a1 : q1) {
434-
for (AnnotationInstance a2 : q2) {
435-
if (!annotationsAreEqual(a1, a2)) {
434+
for (AnnotationInstance a1 : s1) {
435+
for (AnnotationInstance a2 : s2) {
436+
if (!annotationEquals(a1, a2)) {
436437
return false;
437438
}
438439
}
439440
}
440441
return true;
441442
}
442443

443-
private boolean annotationsAreEqual(AnnotationInstance a1, AnnotationInstance a2) {
444+
private static boolean annotationEquals(AnnotationInstance a1, AnnotationInstance a2) {
444445
if (a1 == a2) {
445446
return true;
446447
}
447448
return a1.name().equals(a2.name()) && a1.values().equals(a2.values());
448449
}
449450

451+
private static int annotationSetHashCode(Set<AnnotationInstance> s) {
452+
int result = 1;
453+
for (AnnotationInstance a : s) {
454+
result = 31 * result + annotationHashCode(a);
455+
}
456+
return result;
457+
}
458+
459+
private static int annotationHashCode(AnnotationInstance a) {
460+
int result = a.name().hashCode();
461+
result = 31 * result + a.values().hashCode();
462+
return result;
463+
}
464+
450465
}
451466

452467
}

0 commit comments

Comments
 (0)