| Summary: | Wrong method binding in OCL: overloading wrong handled | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| Product: | [Modeling] OCL | Reporter: | Philipp W. Kutter <kutter> | ||||||
| Component: | Core | Assignee: | OCL Inbox <mdt-ocl-inbox> | ||||||
| Status: | CLOSED WONTFIX | QA Contact: | |||||||
| Severity: | major | ||||||||
| Priority: | P3 | CC: | eclipse, ed, moser | ||||||
| Version: | unspecified | ||||||||
| Target Milestone: | --- | ||||||||
| Hardware: | PC | ||||||||
| OS: | Windows 7 | ||||||||
| Whiteboard: | Legacy | ||||||||
| Bug Depends on: | |||||||||
| Bug Blocks: | 339952, 367822 | ||||||||
| Attachments: |
|
||||||||
Created attachment 208183 [details]
Screenshot
Created attachment 208184 [details]
Ecore to reproduce the bug
Please note it is using the Pivot version of OCL, so the exampls plugin needs to be installed.
Hmm. Interesting, I've had suspicions, while working on the UML 2.5 draft to finally provide auto-generated validation, that visibility of overloaded collection operations may not be correct. However. Emulation of Ecore semantics is desirable, but not mandatory. Currently OCL overload semantics are deferred to UML alignment where function overloading is an implementation variation point! So the challenge is to identify the 'correct' semantics for OCL. My current thinking is to support invariant overloading, just like Java (and so Ecore). X.equals(Object), but not X.equals(X) is an overload of Object.equals(Object). (In order to make the common binary case more useful, an invariant can use the statically determinate type of self as OclSelf. So Collection::"="(OclSelf) is an invariant overload of OclAny::"="(OclSelf) dynamically dispatched on the common super type of source and argument.) In your case, BookSubtype::resultOfOpOclOfSubBook, the self.opOcl(self) is looking for a match for BookSubtype::opOcl(BookSubtype). The local search of BookSubtype finds only BookSubtype::opOcl(Book) which is compatible and so the search terminates without searching the inheritance tree where Book::opOcl(BookSubtype) could have been matched too. Looking at Java semantics [http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#292575], the concept of a local class search is spurious, Book is folded into BookSubType, so both BookSubtype::opOcl(BookSubtype) and BookSubtype::opOcl(Book) exist, and BookSubtype::opOcl(BookSubtype) is a better match, just as you expect. The principles of Java overload resolution seem appropriate for OCL. Thanks for forcing me to look this up. It solves the Collection problems too. Changing to Enhancement since the OCL specification has no semantics with respect to which this can be a bug. Dear Ed Willink. Thanks for your notes. Do I understand you right that: a) you agree that the behavior I request is the one that should be implemented b) you downgraded from major(-bug) to enhancement(-feature-request), since it is formally not defined in OCL standard, how it shall be done? Do you think this can be fixed for Eclipse 3.7.2?? If not, what would be the reasons? Would it help if someone provides a patch? Regards, Philipp It is a major violation of 'common sense' too. I've looked at it. It might be just a matter of deleting the one line where the search short circuits if a result is available locally (in ClassCSScopeAdapter and ClassScopeAdapter). I'm close to pushing my working branch that adds auto-generated validation from OCL-defined spec rules. Then I'll fix this since, after fixing basic errors in the draft UML 2.5 spec, about 5 errors related to this problem for Collection types remain. I hadn't considered SR2. It will depend on how many tests break. If there is too much need for enhanced best match detection, it may be too risky for an SR. bug/318092 has the fix. The fix nominally applies ok on the maintenance branch, but 104 out of 329 pivot tests fail. The problem is that OclSelf was not introduced till just after Indigo, which allows e.g. Boolean::=(OclSelf) to overload OclAny::=(OclSelf) in the Juno library. In the Indigo library, Boolean::=(Boolean) hides OclAny::=(OclAny) until this fix is applied. So, no this will not be in 3.1.2 since too much divergent development will be needed to find API compatible fixes to problems that already have a clean fix. I made a more precise title, as there was confusion created between this bug and bug 339952. YES both bugs should declare, for which of the two implemenations they are fixed. BUT this one is about wrong handling of overloading, which is always based on static types, and the other one is about wrong handling of overriding, which is based on the dynamic type of the self/this object. I created a similar example as the one here, to document the problem of overriding, and renamed this bug here. (In reply to comment #6) > bug/318092 has the fix. I do not see the relation of 318092 to this bug. Could we help fix this bug for the old ECore binding? Both GMF-T and QVTO would profit, as well as other users of the old ECore binding. (In reply to comment #9) > (In reply to comment #6) > > bug/318092 has the fix. > > I do not see the relation of 318092 to this bug. > > Could we help fix this bug for the old ECore binding? > > Both GMF-T and QVTO would profit, as well as other users of the old ECore > binding. I'd certainly appreciate receiving a patch that fixes the behavior. A full hierarchical search would appear to be common sense, and appears to be what OCL 2.3 specifies by defining lookupOperation with respect to UML's allFeatures(). UML notes that "The query allFeatures() gives all of the features in the namespace of the classifier. In general, through mechanisms such as inheritance, this will be a larger set than feature." Unfortunately UML neglects to overload to perform an inheritance search so allFeatures() is local. There is therefore no justification for changing the existing legacy behaviour to fix a bug. As with Bug 367822, the limited lookup is not inconsistent with the OCL 2.0, 2.2 or 2.3 specifications. It is just an offense against Object Oriented principles. (The pivot implementation has a well-defined hierarchical search.) WONTFIX for the legacy implementations wrt OCL 2.3. Raise a new bug if/when an Ecore binding is required to comply with OCL 2.5. I find it hard to accept that we have another year with this type of inconsistent behavior. In my opinion this is going against the spirit of both, the UML and OCL specification, even if you can come up with a theoretical line or reasoning that reduces the issue to some loophole in the specs to declare it consistent. It is also ignoring Philipp's request. I really suggest you re-consider this issue. I am fixing the spirit by a coherent new pivot approach and a modeled OCL 2.5 specification. This is already available; I will tune the API and documentation during the early RC phase. The existing legacy approach is tied down by known and unknown compatibility difficulties and no clear justification in the specification for a change. If some customer wants to anticipate OCL 2.5 semantics for the Ecore binding let them come forward with a funding proposal. There are currently 8 bugs for Ecore binding pain points awaiting review. Please concentrate on those that I feel are worthwhile (without funding). Hi, Ed. I am agreeing 100% with Axel Uhl. I can fund this with development time from Ex-Borland developers, under your management. I cannot fund it with cash, sorry. Can you please send the list of the 8 bugs? I assume it covers overriding, overloading and multiple inheritance issues. We as well have issues with the changed behavior with respect to "undefined" but would be willing to code around it, if the other issues can be fixed. What strikes me most is that by not fixing this, we basically give up with respect to having an alternative to XBase. OCL is only an alternative to XBase, if it has natural behavior with respect to overriding, overloading and multiple inheritance issues. Regards, Philipp (In reply to comment #13) > I am fixing the spirit by a coherent new pivot approach and a modeled OCL 2.5 > specification. This is already available; I will tune the API and documentation > during the early RC phase. > > The existing legacy approach is tied down by known and unknown compatibility > difficulties and no clear justification in the specification for a change. > > If some customer wants to anticipate OCL 2.5 semantics for the Ecore binding > let them come forward with a funding proposal. There are currently 8 bugs for > Ecore binding pain points awaiting review. Please concentrate on those that I > feel are worthwhile (without funding). See Bug 378577 for the actual bug. |
Build Identifier: 20110916-0149 During testing of our tooling, we found a fundamential bug in the OCL implementation. We added the code to the standard tutorial with class Book, that can be run with newes OCL Example plugins dynamically or with generated code. Here is the example textually, using the tutorial syntax, slightly condensed: class Book { operation opOcl(par : BookSubtype) : String = ocl://'calling Book.opOcl(BookSubtype)' operation opJava(par : BookSubtype) : String = java://return "calling Book.opJava(BookSubtype)"; class BookSubtype extends Book { attribute resultOfOpOclOfSubBook : String = ocl://self.opOcl(self) attribute resultOfOpJaveOfSubBook : String = java://return this.opJava(this); operation opOcl(par : Book) : String = ocl://'calling BookSubtype.opOcl(Book)' operation opJava(par : Book) : String = java://return "calling BookSubtype.opJava(Book)"; (please note that the Java code for the Java attribute needs to be added by hand. The operation versions are generated from the GenModel annotation) If you run it, you get different results for the two attributes. You see it in the screenshot. Some explanaitons to the example: So we define opOcl and opJava both in Book and BookSubtype. In Book, we define opOcl/opJava both with one parameter par of type BookSubtype, and in BookSubtype, we define opOcl/opJava both with one parameter par of type Book. All four methods simply return a string, telling in which class they are define and of which type their single parameter is. The returned strings are thus: "calling Book.opOcl(BookSubtype)" "calling Book.opJava(BookSubtype)" "calling BookSubtype.opOcl(Book)" "calling BookSubtype.opJava(Book)" Then with the two attributes Result Of Op Ocl of SubBook Result Op Op Java of Subbook we return the result of applying in the subtype BookSubtype opOcl/opJava to self/this: self.opOcl(self) this.opJava(this) We all know, that the expected behavior is that the same is returned for both attributes. The logic is that we select the most specialized signature of the operations and call it. the versions inherited from Book are features more specialized parameters, thus they SHOULD be called. However, only the Java code behaves like this. The OCL binding binds to the wrong method. Since the exact method binding behavior is a major feature for every language, and since I assume we all agree, that for ECore, that can be loaded from Java, and generates Java, this behavior has to be the same. I consider this a major, breaking bug for any OCL+ECore usage in a larger context. I am attaching the screenshot and the ecore. Reproducible: Always Steps to Reproduce: 1. Generate standard ECore code from this 2. Set the body of the resultOfOpJaveOfSubBook method to return this.opJava(this); 3. Launch an Eclips Application 4. Create an instance of the BookSubtype, and look at the attributes in the property view