JDK-5060485 : The scope of a class type parameter is too wide
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: solaris_2.6
  • CPU: x86
  • Submitted: 2004-06-09
  • Updated: 2017-05-16
  • Resolved: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
JDK 7
7 b03Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
Name: akR10088			Date: 06/09/2004


The JLS3 Draft 8.1.2 Generic Classes and Type Parameters reads:

The scope of a class type parameter is the entire declaration of the class,
except any static members or initializers of the class or of any classes nested within it,
but including the type parameter section itself. Therefore, type parameters can appear
as parts of their own bounds, or as bounds of other type parameters declared in the same
section.

But the following example shows that not only a class type parameter is visible
in a static member, but is not shadowed by a nested declaration.

This test compiles OK:

------------------------------ file X.java
public class X<Z> {

  static public class Y {}

  static public class Y1 <T extends X<Y>> {
  }

}
------------------------
But if we change in the 1st line "Z" to "Y", this "Y" interfere with the
name of a nested class:

------------------------------ file X.java
public class X<Y> {

  static public class Y {}

  static public class Y1 <T extends X<Y>> {
  }

}
------------------------
novo64% javac -source 1.5 X.java
X.java:5: non-static class Y cannot be referenced from a static context
  static public class Y1 <T extends X<Y>> {
                                      ^
1 error
novo64%  

The used JDK version is:

novo64% java -version
java version "1.5.0-beta3"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta3-b54)
Java HotSpot(TM) Client VM (build 1.5.0-beta3-b54, mixed mode)


======================================================================

Comments
SUGGESTED FIX Webrev of changes: http://sa.sfbay/projects/langtools/bugid_summary.pl?bugid=5060485 See also attachment: 5060485.tar.gz
2006-10-31

SUGGESTED FIX It turns out that the changes to Resolve.java to fix 5046972 were incorrect. See http://javac.sfbay/java/jdk/ws/tools/gjc/FIXES/2004/05/24/5046972/webrev/src/share/classes/com/sun/tools/javac/comp/Resolve.java.udiff.html Part of the changes for 5046972 are fine: the local variable staticOnly is set more correctly and that is actually enough to fix 5046972. However, the fix for 5046972 also changes when to look at member types which is not correct. Type variables are not membertypes. So the fix for this bug is to undo some of the changes made for 5046972: @@ -928,13 +928,8 @@ return e.sym; } } - - JCClassDecl encl; - if (env1.baseClause) { - encl = (JCClassDecl)env1.tree; - } else { - sym = findMemberType(env1, env1.enclClass.sym.type, name, - env1.enclClass.sym); + sym = findMemberType( + env1, env1.enclClass.sym.type, name, env1.enclClass.sym); if (staticOnly && sym.kind == TYP && sym.type.tag == CLASS && sym.type.getEnclosingType().tag == CLASS && @@ -943,8 +938,8 @@ return new StaticError(sym); else if (sym.exists()) return sym; else if (sym.kind < bestSoFar.kind) bestSoFar = sym; - encl = env1.enclClass; - } + + JCClassDecl encl = env1.baseClause ? (JCClassDecl)env1.tree : env1.enclClass; if ((encl.sym.flags() & STATIC) != 0) staticOnly = true; } An alternative view of this situation is to diff against the version before 5046972 and the suggested fix for this bug. There are some changes that were caused by API changes for JSR 269 and com.sun.source. Ignoring this, it is clear that the fix now only is concerned with determining if the current environment is static or not: @@ -883,19 +932,19 @@ env1, env1.enclClass.sym.type, name, env1.enclClass.sym); if (staticOnly && sym.kind == TYP && sym.type.tag == CLASS && - sym.type.outer().tag == CLASS && + sym.type.getEnclosingType().tag == CLASS && env1.enclClass.sym.type.isParameterized() && - sym.type.outer().isParameterized()) + sym.type.getEnclosingType().isParameterized()) return new StaticError(sym); else if (sym.exists()) return sym; else if (sym.kind < bestSoFar.kind) bestSoFar = sym; - if ((env1.enclClass.sym.flags() & STATIC) != 0 && - (env1.tree.tag != Tree.CLASSDEF || env1.tree == env1.enclClass)) + JCClassDecl encl = env1.baseClause ? (JCClassDecl)env1.tree : env1.enclClass; + if ((encl.sym.flags() & STATIC) != 0) staticOnly = true; } - if (env.tree.tag != Tree.IMPORT) { + if (env.tree.tag != JCTree.IMPORT) { sym = findGlobalType(env, env.toplevel.namedImportScope, name); if (sym.exists()) return sym; else if (sym.kind < bestSoFar.kind) bestSoFar = sym;
2006-10-31

SUGGESTED FIX No that doesn't work, since this program must compile: public class Method<T extends Number> { static class Y {} <Y extends Number> void test() { Method<Y> m = null; Number n = m.get(); } T get() { return null; } }
2006-10-30

SUGGESTED FIX The solution is fairly simple: Resolve.findType looks at "any other type" before looking at member types. So we just rearrange the code to look at member types before "any other type".
2006-10-30

EVALUATION The exact words are: "Within a class C, a declaration d of a member type named n shadows the declarations of any other types named n that are in scope at the point where d occurs." http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.5 Since the compiler looks at "any other types" before it looks at member types, it is incorrect.
2006-10-30

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: dragon mustang
2004-09-07

EVALUATION This is definitely a bug. The type parameter should be shadowed, or the shadowing should be illegal (need to check the JLS). ###@###.### 2004-06-09 The shadowing rules for type parameters are not yet in the JLS. I'm sure the compiler is wrong in its current behavior, but I don't know what the correct behavior should be. Reassigning to spec for JLS3. For reference, here is a program that should clearly be an error, for one of two (or more) reasons, but I don't know which: interface I1 {} interface I2 {} class A<T extends I1> { class T implements I2 {} void f(T t) { I1 i = t; } } ###@###.### 2004-06-13 JLS 8.5, Member types, states that a declaration of a member type shadows the declarations of any other type of the same name that is in scope. Hence, the compile is in error, and the smaller example above is illegal because if f, T referes to the member type that is a subtype of I2 not I1. ###@###.### 2004-07-09
2004-07-09