7144506: Attr.checkMethod should be called after inference variables have been fixed
Summary: Unify post-inference sanity check with Attr.checkMethod
Reviewed-by: jjg, dlsmith
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Mar 06 13:26:36 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Mar 06 13:28:05 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -1518,8 +1518,6 @@
Type mpt = newMethTemplate(argtypes, typeargtypes);
localEnv.info.varArgs = false;
Type mtype = attribExpr(tree.meth, localEnv, mpt);
- if (localEnv.info.varArgs)
- Assert.check(mtype.isErroneous() || tree.varargsElement != null);
// Compute the result type.
Type restype = mtype.getReturnType();
@@ -1553,6 +1551,9 @@
// Check that value of resulting type is admissible in the
// current context. Also, capture the return type
result = check(tree, capture(restype), VAL, pkind, pt);
+
+ if (localEnv.info.varArgs)
+ Assert.check(result.isErroneous() || tree.varargsElement != null);
}
chk.validate(tree.typeargs, localEnv);
}
@@ -1730,7 +1731,7 @@
tree.pos(), rsEnv, clazztype, argtypes, typeargtypes);
tree.constructorType = tree.constructor.type.isErroneous() ?
syms.errType :
- checkMethod(clazztype,
+ checkConstructor(clazztype,
tree.constructor,
rsEnv,
tree.args,
@@ -1805,7 +1806,7 @@
tree.constructorType = syms.errType;
}
else {
- tree.constructorType = checkMethod(clazztype,
+ tree.constructorType = checkConstructor(clazztype,
tree.constructor,
localEnv,
tree.args,
@@ -2675,7 +2676,7 @@
Warner noteWarner = new Warner();
/**
- * Check that method arguments conform to its instantation.
+ * Check that method arguments conform to its instantiation.
**/
public Type checkMethod(Type site,
Symbol sym,
@@ -2712,109 +2713,39 @@
true,
useVarargs,
noteWarner);
- boolean warned = noteWarner.hasNonSilentLint(LintCategory.UNCHECKED);
// If this fails, something went wrong; we should not have
// found the identifier in the first place.
if (owntype == null) {
if (!pt.isErroneous())
log.error(env.tree.pos(),
- "internal.error.cant.instantiate",
- sym, site,
+ "internal.error.cant.instantiate",
+ sym, site,
Type.toString(pt.getParameterTypes()));
owntype = types.createErrorType(site);
+ return types.createErrorType(site);
+ } else if (owntype.getReturnType().tag == FORALL) {
+ return owntype;
} else {
- // System.out.println("call : " + env.tree);
- // System.out.println("method : " + owntype);
- // System.out.println("actuals: " + argtypes);
- List<Type> formals = owntype.getParameterTypes();
- Type last = useVarargs ? formals.last() : null;
- if (sym.name==names.init &&
- sym.owner == syms.enumSym)
- formals = formals.tail.tail;
- List<JCExpression> args = argtrees;
- while (formals.head != last) {
- JCTree arg = args.head;
- Warner warn = chk.convertWarner(arg.pos(), arg.type, formals.head);
- assertConvertible(arg, arg.type, formals.head, warn);
- warned |= warn.hasNonSilentLint(LintCategory.UNCHECKED);
- args = args.tail;
- formals = formals.tail;
- }
- if (useVarargs) {
- Type varArg = types.elemtype(last);
- while (args.tail != null) {
- JCTree arg = args.head;
- Warner warn = chk.convertWarner(arg.pos(), arg.type, varArg);
- assertConvertible(arg, arg.type, varArg, warn);
- warned |= warn.hasNonSilentLint(LintCategory.UNCHECKED);
- args = args.tail;
- }
- } else if ((sym.flags() & VARARGS) != 0 && allowVarargs) {
- // non-varargs call to varargs method
- Type varParam = owntype.getParameterTypes().last();
- Type lastArg = argtypes.last();
- if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
- !types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
- log.warning(argtrees.last().pos(), "inexact.non-varargs.call",
- types.elemtype(varParam),
- varParam);
- }
-
- if (warned && sym.type.tag == FORALL) {
- chk.warnUnchecked(env.tree.pos(),
- "unchecked.meth.invocation.applied",
- kindName(sym),
- sym.name,
- rs.methodArguments(sym.type.getParameterTypes()),
- rs.methodArguments(argtypes),
- kindName(sym.location()),
- sym.location());
- owntype = new MethodType(owntype.getParameterTypes(),
- types.erasure(owntype.getReturnType()),
- types.erasure(owntype.getThrownTypes()),
- syms.methodClass);
- }
- if (useVarargs) {
- JCTree tree = env.tree;
- Type argtype = owntype.getParameterTypes().last();
- if (owntype.getReturnType().tag != FORALL || warned) {
- chk.checkVararg(env.tree.pos(), owntype.getParameterTypes(), sym);
- }
- Type elemtype = types.elemtype(argtype);
- switch (tree.getTag()) {
- case APPLY:
- ((JCMethodInvocation) tree).varargsElement = elemtype;
- break;
- case NEWCLASS:
- ((JCNewClass) tree).varargsElement = elemtype;
- break;
- default:
- throw new AssertionError(""+tree);
- }
- }
+ return chk.checkMethod(owntype, sym, env, argtrees, argtypes, useVarargs);
}
+ }
+
+ /**
+ * Check that constructor arguments conform to its instantiation.
+ **/
+ public Type checkConstructor(Type site,
+ Symbol sym,
+ Env<AttrContext> env,
+ final List<JCExpression> argtrees,
+ List<Type> argtypes,
+ List<Type> typeargtypes,
+ boolean useVarargs) {
+ Type owntype = checkMethod(site, sym, env, argtrees, argtypes, typeargtypes, useVarargs);
+ chk.checkType(env.tree.pos(), owntype.getReturnType(), syms.voidType);
return owntype;
}
- private void assertConvertible(JCTree tree, Type actual, Type formal, Warner warn) {
- if (types.isConvertible(actual, formal, warn))
- return;
-
- if (formal.isCompound()
- && types.isSubtype(actual, types.supertype(formal))
- && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn))
- return;
-
- if (false) {
- // TODO: make assertConvertible work
- chk.typeError(tree.pos(), diags.fragment("incompatible.types"), actual, formal);
- throw new AssertionError("Tree: " + tree
- + " actual:" + actual
- + " formal: " + formal);
- }
- }
-
public void visitLiteral(JCLiteral tree) {
result = check(
tree, litType(tree.typetag).constType(tree.value), VAL, pkind, pt);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Mar 06 13:26:36 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Mar 06 13:28:05 2012 +0000
@@ -63,6 +63,7 @@
private final Names names;
private final Log log;
+ private final Resolve rs;
private final Symtab syms;
private final Enter enter;
private final Infer infer;
@@ -95,6 +96,7 @@
names = Names.instance(context);
log = Log.instance(context);
+ rs = Resolve.instance(context);
syms = Symtab.instance(context);
enter = Enter.instance(context);
infer = Infer.instance(context);
@@ -106,6 +108,7 @@
Source source = Source.instance(context);
allowGenerics = source.allowGenerics();
+ allowVarargs = source.allowVarargs();
allowAnnotations = source.allowAnnotations();
allowCovariantReturns = source.allowCovariantReturns();
allowSimplifiedVarargs = source.allowSimplifiedVarargs();
@@ -137,6 +140,10 @@
*/
boolean allowGenerics;
+ /** Switch: varargs enabled?
+ */
+ boolean allowVarargs;
+
/** Switch: annotations enabled?
*/
boolean allowAnnotations;
@@ -743,22 +750,105 @@
(s.flags() & (STATIC | FINAL)) != 0);
}
- /**
- * Check that vararg method call is sound
- * @param pos Position to be used for error reporting.
- * @param argtypes Actual arguments supplied to vararg method.
- */
- void checkVararg(DiagnosticPosition pos, List<Type> argtypes, Symbol msym) {
- Type argtype = argtypes.last();
- if (!types.isReifiable(argtype) &&
- (!allowSimplifiedVarargs ||
- msym.attribute(syms.trustMeType.tsym) == null ||
- !isTrustMeAllowedOnMethod(msym))) {
- warnUnchecked(pos,
- "unchecked.generic.array.creation",
- argtype);
+ Type checkMethod(Type owntype,
+ Symbol sym,
+ Env<AttrContext> env,
+ final List<JCExpression> argtrees,
+ List<Type> argtypes,
+ boolean useVarargs) {
+ boolean warned = false;
+ // System.out.println("call : " + env.tree);
+ // System.out.println("method : " + owntype);
+ // System.out.println("actuals: " + argtypes);
+ List<Type> formals = owntype.getParameterTypes();
+ Type last = useVarargs ? formals.last() : null;
+ if (sym.name==names.init &&
+ sym.owner == syms.enumSym)
+ formals = formals.tail.tail;
+ List<JCExpression> args = argtrees;
+ while (formals.head != last) {
+ JCTree arg = args.head;
+ Warner warn = convertWarner(arg.pos(), arg.type, formals.head);
+ assertConvertible(arg, arg.type, formals.head, warn);
+ warned |= warn.hasNonSilentLint(LintCategory.UNCHECKED);
+ args = args.tail;
+ formals = formals.tail;
+ }
+ if (useVarargs) {
+ Type varArg = types.elemtype(last);
+ while (args.tail != null) {
+ JCTree arg = args.head;
+ Warner warn = convertWarner(arg.pos(), arg.type, varArg);
+ assertConvertible(arg, arg.type, varArg, warn);
+ warned |= warn.hasNonSilentLint(LintCategory.UNCHECKED);
+ args = args.tail;
+ }
+ } else if ((sym.flags() & VARARGS) != 0 && allowVarargs) {
+ // non-varargs call to varargs method
+ Type varParam = owntype.getParameterTypes().last();
+ Type lastArg = argtypes.last();
+ if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
+ !types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
+ log.warning(argtrees.last().pos(), "inexact.non-varargs.call",
+ types.elemtype(varParam), varParam);
}
+ if (warned) {
+ warnUnchecked(env.tree.pos(),
+ "unchecked.meth.invocation.applied",
+ kindName(sym),
+ sym.name,
+ rs.methodArguments(sym.type.getParameterTypes()),
+ rs.methodArguments(argtypes),
+ kindName(sym.location()),
+ sym.location());
+ owntype = new MethodType(owntype.getParameterTypes(),
+ types.erasure(owntype.getReturnType()),
+ types.erasure(owntype.getThrownTypes()),
+ syms.methodClass);
+ }
+ if (useVarargs) {
+ JCTree tree = env.tree;
+ Type argtype = owntype.getParameterTypes().last();
+ if (!types.isReifiable(argtype) &&
+ (!allowSimplifiedVarargs ||
+ sym.attribute(syms.trustMeType.tsym) == null ||
+ !isTrustMeAllowedOnMethod(sym))) {
+ warnUnchecked(env.tree.pos(),
+ "unchecked.generic.array.creation",
+ argtype);
+ }
+ Type elemtype = types.elemtype(argtype);
+ switch (tree.getTag()) {
+ case APPLY:
+ ((JCMethodInvocation) tree).varargsElement = elemtype;
+ break;
+ case NEWCLASS:
+ ((JCNewClass) tree).varargsElement = elemtype;
+ break;
+ default:
+ throw new AssertionError(""+tree);
+ }
+ }
+ return owntype;
}
+ //where
+ private void assertConvertible(JCTree tree, Type actual, Type formal, Warner warn) {
+ if (types.isConvertible(actual, formal, warn))
+ return;
+
+ if (formal.isCompound()
+ && types.isSubtype(actual, types.supertype(formal))
+ && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn))
+ return;
+
+ if (false) {
+ // TODO: make assertConvertible work
+ typeError(tree.pos(), diags.fragment("incompatible.types"), actual, formal);
+ throw new AssertionError("Tree: " + tree
+ + " actual:" + actual
+ + " formal: " + formal);
+ }
+ }
/**
* Check that type 't' is a valid instantiation of a generic class
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Tue Mar 06 13:26:36 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Tue Mar 06 13:28:05 2012 +0000
@@ -445,16 +445,19 @@
return List.nil();
}
@Override
- void check(List<Type> inferred, Types types) throws NoInstanceException {
+ void instantiateReturnType(Type restype, List<Type> inferred, Types types) throws NoInstanceException {
+ Type owntype = new MethodType(types.subst(getParameterTypes(), tvars, inferred),
+ restype,
+ types.subst(getThrownTypes(), tvars, inferred),
+ qtype.tsym);
// check that actuals conform to inferred formals
- checkArgumentsAcceptable(env, capturedArgs, getParameterTypes(), allowBoxing, useVarargs, warn);
+ checkArgumentsAcceptable(env, capturedArgs, owntype.getParameterTypes(), allowBoxing, useVarargs, warn);
// check that inferred bounds conform to their bounds
checkWithinBounds(all_tvars,
types.subst(inferredTypes, tvars, inferred), warn);
- if (useVarargs) {
- chk.checkVararg(env.tree.pos(), getParameterTypes(), msym);
- }
- }};
+ qtype = chk.checkMethod(owntype, msym, env, TreeInfo.args(env.tree), capturedArgs, useVarargs);
+ }
+ };
}
else {
// check that actuals conform to inferred formals
@@ -520,16 +523,7 @@
return qtype.map(f);
}
- void instantiateReturnType(Type restype, List<Type> inferred, Types types) throws NoInstanceException {
- //update method type with newly inferred type-arguments
- qtype = new MethodType(types.subst(getParameterTypes(), tvars, inferred),
- restype,
- types.subst(UninferredMethodType.this.getThrownTypes(), tvars, inferred),
- UninferredMethodType.this.qtype.tsym);
- check(inferred, types);
- }
-
- abstract void check(List<Type> inferred, Types types) throws NoInstanceException;
+ abstract void instantiateReturnType(Type restype, List<Type> inferred, Types types);
abstract List<Type> getConstraints(TypeVar tv, ConstraintKind ck);
@@ -544,7 +538,7 @@
if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
log.note(pos, "deferred.method.inst", msym, UninferredMethodType.this.qtype, newRestype);
}
- return newRestype;
+ return UninferredMethodType.this.qtype.getReturnType();
}
@Override
public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Tue Mar 06 13:26:36 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Tue Mar 06 13:28:05 2012 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -102,6 +102,16 @@
setOpname(MOD, "%", names);
}
+ public static List<JCExpression> args(JCTree t) {
+ switch (t.getTag()) {
+ case APPLY:
+ return ((JCMethodInvocation)t).args;
+ case NEWCLASS:
+ return ((JCNewClass)t).args;
+ default:
+ return null;
+ }
+ }
/** Return name of operator with given tree tag.
*/
--- a/langtools/test/tools/javac/6758789/T6758789b.out Tue Mar 06 13:26:36 2012 +0000
+++ b/langtools/test/tools/javac/6758789/T6758789b.out Tue Mar 06 13:28:05 2012 +0000
@@ -1,4 +1,4 @@
-T6758789b.java:16:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo<X>
+T6758789b.java:16:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo<java.lang.Object>
T6758789b.java:16:10: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, T6758789a.Foo<X>, T6758789a.Foo, kindname.class, T6758789a
- compiler.err.warnings.and.werror
1 error
--- a/langtools/test/tools/javac/generics/6723444/T6723444.out Tue Mar 06 13:26:36 2012 +0000
+++ b/langtools/test/tools/javac/generics/6723444/T6723444.out Tue Mar 06 13:28:05 2012 +0000
@@ -1,5 +1,5 @@
-T6723444.java:42:9: compiler.err.unreported.exception.need.to.catch.or.throw: X2
-T6723444.java:43:9: compiler.err.unreported.exception.need.to.catch.or.throw: X2
+T6723444.java:42:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:43:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
T6723444.java:45:32: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
T6723444.java:46:17: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
T6723444.java:48:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
--- a/langtools/test/tools/javac/generics/7015430/T7015430.out Tue Mar 06 13:26:36 2012 +0000
+++ b/langtools/test/tools/javac/generics/7015430/T7015430.out Tue Mar 06 13:28:05 2012 +0000
@@ -1,14 +1,14 @@
-T7015430.java:41:15: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E>
+T7015430.java:41:15: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
T7015430.java:41:14: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
T7015430.java:50:42: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
T7015430.java:50:41: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
-T7015430.java:68:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E>
+T7015430.java:68:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
T7015430.java:68:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
T7015430.java:77:40: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
T7015430.java:77:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
T7015430.java:104:41: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
T7015430.java:104:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
-T7015430.java:113:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E>
+T7015430.java:113:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
T7015430.java:113:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
T7015430.java:41:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
T7015430.java:68:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception