7188968: New instance creation expression using diamond is checked twice

Unify method and constructor check logic

Reviewed-by: jjg
This commit is contained in:
Maurizio Cimadamore 2012-09-26 14:22:41 +01:00
parent 6a310eb049
commit 5f629e503c
12 changed files with 147 additions and 121 deletions

View File

@ -168,6 +168,10 @@ public abstract class Symbol implements Element {
return owner; return owner;
} }
public Symbol baseSymbol() {
return this;
}
/** The symbol's erased type. /** The symbol's erased type.
*/ */
public Type erasure(Types types) { public Type erasure(Types types) {

View File

@ -1730,39 +1730,16 @@ public class Attr extends JCTree.Visitor {
List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv); List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv);
if (TreeInfo.isDiamond(tree) && !clazztype.isErroneous()) { if (TreeInfo.isDiamond(tree) && !clazztype.isErroneous()) {
clazztype = attribDiamond(localEnv, tree, clazztype, argtypes, typeargtypes); Pair<Symbol, Type> diamondResult =
clazz.type = clazztype; attribDiamond(localEnv, tree, clazztype, argtypes, typeargtypes);
} else if (allowDiamondFinder && tree.clazz.type = types.createErrorType(clazztype);
tree.def == null && tree.constructor = diamondResult.fst;
!clazztype.isErroneous() && tree.constructorType = diamondResult.snd;
clazztype.getTypeArguments().nonEmpty() && if (!diamondResult.snd.isErroneous()) {
findDiamonds) { tree.clazz.type = clazztype = diamondResult.snd.getReturnType();
boolean prevDeferDiags = log.deferDiagnostics; tree.constructorType = types.createMethodTypeWithReturn(diamondResult.snd, syms.voidType);
Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;
Type inferred = null;
try {
//disable diamond-related diagnostics
log.deferDiagnostics = true;
log.deferredDiagnostics = ListBuffer.lb();
inferred = attribDiamond(localEnv,
tree,
clazztype,
argtypes,
typeargtypes);
}
finally {
log.deferDiagnostics = prevDeferDiags;
log.deferredDiagnostics = prevDeferredDiags;
}
if (inferred != null &&
!inferred.isErroneous() &&
inferred.tag == CLASS &&
types.isAssignable(inferred, pt().tag == NONE ? clazztype : pt(), Warner.noWarnings)) {
String key = types.isSameType(clazztype, inferred) ?
"diamond.redundant.args" :
"diamond.redundant.args.1";
log.warning(tree.clazz.pos(), key, clazztype, inferred);
} }
clazztype = chk.checkClassType(tree.clazz, tree.clazz.type, true);
} }
// If we have made no mistakes in the class type... // If we have made no mistakes in the class type...
@ -1796,7 +1773,7 @@ public class Attr extends JCTree.Visitor {
// Resolve the called constructor under the assumption // Resolve the called constructor under the assumption
// that we are referring to a superclass instance of the // that we are referring to a superclass instance of the
// current instance (JLS ???). // current instance (JLS ???).
else { else if (!TreeInfo.isDiamond(tree)) {
//the following code alters some of the fields in the current //the following code alters some of the fields in the current
//AttrContext - hence, the current context must be dup'ed in //AttrContext - hence, the current context must be dup'ed in
//order to avoid downstream failures //order to avoid downstream failures
@ -1805,17 +1782,47 @@ public class Attr extends JCTree.Visitor {
rsEnv.info.varArgs = false; rsEnv.info.varArgs = false;
tree.constructor = rs.resolveConstructor( tree.constructor = rs.resolveConstructor(
tree.pos(), rsEnv, clazztype, argtypes, typeargtypes); tree.pos(), rsEnv, clazztype, argtypes, typeargtypes);
tree.constructorType = tree.constructor.type.isErroneous() ? if (cdef == null) { //do not check twice!
syms.errType : tree.constructorType = checkId(tree,
checkConstructor(clazztype, clazztype,
tree.constructor, tree.constructor,
rsEnv, rsEnv,
tree.args, new ResultInfo(MTH, newMethodTemplate(syms.voidType, argtypes, typeargtypes)),
argtypes, rsEnv.info.varArgs);
typeargtypes, if (rsEnv.info.varArgs)
rsEnv.info.varArgs); Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null);
if (rsEnv.info.varArgs) }
Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null); if (tree.def == null &&
!clazztype.isErroneous() &&
clazztype.getTypeArguments().nonEmpty() &&
findDiamonds) {
boolean prevDeferDiags = log.deferDiagnostics;
Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;
Type inferred = null;
try {
//disable diamond-related diagnostics
log.deferDiagnostics = true;
log.deferredDiagnostics = ListBuffer.lb();
inferred = attribDiamond(localEnv,
tree,
clazztype,
argtypes,
typeargtypes).snd;
} finally {
log.deferDiagnostics = prevDeferDiags;
log.deferredDiagnostics = prevDeferredDiags;
}
if (!inferred.isErroneous()) {
inferred = inferred.getReturnType();
}
if (inferred != null &&
types.isAssignable(inferred, pt().tag == NONE ? syms.objectType : pt(), Warner.noWarnings)) {
String key = types.isSameType(clazztype, inferred) ?
"diamond.redundant.args" :
"diamond.redundant.args.1";
log.warning(tree.clazz.pos(), key, clazztype, inferred);
}
}
} }
if (cdef != null) { if (cdef != null) {
@ -1872,24 +1879,16 @@ public class Attr extends JCTree.Visitor {
// Reassign clazztype and recompute constructor. // Reassign clazztype and recompute constructor.
clazztype = cdef.sym.type; clazztype = cdef.sym.type;
boolean useVarargs = tree.varargsElement != null; Symbol sym = tree.constructor = rs.resolveConstructor(
Symbol sym = rs.resolveConstructor( tree.pos(), localEnv, clazztype, argtypes, typeargtypes);
tree.pos(), localEnv, clazztype, argtypes, Assert.check(sym.kind < AMBIGUOUS);
typeargtypes, true, useVarargs);
Assert.check(sym.kind < AMBIGUOUS || tree.constructor.type.isErroneous());
tree.constructor = sym; tree.constructor = sym;
if (tree.constructor.kind > ERRONEOUS) { tree.constructorType = checkId(tree,
tree.constructorType = syms.errType; clazztype,
} tree.constructor,
else { localEnv,
tree.constructorType = checkConstructor(clazztype, new ResultInfo(VAL, newMethodTemplate(syms.voidType, argtypes, typeargtypes)),
tree.constructor, localEnv.info.varArgs);
localEnv,
tree.args,
argtypes,
typeargtypes,
useVarargs);
}
} }
if (tree.constructor != null && tree.constructor.kind == MTH) if (tree.constructor != null && tree.constructor.kind == MTH)
@ -1899,7 +1898,7 @@ public class Attr extends JCTree.Visitor {
chk.validate(tree.typeargs, localEnv); chk.validate(tree.typeargs, localEnv);
} }
Type attribDiamond(Env<AttrContext> env, Pair<Symbol, Type> attribDiamond(Env<AttrContext> env,
final JCNewClass tree, final JCNewClass tree,
final Type clazztype, final Type clazztype,
List<Type> argtypes, List<Type> argtypes,
@ -1909,7 +1908,7 @@ public class Attr extends JCTree.Visitor {
//if the type of the instance creation expression is erroneous, //if the type of the instance creation expression is erroneous,
//or if it's an interface, or if something prevented us to form a valid //or if it's an interface, or if something prevented us to form a valid
//mapping, return the (possibly erroneous) type unchanged //mapping, return the (possibly erroneous) type unchanged
return clazztype; return new Pair<Symbol, Type>(syms.noSymbol, clazztype);
} }
//dup attribution environment and augment the set of inference variables //dup attribution environment and augment the set of inference variables
@ -1928,26 +1927,21 @@ public class Attr extends JCTree.Visitor {
argtypes, argtypes,
typeargtypes); typeargtypes);
Type owntype = types.createErrorType(clazztype); Type constructorType = types.createErrorType(clazztype);
if (constructor.kind == MTH) { ResultInfo diamondResult = new ResultInfo(MTH, newMethodTemplate(resultInfo.pt, argtypes, typeargtypes), new Check.NestedCheckContext(resultInfo.checkContext) {
ResultInfo diamondResult = new ResultInfo(VAL, resultInfo.pt, new Check.NestedCheckContext(resultInfo.checkContext) { @Override
@Override public void report(DiagnosticPosition _unused, JCDiagnostic details) {
public void report(DiagnosticPosition pos, JCDiagnostic details) { enclosingContext.report(tree.clazz,
enclosingContext.report(tree.clazz.pos(), diags.fragment("cant.apply.diamond.1", diags.fragment("diamond", clazztype.tsym), details));
diags.fragment("cant.apply.diamond.1", diags.fragment("diamond", clazztype.tsym), details)); }
} });
}); constructorType = checkId(tree, site,
owntype = checkMethod(site, constructor,
constructor, localEnv,
diamondResult, diamondResult,
localEnv, localEnv.info.varArgs);
tree.args,
argtypes,
typeargtypes,
localEnv.info.varArgs).getReturnType();
}
return chk.checkClassType(tree.clazz.pos(), owntype, true); return new Pair<Symbol, Type>(constructor.baseSymbol(), constructorType);
} }
/** Make an attributed null check tree. /** Make an attributed null check tree.
@ -2563,10 +2557,9 @@ public class Attr extends JCTree.Visitor {
} }
break; break;
case MTH: { case MTH: {
JCMethodInvocation app = (JCMethodInvocation)env.tree;
owntype = checkMethod(site, sym, owntype = checkMethod(site, sym,
new ResultInfo(VAL, resultInfo.pt.getReturnType(), resultInfo.checkContext), new ResultInfo(VAL, resultInfo.pt.getReturnType(), resultInfo.checkContext),
env, app.args, resultInfo.pt.getParameterTypes(), env, TreeInfo.args(env.tree), resultInfo.pt.getParameterTypes(),
resultInfo.pt.getTypeArguments(), env.info.varArgs); resultInfo.pt.getTypeArguments(), env.info.varArgs);
break; break;
} }
@ -2757,21 +2750,6 @@ public class Attr extends JCTree.Visitor {
} }
} }
/**
* 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, new ResultInfo(VAL, syms.voidType), env, argtrees, argtypes, typeargtypes, useVarargs);
chk.checkType(env.tree.pos(), owntype.getReturnType(), syms.voidType);
return owntype;
}
public void visitLiteral(JCLiteral tree) { public void visitLiteral(JCLiteral tree) {
result = check( result = check(
tree, litType(tree.typetag).constType(tree.value), VAL, resultInfo); tree, litType(tree.typetag).constType(tree.value), VAL, resultInfo);

View File

@ -970,9 +970,11 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
List<Type> thrown = List.nil(); List<Type> thrown = List.nil();
long ctorFlags = 0; long ctorFlags = 0;
boolean based = false; boolean based = false;
boolean addConstructor = true;
if (c.name.isEmpty()) { if (c.name.isEmpty()) {
JCNewClass nc = (JCNewClass)env.next.tree; JCNewClass nc = (JCNewClass)env.next.tree;
if (nc.constructor != null) { if (nc.constructor != null) {
addConstructor = nc.constructor.kind != ERR;
Type superConstrType = types.memberType(c.type, Type superConstrType = types.memberType(c.type,
nc.constructor); nc.constructor);
argtypes = superConstrType.getParameterTypes(); argtypes = superConstrType.getParameterTypes();
@ -985,10 +987,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
thrown = superConstrType.getThrownTypes(); thrown = superConstrType.getThrownTypes();
} }
} }
JCTree constrDef = DefaultConstructor(make.at(tree.pos), c, if (addConstructor) {
typarams, argtypes, thrown, JCTree constrDef = DefaultConstructor(make.at(tree.pos), c,
ctorFlags, based); typarams, argtypes, thrown,
tree.defs = tree.defs.prepend(constrDef); ctorFlags, based);
tree.defs = tree.defs.prepend(constrDef);
}
} }
// If this is a class, enter symbols for this and super into // If this is a class, enter symbols for this and super into

View File

@ -1972,10 +1972,12 @@ public class Resolve {
steps = steps.tail; steps = steps.tail;
} }
if (sym.kind >= AMBIGUOUS) { if (sym.kind >= AMBIGUOUS) {
final JCDiagnostic details = sym.kind == WRONG_MTH ? Symbol errSym =
currentResolutionContext.candidates.head.details : currentResolutionContext.resolutionCache.get(currentResolutionContext.firstErroneousResolutionPhase());
final JCDiagnostic details = errSym.kind == WRONG_MTH ?
((InapplicableSymbolError)errSym).errCandidate().details :
null; null;
Symbol errSym = new ResolveError(WRONG_MTH, "diamond error") { errSym = new InapplicableSymbolError(errSym.kind, "diamondError") {
@Override @Override
JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
@ -2015,16 +2017,23 @@ public class Resolve {
for (Scope.Entry e = site.tsym.members().lookup(names.init); for (Scope.Entry e = site.tsym.members().lookup(names.init);
e.scope != null; e.scope != null;
e = e.next()) { e = e.next()) {
final Symbol sym = e.sym;
//- System.out.println(" e " + e.sym); //- System.out.println(" e " + e.sym);
if (e.sym.kind == MTH && if (sym.kind == MTH &&
(e.sym.flags_field & SYNTHETIC) == 0) { (sym.flags_field & SYNTHETIC) == 0) {
List<Type> oldParams = e.sym.type.tag == FORALL ? List<Type> oldParams = e.sym.type.tag == FORALL ?
((ForAll)e.sym.type).tvars : ((ForAll)sym.type).tvars :
List.<Type>nil(); List.<Type>nil();
Type constrType = new ForAll(site.tsym.type.getTypeArguments().appendList(oldParams), Type constrType = new ForAll(site.tsym.type.getTypeArguments().appendList(oldParams),
types.createMethodTypeWithReturn(e.sym.type.asMethodType(), site)); types.createMethodTypeWithReturn(sym.type.asMethodType(), site));
MethodSymbol newConstr = new MethodSymbol(sym.flags(), names.init, constrType, site.tsym) {
@Override
public Symbol baseSymbol() {
return sym;
}
};
bestSoFar = selectBest(env, site, argtypes, typeargtypes, bestSoFar = selectBest(env, site, argtypes, typeargtypes,
new MethodSymbol(e.sym.flags(), names.init, constrType, site.tsym), newConstr,
bestSoFar, bestSoFar,
allowBoxing, allowBoxing,
useVarargs, useVarargs,

View File

@ -1,3 +1,2 @@
T6840059.java:15:9: compiler.err.cant.apply.symbol.1: kindname.constructor, T6840059, java.lang.Integer, java.lang.String, kindname.class, T6840059, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer)) T6840059.java:15:9: compiler.err.cant.apply.symbol.1: kindname.constructor, T6840059, java.lang.Integer, java.lang.String, kindname.class, T6840059, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
T6840059.java:15:25: compiler.err.cant.apply.symbol.1: kindname.constructor, T6840059, java.lang.Integer, compiler.misc.no.args, kindname.class, T6840059, (compiler.misc.arg.length.mismatch) 1 error
2 errors

View File

@ -1,3 +1,2 @@
T6857948.java:16:32: compiler.err.cant.resolve.location.args: kindname.method, nosuchfunction, , , (compiler.misc.location: kindname.class, Test, null) T6857948.java:16:32: compiler.err.cant.resolve.location.args: kindname.method, nosuchfunction, , , (compiler.misc.location: kindname.class, Test, null)
T6857948.java:16:50: compiler.err.cant.apply.symbol.1: kindname.constructor, Foo, java.lang.String, compiler.misc.no.args, kindname.class, Foo, (compiler.misc.arg.length.mismatch) 1 error
2 errors

View File

@ -23,12 +23,10 @@
// key: compiler.misc.kindname.constructor // key: compiler.misc.kindname.constructor
// key: compiler.misc.kindname.class // key: compiler.misc.kindname.class
// key: compiler.misc.no.args
// key: compiler.err.cant.apply.symbol.1 // key: compiler.err.cant.apply.symbol.1
// key: compiler.misc.arg.length.mismatch
// key: compiler.misc.no.conforming.assignment.exists // key: compiler.misc.no.conforming.assignment.exists
// key: compiler.misc.inconvertible.types // key: compiler.misc.inconvertible.types
// key: compiler.misc.count.error.plural // key: compiler.misc.count.error
// key: compiler.err.error // key: compiler.err.error
// run: backdoor // run: backdoor

View File

@ -4,7 +4,7 @@
* *
* @summary Diamond: javac generates diamond inference errors when in 'finder' mode * @summary Diamond: javac generates diamond inference errors when in 'finder' mode
* @author mcimadamore * @author mcimadamore
* @compile -Werror -XDfindDiamond T7002837.java * @compile/fail/ref=T7002837.out -Werror -XDrawDiagnostics -XDfindDiamond T7002837.java
* *
*/ */

View File

@ -0,0 +1,4 @@
T7002837.java:13:19: compiler.warn.diamond.redundant.args.1: T7002837<java.lang.Integer>, T7002837<java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>
- compiler.err.warnings.and.werror
1 error
1 warning

View File

@ -0,0 +1,25 @@
/*
* @test /nodynamiccopyright/
* @bug 7188968
*
* @summary Diamond: javac generates diamond inference errors when in 'finder' mode
* @author mcimadamore
* @compile/fail/ref=T7188968.out -Xlint:unchecked -XDrawDiagnostics T7188968.java
*
*/
import java.util.List;
class T7188968 {
static class Foo<X> {
Foo(List<X> ls, Object o) { }
static <Z> Foo<Z> makeFoo(List<Z> lz, Object o) { return null; }
}
void test(List l) {
new Foo(l, unknown);
new Foo(l, unknown) { };
new Foo<>(l, unknown);
Foo.makeFoo(l, unknown);
}
}

View File

@ -0,0 +1,7 @@
T7188968.java:20:20: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
T7188968.java:21:20: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
T7188968.java:21:29: compiler.warn.unchecked.call.mbr.of.raw.type: T7188968.Foo(java.util.List<X>,java.lang.Object), T7188968.Foo
T7188968.java:22:22: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
T7188968.java:23:24: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
4 errors
1 warning

View File

@ -1,3 +1,2 @@
T6264029.java:15:19: compiler.warn.unchecked.call.mbr.of.raw.type: T6264029A(K), T6264029A
T6264029.java:15:41: compiler.warn.unchecked.call.mbr.of.raw.type: T6264029A(K), T6264029A T6264029.java:15:41: compiler.warn.unchecked.call.mbr.of.raw.type: T6264029A(K), T6264029A
2 warnings 1 warning