# HG changeset patch # User asaha # Date 1454693687 28800 # Node ID 6d41db46322dc616e16cbc2dabfe81bd6c0b5822 # Parent b561ebc6e8e66f7bbf77467244efc85f7ab17746# Parent 4ba5c112dc4763497ce1ffceb1d34378a95873bc Merge diff -r b561ebc6e8e6 -r 6d41db46322d src/share/classes/com/sun/tools/javac/util/GraphUtils.java --- a/src/share/classes/com/sun/tools/javac/util/GraphUtils.java Mon Feb 01 16:40:53 2016 -0800 +++ b/src/share/classes/com/sun/tools/javac/util/GraphUtils.java Fri Feb 05 09:34:47 2016 -0800 @@ -103,34 +103,60 @@ * directed graph in linear time. Works on TarjanNode. */ public static > List> tarjan(Iterable nodes) { - ListBuffer> cycles = new ListBuffer<>(); + Tarjan tarjan = new Tarjan<>(); + return tarjan.findSCC(nodes); + } + + //where + private static class Tarjan> { + + /** Unique node identifier. */ + int index = 0; + + /** List of SCCs found so far. */ + ListBuffer> sccs = new ListBuffer<>(); + + /** Stack of all reacheable nodes from given root. */ ListBuffer stack = new ListBuffer<>(); - int index = 0; - for (N node: nodes) { - if (node.index == -1) { - index += tarjan(node, index, stack, cycles); + + private List> findSCC(Iterable nodes) { + for (N node : nodes) { + if (node.index == -1) { + findSCC(node); + } + } + return sccs.toList(); + } + + private void findSCC(N v) { + visitNode(v); + for (TarjanNode tn : v.getAllDependencies()) { + @SuppressWarnings("unchecked") + N n = (N)tn; + if (n.index == -1) { + //it's the first time we see this node + findSCC(n); + v.lowlink = Math.min(v.lowlink, n.lowlink); + } else if (stack.contains(n)) { + //this node is already reachable from current root + v.lowlink = Math.min(v.lowlink, n.index); + } + } + if (v.lowlink == v.index) { + //v is the root of a SCC + addSCC(v); } } - return cycles.toList(); - } - private static > int tarjan(N v, int index, ListBuffer stack, ListBuffer> cycles) { - v.index = index; - v.lowlink = index; - index++; - stack.prepend(v); - v.active = true; - for (TarjanNode nd: v.getAllDependencies()) { - @SuppressWarnings("unchecked") - N n = (N)nd; - if (n.index == -1) { - tarjan(n, index, stack, cycles); - v.lowlink = Math.min(v.lowlink, n.lowlink); - } else if (stack.contains(n)) { - v.lowlink = Math.min(v.lowlink, n.index); - } + private void visitNode(N n) { + n.index = index; + n.lowlink = index; + index++; + stack.prepend(n); + n.active = true; } - if (v.lowlink == v.index) { + + private void addSCC(N v) { N n; ListBuffer cycle = new ListBuffer<>(); do { @@ -138,9 +164,8 @@ n.active = false; cycle.add(n); } while (n != v); - cycles.add(cycle.toList()); + sccs.add(cycle.toList()); } - return index; } /** diff -r b561ebc6e8e6 -r 6d41db46322d test/tools/javac/generics/inference/8130304/T8130304.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/generics/inference/8130304/T8130304.java Fri Feb 05 09:34:47 2016 -0800 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8130304 + * @summary Inference: NodeNotFoundException thrown with deep generic method call chain + * @compile T8130304.java + */ +class T8130304 { + + void test() { + outer( + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner(), + inner()); + } + + void outer(T... ts) { } + + T inner() { + return null; + } +} diff -r b561ebc6e8e6 -r 6d41db46322d test/tools/javac/generics/inference/8130304/T8130304b.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/generics/inference/8130304/T8130304b.java Fri Feb 05 09:34:47 2016 -0800 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8130304 + * @summary Inference: NodeNotFoundException thrown with deep generic method call chain + * @compile T8130304b.java + */ +class T8130304b { + + void test() { + TestZ r = null; + Crazy x = r.m3("X"); + r.m1(r.m4(r.m2(x, r.m3("a")), t -> "x"), r.m3("a")); + } + + interface Crazy { } + + interface TestZ { + public Crazy m1(Crazy... d); + public Crazy> m2(Crazy e, Crazy f); + public Crazy m3(A g); + public Crazy m4(Crazy h, java.util.function.Function i); + } +}