Bug 341795 - [1.7][compiler] Cannot assign a generic method with multiple bounds return value to any variable
Summary: [1.7][compiler] Cannot assign a generic method with multiple bounds return va...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.6.2   Edit
Hardware: PC Windows 7
: P3 major (vote)
Target Milestone: 3.7.1   Edit
Assignee: Srikanth Sankaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 319436 346026 (view as bug list)
Depends on:
Blocks:
 
Reported: 2011-04-04 10:49 EDT by Mauro Molinari CLA
Modified: 2011-08-05 02:54 EDT (History)
3 users (show)

See Also:


Attachments
Patch under consideration. (26.61 KB, patch)
2011-05-25 02:02 EDT, Srikanth Sankaran CLA
no flags Details | Diff
Revised cumulative patch under consideration. (29.55 KB, patch)
2011-05-26 04:42 EDT, 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 Mauro Molinari CLA 2011-04-04 10:49:57 EDT
Build Identifier: M20110210-1200

See the steps to repro

Reproducible: Always

Steps to Reproduce:
1. write the following classes:

public interface A
{
	<T extends B & C> T getaMethod();
	<T extends B & C> void setaMethod(T param);
}

public class B
{
}

public interface C
{
}

public class D
{
	public void someMethod(A aInstance)
	{
		aInstance.getaMethod();
	}
}

2. expected result: I should be able to assign the return value of aInstance.getaMethod() to either a B variable or C variable (or Object variable...)

3. actual result: I can't assign it to anything, the compiler always complains about:

Bound mismatch: The generic method getaMethod() of type A is not applicable for the arguments (). The 
 inferred type B is not a valid substitute for the bounded parameter <T extends B & C>

Actually, also javac 6 complains:
D.java:6: type parameters of <T>T cannot be determined; no unique maximal instan
ce exists for type variable T with upper bounds java.lang.Object,B,C
                aInstance.getaMethod();

However, this sounds to me as a bug in javac, isn't it?
Comment 1 Mauro Molinari CLA 2011-04-04 11:35:46 EDT
javac7 compiles the code fine with all the following variants:

Object o = aInstance.getaMethod();
A o = aInstance.getaMethod();
B o = aInstance.getaMethod();
Comment 2 Mauro Molinari CLA 2011-04-04 11:41:38 EDT
Do you think there's any dirty workaround to make such code compile even with Eclipse 3.6.x or javac<7?
Comment 3 Olivier Thomann CLA 2011-04-04 12:31:02 EDT
(In reply to comment #2)
> Do you think there's any dirty workaround to make such code compile even with
> Eclipse 3.6.x or javac<7?
Having B implements C would workaround the reported error.
Comment 4 Olivier Thomann CLA 2011-04-04 13:49:56 EDT
*** Bug 341789 has been marked as a duplicate of this bug. ***
Comment 5 Mauro Molinari CLA 2011-04-05 03:47:48 EDT
(In reply to comment #3)
> Having B implements C would workaround the reported error.

Thank you. However this is not applicable in my real-world case, since otherwise I wouldn't have needed to use the multiple bounds on the counterpart of A. I think I will have to leave a documented less strict bound and use casts by now. Thanks anyway.
Comment 6 Srikanth Sankaran CLA 2011-05-24 12:17:33 EDT
I know what is the problem here, it is too late for
3.7, but I can include a fix for subsequent versions.
Comment 7 Srikanth Sankaran CLA 2011-05-24 18:54:56 EDT
*** Bug 319436 has been marked as a duplicate of this bug. ***
Comment 8 Srikanth Sankaran CLA 2011-05-24 18:55:58 EDT
Another test case:

import java.io.Serializable;

public class Test {

  public static void main(String[] args) {
    createObject();
  }

  private static <T extends Comparable<?> & Serializable> T createObject() {
    return null;
  }
}
Comment 9 Srikanth Sankaran CLA 2011-05-24 18:58:46 EDT
*** Bug 346026 has been marked as a duplicate of this bug. ***
Comment 10 Srikanth Sankaran CLA 2011-05-24 19:03:31 EDT
More tests: (some of them Java 7):

1. 


class C {}
interface I {}

public class X<T extends C & I> {
    X() {}
    X f = new X<>();
}


2.

class C {}
interface I {}

public class X<T extends C & I> {
    static <U extends C & I> X<U> getX() {
        return null;
    }
    X f2 = getX();
}

3.


class C {}
interface I {}

public class X<T extends C & I> {
    static <U extends C & I> X<U> getX() {
        return null;
    }
    X<?> f2 = getX();
}
  
Junits 
org.eclipse.jdt.core.tests.compiler.regression.GenericsRegressionTest_1_7._test0030() - _test033() need to be enabled after the fix.
Comment 11 Srikanth Sankaran CLA 2011-05-25 02:02:01 EDT
Created attachment 196509 [details]
Patch under consideration.

This is a cumulative patch and includes also the changes being
considered for bug 242159. The code changes inside
org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding.resolveSubstituteConstraints(Scope,
TypeVariableBinding[], InferenceContext, boolean)
are for the bug 341795. Other changes are for bug 242159

This patch is under test.
Comment 12 Srikanth Sankaran CLA 2011-05-25 03:27:19 EDT
Passes all JDT/Core tests. I'll play around with it some more
before releasing it. It is too late for 3.7, so this will be
released only in the BETA_JAVA7 branch and will become available
through a supported release when eclipse releases a java 7 enabled
version later this year (per current plan)
Comment 13 Mauro Molinari CLA 2011-05-26 02:27:10 EDT
Does the [1.7] tag added in the subject mean that the fix will be available only when using Eclipse compiler compliance level to 1.7? Or will it be available also for 1.5 and 1.6 compliance levels?
Comment 14 Srikanth Sankaran CLA 2011-05-26 02:32:52 EDT
(In reply to comment #13)
> Does the [1.7] tag added in the subject mean that the fix will be available
> only when using Eclipse compiler compliance level to 1.7? Or will it be
> available also for 1.5 and 1.6 compliance levels?

At this point, we are looking at the fix being available for all
levels, but only through a release enabled for Java 7. So the fix
will be released only into the branch on which Java 7 development
work is happening.
Comment 15 Srikanth Sankaran CLA 2011-05-26 04:42:42 EDT
Created attachment 196639 [details]
Revised cumulative patch under consideration.

This is a cleaner, better documented patch.
Comment 16 Srikanth Sankaran CLA 2011-05-26 06:11:44 EDT
As a part of this cumulative fix, I had to remaster 13 tests from
GenericTypeTests suite - I have verified that in every one of these
cases, the new behavior matches JDK 7b142 - javac compiler.

The fix applies to all compliance levels.

Released in BETA_JAVA7 branch only - this is too late for 3.7
stream (HEAD)
Comment 17 Mauro Molinari CLA 2011-05-27 11:59:21 EDT
(In reply to comment #14)
> At this point, we are looking at the fix being available for all
> levels, but only through a release enabled for Java 7. So the fix
> will be released only into the branch on which Java 7 development
> work is happening.

This is clear now, thank you!
Comment 18 Olivier Thomann CLA 2011-06-28 09:47:47 EDT
Verified using Java 7 feature patch.