Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 399224 - [1.8][compiler][internal] Implement TypeBinding.getSingleAbstractMethod
Summary: [1.8][compiler][internal] Implement TypeBinding.getSingleAbstractMethod
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 4.3   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: BETA J8   Edit
Assignee: Srikanth Sankaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on: 399263
Blocks: 382701
  Show dependency tree
 
Reported: 2013-01-28 02:57 EST by Srikanth Sankaran CLA
Modified: 2013-02-06 07:47 EST (History)
3 users (show)

See Also:


Attachments
getSingleAbstractMethod is doing override check (3.64 KB, patch)
2013-02-01 02:10 EST, ANIRBAN CHAKRABORTY CLA
no flags Details | Diff
Alternate work in progress - minimally tested (16.30 KB, patch)
2013-02-03 09:35 EST, Srikanth Sankaran CLA
no flags Details | Diff
Alternate patch - more evolved. (20.42 KB, patch)
2013-02-03 14:55 EST, Srikanth Sankaran CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Srikanth Sankaran CLA 2013-01-28 02:57:30 EST
BETA_JAVA8:

From https://bugs.eclipse.org/bugs/show_bug.cgi?id=382701#c17:

// Stuff ...

(2) Implementation of a skeleton method for TypeBinding#getSingleAbstractMethod
(returns null or a PMB) and ReferenceBinding#getSingleAbstractMethod. The 
latter could at this point return null for non-interfaces and for interfaces
could ignore inheritance, object method redefinitions etc. If no single method
could be found, this method should ideally return a ProblemMethodBinding
with ProblemReasons set to NoSuchSingleAbstractMethod. 

// Stuff ...

While that bug will put in place the skeleton, the present one is tighten
the implementation and take care of all the myriad details.
Comment 1 Srikanth Sankaran CLA 2013-01-28 02:57:58 EST
Anirbhan, please follow up on a priority basis.
Comment 2 Srikanth Sankaran CLA 2013-01-28 05:56:56 EST
This work would be greatly simplified if we could turn org.eclipse.jdt.internal.compiler.lookup.MethodVerifier.doesMethodOverride(MethodBinding, MethodBinding) into a static method. This will have quite a bit of ripples
but I think it would save us huge trouble and is worth trying instead of
duplicating code.

org.eclipse.jdt.internal.compiler.lookup.Scope.getJavaLangObject() would
also come in handy.
Comment 3 Srikanth Sankaran CLA 2013-01-28 06:01:42 EST
(In reply to comment #2)
> This work would be greatly simplified if we could turn
> org.eclipse.jdt.internal.compiler.lookup.MethodVerifier.
> doesMethodOverride(MethodBinding, MethodBinding) into a static method.

We may have to tunnel scope/environment through a bunch of methods.
Comment 4 Srikanth Sankaran CLA 2013-01-28 07:10:32 EST
(In reply to comment #2)
> This work would be greatly simplified if we could turn
> org.eclipse.jdt.internal.compiler.lookup.MethodVerifier.
> doesMethodOverride(MethodBinding, MethodBinding) into a static method. This
> will have quite a bit of ripples
> but I think it would save us huge trouble and is worth trying instead of
> duplicating code.

Actually, this is a bit tricky. We never instantiate MethodVerifier anymore
and MethodVerifier and MethodVerifier15 should be merged ideally into
MethodVerifier itself, but now may not be the right time for that task 
and unless we merge them, method dispatch will break for those methods 
converted to static since all clients typically use MethodVerifier as the reference/handle.

So we need to take a look at the set of methods that need to be turned into
static ones, look at their call sites to see if anyone super calls them, inline
the code in those places, if not delete the instance method altogether and
bubble up the MethodVerifier15's implementation to the super class.

// ----------

A simpler approach would simply be to instantiate a method verifier and
invoke the doesMethodOverride call on it. The only problem is that method
verifier's various methods expect to operate on a source type, but I am fairly
certain the code paths we need would not rely irreconcilably on the type
field.

Still, the original plan of converting them into statics would be the
most rigorous way of satisfying ourselves that there are no side effects.
Comment 5 Srikanth Sankaran CLA 2013-01-28 09:27:19 EST
(In reply to comment #2)
> This work would be greatly simplified if we could turn
> org.eclipse.jdt.internal.compiler.lookup.MethodVerifier.
> doesMethodOverride(MethodBinding, MethodBinding) into a static method.

Raised bug 399263 to track this. Anirbhan, please follow up.
Comment 6 ANIRBAN CHAKRABORTY CLA 2013-01-29 00:25:44 EST
Hello,
Provided the skeleton (as specified in this bug) to Srikanth. Working on making the functional interface verifier more exxhaustive.
Thanks
Anirban
Comment 7 ANIRBAN CHAKRABORTY CLA 2013-02-01 02:10:37 EST
Created attachment 226440 [details]
getSingleAbstractMethod is doing override check

Hello,
This patch enriches getSingleAbstractMethod to use the override check. This patch passes the regression with no failure.
Thanks
Anirban
Comment 8 Srikanth Sankaran CLA 2013-02-01 06:30:27 EST
(In reply to comment #7)
> Created attachment 226440 [details]
> getSingleAbstractMethod is doing override check
> 
> Hello,
> This patch enriches getSingleAbstractMethod to use the override check. This
> patch passes the regression with no failure.
> Thanks
> Anirban

Anirban, There are a bunch of problems with this patch both major and minor.

(1) The patch does not apply. Always pull from repository before creating
a patch.
(2) The method completely ignores super types and fails even for basic tests:
The following program should fail since I is NOT a functional interface, but
the patch incorrectly tags it as a functional interface:

// ---
interface J {
	void another();
}
interface I extends J {
	void doit();
}
public class X {
	static void foo() {
		I i = this::foo;
	}
}

javac correctly complains:
C:\jtests>C:\work\lambda-8-b74-windows-x64-21_jan_2013\bin\javac -cp c:\jtests X
.java
X.java:9: error: incompatible types: I is not a functional interface
                I i = () -> {}; // new
                      ^
    multiple non-overriding abstract methods found in interface I
1 error

(3) Overriding is a concept that occurs across class boundaries. A class's
methods cannot override each other, so much of the code there is suspect.

(4) for(int indx = 0; indx < methodArray.length ; indx++):
would have been better with index variable being 'i' and the length extracted
into a local variable instead of being computed afresh each time - it is
loop invariant.

(5) The algorithm could be constructed so it can terminate way earlier.

(6) You need to add junits. Without tests, no code can be released.
Comment 9 Srikanth Sankaran CLA 2013-02-03 09:35:45 EST
Created attachment 226481 [details]
Alternate work in progress - minimally tested
Comment 10 Srikanth Sankaran CLA 2013-02-03 14:55:02 EST
Created attachment 226483 [details]
Alternate patch - more evolved.

Except for intersection types in casts for which grammar support is lacking
this patch should do the trick for computation of functional descriptor.

Tests are still lacking.
Comment 11 Srikanth Sankaran CLA 2013-02-04 03:44:13 EST
Released the implementation via http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=5138a70372af4817aefdd3da44dfadf7f7557bf3.

Leaving this bug open until tests are written and released.

This work computes the functional descriptor of a functional interface and
the parameterization of a functional interface.

Intersection types will be dealt with in bug 399773.