提交 b8aba9ef 编写于 作者: M mcimadamore

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
上级 5d8a6a9c
/*
* 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 @@ public class Attr extends JCTree.Visitor {
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 @@ public class Attr extends JCTree.Visitor {
// 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 @@ public class Attr extends JCTree.Visitor {
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 @@ public class Attr extends JCTree.Visitor {
tree.constructorType = syms.errType;
}
else {
tree.constructorType = checkMethod(clazztype,
tree.constructorType = checkConstructor(clazztype,
tree.constructor,
localEnv,
tree.args,
......@@ -2675,7 +2676,7 @@ public class Attr extends JCTree.Visitor {
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,107 +2713,37 @@ public class Attr extends JCTree.Visitor {
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);
}
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);
}
/**
* 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;
}
public void visitLiteral(JCLiteral tree) {
......
......@@ -63,6 +63,7 @@ public class Check {
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 @@ public class Check {
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 @@ public class Check {
Source source = Source.instance(context);
allowGenerics = source.allowGenerics();
allowVarargs = source.allowVarargs();
allowAnnotations = source.allowAnnotations();
allowCovariantReturns = source.allowCovariantReturns();
allowSimplifiedVarargs = source.allowSimplifiedVarargs();
......@@ -137,6 +140,10 @@ public class Check {
*/
boolean allowGenerics;
/** Switch: varargs enabled?
*/
boolean allowVarargs;
/** Switch: annotations enabled?
*/
boolean allowAnnotations;
......@@ -743,22 +750,105 @@ public class Check {
(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
......
......@@ -445,16 +445,19 @@ public class Infer {
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 @@ public class Infer {
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 @@ public class Infer {
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) {
......
/*
* 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 @@ public class TreeInfo {
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.
*/
......
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
......
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
......
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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册