diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java
index 80a8d002a15..f7d0352bc28 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java
@@ -3213,6 +3213,7 @@ public class Types {
containsType(t, s) && containsType(s, t);
}
+ //
/**
* Adapt a type by computing a substitution which maps a source
* type to a target type.
@@ -3226,92 +3227,113 @@ public class Types {
Type target,
ListBuffer from,
ListBuffer to) throws AdaptFailure {
- Map mapping = new HashMap();
- adaptRecursive(source, target, from, to, mapping);
- List fromList = from.toList();
- List toList = to.toList();
- while (!fromList.isEmpty()) {
- Type val = mapping.get(fromList.head.tsym);
- if (toList.head != val)
- toList.head = val;
- fromList = fromList.tail;
- toList = toList.tail;
- }
+ new Adapter(from, to).adapt(source, target);
}
- // where
- private void adaptRecursive(Type source,
- Type target,
- ListBuffer from,
- ListBuffer to,
- Map mapping) throws AdaptFailure {
- if (source.tag == TYPEVAR) {
- // Check to see if there is
- // already a mapping for $source$, in which case
- // the old mapping will be merged with the new
- Type val = mapping.get(source.tsym);
- if (val != null) {
- if (val.isSuperBound() && target.isSuperBound()) {
- val = isSubtype(lowerBound(val), lowerBound(target))
- ? target : val;
- } else if (val.isExtendsBound() && target.isExtendsBound()) {
- val = isSubtype(upperBound(val), upperBound(target))
- ? val : target;
- } else if (!isSameType(val, target)) {
- throw new AdaptFailure();
- }
- } else {
- val = target;
- from.append(source);
- to.append(target);
- }
- mapping.put(source.tsym, val);
- } else if (source.tag == target.tag) {
- switch (source.tag) {
- case CLASS:
- adapt(source.allparams(), target.allparams(),
- from, to, mapping);
- break;
- case ARRAY:
- adaptRecursive(elemtype(source), elemtype(target),
- from, to, mapping);
- break;
- case WILDCARD:
- if (source.isExtendsBound()) {
- adaptRecursive(upperBound(source), upperBound(target),
- from, to, mapping);
- } else if (source.isSuperBound()) {
- adaptRecursive(lowerBound(source), lowerBound(target),
- from, to, mapping);
- }
- break;
- }
- }
- }
- public static class AdaptFailure extends Exception {
- static final long serialVersionUID = -7490231548272701566L;
+
+ class Adapter extends SimpleVisitor {
+
+ ListBuffer from;
+ ListBuffer to;
+ Map mapping;
+
+ Adapter(ListBuffer from, ListBuffer to) {
+ this.from = from;
+ this.to = to;
+ mapping = new HashMap();
}
- /**
- * Adapt a type by computing a substitution which maps a list of
- * source types to a list of target types.
- *
- * @param source the source type
- * @param target the target type
- * @param from the type variables of the computed substitution
- * @param to the types of the computed substitution.
- */
- private void adapt(List source,
- List target,
- ListBuffer from,
- ListBuffer to,
- Map mapping) throws AdaptFailure {
- if (source.length() == target.length()) {
- while (source.nonEmpty()) {
- adaptRecursive(source.head, target.head, from, to, mapping);
- source = source.tail;
- target = target.tail;
+ public void adapt(Type source, Type target) throws AdaptFailure {
+ visit(source, target);
+ List fromList = from.toList();
+ List toList = to.toList();
+ while (!fromList.isEmpty()) {
+ Type val = mapping.get(fromList.head.tsym);
+ if (toList.head != val)
+ toList.head = val;
+ fromList = fromList.tail;
+ toList = toList.tail;
}
}
+
+ @Override
+ public Void visitClassType(ClassType source, Type target) throws AdaptFailure {
+ if (target.tag == CLASS)
+ adaptRecursive(source.allparams(), target.allparams());
+ return null;
+ }
+
+ @Override
+ public Void visitArrayType(ArrayType source, Type target) throws AdaptFailure {
+ if (target.tag == ARRAY)
+ adaptRecursive(elemtype(source), elemtype(target));
+ return null;
+ }
+
+ @Override
+ public Void visitWildcardType(WildcardType source, Type target) throws AdaptFailure {
+ if (source.isExtendsBound())
+ adaptRecursive(upperBound(source), upperBound(target));
+ else if (source.isSuperBound())
+ adaptRecursive(lowerBound(source), lowerBound(target));
+ return null;
+ }
+
+ @Override
+ public Void visitTypeVar(TypeVar source, Type target) throws AdaptFailure {
+ // Check to see if there is
+ // already a mapping for $source$, in which case
+ // the old mapping will be merged with the new
+ Type val = mapping.get(source.tsym);
+ if (val != null) {
+ if (val.isSuperBound() && target.isSuperBound()) {
+ val = isSubtype(lowerBound(val), lowerBound(target))
+ ? target : val;
+ } else if (val.isExtendsBound() && target.isExtendsBound()) {
+ val = isSubtype(upperBound(val), upperBound(target))
+ ? val : target;
+ } else if (!isSameType(val, target)) {
+ throw new AdaptFailure();
+ }
+ } else {
+ val = target;
+ from.append(source);
+ to.append(target);
+ }
+ mapping.put(source.tsym, val);
+ return null;
+ }
+
+ @Override
+ public Void visitType(Type source, Type target) {
+ return null;
+ }
+
+ private Set cache = new HashSet();
+
+ private void adaptRecursive(Type source, Type target) {
+ TypePair pair = new TypePair(source, target);
+ if (cache.add(pair)) {
+ try {
+ visit(source, target);
+ } finally {
+ cache.remove(pair);
+ }
+ }
+ }
+
+ private void adaptRecursive(List source, List target) {
+ if (source.length() == target.length()) {
+ while (source.nonEmpty()) {
+ adaptRecursive(source.head, target.head);
+ source = source.tail;
+ target = target.tail;
+ }
+ }
+ }
+ }
+
+ public static class AdaptFailure extends RuntimeException {
+ static final long serialVersionUID = -7490231548272701566L;
}
private void adaptSelf(Type t,
@@ -3326,6 +3348,7 @@ public class Types {
throw new AssertionError(ex);
}
}
+ //
/**
* Rewrite all type variables (universal quantifiers) in the given
diff --git a/langtools/test/tools/javac/cast/6586091/T6586091.java b/langtools/test/tools/javac/cast/6586091/T6586091.java
new file mode 100644
index 00000000000..5cc9ae8aa75
--- /dev/null
+++ b/langtools/test/tools/javac/cast/6586091/T6586091.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @author Maurizio Cimadamore
+ * @bug 6586091
+ * @summary javac crashes with StackOverflowError
+ * @compile T6586091.java
+ */
+
+class T6586091 {
+ static class A> {}
+ static class B extends A> {}
+
+ A> t = null;
+ B c = (B)t;
+}
\ No newline at end of file