JDK-6193717 : Spurious "unchecked conversion" Xlint warning under certain conditions
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2004-11-11
  • Updated: 2010-04-02
  • Resolved: 2004-11-12
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]


A DESCRIPTION OF THE PROBLEM :
Under certain conditions the following line generates a
spurious "unchecked conversion" warning.

  Set<String> charts = data.getDataSet();

where getDataSet is declared as follows:

    protected Set<String> getDataSet()

Here is the warning it produces:

LintTemplateBug.java:67: warning: [unchecked] unchecked conversion
LintTemplateBug.java:120: warning: [unchecked] unchecked conversion
found   : java.util.Set
required: java.util.Set<java.lang.String>
    Set<String> charts = data.getDataSet();
                                        ^
This is clearly an incorrect warning. However, it is only generated when the
previous line declares the variable "data" without using generics. This may
call for a warning (none is generated), but the warning produced is incorrect
and misleading.

If the previous line is this:
    CData<Integer> data=new CData<Integer>();
no warning will be generated. But if the previous line is this:
    CData data=new CData();
the line that follows (above) will generate the spurious warning.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the test case with the -Xlint option:

You can make the spurious warning go away by changeing the preceeding
line given in the code. The bug also seems to depend on the
CData class's generic types since calling a local method with an
equivalent signature doesn't generate the strange warning. This is also
shown in the code.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I don't know if the preceeding line should generate a warning but
this line is correct and shouldn't generate any warning:
    Set<String> charts = data.getDataSet();
This is correct because both "charts" and CData.getDataSet() are of
type Set<String>

ACTUAL -
The assignment of the variable produces the warning below:

(Note: In case this web site strips leading spaces, the caret in the warning points to the open parenthesis.)


ERROR MESSAGES/STACK TRACES THAT OCCUR :
LintTemplateBug.java:120: warning: [unchecked] unchecked conversion
found   : java.util.Set
required: java.util.Set<java.lang.String>
    Set<String> charts = data.getDataSet();
                                        ^


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.*;
public class LintTemplateBug
{
  public LintTemplateBug()
  {
    CData data=new CData();
    // Using this line instead of the previous one makes the lint bug go away.
//    CData<Integer> data=new CData<Integer>();

    // This line generates the spurious warning.
    Set<String> charts = data.getDataSet();
    // Using this line insted of the previous one also makes the bug go away.
//    Set<String> theSet = getSet();
  }
  
  private Set<String> getSet() { return new HashSet<String>(); }

  static class CData<_Thing>
  {
    protected CData() { }
    
    protected Set<String> getDataSet()
    {
      return new TreeSet<String>();
    }
  }
}

---------- END SOURCE ----------
###@###.### 2004-11-11 00:06:00 GMT

Comments
EVALUATION Using raw types is reserved for interfacing with non-generic code. A raw type refers to a generic type used without type parameters. For example, this example uses the raw type CData twice: CData data=new CData(); Notice that java.lang.String is not a raw type, it is simply not generic. Raw types existence is motivated by migration compatibily, meaning you can start using generics in some parts of your application without having to use generics in all of your application. This is very important in cases where you don't have complete control of all the sources but want to use generics in our part of n application. There is a good description of the issues here: http://gafter.blogspot.com/2004/09/puzzling-through-erasure-answer.html Returning to the "spurious" warning. To be as backwards compatible as possible, all generic information is erased from members of a raw type. So even though getDataSet looks like this: Set<String> getDataSet() when accessed through a raw type it will actually look like this: Set getDataSet() The reason the warning is unchecked is that generic types aren't available at run time, so the compiler has no way to implement a check that would ensure that the Set returned actually is a Set<String>. ###@###.### 2004-11-12 01:03:22 GMT
12-11-2004