On Fri, 25 Feb 2022 20:30:45 GMT, Jonathan Gibbons <j...@openjdk.org> wrote:

>> Pavel Rappo has updated the pull request with a new target base due to a 
>> merge or a rebase. The pull request now contains 28 commits:
>> 
>>  - Merge branch 'master' into 8280713
>>  - Fix outdated code
>>    
>>    Uses a set instead of list for quick method search. In a future commit 
>> we'll try to figure out why `found` are not unique.
>>  - Fix outdated code
>>    
>>    Fix outdated inline comments and names. Both the assertion and the 
>> `contains` method will be removed in a future commit.
>>  - Fix ImplementedMethods.overridingMethodFound
>>    
>>    Removes code from 
>> VisibleMemberTable.ImplementedMethods.overridingMethodFound; the removed 
>> code is dead for the reasons similar to those in the previous commit. This 
>> commit makes overridingMethodFound degrade to linear search, which could be 
>> substituted with hashing in a later commit.
>>  - Remove ImplementedMethods::removeOverriddenMethod
>>    
>>    First of all, this commit has been tested and the before and after JDK 
>> API Documentation compared.
>>    
>>    `removeOverriddenMethod` does not seem to do any visible work and only 
>> confuses the reader. Here are some problems, all of which has been confirmed 
>> while debugging. Hopefully, the bellow bullet points in conjunction with the 
>> source code will help you see these problems.
>>    
>>    Outside:
>>    
>>    1. `removeOverriddenMethod` is private and is only used in one place: 
>> VisibleMemberTable.java:1015
>>    2. `VisibleMemberTable` passes `removeOverriddenMethod` with a direct 
>> interface method, an interface method that is either defined or overridden 
>> by an interface, but not passively inherited.
>>    
>>    Inside:
>>    
>>    1. `overriddenClass` is either a class that first defined a method that 
>> the passed `method` overrides, or `null` if there's no such class.
>>    2. `overriddenClass` is searched for recursively, using only supertypes.
>>    3. Regardless of any interfaces it might extend, an interface's supertype 
>> is `java.lang.Object`; see, for example, 
>> `javax.lang.model.element.TypeElement#getSuperclass`.
>>    4. `method` belongs to an interface; see "Outside" (2).
>>    5. Given 1-4, the only class `overriddenClass` can be is 
>> `java.lang.Object`. This can happen, for example, if `method` is an 
>> interface-override of one of the methods defined in `java.lang.Object`. 
>> Typically those are `equals`, `hashCode` or `toString`.
>>    7. `isSubclassOf(a, b)` checks if `a` is a subtype of `b`.
>>    8. Since `a` is `java.lang.Object`, condition `b == a || isSubclassOf(a, 
>> b)` can be `true` only if `b` is also `java.lang.Object`. `java.lang.Object` 
>> is not a subclass of anything but itself.
>>    9. `b` can never be a class, let alone `java.lang.Object`. This is 
>> because `b` is an immediately enclosing type of an interface method (by 
>> construction of `methlist`), i.e. `b` is an interface.
>>    10. So the above check always fails, which means that 
>> `methlist.remove(i)` is never executed.
>>  - Simplify VisibleMemberTable.ImplementedMethods
>>    
>>    Also adds a TODO to remind us to investigate an important issue later; 
>> either in this or a follow-up PR.
>>  - Fix confusing doc
>>  - Merge branch 'master' into 8280713
>>  - Refine overriddenType(ExecutableElement)
>>    
>>    Makes it clear that the returned TypeMirror is DeclaredType which 
>> represents a class and never an interface.
>>  - Refactor how superinterfaces are collected
>>    
>>    Improves readability of Utils.getAllInterfaces and friends.
>>  - ... and 18 more: 
>> https://git.openjdk.java.net/jdk/compare/efd3967b...41a00ce9
>
> src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java
>  line 1012:
> 
>> 1010:             for (TypeMirror interfaceType : intfacs) {
>> 1011:                 // TODO: this method also finds static methods which 
>> are pseudo-inherited;
>> 1012:                 //  this needs to be fixed
> 
> I can't add this comment where I'd like to ... line 992, the declaration of 
> the `ImplementedMethods` class.
> Especially given the "curious" nature of the constructor, it would help to 
> have descriptive comments on either the class or constructor.  It seems like 
> `ImplementedMethods` should be a collection of methods implemented by a 
> `TypeElement` (i.e. similar to filtering `Element.getEnclosedElements`). But 
> it seems like this collection is more like the collection of methods in a 
> class hierarchy that "match" a given signature .. perhaps to get a candidate 
> list of methods from which to gather documentation (e.g with `{@inheritDoc}`).
> 
> Given that, would it be a reasonable alternative rationale for removing the 
> `removeOverriddenMethod` because by construction, nothing ever gets added 
> that subsequently needs to be removed?
> 
> I'm still trying to understand this one. I think I know what it is trying to 
> do, but I'm concerned that while it might be trying to do something useful, 
> it might be implemented incorrectly ... in which case, it should be fixed, 
> not removed.
> 
> I guess I'd be interest to hear the actual/intended operation when a 
> collection of different possibly-unrelated interfaces all implement the 
> "same" method according to its signature.   Think: the "graphical cowboy" 
> issue.   Two unrelated interfaces that both implement the `draw()` method. 
> Now create a hierarchy of subtypes of those interfaces that start overriding 
> methods with either simple overrides on not-simple overrides.  Then see if 
> `removeOverriddenMethod` kicks in. My guess is that this situation is 
> uncommon and does not arise in JDK API or even our tests.

> I'm not convinced by this one. I'd like to see more investigation.

I couldn't find a case where `removeOverriddenMethod` removed an element from 
`methlist`. I tried to find it by reasoning and by debugging our tests, which 
in conjunction convinced me that `methlist.remove(i)` is currently unreachable.

Has it ever been reachable? This might depend on how `Utils.overriddenClass` 
and its predecessors were implemented. Had they ever been capable of returning 
an *interface* rather than only a class? If not, I cannot see how this could 
ever work.

If at some point `overriddenClass` could return an interface, then my 
hypothesis is that those two methods, removeOverriddenMethod and 
overridingMethodFound, ensured that we constructed `methlist` in such a way 
that it only contained the *most derived* methods. That is, that for every 
method m1 from `methlist` there were no method m2 in `methlist` such that m2 
overrode m1.

I think that at this point `ImplementedMethods` can work with these two methods 
being broken because of the way override-candidates are collected by 
`utils.getAllInterfaces`.

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

PR: https://git.openjdk.java.net/jdk/pull/7233

Reply via email to