Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8244711: [lworld] Javac needs to tweak checks for interface implementation by an inline type. #41

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -2165,6 +2165,23 @@ public ArrayType makeArrayType(Type t) {
* @param sym a symbol
*/
public Type asSuper(Type t, Symbol sym) {
return asSuper(t, sym, false);
}

/**
* Return the (most specific) base type of t that starts with the
* given symbol. If none exists, return null.
*
* Caveat Emptor: Since javac represents the class of all arrays with a singleton
* symbol Symtab.arrayClass, which by being a singleton cannot hold any discriminant,
* this method could yield surprising answers when invoked on arrays. For example when
* invoked with t being byte [] and sym being t.sym itself, asSuper would answer null.
*
* @param t a type
* @param sym a symbol
* @param checkReferenceProjection if true, first compute reference projection of t
*/
public Type asSuper(Type t, Symbol sym, boolean checkReferenceProjection) {
/* Some examples:
*
* (Enum<E>, Comparable) => Comparable<E>
@@ -2173,6 +2190,14 @@ public Type asSuper(Type t, Symbol sym) {
* (j.u.List<capture#160 of ? extends c.s.s.d.DocTree>, Iterable) =>
* Iterable<capture#160 of ? extends c.s.s.d.DocTree>
*/

/* For a (value or identity) class V, whether it implements an interface I, boils down to whether
V.ref is a subtype of I. OIOW, whether asSuper(V.ref, sym) != null. (Likewise for an abstract
superclass)
*/
if (checkReferenceProjection)
t = t.isValue() ? t.referenceProjection() : t;

if (sym.type == syms.objectType) { //optimization
if (!isValue(t))
return syms.objectType;
@@ -1572,7 +1572,7 @@ public void visitForeachLoop(JCEnhancedForLoop tree) {
Type elemtype = types.elemtype(exprType); // perhaps expr is an array?
if (elemtype == null) {
// or perhaps expr implements Iterable<T>?
Type base = types.asSuper(exprType, syms.iterableType.tsym);
Type base = types.asSuper(exprType, syms.iterableType.tsym, true);
if (base == null) {
log.error(tree.expr.pos(),
Errors.ForeachNotApplicableToType(exprType,
@@ -1867,7 +1867,7 @@ public void report(DiagnosticPosition pos, JCDiagnostic details) {

void checkAutoCloseable(DiagnosticPosition pos, Env<AttrContext> env, Type resource) {
if (!resource.isErroneous() &&
types.asSuper(resource, syms.autoCloseableType.tsym) != null &&
types.asSuper(resource, syms.autoCloseableType.tsym, true) != null &&
!types.isSameType(resource, syms.autoCloseableType)) { // Don't emit warning for AutoCloseable itself
Symbol close = syms.noSymbol;
Log.DiagnosticHandler discardHandler = new Log.DiscardDiagnosticHandler(log);
@@ -2678,12 +2678,8 @@ void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) {
}
checkCompatibleConcretes(pos, c);

/* Check for inline/identity incompatibilities: But first, we may need to switch to the
reference universe to make the hierarchy navigable.
*/
Type asRefType = c.isValue() ? c.referenceProjection() : c;
boolean isIdentityObject = types.asSuper(asRefType, syms.identityObjectType.tsym) != null;
boolean isInlineObject = types.asSuper(asRefType, syms.inlineObjectType.tsym) != null;
boolean isIdentityObject = types.asSuper(c, syms.identityObjectType.tsym, true) != null;
boolean isInlineObject = types.asSuper(c, syms.inlineObjectType.tsym, true) != null;
if (c.isValue() && isIdentityObject) {
log.error(pos, Errors.InlineTypeMustNotImplementIdentityObject(c));
} else if (!c.isInterface() && !c.tsym.isAbstract() && !c.isValue() && isInlineObject) {
@@ -1225,7 +1225,7 @@ public void visitTry(JCTry tree) {
types.interfaces(resource.type).prepend(types.supertype(resource.type)) :
List.of(resource.type);
for (Type sup : closeableSupertypes) {
if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) {
if (types.asSuper(sup, syms.autoCloseableType.tsym, true) != null) {
Symbol closeMethod = rs.resolveQualifiedMethod(tree,
attrEnv,
types.skipTypeVars(sup, false),
@@ -1718,7 +1718,7 @@ private JCBlock makeTwrBlock(List<JCTree> resources, JCBlock block, int depth) {

private JCStatement makeResourceCloseInvocation(JCExpression resource) {
// convert to AutoCloseable if needed
if (types.asSuper(resource.type, syms.autoCloseableType.tsym) == null) {
if (types.asSuper(resource.type, syms.autoCloseableType.tsym, true) == null) {
resource = convert(resource, syms.autoCloseableType);
}

@@ -3506,7 +3506,7 @@ private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
make_at(tree.expr.pos());
Type iteratorTarget = syms.objectType;
Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type),
syms.iterableType.tsym);
syms.iterableType.tsym, true);
if (iterableType.getTypeArguments().nonEmpty())
iteratorTarget = types.erasure(iterableType.getTypeArguments().head);
Type eType = types.skipTypeVars(tree.expr.type, false);
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2020, 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 8244711
* @summary Test that inline types work well with TWR
* @run main AutoCloseableTest
*/

public class AutoCloseableTest {

inline static class Foo implements AutoCloseable {

String s = "Exception while closing AutoCloseable";

@Override
public void close() throws Exception {
throw new Exception(s);
}

}

public static void main(String[] args) {
String expected = "";
String found = "";
try (Foo foo = new Foo()) {
expected = foo.s;
} catch (Exception e) {
found = e.getMessage();
}
if (expected.length() == 0 || !expected.equals(found))
throw new AssertionError("Should not get here!");
}
}
@@ -0,0 +1,15 @@
/*
sadayapalam marked this conversation as resolved.
Show resolved Hide resolved
* @test /nodynamiccopyright/
* @bug 8244711
* @summary Javac should complain about an inline class with conflicting super interfaces.
* @compile/fail/ref=ConflictingSuperInterfaceTest.out -XDrawDiagnostics ConflictingSuperInterfaceTest.java
*/

public class ConflictingSuperInterfaceTest {

interface I<T> {}
abstract class S implements I<String> {}
inline static class Foo extends S implements I<Integer> {
String s = "";
}
}
@@ -0,0 +1,2 @@
ConflictingSuperInterfaceTest.java:12:19: compiler.err.cant.inherit.diff.arg: ConflictingSuperInterfaceTest.I, java.lang.Integer, java.lang.String
1 error
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2020, 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 8244711
* @summary Test that inline types work well with enhanced for loop.
* @run main EnhancedForLoopTest
*/

import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;

public class EnhancedForLoopTest {

inline static class Foo<V> implements Iterable<V> {

List<V> lv;

public Foo() {
lv = new ArrayList<>();
}

public void add(V v) {
lv.add(v);
}

public Iterator<V> iterator() {
return lv.iterator();
}
}

public static void main(String[] args) {
Foo<String> foo = new Foo<String>();
foo.add ("Hello");
foo.add (" ");
foo.add ("World");
foo.add ("!");
String output = "";
for (var s : foo) {
output += s;
}
if (!output.equals("Hello World!"))
throw new AssertionError("Unexpected: " + output);
}
}