8147546: regression when type-checking generic calls inside nested declarations occurring in method context

Attr.visitClassDef should set a temporary ArgumentAttr cache when in speculative mode

Reviewed-by: vromero
This commit is contained in:
Maurizio Cimadamore 2016-01-20 10:53:29 +00:00
parent 9dcc8b2068
commit e782acbf37
3 changed files with 136 additions and 32 deletions

View File

@ -42,6 +42,7 @@ import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.TypeMetadata.Annotations;
import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
import com.sun.tools.javac.comp.Check.CheckContext;
import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
import com.sun.tools.javac.comp.Infer.FreeTypeListener;
@ -885,40 +886,46 @@ public class Attr extends JCTree.Visitor {
}
public void visitClassDef(JCClassDecl tree) {
// Local and anonymous classes have not been entered yet, so we need to
// do it now.
if (env.info.scope.owner.kind.matches(KindSelector.VAL_MTH)) {
enter.classEnter(tree, env);
} else {
// If this class declaration is part of a class level annotation,
// as in @MyAnno(new Object() {}) class MyClass {}, enter it in
// order to simplify later steps and allow for sensible error
// messages.
if (env.tree.hasTag(NEWCLASS) && TreeInfo.isInAnnotation(env, tree))
Optional<ArgumentAttr.LocalCacheContext> localCacheContext =
Optional.ofNullable(env.info.isSpeculative ?
argumentAttr.withLocalCacheContext() : null);
try {
// Local and anonymous classes have not been entered yet, so we need to
// do it now.
if (env.info.scope.owner.kind.matches(KindSelector.VAL_MTH)) {
enter.classEnter(tree, env);
}
ClassSymbol c = tree.sym;
if (c == null) {
// exit in case something drastic went wrong during enter.
result = null;
} else {
// make sure class has been completed:
c.complete();
// If this class appears as an anonymous class
// in a superclass constructor call where
// no explicit outer instance is given,
// disable implicit outer instance from being passed.
// (This would be an illegal access to "this before super").
if (env.info.isSelfCall &&
env.tree.hasTag(NEWCLASS) &&
((JCNewClass) env.tree).encl == null)
{
c.flags_field |= NOOUTERTHIS;
} else {
// If this class declaration is part of a class level annotation,
// as in @MyAnno(new Object() {}) class MyClass {}, enter it in
// order to simplify later steps and allow for sensible error
// messages.
if (env.tree.hasTag(NEWCLASS) && TreeInfo.isInAnnotation(env, tree))
enter.classEnter(tree, env);
}
attribClass(tree.pos(), c);
result = tree.type = c.type;
ClassSymbol c = tree.sym;
if (c == null) {
// exit in case something drastic went wrong during enter.
result = null;
} else {
// make sure class has been completed:
c.complete();
// If this class appears as an anonymous class
// in a superclass constructor call where
// no explicit outer instance is given,
// disable implicit outer instance from being passed.
// (This would be an illegal access to "this before super").
if (env.info.isSelfCall &&
env.tree.hasTag(NEWCLASS) &&
((JCNewClass)env.tree).encl == null) {
c.flags_field |= NOOUTERTHIS;
}
attribClass(tree.pos(), c);
result = tree.type = c.type;
}
} finally {
localCacheContext.ifPresent(LocalCacheContext::leave);
}
}

View File

@ -0,0 +1,46 @@
/*
* 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 8147546
* @summary regression when type-checking generic calls inside nested declarations occurring in method context
* @compile T8147546a.java
*/
abstract class T8147546a {
interface I<O> { void t(O clazz); }
abstract <A> I<A> a(Class<A> clazz);
abstract <B> B b(Class<B> t);
abstract <C> C c(C a);
Object f(Iterable<Object> xs) {
return c(c(new Object() {
<T> void g(Class<T> clazz) {
a(clazz).t(b(clazz));
}
}));
}
}

View File

@ -0,0 +1,51 @@
/*
* 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 8147546
* @summary regression when type-checking generic calls inside nested declarations occurring in method context
* @compile T8147546b.java
*/
abstract class T8147546b {
interface I<O> { void t(O clazz); }
abstract <B> B b(Class<B> t);
abstract <C> C c(C a);
abstract Object d(Runnable r);
Object f(Iterable<Object> xs) {
return c(d(
() -> {
class Foo {
<T> void g(Class<T> clazz, I<T> i) {
i.t(b(clazz));
}
}
}));
}
}