> This makes jdk.javadoc compare javax.lang.model primitives correctly: 
> elements with `Object.equals` and type mirrors with `Types.isSameType`.
> 
> jdk.javadoc sometimes compares elements using identity comparison (`==`) and 
> type mirrors using equality comparison (`equals`). While this is generally 
> wrong, we likely get away with it because of the implementation specifics. 
> I've heard that javac is very forgiving in the sense that there's no 
> difference between `==` and `equals` for elements. In addition to that, I 
> noticed that more often than not there's no difference between `equals` and 
> `isSameType` for type mirrors in the context of jdk.javadoc.
> 
> Since there's no guarantee that a different compiler implementation or the 
> future javac itself will be implemented similarly, it's better to abandon 
> these bad practices while we are still lucky.
> 
> ----
> 
> With a change like this, there are two main concerns. The first is nullity. 
> When it's not immediately obvious if `a`, `b`, or both can be null, it's not 
> clear how to check for equality. To avoid introducing bugs to a code that I 
> don't know that much, I use the `java.util.Objects.equals` method, which 
> takes care of nullity the same way the existing code does: if any of `a` or 
> `b` are null, `Objects.equals(a, b)` behaves exactly as `a == b`, provided 
> `equals` is well-defined and returns false for the null argument.
> 
> The second concern is identity. If equality does not imply identity, it might 
> be important to distinguish between equal elements and identical elements. 
> There are a few cases in jdk.javadoc where it's identity that is required; 
> for example, consider:
> 
>     SortedSet<ExecutableElement> members = 
> utils.serializationMethods(currentTypeElement);
>     for (ExecutableElement member : members) {
>         currentMember = member;
>         Content methodsContent = methodWriter.getMethodsContentHeader(
>                 currentMember == members.last());
>     ...
> 
> Here's the loop computes a boolean indicating the last iteration. If 
> `members` contained identical elements, then that check could misjudge the 
> last iteration and exit prematurely. Thankfully, in that and the similar 
> cases, iteration happens on a (sorted) set, which by definition cannot have 
> duplicates, provided the comparator used by the set is consistent with 
> `equals`, which is also consistent with `==`.  So in this case we can safely 
> change `==` to `equals`.
> 
> However, when I fixed those iterations to use `equals`, it didn't feel right; 
> it felt marginally less brittle than what there was before. I then 
> restructured the loops to avoid equality comparison altogether, which had a 
> side-benefit of widening abstractions from `SortedSet` to just `Iterable`.

Pavel Rappo has updated the pull request incrementally with two additional 
commits since the last revision:

 - Update copyright years
 - Clean up emptiness conditions
   
   Removes one useless condition; restructures the other, as suggested in
   the review. In each case moves the iterator into the loop to reduce
   that iterator's scope.

-------------

Changes:
  - all: https://git.openjdk.org/jdk/pull/12369/files
  - new: https://git.openjdk.org/jdk/pull/12369/files/69e98e22..cb56cfe9

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=12369&range=01
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=12369&range=00-01

  Stats: 24 lines in 4 files changed: 1 ins; 5 del; 18 mod
  Patch: https://git.openjdk.org/jdk/pull/12369.diff
  Fetch: git fetch https://git.openjdk.org/jdk pull/12369/head:pull/12369

PR: https://git.openjdk.org/jdk/pull/12369

Reply via email to