提交 49901e0c 编写于 作者: M mcimadamore

7175433: Inference cleanup: add helper class to handle inference variables

Summary: Add class to handle inference variables instantiation and associated info
Reviewed-by: jjg, dlsmith
上级 bd6a624a
...@@ -40,6 +40,8 @@ import com.sun.tools.javac.code.Lint; ...@@ -40,6 +40,8 @@ import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.Infer.InferenceContext;
import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Flags.ANNOTATION; import static com.sun.tools.javac.code.Flags.ANNOTATION;
...@@ -429,6 +431,8 @@ public class Check { ...@@ -429,6 +431,8 @@ public class Check {
* Obtain a warner for this check context * Obtain a warner for this check context
*/ */
public Warner checkWarner(DiagnosticPosition pos, Type found, Type req); public Warner checkWarner(DiagnosticPosition pos, Type found, Type req);
public Infer.InferenceContext inferenceContext();
} }
/** /**
...@@ -455,6 +459,10 @@ public class Check { ...@@ -455,6 +459,10 @@ public class Check {
public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
return enclosingContext.checkWarner(pos, found, req); return enclosingContext.checkWarner(pos, found, req);
} }
public Infer.InferenceContext inferenceContext() {
return enclosingContext.inferenceContext();
}
} }
/** /**
...@@ -471,6 +479,10 @@ public class Check { ...@@ -471,6 +479,10 @@ public class Check {
public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
return convertWarner(pos, found, req); return convertWarner(pos, found, req);
} }
public InferenceContext inferenceContext() {
return infer.emptyContext;
}
}; };
/** Check that a given type is assignable to a given proto-type. /** Check that a given type is assignable to a given proto-type.
...@@ -483,7 +495,16 @@ public class Check { ...@@ -483,7 +495,16 @@ public class Check {
return checkType(pos, found, req, basicHandler); return checkType(pos, found, req, basicHandler);
} }
Type checkType(final DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) { Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) {
final Infer.InferenceContext inferenceContext = checkContext.inferenceContext();
if (inferenceContext.free(req)) {
inferenceContext.addFreeTypeListener(List.of(req), new FreeTypeListener() {
@Override
public void typesInferred(InferenceContext inferenceContext) {
checkType(pos, found, inferenceContext.asInstType(req, types), checkContext);
}
});
}
if (req.tag == ERROR) if (req.tag == ERROR)
return req; return req;
if (req.tag == NONE) if (req.tag == NONE)
......
...@@ -31,6 +31,8 @@ import com.sun.tools.javac.code.Type.*; ...@@ -31,6 +31,8 @@ import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.Attr.ResultInfo; import com.sun.tools.javac.comp.Attr.ResultInfo;
import com.sun.tools.javac.comp.Check.CheckContext; import com.sun.tools.javac.comp.Check.CheckContext;
import com.sun.tools.javac.comp.Infer.InferenceContext;
import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate; import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
import com.sun.tools.javac.jvm.*; import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.*;
...@@ -586,7 +588,7 @@ public class Resolve { ...@@ -586,7 +588,7 @@ public class Resolve {
boolean allowBoxing, boolean allowBoxing,
boolean useVarargs, boolean useVarargs,
Warner warn) { Warner warn) {
checkRawArgumentsAcceptable(env, List.<Type>nil(), argtypes, formals, checkRawArgumentsAcceptable(env, infer.emptyContext, argtypes, formals,
allowBoxing, useVarargs, warn, resolveHandler); allowBoxing, useVarargs, warn, resolveHandler);
} }
...@@ -606,8 +608,8 @@ public class Resolve { ...@@ -606,8 +608,8 @@ public class Resolve {
* *
* A method check handler (see above) is used in order to report errors. * A method check handler (see above) is used in order to report errors.
*/ */
List<Type> checkRawArgumentsAcceptable(Env<AttrContext> env, void checkRawArgumentsAcceptable(final Env<AttrContext> env,
List<Type> undetvars, final Infer.InferenceContext inferenceContext,
List<Type> argtypes, List<Type> argtypes,
List<Type> formals, List<Type> formals,
boolean allowBoxing, boolean allowBoxing,
...@@ -623,7 +625,7 @@ public class Resolve { ...@@ -623,7 +625,7 @@ public class Resolve {
} }
while (argtypes.nonEmpty() && formals.head != varargsFormal) { while (argtypes.nonEmpty() && formals.head != varargsFormal) {
ResultInfo resultInfo = methodCheckResult(formals.head, allowBoxing, false, undetvars, handler, warn); ResultInfo resultInfo = methodCheckResult(formals.head, allowBoxing, false, inferenceContext, handler, warn);
checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head)); checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head));
argtypes = argtypes.tail; argtypes = argtypes.tail;
formals = formals.tail; formals = formals.tail;
...@@ -638,17 +640,29 @@ public class Resolve { ...@@ -638,17 +640,29 @@ public class Resolve {
//the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5) //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
Type elt = types.elemtype(varargsFormal); Type elt = types.elemtype(varargsFormal);
while (argtypes.nonEmpty()) { while (argtypes.nonEmpty()) {
ResultInfo resultInfo = methodCheckResult(elt, allowBoxing, true, undetvars, handler, warn); ResultInfo resultInfo = methodCheckResult(elt, allowBoxing, true, inferenceContext, handler, warn);
checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head)); checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head));
argtypes = argtypes.tail; argtypes = argtypes.tail;
} }
//check varargs element type accessibility //check varargs element type accessibility
if (undetvars.isEmpty() && !isAccessible(env, elt)) { varargsAccessible(env, elt, handler, inferenceContext);
}
}
void varargsAccessible(final Env<AttrContext> env, final Type t, final Resolve.MethodCheckHandler handler, final InferenceContext inferenceContext) {
if (inferenceContext.free(t)) {
inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() {
@Override
public void typesInferred(InferenceContext inferenceContext) {
varargsAccessible(env, inferenceContext.asInstType(t, types), handler, inferenceContext);
}
});
} else {
if (!isAccessible(env, t)) {
Symbol location = env.enclClass.sym; Symbol location = env.enclClass.sym;
throw handler.inaccessibleVarargs(location, elt); throw handler.inaccessibleVarargs(location, t);
} }
} }
return checkedArgs.toList();
} }
/** /**
...@@ -659,13 +673,13 @@ public class Resolve { ...@@ -659,13 +673,13 @@ public class Resolve {
MethodCheckHandler handler; MethodCheckHandler handler;
boolean useVarargs; boolean useVarargs;
List<Type> undetvars; Infer.InferenceContext inferenceContext;
Warner rsWarner; Warner rsWarner;
public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) { public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs, Infer.InferenceContext inferenceContext, Warner rsWarner) {
this.handler = handler; this.handler = handler;
this.useVarargs = useVarargs; this.useVarargs = useVarargs;
this.undetvars = undetvars; this.inferenceContext = inferenceContext;
this.rsWarner = rsWarner; this.rsWarner = rsWarner;
} }
...@@ -676,6 +690,10 @@ public class Resolve { ...@@ -676,6 +690,10 @@ public class Resolve {
public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
return rsWarner; return rsWarner;
} }
public InferenceContext inferenceContext() {
return inferenceContext;
}
} }
/** /**
...@@ -684,12 +702,12 @@ public class Resolve { ...@@ -684,12 +702,12 @@ public class Resolve {
*/ */
class StrictMethodContext extends MethodCheckContext { class StrictMethodContext extends MethodCheckContext {
public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) { public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs, Infer.InferenceContext inferenceContext, Warner rsWarner) {
super(handler, useVarargs, undetvars, rsWarner); super(handler, useVarargs, inferenceContext, rsWarner);
} }
public boolean compatible(Type found, Type req, Warner warn) { public boolean compatible(Type found, Type req, Warner warn) {
return types.isSubtypeUnchecked(found, infer.asUndetType(req, undetvars), warn); return types.isSubtypeUnchecked(found, inferenceContext.asFree(req, types), warn);
} }
} }
...@@ -699,12 +717,12 @@ public class Resolve { ...@@ -699,12 +717,12 @@ public class Resolve {
*/ */
class LooseMethodContext extends MethodCheckContext { class LooseMethodContext extends MethodCheckContext {
public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) { public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs, Infer.InferenceContext inferenceContext, Warner rsWarner) {
super(handler, useVarargs, undetvars, rsWarner); super(handler, useVarargs, inferenceContext, rsWarner);
} }
public boolean compatible(Type found, Type req, Warner warn) { public boolean compatible(Type found, Type req, Warner warn) {
return types.isConvertible(found, infer.asUndetType(req, undetvars), warn); return types.isConvertible(found, inferenceContext.asFree(req, types), warn);
} }
} }
...@@ -712,10 +730,10 @@ public class Resolve { ...@@ -712,10 +730,10 @@ public class Resolve {
* Create a method check context to be used during method applicability check * Create a method check context to be used during method applicability check
*/ */
ResultInfo methodCheckResult(Type to, boolean allowBoxing, boolean useVarargs, ResultInfo methodCheckResult(Type to, boolean allowBoxing, boolean useVarargs,
List<Type> undetvars, MethodCheckHandler methodHandler, Warner rsWarner) { Infer.InferenceContext inferenceContext, MethodCheckHandler methodHandler, Warner rsWarner) {
MethodCheckContext checkContext = allowBoxing ? MethodCheckContext checkContext = allowBoxing ?
new LooseMethodContext(methodHandler, useVarargs, undetvars, rsWarner) : new LooseMethodContext(methodHandler, useVarargs, inferenceContext, rsWarner) :
new StrictMethodContext(methodHandler, useVarargs, undetvars, rsWarner); new StrictMethodContext(methodHandler, useVarargs, inferenceContext, rsWarner);
return attr.new ResultInfo(VAL, to, checkContext) { return attr.new ResultInfo(VAL, to, checkContext) {
@Override @Override
protected Type check(DiagnosticPosition pos, Type found) { protected Type check(DiagnosticPosition pos, Type found) {
...@@ -735,16 +753,13 @@ public class Resolve { ...@@ -735,16 +753,13 @@ public class Resolve {
this.diags = diags; this.diags = diags;
} }
InapplicableMethodException setMessage() { InapplicableMethodException setMessage() {
this.diagnostic = null; return setMessage((JCDiagnostic)null);
return this;
} }
InapplicableMethodException setMessage(String key) { InapplicableMethodException setMessage(String key) {
this.diagnostic = key != null ? diags.fragment(key) : null; return setMessage(key != null ? diags.fragment(key) : null);
return this;
} }
InapplicableMethodException setMessage(String key, Object... args) { InapplicableMethodException setMessage(String key, Object... args) {
this.diagnostic = key != null ? diags.fragment(key, args) : null; return setMessage(key != null ? diags.fragment(key, args) : null);
return this;
} }
InapplicableMethodException setMessage(JCDiagnostic diag) { InapplicableMethodException setMessage(JCDiagnostic diag) {
this.diagnostic = diag; this.diagnostic = diag;
......
T6638712c.java:16:9: compiler.err.cant.apply.symbol.1: kindname.method, sort, T[],java.util.Comparator<? super T>, java.lang.Enum[],java.util.Comparator<java.lang.Enum<?>>, kindname.class, T6638712c, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.util.Comparator<java.lang.Enum<?>>, java.util.Comparator<? super java.lang.Enum>)) T6638712c.java:16:9: compiler.err.cant.apply.symbol.1: kindname.method, sort, T[],java.util.Comparator<? super T>, java.lang.Enum[],java.util.Comparator<java.lang.Enum<?>>, kindname.class, T6638712c, (compiler.misc.infer.no.conforming.assignment.exists: T, (compiler.misc.inconvertible.types: java.util.Comparator<java.lang.Enum<?>>, java.util.Comparator<? super java.lang.Enum>))
1 error 1 error
/*
* Copyright (c) 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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 7175433 6313164
* @summary Inference cleanup: add helper class to handle inference variables
*
*/
import java.util.List;
class Bar {
private class Foo { }
<Z> List<Z> m(Object... o) { T7175433.assertTrue(true); return null; }
<Z> List<Z> m(Foo... o) { T7175433.assertTrue(false); return null; }
Foo getFoo() { return null; }
}
public class T7175433 {
static int assertionCount;
static void assertTrue(boolean b) {
assertionCount++;
if (!b) {
throw new AssertionError();
}
}
public static void main(String[] args) {
Bar b = new Bar();
b.m(b.getFoo());
assertTrue(assertionCount == 1);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册