Skip to content

Commit 5e4a2ea

Browse files
biboudismcimadamore
andcommitted
8357653: Inner classes of type parameters emitted as raw types in signatures
8357472: NPE in Types.containsType for type variable used as a qualifier Co-authored-by: Maurizio Cimadamore <[email protected]> Reviewed-by: mcimadamore, vromero, liach
1 parent b787ad6 commit 5e4a2ea

File tree

5 files changed

+424
-53
lines changed

5 files changed

+424
-53
lines changed

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java

Lines changed: 48 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,12 @@
4242

4343
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
4444
import com.sun.tools.javac.code.Lint.LintCategory;
45-
import com.sun.tools.javac.code.Source.Feature;
4645
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
4746
import com.sun.tools.javac.code.TypeMetadata.Annotations;
4847
import com.sun.tools.javac.comp.AttrContext;
4948
import com.sun.tools.javac.comp.Check;
5049
import com.sun.tools.javac.comp.Enter;
5150
import com.sun.tools.javac.comp.Env;
52-
import com.sun.tools.javac.comp.LambdaToMethod;
5351
import com.sun.tools.javac.jvm.ClassFile;
5452
import com.sun.tools.javac.util.*;
5553

@@ -2236,60 +2234,64 @@ public Type visitErrorType(ErrorType t, Symbol sym) {
22362234
};
22372235

22382236
/**
2239-
* Return the base type of t or any of its outer types that starts
2240-
* with the given symbol. If none exists, return null.
2237+
* This method returns the first type in a sequence (starting at `t`) that is
2238+
* a subclass of `sym`. The next type in the sequence is obtained by calling
2239+
* `getEnclosingType()` on the previous type in the sequence. Note, this is
2240+
* typically used to compute the implicit qualifier in a method/field access
2241+
* expression. Example:
22412242
*
2242-
* @param t a type
2243-
* @param sym a symbol
2243+
* static class Sup<F> { public F f; }
2244+
* class Outer {
2245+
* static class Sub extends Sup<String> {
2246+
* class I {
2247+
* void test() {
2248+
* String f2 = f; // Sup<String>::f
2249+
* }
2250+
* }
2251+
* }
2252+
* }
2253+
*
2254+
* @param t a type
2255+
* @param sym a symbol
22442256
*/
22452257
public Type asOuterSuper(Type t, Symbol sym) {
2246-
switch (t.getTag()) {
2247-
case CLASS:
2248-
do {
2249-
Type s = asSuper(t, sym);
2250-
if (s != null) return s;
2251-
t = t.getEnclosingType();
2252-
} while (t.hasTag(CLASS));
2253-
return null;
2254-
case ARRAY:
2255-
return isSubtype(t, sym.type) ? sym.type : null;
2256-
case TYPEVAR:
2257-
return asSuper(t, sym);
2258-
case ERROR:
2259-
return t;
2260-
default:
2261-
return null;
2258+
Type t1 = t;
2259+
while (!t1.hasTag(NONE)) {
2260+
Type s = asSuper(t1, sym);
2261+
if (s != null) return s;
2262+
t1 = t1.getEnclosingType();
22622263
}
2264+
return null;
22632265
}
22642266

22652267
/**
2266-
* Return the base type of t or any of its enclosing types that
2267-
* starts with the given symbol. If none exists, return null.
2268+
* This method returns the first type in a sequence (starting at `t`) that is
2269+
* a subclass of `sym`. The next type in the sequence is obtained by obtaining
2270+
* innermost lexically enclosing class type of the previous type in the sequence.
2271+
* Note, this is typically used to compute the implicit qualifier in
2272+
* a type expression. Example:
2273+
*
2274+
* class A<T> { class B { } }
2275+
*
2276+
* class C extends A<String> {
2277+
* static class D {
2278+
* B b; // A<String>.B
2279+
* }
2280+
* }
22682281
*
22692282
* @param t a type
22702283
* @param sym a symbol
22712284
*/
22722285
public Type asEnclosingSuper(Type t, Symbol sym) {
2273-
switch (t.getTag()) {
2274-
case CLASS:
2275-
do {
2276-
Type s = asSuper(t, sym);
2277-
if (s != null) return s;
2278-
Type outer = t.getEnclosingType();
2279-
t = (outer.hasTag(CLASS)) ? outer :
2280-
(t.tsym.owner.enclClass() != null) ? t.tsym.owner.enclClass().type :
2281-
Type.noType;
2282-
} while (t.hasTag(CLASS));
2283-
return null;
2284-
case ARRAY:
2285-
return isSubtype(t, sym.type) ? sym.type : null;
2286-
case TYPEVAR:
2287-
return asSuper(t, sym);
2288-
case ERROR:
2289-
return t;
2290-
default:
2291-
return null;
2286+
Type t1 = t;
2287+
while (!t1.hasTag(NONE)) {
2288+
Type s = asSuper(t1, sym);
2289+
if (s != null) return s;
2290+
t1 = (t1.tsym.owner.enclClass() != null)
2291+
? t1.tsym.owner.enclClass().type
2292+
: noType;
22922293
}
2294+
return null;
22932295
}
22942296
// </editor-fold>
22952297

@@ -4514,7 +4516,7 @@ private boolean sideCast(Type from, Type to, Warner warn) {
45144516
to = from;
45154517
from = target;
45164518
}
4517-
List<Type> commonSupers = superClosure(to, erasure(from));
4519+
List<Type> commonSupers = supertypeClosure(to, erasure(from));
45184520
boolean giveWarning = commonSupers.isEmpty();
45194521
// The arguments to the supers could be unified here to
45204522
// get a more accurate analysis
@@ -4572,13 +4574,13 @@ private boolean giveWarning(Type from, Type to) {
45724574
return false;
45734575
}
45744576

4575-
private List<Type> superClosure(Type t, Type s) {
4577+
private List<Type> supertypeClosure(Type t, Type s) {
45764578
List<Type> cl = List.nil();
45774579
for (List<Type> l = interfaces(t); l.nonEmpty(); l = l.tail) {
45784580
if (isSubtype(s, erasure(l.head))) {
45794581
cl = insert(cl, l.head);
45804582
} else {
4581-
cl = union(cl, superClosure(l.head, s));
4583+
cl = union(cl, supertypeClosure(l.head, s));
45824584
}
45834585
}
45844586
return cl;

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4673,11 +4673,8 @@ Type checkIdInternal(JCTree tree,
46734673
//
46744674
// Then the type of the last expression above is
46754675
// Tree<Point>.Visitor.
4676-
else if (ownOuter.hasTag(CLASS) && site != ownOuter) {
4677-
Type normOuter = site;
4678-
if (normOuter.hasTag(CLASS)) {
4679-
normOuter = types.asEnclosingSuper(site, ownOuter.tsym);
4680-
}
4676+
else if ((ownOuter.hasTag(CLASS) || ownOuter.hasTag(TYPEVAR)) && site != ownOuter) {
4677+
Type normOuter = types.asEnclosingSuper(site, ownOuter.tsym);
46814678
if (normOuter == null) // perhaps from an import
46824679
normOuter = types.erasure(ownOuter);
46834680
if (normOuter != ownOuter)
@@ -5063,8 +5060,8 @@ public void visitTypeApply(JCTypeApply tree) {
50635060
site = ((JCFieldAccess) clazz).selected.type;
50645061
} else throw new AssertionError(""+tree);
50655062
if (clazzOuter.hasTag(CLASS) && site != clazzOuter) {
5066-
if (site.hasTag(CLASS))
5067-
site = types.asOuterSuper(site, clazzOuter.tsym);
5063+
if (site.hasTag(CLASS) || site.hasTag(TYPEVAR))
5064+
site = types.asEnclosingSuper(site, clazzOuter.tsym);
50685065
if (site == null)
50695066
site = types.erasure(clazzOuter);
50705067
clazzOuter = site;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8357472
27+
* @summary NPE in Types.containsType for type variable used as a qualifier
28+
* @compile T8357472.java
29+
*/
30+
31+
class T8357472 {
32+
class A<T> {
33+
protected class B<V> {}
34+
35+
public static <T, M extends A<T>> void f(Object g) {
36+
@SuppressWarnings("unchecked")
37+
M.B<?> mapping = (M.B<?>) g;
38+
M.B<?>[] mapping2 = new M.B[1];
39+
mapping2[0] = mapping;
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)