Bug 151275

Summary: [1.5][compiler] generic type inference on return type with primitive works differently in Eclipse and javac
Product: [Eclipse Project] JDT Reporter: Brad Cupit <brad.cupit>
Component: CoreAssignee: JDT-Core-Inbox <jdt-core-inbox>
Status: RESOLVED WORKSFORME QA Contact:
Severity: minor    
Priority: P3    
Version: 3.2   
Target Milestone: 3.3 M1   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Brad Cupit CLA 2006-07-20 12:48:50 EDT
When the only way to infer the type of a Type Parameter is based on the type of the return value, and if the return value is expected to be a primitive type, Eclipse knows to use the wrapper type, but javac fails.

Example code:

class GenericTest {
    public static void main(String[] args) {
        Integer castInteger = genericCast(1);               // works
        int castInt1 = genericCast(1);                      // fails in javac but works in Eclipse
        int castInt2 = GenericTest.<Integer>genericCast(1); // workaround for javac
        int castInt3 = (Integer) genericCast(1);            // workaround for javac
    }
    
    private static <T> T genericCast(Object input) {
        @SuppressWarnings("unchecked")
        T castValue = (T) input;
        
        return castValue;
    }
}

I'm not sure which side the bug is in (Eclipse or javac) but I like the Eclipse functionality much better. Unfortunately the discrepancy between the two compilers has caused issues in our build process.

The workaround for javac is to cast the value to the wrapper type, or to explicitly state the Generic type when invoking the method.

javac generates the following error:
type parameters of <T>T cannot be determined; no unique maximal instance exists for type variable T with upper bounds int,java.lang.Object

The following bugs might be related to this (although they each seem very different to me):
Bug 81923
Bug 101779
Bug 105524
Comment 1 Brad Cupit CLA 2006-07-20 13:43:00 EDT
This bug has also been submitted to Sun's bug database, however, at the time of this comment, it had not yet been made publicly visible.
Comment 2 Philipe Mulet CLA 2006-07-21 04:59:23 EDT
Inference based on expected return type is described in JLS 15.12.2.8 (Inferring Unresolved Type Arguments)

• If the method result occurs in a context where it will be subject to assignment
conversion (§5.2) to a type S, then let R be the declared result type of the
method, and let R’ = R[T1 = B(T1) ... Tn = B(Tn)] where B(Ti) is the
type inferred for Ti in the previous section, or Ti if no type was inferred.

Then JLS 5.2 for assignment conversion allows boxing/unboxing conversions.
[...]
Assignment contexts allow the use of one of the following:
• an identity conversion (§5.1.1)
• a widening primitive conversion (§5.1.2)
• a widening reference conversion (§5.1.5)
• a boxing conversion (§5.1.7) optionally followed by a widening reference
conversion
• an unboxing conversion (§5.1.8) optionally followed by a widening primitive
conversion.


So in brief, I believe our behavior is the right one. 
Added GenericTypeTest#test1024.
Comment 3 Brad Cupit CLA 2006-07-24 10:43:16 EDT
(In reply to comment #2)
> So in brief, I believe our behavior is the right one. 
> Added GenericTypeTest#test1024.
> 
That's excellent news! Once Sun makes the bug that I submitted on javac public (see comment #1), I'll post their response and the bug id back here.

Thank you so much for looking that up Phillipe!