-
Notifications
You must be signed in to change notification settings - Fork 139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Null-Analysis - The interface ... cannot be implemented more than once with different arguments ... #2173
Null-Analysis - The interface ... cannot be implemented more than once with different arguments ... #2173
Conversation
with different arguments ... fixes eclipse-jdt#2158
I observed something suspicious regarding type identity, indeed:
This seems to create some schizophrenia among types that should be "mostly equal" (ignoring annotations), but get different With the proposed change, this situation no longer causes harm (no longer occurs?), but I can't predict whether/when this will cause grief again. Thus I'm thinking of a way to update the PTBKey where the TVB is stored. |
AFAICR, it should disregard all type annotations anywhere - so yes types that differ only regarding an annotation on a type argument share the same |
with different arguments ... Additional fix ensuring proper interning in TypeSystem
Thanks.
I'd say that behaviour was latent for a long time, but it requires a very specific ordering of processing steps for it to surface. Digging into history I find these stages:
In commit 3929efa I addressed this by setting up a protocol for swapping the TVB not only in Since the reported symptom was already fixed in Brainstorming an alternative solution, in case the above is considered too much magic piled up: when we create a TVB we may not yet know if annotations will be applied (either explicitly, or worse: from a
Could we resolve this by always cloning all TVB right when created? We'd put the clone in slot 0 of This would introduce a lot of cloning for TVB that are never annotated. Plus: any |
@srikanth-sankaran with all the wizardry involved, may I ask for a review? |
Sure, I have cleared up the urgent items - I will review this tomorrow. Woefully rusty on type annotation related code, but I will take look. I demand my pound of flesh, ;-) in the form of help in moving forward with #1181 - Manoj helped with some "stress testing" on this PR and things look good to go according to him too. I was hoping to dig up the old draft specs but that pursuit has not been effective. So we will have to rely on https://bugs.eclipse.org/bugs/show_bug.cgi?id=422489#c2 and other proof my argument attempted at #1181 |
It's a deal! :) |
Hi Stephan, I have looked at the changes, but it requires way too much context to meaningfully critique it - way too much context than can be reasonably acquired during the review of a bug fix. I think the key to unravelling all this really lies in "untangling the order of processing steps" - You may very well be correct in asserting "further untangling the order of processing steps doesn't look very feasible," - but I would like to make a very comprehensive study of where we stand wrt to the order of processing steps particularly in relation to what javac does (which itself would need reconstructing in my mind - IIRC, javac processes supertypes in two passes, in the first pass ignoring type arguments and in the subsequent one including them, likewise annotations get queued up for processing and get taken up at a specific time) I am observing this "order of processing steps" perhaps not being precisely nailed showing up in other places too - the permits clauses appear to be resolved at the "wrong" time - I have a set of issues relating to that under investigation. Also in the case of records, various places avoiding reentrancy give me an uneasy feeling. It is a sizeable project to comprehensively study all this and implement an alternate pipeline if/as deemed necessary - until then point fixes of the present kind are the only option. Please proceed to merge. I will take up this study - but hard to put a date on it. The grammar changes for lambdas is in the queue too :) Following on the pattern (pun intended) of 4.31 where I did a comprehensive review and rewrite of (a) JEP 394: Pattern Matching for instanceof (b) JEP 441: Pattern Matching for switch (c) JEP 440: Record Patterns and (d) JEP 456: Unnamed Variables & Patterns So the present topic will have to wait until after this. But we can reopen the discussions and brainstorming at that point - what do you say ? |
Also, when we open it to consider alternative approaches - we may want to evaluate whether it makes sense to come up with an implementation where That could allow for some "fault tolerance" so to speak and by taking away the current hard guarantee about underlying type identity that |
While a comprehensive study of the "order of processing steps" and implementation of an alternate pipeline is a sizeable project, do you think using |
What would this buy us ? I posit the slow path need not actually be slow - structural comparisons between wildly different types would fail fast I think. |
If such a change to |
As for the ordering of processing steps: Originally connectTypeHierarchy was just a single phase, covering all of
Only bound check during In the context of type annotations we received various bug reports, that boiled down to the fact, that evaluating annotations right during connectTypeHierarchy can have ill effects. Initially we tried to handle individual bug patterns with more deferring (like https://bugs.eclipse.org/bugs/show_bug.cgi?id=434570) and more on-demand evaluation (like #630), but obviously this didn't produce a clean solution. For that reason I gradually disentangled that aspect from connectTypeHierarchy (centrally: #1077 with follow-ups). The net effect is that now we have one more top-level phase, and a somewhat more systematic approach to technically handle those phases that are driven by LookupEnvironment (see The idea of phase INTEGRATE_ANNOTATIONS_IN_HIERARCHY is: after super types and their type parameters have been properly resolved, resolving annotations should not cause any harm. But since supertype bindings (possibly parameterized) already exist at that point in time, the new phase needs to take a deep dive into all these bindings and update them with annotations, where appropriate. That's already a lot of traversals, but the idea is: it should be enough to traverse supertypes, since types in signatures have not yet been resolved at that time ( I believe this is already significantly safer than the previous state, but surely discussing if ecj's phase-model is overly simplistic is a worthy topic. I see only one downside in introducing more phases: for every type that is incrementally attributed (with type parameters, annotations ...) it looks very tricky, into which derived bindings (in particular PTB) do we need to propagate all late added information? As for the current bug I should note, that the conflict did not originate from any resolving happening too early or too late, but only from the internal structure |
It seems like https://bugs.eclipse.org/bugs/show_bug.cgi?id=418041 is also already relevant for our discussion. |
Thanks, this is very useful! I have created #2209 and assigned it to myself. |
Thanks, this made me rethink our original invariants about type identity, derived types, prototypes etc. So I wrote a little essay as #2210 - to be picked up at our leisure. |
The interesting discussions resulting from your comments prove the opposite: this was indeed meaningful critique 😄 Thanks! To be continued in #2209 and #2210 ... Meanwhile I merged the current bug fix as the best thing we have today - if some day we come up with a more consistent story, I'll be happy to remove this and previous situational fixes. |
may eventually resolve eclipse-jdt#2210 + revert part of eclipse-jdt#2173 + play with annotated TVB as the 'original' type
…e with different arguments ... (eclipse-jdt#2173) fixes eclipse-jdt#2158 + Propagate late annotations also into parameterized supertypes + Additional fix ensuring proper interning in TypeSystem
…e with different arguments ... (eclipse-jdt#2173) fixes eclipse-jdt#2158 + Propagate late annotations also into parameterized supertypes + Additional fix ensuring proper interning in TypeSystem
fixes #2158
This was tricky: the "duplicate" supertype exists in two variants that differ only in type annotations on type arguments.
@srikanth-sankaran when we introduced
TypeBinding.equalsEquals()
and..notEquals()
, the intention was to ignore differences only regarding annotations (by comparingid
), but it seems this works only for annotations on the main type? Should types that differ only regarding an annotation on a type argument share the sameid
, or is that outside the contract?Anyway, working with those variants was wrong from the outset. It happened because a
ParameterizedTypeBinding
was created (as a super interface binding) before the underlying generic type was fully updated (CompleteTypeBindingsSteps.INTEGRATE_ANNOTATIONS_IN_HIERARCHY
) which clearly is a bug.While further untangling the order of processing steps doesn't look very feasible, I found a way to fix this super type after the fact (during
TypeDeclaration.updateSupertypesWithAnnotations()
, which already exists for this kind of udpate).This is done by (a) detecting this situation (with help of
SourceTypeBinding.supertypeAnnotationsUpdated
) and if necessary (b) re-create the parameterized type from the updated generic type. This should be OK, since at that point we haven't yet started referencing such types from fields and method (STB.resolveType(s)For
methods).