RFR: 8325088: Overloads that differ in type parameters may be lost [v3]

Chen Liang liach at openjdk.org
Wed Apr 3 23:32:11 UTC 2024


On Wed, 3 Apr 2024 18:14:39 GMT, Pavel Rappo <prappo at openjdk.org> wrote:

>> Creating a link to a constructor or a method or comparing constructors or methods __does not__ factor in type parameters. When constructors or methods are overloaded and differ only in type parameters -- a situation which is absent in JDK API, but present elsewhere -- that causes significant defects, such as:
>> 
>>   - missing entries in summary tables, lists and indexes,
>>   - duplicating links in the table of contents.
>> 
>> This PR fixes those defects, and the fix is two-fold. Firstly, we update comparators to consider type parameters. That takes care of missing constructors and methods. Secondly, we update id (anchor) and link generation to always use the "erased" notation. That takes care of duplicating links.
>> 
>> What's the "erased" notation? Suppose we have the following method:
>> 
>>     <T extends String> T m(T arg)
>> 
>> The current notation refers to it as `m(T)`. That works fine until there's no other method, such as
>> 
>>     <T> T m(T arg)
>> 
>> In which case, the current notation will produce a collision: `m(T)`. By contrast, the erased notation for those two methods is `m(java.lang.String)` and `m(java.lang.Object)` respectively. No collision.
>> 
>> While longer, I believe that the erased notation is collision-proof. Why? Because [JLS 8.4.2][] says that "it is a compile-time error to declare two methods with override-equivalent signatures in a class". Which means that for any two constructors or methods the erasure of their signatures must differ, or else it won't compile.
>> 
>> The change is pretty straightforward, except for some test fallout that required attention.
>> 
>> [JLS 8.4.2]: https://docs.oracle.com/javase/specs/jls/se22/html/jls-8.html#jls-8.4.2
>
> Pavel Rappo has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 11 additional commits since the last revision:
> 
>  - Merge branch 'master' into 8325088
>  - Remove registration phase
>    
>    Makes the code more robust and simple.
>  - Merge branch 'master' into 8325088
>  - Update copyright years
>    
>    Note: any commit hashes below might be outdated due to subsequent
>    history rewriting (e.g. git rebase).
>    
>     - revert src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIndexBuilder.java as spurious
>     - revert test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java as spurious
>     - revert test/langtools/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java as spurious
>     - revert test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java as spurious
>     - revert test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java as spurious
>     - revert test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java as spurious
>     - revert test/langtools/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java as spurious
>     - revert test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java as spurious
>     - revert test/langtools/jdk/javadoc/doclet/testVisibleMembers/TestVisibleMembers.java as spurious
>  - Use erased notation only when necessary
>    
>    Partially reverts 4f028269, which is the bulk of the previous solution,
>    then adds a centralised ID registry for executable elements.
>    
>    The centralised registry is an alternative solution, which is more
>    gentle and less disruptive to tests and composability (-link and
>    -linkoffline).
>  - Update copyright years
>    
>    Note: any commit hashes below might be outdated due to subsequent
>    history rewriting (e.g. git rebase).
>    
>     + update src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIndexBuilder.java due to 4f0282694fd
>     + update test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java due to 4f0282694fd
>     + update test/langtools/jdk/javadoc/doclet/testMemberSummary/TestMemberSummary.java due to 4f0282694fd
>     + update test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java due to 4f0282694fd
>     + update test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering....

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriter.java line 195:

> 193:         HtmlId erasureAnchor = htmlIds.forErasure(constructor);
> 194:         if (erasureAnchor != null
> 195:                 && !erasureAnchor.name().equals(memberAnchor.name())) {

Is this redundant now that the erasure handling is encapsulated within forMember?

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java line 562:

> 560:                 && e.getKind() != ElementKind.METHOD)
> 561:             throw new IllegalArgumentException(String.valueOf(e.getKind()));
> 562:         var vmt = configuration.getVisibleMemberTable((TypeElement) e.getEnclosingElement());

Will the vmt differ if we specify `-private`? And say if we have 2 methods like:

private <T extends Runnable> void method(T arg) {}
public <T extends Number> void method(T arg) {}

Will the Number public method be consistently erased whether or not `-private` is set?

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java line 571:

> 569:         var list = Stream.concat(Stream.concat(ctors.stream(), methods.stream()), otherMethods.stream())
> 570:                 .map(e1 -> (ExecutableElement) e1)
> 571:                 .toList();

We can maybe do something like:

record ErasureCheck(ExecutableElement element, HtmlId erasure) {}

// ...
    .map(e1 -> new ErasureCheck(e1, forErasure(e1)))
    .collect(Collectors.groupingBy(check -> check.erasure == null));

// 1. Map all elements that can _only_ be addressed by the simple id
for (var m : groups.get(true)) {...}

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

PR Review Comment: https://git.openjdk.org/jdk/pull/18519#discussion_r1550637811
PR Review Comment: https://git.openjdk.org/jdk/pull/18519#discussion_r1550635930
PR Review Comment: https://git.openjdk.org/jdk/pull/18519#discussion_r1550643002


More information about the javadoc-dev mailing list