src/share/classes/com/sun/tools/javac/comp/Infer.java

Mon, 26 Mar 2012 15:28:22 +0100

author
mcimadamore
date
Mon, 26 Mar 2012 15:28:22 +0100
changeset 1238
e28a06a3c5d9
parent 1226
97bec6ab1227
child 1239
2827076dbf64
permissions
-rw-r--r--

7151492: Encapsulate check logic into Attr.ResultInfo
Summary: ResultInfo class should be used to make attribution code transparent w.r.t. check logic being used
Reviewed-by: jjg, dlsmith

duke@1 1 /*
mcimadamore@1178 2 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
duke@1 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1 4 *
duke@1 5 * This code is free software; you can redistribute it and/or modify it
duke@1 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
duke@1 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
duke@1 10 *
duke@1 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@1 15 * accompanied this code).
duke@1 16 *
duke@1 17 * You should have received a copy of the GNU General Public License version
duke@1 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@1 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
duke@1 24 */
duke@1 25
duke@1 26 package com.sun.tools.javac.comp;
duke@1 27
mcimadamore@674 28 import com.sun.tools.javac.tree.JCTree;
mcimadamore@674 29 import com.sun.tools.javac.tree.JCTree.JCTypeCast;
mcimadamore@820 30 import com.sun.tools.javac.tree.TreeInfo;
duke@1 31 import com.sun.tools.javac.util.*;
duke@1 32 import com.sun.tools.javac.util.List;
duke@1 33 import com.sun.tools.javac.code.*;
duke@1 34 import com.sun.tools.javac.code.Type.*;
mcimadamore@396 35 import com.sun.tools.javac.code.Type.ForAll.ConstraintKind;
mcimadamore@299 36 import com.sun.tools.javac.code.Symbol.*;
mcimadamore@1186 37 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
mcimadamore@1114 38 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
mcimadamore@1114 39 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
duke@1 40
duke@1 41 import static com.sun.tools.javac.code.TypeTags.*;
duke@1 42
duke@1 43 /** Helper class for type parameter inference, used by the attribution phase.
duke@1 44 *
jjg@581 45 * <p><b>This is NOT part of any supported API.
jjg@581 46 * If you write code that depends on this, you do so at your own risk.
duke@1 47 * This code and its internal interfaces are subject to change or
duke@1 48 * deletion without notice.</b>
duke@1 49 */
duke@1 50 public class Infer {
duke@1 51 protected static final Context.Key<Infer> inferKey =
duke@1 52 new Context.Key<Infer>();
duke@1 53
duke@1 54 /** A value for prototypes that admit any type, including polymorphic ones. */
duke@1 55 public static final Type anyPoly = new Type(NONE, null);
duke@1 56
duke@1 57 Symtab syms;
duke@1 58 Types types;
mcimadamore@396 59 Check chk;
mcimadamore@299 60 Resolve rs;
mcimadamore@1114 61 Log log;
mcimadamore@89 62 JCDiagnostic.Factory diags;
duke@1 63
duke@1 64 public static Infer instance(Context context) {
duke@1 65 Infer instance = context.get(inferKey);
duke@1 66 if (instance == null)
duke@1 67 instance = new Infer(context);
duke@1 68 return instance;
duke@1 69 }
duke@1 70
duke@1 71 protected Infer(Context context) {
duke@1 72 context.put(inferKey, this);
duke@1 73 syms = Symtab.instance(context);
duke@1 74 types = Types.instance(context);
mcimadamore@299 75 rs = Resolve.instance(context);
mcimadamore@1114 76 log = Log.instance(context);
mcimadamore@396 77 chk = Check.instance(context);
mcimadamore@89 78 diags = JCDiagnostic.Factory.instance(context);
mcimadamore@89 79 ambiguousNoInstanceException =
mcimadamore@89 80 new NoInstanceException(true, diags);
mcimadamore@89 81 unambiguousNoInstanceException =
mcimadamore@89 82 new NoInstanceException(false, diags);
mcimadamore@299 83 invalidInstanceException =
mcimadamore@299 84 new InvalidInstanceException(diags);
mcimadamore@299 85
duke@1 86 }
duke@1 87
mcimadamore@1186 88 public static class InferenceException extends InapplicableMethodException {
duke@1 89 private static final long serialVersionUID = 0;
duke@1 90
mcimadamore@299 91 InferenceException(JCDiagnostic.Factory diags) {
mcimadamore@689 92 super(diags);
duke@1 93 }
mcimadamore@299 94 }
mcimadamore@299 95
mcimadamore@299 96 public static class NoInstanceException extends InferenceException {
mcimadamore@299 97 private static final long serialVersionUID = 1;
mcimadamore@299 98
mcimadamore@299 99 boolean isAmbiguous; // exist several incomparable best instances?
mcimadamore@299 100
mcimadamore@299 101 NoInstanceException(boolean isAmbiguous, JCDiagnostic.Factory diags) {
mcimadamore@299 102 super(diags);
mcimadamore@299 103 this.isAmbiguous = isAmbiguous;
duke@1 104 }
duke@1 105 }
mcimadamore@299 106
mcimadamore@299 107 public static class InvalidInstanceException extends InferenceException {
mcimadamore@299 108 private static final long serialVersionUID = 2;
mcimadamore@299 109
mcimadamore@299 110 InvalidInstanceException(JCDiagnostic.Factory diags) {
mcimadamore@299 111 super(diags);
mcimadamore@299 112 }
mcimadamore@299 113 }
mcimadamore@299 114
mcimadamore@89 115 private final NoInstanceException ambiguousNoInstanceException;
mcimadamore@89 116 private final NoInstanceException unambiguousNoInstanceException;
mcimadamore@299 117 private final InvalidInstanceException invalidInstanceException;
duke@1 118
duke@1 119 /***************************************************************************
duke@1 120 * Auxiliary type values and classes
duke@1 121 ***************************************************************************/
duke@1 122
duke@1 123 /** A mapping that turns type variables into undetermined type variables.
duke@1 124 */
duke@1 125 Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") {
duke@1 126 public Type apply(Type t) {
duke@1 127 if (t.tag == TYPEVAR) return new UndetVar(t);
duke@1 128 else return t.map(this);
duke@1 129 }
duke@1 130 };
duke@1 131
duke@1 132 /** A mapping that returns its type argument with every UndetVar replaced
duke@1 133 * by its `inst' field. Throws a NoInstanceException
duke@1 134 * if this not possible because an `inst' field is null.
mcimadamore@635 135 * Note: mutually referring undertvars will be left uninstantiated
mcimadamore@635 136 * (that is, they will be replaced by the underlying type-variable).
duke@1 137 */
mcimadamore@635 138
duke@1 139 Mapping getInstFun = new Mapping("getInstFun") {
duke@1 140 public Type apply(Type t) {
duke@1 141 switch (t.tag) {
mcimadamore@635 142 case UNKNOWN:
duke@1 143 throw ambiguousNoInstanceException
mcimadamore@635 144 .setMessage("undetermined.type");
mcimadamore@635 145 case UNDETVAR:
mcimadamore@635 146 UndetVar that = (UndetVar) t;
mcimadamore@635 147 if (that.inst == null)
mcimadamore@635 148 throw ambiguousNoInstanceException
mcimadamore@635 149 .setMessage("type.variable.has.undetermined.type",
mcimadamore@635 150 that.qtype);
mcimadamore@635 151 return isConstraintCyclic(that) ?
mcimadamore@635 152 that.qtype :
mcimadamore@635 153 apply(that.inst);
mcimadamore@635 154 default:
mcimadamore@635 155 return t.map(this);
duke@1 156 }
duke@1 157 }
mcimadamore@635 158
mcimadamore@635 159 private boolean isConstraintCyclic(UndetVar uv) {
mcimadamore@635 160 Types.UnaryVisitor<Boolean> constraintScanner =
mcimadamore@635 161 new Types.UnaryVisitor<Boolean>() {
mcimadamore@635 162
mcimadamore@635 163 List<Type> seen = List.nil();
mcimadamore@635 164
mcimadamore@635 165 Boolean visit(List<Type> ts) {
mcimadamore@635 166 for (Type t : ts) {
mcimadamore@635 167 if (visit(t)) return true;
mcimadamore@635 168 }
mcimadamore@635 169 return false;
mcimadamore@635 170 }
mcimadamore@635 171
mcimadamore@635 172 public Boolean visitType(Type t, Void ignored) {
mcimadamore@635 173 return false;
mcimadamore@635 174 }
mcimadamore@635 175
mcimadamore@635 176 @Override
mcimadamore@635 177 public Boolean visitClassType(ClassType t, Void ignored) {
mcimadamore@635 178 if (t.isCompound()) {
mcimadamore@635 179 return visit(types.supertype(t)) ||
mcimadamore@635 180 visit(types.interfaces(t));
mcimadamore@635 181 } else {
mcimadamore@635 182 return visit(t.getTypeArguments());
mcimadamore@635 183 }
mcimadamore@635 184 }
mcimadamore@635 185 @Override
mcimadamore@635 186 public Boolean visitWildcardType(WildcardType t, Void ignored) {
mcimadamore@635 187 return visit(t.type);
mcimadamore@635 188 }
mcimadamore@635 189
mcimadamore@635 190 @Override
mcimadamore@635 191 public Boolean visitUndetVar(UndetVar t, Void ignored) {
mcimadamore@635 192 if (seen.contains(t)) {
mcimadamore@635 193 return true;
mcimadamore@635 194 } else {
mcimadamore@635 195 seen = seen.prepend(t);
mcimadamore@635 196 return visit(t.inst);
mcimadamore@635 197 }
mcimadamore@635 198 }
mcimadamore@635 199 };
mcimadamore@635 200 return constraintScanner.visit(uv);
mcimadamore@635 201 }
duke@1 202 };
duke@1 203
duke@1 204 /***************************************************************************
duke@1 205 * Mini/Maximization of UndetVars
duke@1 206 ***************************************************************************/
duke@1 207
duke@1 208 /** Instantiate undetermined type variable to its minimal upper bound.
duke@1 209 * Throw a NoInstanceException if this not possible.
duke@1 210 */
duke@1 211 void maximizeInst(UndetVar that, Warner warn) throws NoInstanceException {
mcimadamore@828 212 List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
duke@1 213 if (that.inst == null) {
mcimadamore@828 214 if (hibounds.isEmpty())
duke@1 215 that.inst = syms.objectType;
mcimadamore@828 216 else if (hibounds.tail.isEmpty())
mcimadamore@828 217 that.inst = hibounds.head;
mcimadamore@210 218 else
mcimadamore@828 219 that.inst = types.glb(hibounds);
duke@1 220 }
mcimadamore@210 221 if (that.inst == null ||
mcimadamore@298 222 that.inst.isErroneous())
mcimadamore@210 223 throw ambiguousNoInstanceException
mcimadamore@210 224 .setMessage("no.unique.maximal.instance.exists",
mcimadamore@828 225 that.qtype, hibounds);
duke@1 226 }
duke@1 227 //where
duke@1 228 private boolean isSubClass(Type t, final List<Type> ts) {
duke@1 229 t = t.baseType();
duke@1 230 if (t.tag == TYPEVAR) {
duke@1 231 List<Type> bounds = types.getBounds((TypeVar)t);
duke@1 232 for (Type s : ts) {
duke@1 233 if (!types.isSameType(t, s.baseType())) {
duke@1 234 for (Type bound : bounds) {
duke@1 235 if (!isSubClass(bound, List.of(s.baseType())))
duke@1 236 return false;
duke@1 237 }
duke@1 238 }
duke@1 239 }
duke@1 240 } else {
duke@1 241 for (Type s : ts) {
duke@1 242 if (!t.tsym.isSubClass(s.baseType().tsym, types))
duke@1 243 return false;
duke@1 244 }
duke@1 245 }
duke@1 246 return true;
duke@1 247 }
duke@1 248
mcimadamore@828 249 private Filter<Type> errorFilter = new Filter<Type>() {
mcimadamore@828 250 @Override
mcimadamore@828 251 public boolean accepts(Type t) {
mcimadamore@828 252 return !t.isErroneous();
mcimadamore@828 253 }
mcimadamore@828 254 };
mcimadamore@828 255
jjg@110 256 /** Instantiate undetermined type variable to the lub of all its lower bounds.
duke@1 257 * Throw a NoInstanceException if this not possible.
duke@1 258 */
duke@1 259 void minimizeInst(UndetVar that, Warner warn) throws NoInstanceException {
mcimadamore@828 260 List<Type> lobounds = Type.filter(that.lobounds, errorFilter);
duke@1 261 if (that.inst == null) {
mcimadamore@828 262 if (lobounds.isEmpty())
duke@1 263 that.inst = syms.botType;
mcimadamore@828 264 else if (lobounds.tail.isEmpty())
mcimadamore@828 265 that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head;
duke@1 266 else {
mcimadamore@828 267 that.inst = types.lub(lobounds);
mcimadamore@5 268 }
jjg@110 269 if (that.inst == null || that.inst.tag == ERROR)
duke@1 270 throw ambiguousNoInstanceException
duke@1 271 .setMessage("no.unique.minimal.instance.exists",
mcimadamore@828 272 that.qtype, lobounds);
duke@1 273 // VGJ: sort of inlined maximizeInst() below. Adding
duke@1 274 // bounds can cause lobounds that are above hibounds.
mcimadamore@828 275 List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
mcimadamore@1087 276 Type hb = null;
mcimadamore@828 277 if (hibounds.isEmpty())
mcimadamore@1087 278 hb = syms.objectType;
mcimadamore@1087 279 else if (hibounds.tail.isEmpty())
mcimadamore@828 280 hb = hibounds.head;
mcimadamore@1087 281 else
mcimadamore@1087 282 hb = types.glb(hibounds);
duke@1 283 if (hb == null ||
mcimadamore@1087 284 hb.isErroneous())
mcimadamore@1087 285 throw ambiguousNoInstanceException
mcimadamore@1087 286 .setMessage("incompatible.upper.bounds",
mcimadamore@1087 287 that.qtype, hibounds);
duke@1 288 }
duke@1 289 }
duke@1 290
mcimadamore@1186 291 Type asUndetType(Type t, List<Type> undetvars) {
mcimadamore@1186 292 return types.subst(t, inferenceVars(undetvars), undetvars);
mcimadamore@1186 293 }
mcimadamore@1186 294
mcimadamore@1186 295 List<Type> inferenceVars(List<Type> undetvars) {
mcimadamore@1186 296 ListBuffer<Type> tvars = ListBuffer.lb();
mcimadamore@1186 297 for (Type uv : undetvars) {
mcimadamore@1186 298 tvars.append(((UndetVar)uv).qtype);
mcimadamore@1186 299 }
mcimadamore@1186 300 return tvars.toList();
mcimadamore@1186 301 }
mcimadamore@1186 302
duke@1 303 /***************************************************************************
duke@1 304 * Exported Methods
duke@1 305 ***************************************************************************/
duke@1 306
duke@1 307 /** Try to instantiate expression type `that' to given type `to'.
duke@1 308 * If a maximal instantiation exists which makes this type
duke@1 309 * a subtype of type `to', return the instantiated type.
duke@1 310 * If no instantiation exists, or if several incomparable
duke@1 311 * best instantiations exist throw a NoInstanceException.
duke@1 312 */
duke@1 313 public Type instantiateExpr(ForAll that,
duke@1 314 Type to,
mcimadamore@299 315 Warner warn) throws InferenceException {
duke@1 316 List<Type> undetvars = Type.map(that.tvars, fromTypeVarFun);
duke@1 317 for (List<Type> l = undetvars; l.nonEmpty(); l = l.tail) {
mcimadamore@396 318 UndetVar uv = (UndetVar) l.head;
mcimadamore@396 319 TypeVar tv = (TypeVar)uv.qtype;
duke@1 320 ListBuffer<Type> hibounds = new ListBuffer<Type>();
mcimadamore@615 321 for (Type t : that.getConstraints(tv, ConstraintKind.EXTENDS)) {
mcimadamore@635 322 hibounds.append(types.subst(t, that.tvars, undetvars));
duke@1 323 }
mcimadamore@635 324
mcimadamore@396 325 List<Type> inst = that.getConstraints(tv, ConstraintKind.EQUAL);
mcimadamore@396 326 if (inst.nonEmpty() && inst.head.tag != BOT) {
mcimadamore@396 327 uv.inst = inst.head;
mcimadamore@396 328 }
mcimadamore@396 329 uv.hibounds = hibounds.toList();
duke@1 330 }
duke@1 331 Type qtype1 = types.subst(that.qtype, that.tvars, undetvars);
mcimadamore@753 332 if (!types.isSubtype(qtype1,
mcimadamore@753 333 qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) {
duke@1 334 throw unambiguousNoInstanceException
mcimadamore@689 335 .setMessage("infer.no.conforming.instance.exists",
duke@1 336 that.tvars, that.qtype, to);
duke@1 337 }
duke@1 338 for (List<Type> l = undetvars; l.nonEmpty(); l = l.tail)
duke@1 339 maximizeInst((UndetVar) l.head, warn);
duke@1 340 // System.out.println(" = " + qtype1.map(getInstFun));//DEBUG
duke@1 341
duke@1 342 // check bounds
duke@1 343 List<Type> targs = Type.map(undetvars, getInstFun);
mcimadamore@635 344 if (Type.containsAny(targs, that.tvars)) {
mcimadamore@635 345 //replace uninferred type-vars
mcimadamore@635 346 targs = types.subst(targs,
mcimadamore@635 347 that.tvars,
mcimadamore@1178 348 instantiateAsUninferredVars(undetvars, that.tvars));
mcimadamore@635 349 }
mcimadamore@1238 350 return that.inst(targs, types);
duke@1 351 }
mcimadamore@635 352 //where
mcimadamore@1178 353 private List<Type> instantiateAsUninferredVars(List<Type> undetvars, List<Type> tvars) {
mcimadamore@1178 354 Assert.check(undetvars.length() == tvars.length());
mcimadamore@635 355 ListBuffer<Type> new_targs = ListBuffer.lb();
mcimadamore@1178 356 //step 1 - create synthetic captured vars
mcimadamore@635 357 for (Type t : undetvars) {
mcimadamore@635 358 UndetVar uv = (UndetVar)t;
mcimadamore@635 359 Type newArg = new CapturedType(t.tsym.name, t.tsym, uv.inst, syms.botType, null);
mcimadamore@635 360 new_targs = new_targs.append(newArg);
mcimadamore@635 361 }
mcimadamore@635 362 //step 2 - replace synthetic vars in their bounds
mcimadamore@1178 363 List<Type> formals = tvars;
mcimadamore@635 364 for (Type t : new_targs.toList()) {
mcimadamore@635 365 CapturedType ct = (CapturedType)t;
mcimadamore@635 366 ct.bound = types.subst(ct.bound, tvars, new_targs.toList());
mcimadamore@1178 367 WildcardType wt = new WildcardType(syms.objectType, BoundKind.UNBOUND, syms.boundClass);
mcimadamore@1178 368 wt.bound = (TypeVar)formals.head;
mcimadamore@635 369 ct.wildcard = wt;
mcimadamore@1178 370 formals = formals.tail;
mcimadamore@635 371 }
mcimadamore@635 372 return new_targs.toList();
mcimadamore@635 373 }
duke@1 374
duke@1 375 /** Instantiate method type `mt' by finding instantiations of
duke@1 376 * `tvars' so that method can be applied to `argtypes'.
duke@1 377 */
mcimadamore@547 378 public Type instantiateMethod(final Env<AttrContext> env,
mcimadamore@547 379 List<Type> tvars,
duke@1 380 MethodType mt,
mcimadamore@580 381 final Symbol msym,
mcimadamore@299 382 final List<Type> argtypes,
mcimadamore@299 383 final boolean allowBoxing,
mcimadamore@299 384 final boolean useVarargs,
mcimadamore@299 385 final Warner warn) throws InferenceException {
duke@1 386 //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
duke@1 387 List<Type> undetvars = Type.map(tvars, fromTypeVarFun);
mcimadamore@689 388
mcimadamore@1186 389 final List<Type> capturedArgs =
mcimadamore@1186 390 rs.checkRawArgumentsAcceptable(env, undetvars, argtypes, mt.getParameterTypes(),
mcimadamore@1186 391 allowBoxing, useVarargs, warn, new InferenceCheckHandler(undetvars));
duke@1 392
duke@1 393 // minimize as yet undetermined type variables
duke@1 394 for (Type t : undetvars)
duke@1 395 minimizeInst((UndetVar) t, warn);
duke@1 396
duke@1 397 /** Type variables instantiated to bottom */
duke@1 398 ListBuffer<Type> restvars = new ListBuffer<Type>();
duke@1 399
mcimadamore@396 400 /** Undet vars instantiated to bottom */
mcimadamore@396 401 final ListBuffer<Type> restundet = new ListBuffer<Type>();
mcimadamore@396 402
duke@1 403 /** Instantiated types or TypeVars if under-constrained */
duke@1 404 ListBuffer<Type> insttypes = new ListBuffer<Type>();
duke@1 405
duke@1 406 /** Instantiated types or UndetVars if under-constrained */
duke@1 407 ListBuffer<Type> undettypes = new ListBuffer<Type>();
duke@1 408
duke@1 409 for (Type t : undetvars) {
duke@1 410 UndetVar uv = (UndetVar)t;
duke@1 411 if (uv.inst.tag == BOT) {
duke@1 412 restvars.append(uv.qtype);
mcimadamore@396 413 restundet.append(uv);
duke@1 414 insttypes.append(uv.qtype);
duke@1 415 undettypes.append(uv);
duke@1 416 uv.inst = null;
duke@1 417 } else {
duke@1 418 insttypes.append(uv.inst);
duke@1 419 undettypes.append(uv.inst);
duke@1 420 }
duke@1 421 }
duke@1 422 checkWithinBounds(tvars, undettypes.toList(), warn);
duke@1 423
mcimadamore@299 424 mt = (MethodType)types.subst(mt, tvars, insttypes.toList());
mcimadamore@299 425
duke@1 426 if (!restvars.isEmpty()) {
duke@1 427 // if there are uninstantiated variables,
duke@1 428 // quantify result type with them
mcimadamore@299 429 final List<Type> inferredTypes = insttypes.toList();
mcimadamore@299 430 final List<Type> all_tvars = tvars; //this is the wrong tvars
mcimadamore@1114 431 return new UninferredMethodType(env.tree.pos(), msym, mt, restvars.toList()) {
mcimadamore@299 432 @Override
mcimadamore@895 433 List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
mcimadamore@396 434 for (Type t : restundet.toList()) {
mcimadamore@396 435 UndetVar uv = (UndetVar)t;
mcimadamore@396 436 if (uv.qtype == tv) {
mcimadamore@396 437 switch (ck) {
mcimadamore@615 438 case EXTENDS: return uv.hibounds.appendList(types.subst(types.getBounds(tv), all_tvars, inferredTypes));
mcimadamore@396 439 case SUPER: return uv.lobounds;
mcimadamore@396 440 case EQUAL: return uv.inst != null ? List.of(uv.inst) : List.<Type>nil();
mcimadamore@396 441 }
mcimadamore@396 442 }
mcimadamore@396 443 }
mcimadamore@396 444 return List.nil();
mcimadamore@396 445 }
mcimadamore@396 446 @Override
mcimadamore@1219 447 void instantiateReturnType(Type restype, List<Type> inferred, Types types) throws NoInstanceException {
mcimadamore@1219 448 Type owntype = new MethodType(types.subst(getParameterTypes(), tvars, inferred),
mcimadamore@1219 449 restype,
mcimadamore@1219 450 types.subst(getThrownTypes(), tvars, inferred),
mcimadamore@1219 451 qtype.tsym);
mcimadamore@845 452 // check that actuals conform to inferred formals
mcimadamore@1226 453 warn.clear();
mcimadamore@1219 454 checkArgumentsAcceptable(env, capturedArgs, owntype.getParameterTypes(), allowBoxing, useVarargs, warn);
mcimadamore@396 455 // check that inferred bounds conform to their bounds
mcimadamore@396 456 checkWithinBounds(all_tvars,
mcimadamore@299 457 types.subst(inferredTypes, tvars, inferred), warn);
mcimadamore@1226 458 qtype = chk.checkMethod(owntype, msym, env, TreeInfo.args(env.tree), capturedArgs, useVarargs, warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED));
mcimadamore@1219 459 }
mcimadamore@1219 460 };
duke@1 461 }
mcimadamore@299 462 else {
mcimadamore@845 463 // check that actuals conform to inferred formals
mcimadamore@845 464 checkArgumentsAcceptable(env, capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn);
mcimadamore@299 465 // return instantiated version of method type
mcimadamore@299 466 return mt;
mcimadamore@299 467 }
duke@1 468 }
duke@1 469 //where
duke@1 470
mcimadamore@1186 471 /** inference check handler **/
mcimadamore@1186 472 class InferenceCheckHandler implements Resolve.MethodCheckHandler {
mcimadamore@1186 473
mcimadamore@1186 474 List<Type> undetvars;
mcimadamore@1186 475
mcimadamore@1186 476 public InferenceCheckHandler(List<Type> undetvars) {
mcimadamore@1186 477 this.undetvars = undetvars;
mcimadamore@1186 478 }
mcimadamore@1186 479
mcimadamore@1186 480 public InapplicableMethodException arityMismatch() {
mcimadamore@1186 481 return unambiguousNoInstanceException.setMessage("infer.arg.length.mismatch");
mcimadamore@1186 482 }
mcimadamore@1186 483 public InapplicableMethodException argumentMismatch(boolean varargs, Type found, Type expected) {
mcimadamore@1186 484 String key = varargs ?
mcimadamore@1186 485 "infer.varargs.argument.mismatch" :
mcimadamore@1186 486 "infer.no.conforming.assignment.exists";
mcimadamore@1186 487 return unambiguousNoInstanceException.setMessage(key,
mcimadamore@1186 488 inferenceVars(undetvars), found, expected);
mcimadamore@1186 489 }
mcimadamore@1186 490 public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
mcimadamore@1186 491 return unambiguousNoInstanceException.setMessage("inaccessible.varargs.type",
mcimadamore@1186 492 expected, Kinds.kindName(location), location);
mcimadamore@1186 493 }
mcimadamore@1186 494 }
mcimadamore@1186 495
mcimadamore@895 496 /**
mcimadamore@895 497 * A delegated type representing a partially uninferred method type.
mcimadamore@895 498 * The return type of a partially uninferred method type is a ForAll
mcimadamore@895 499 * type - when the return type is instantiated (see Infer.instantiateExpr)
mcimadamore@895 500 * the underlying method type is also updated.
mcimadamore@895 501 */
mcimadamore@1114 502 abstract class UninferredMethodType extends DelegatedType {
mcimadamore@895 503
mcimadamore@895 504 final List<Type> tvars;
mcimadamore@1114 505 final Symbol msym;
mcimadamore@1114 506 final DiagnosticPosition pos;
mcimadamore@895 507
mcimadamore@1114 508 public UninferredMethodType(DiagnosticPosition pos, Symbol msym, MethodType mtype, List<Type> tvars) {
mcimadamore@895 509 super(METHOD, new MethodType(mtype.argtypes, null, mtype.thrown, mtype.tsym));
mcimadamore@895 510 this.tvars = tvars;
mcimadamore@1114 511 this.msym = msym;
mcimadamore@1114 512 this.pos = pos;
mcimadamore@895 513 asMethodType().restype = new UninferredReturnType(tvars, mtype.restype);
mcimadamore@895 514 }
mcimadamore@895 515
mcimadamore@895 516 @Override
mcimadamore@895 517 public MethodType asMethodType() {
mcimadamore@895 518 return qtype.asMethodType();
mcimadamore@895 519 }
mcimadamore@895 520
mcimadamore@895 521 @Override
mcimadamore@895 522 public Type map(Mapping f) {
mcimadamore@895 523 return qtype.map(f);
mcimadamore@895 524 }
mcimadamore@895 525
mcimadamore@1219 526 abstract void instantiateReturnType(Type restype, List<Type> inferred, Types types);
mcimadamore@895 527
mcimadamore@895 528 abstract List<Type> getConstraints(TypeVar tv, ConstraintKind ck);
mcimadamore@895 529
mcimadamore@895 530 class UninferredReturnType extends ForAll {
mcimadamore@895 531 public UninferredReturnType(List<Type> tvars, Type restype) {
mcimadamore@895 532 super(tvars, restype);
mcimadamore@895 533 }
mcimadamore@895 534 @Override
mcimadamore@895 535 public Type inst(List<Type> actuals, Types types) {
mcimadamore@895 536 Type newRestype = super.inst(actuals, types);
mcimadamore@895 537 instantiateReturnType(newRestype, actuals, types);
mcimadamore@1114 538 if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
mcimadamore@1114 539 log.note(pos, "deferred.method.inst", msym, UninferredMethodType.this.qtype, newRestype);
mcimadamore@1114 540 }
mcimadamore@1219 541 return UninferredMethodType.this.qtype.getReturnType();
mcimadamore@895 542 }
mcimadamore@895 543 @Override
mcimadamore@895 544 public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
mcimadamore@895 545 return UninferredMethodType.this.getConstraints(tv, ck);
mcimadamore@895 546 }
mcimadamore@895 547 }
mcimadamore@895 548 }
mcimadamore@895 549
mcimadamore@845 550 private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
mcimadamore@845 551 boolean allowBoxing, boolean useVarargs, Warner warn) {
mcimadamore@845 552 try {
mcimadamore@845 553 rs.checkRawArgumentsAcceptable(env, actuals, formals,
mcimadamore@845 554 allowBoxing, useVarargs, warn);
mcimadamore@845 555 }
mcimadamore@1186 556 catch (InapplicableMethodException ex) {
mcimadamore@845 557 // inferred method is not applicable
mcimadamore@845 558 throw invalidInstanceException.setMessage(ex.getDiagnostic());
mcimadamore@845 559 }
mcimadamore@845 560 }
mcimadamore@845 561
mcimadamore@895 562 /** Try to instantiate argument type `that' to given type `to'.
mcimadamore@895 563 * If this fails, try to insantiate `that' to `to' where
mcimadamore@895 564 * every occurrence of a type variable in `tvars' is replaced
mcimadamore@895 565 * by an unknown type.
mcimadamore@895 566 */
mcimadamore@895 567 private Type instantiateArg(ForAll that,
mcimadamore@895 568 Type to,
mcimadamore@895 569 List<Type> tvars,
mcimadamore@895 570 Warner warn) throws InferenceException {
mcimadamore@895 571 List<Type> targs;
mcimadamore@895 572 try {
mcimadamore@895 573 return instantiateExpr(that, to, warn);
mcimadamore@895 574 } catch (NoInstanceException ex) {
mcimadamore@895 575 Type to1 = to;
mcimadamore@895 576 for (List<Type> l = tvars; l.nonEmpty(); l = l.tail)
mcimadamore@895 577 to1 = types.subst(to1, List.of(l.head), List.of(syms.unknownType));
mcimadamore@895 578 return instantiateExpr(that, to1, warn);
duke@1 579 }
mcimadamore@895 580 }
duke@1 581
duke@1 582 /** check that type parameters are within their bounds.
duke@1 583 */
mcimadamore@615 584 void checkWithinBounds(List<Type> tvars,
duke@1 585 List<Type> arguments,
duke@1 586 Warner warn)
mcimadamore@299 587 throws InvalidInstanceException {
duke@1 588 for (List<Type> tvs = tvars, args = arguments;
duke@1 589 tvs.nonEmpty();
duke@1 590 tvs = tvs.tail, args = args.tail) {
mcimadamore@828 591 if (args.head instanceof UndetVar ||
mcimadamore@828 592 tvars.head.getUpperBound().isErroneous()) continue;
duke@1 593 List<Type> bounds = types.subst(types.getBounds((TypeVar)tvs.head), tvars, arguments);
duke@1 594 if (!types.isSubtypeUnchecked(args.head, bounds, warn))
mcimadamore@299 595 throw invalidInstanceException
duke@1 596 .setMessage("inferred.do.not.conform.to.bounds",
mcimadamore@299 597 args.head, bounds);
duke@1 598 }
duke@1 599 }
mcimadamore@674 600
mcimadamore@674 601 /**
mcimadamore@674 602 * Compute a synthetic method type corresponding to the requested polymorphic
mcimadamore@820 603 * method signature. The target return type is computed from the immediately
mcimadamore@820 604 * enclosing scope surrounding the polymorphic-signature call.
mcimadamore@674 605 */
mcimadamore@674 606 Type instantiatePolymorphicSignatureInstance(Env<AttrContext> env, Type site,
mcimadamore@674 607 Name name,
mcimadamore@674 608 MethodSymbol spMethod, // sig. poly. method or null if none
mcimadamore@820 609 List<Type> argtypes) {
mcimadamore@674 610 final Type restype;
mcimadamore@716 611
mcimadamore@820 612 //The return type for a polymorphic signature call is computed from
mcimadamore@820 613 //the enclosing tree E, as follows: if E is a cast, then use the
mcimadamore@820 614 //target type of the cast expression as a return type; if E is an
mcimadamore@820 615 //expression statement, the return type is 'void' - otherwise the
mcimadamore@820 616 //return type is simply 'Object'. A correctness check ensures that
mcimadamore@820 617 //env.next refers to the lexically enclosing environment in which
mcimadamore@820 618 //the polymorphic signature call environment is nested.
mcimadamore@820 619
mcimadamore@820 620 switch (env.next.tree.getTag()) {
jjg@1127 621 case TYPECAST:
mcimadamore@820 622 JCTypeCast castTree = (JCTypeCast)env.next.tree;
mcimadamore@820 623 restype = (TreeInfo.skipParens(castTree.expr) == env.tree) ?
mcimadamore@820 624 castTree.clazz.type :
mcimadamore@820 625 syms.objectType;
mcimadamore@820 626 break;
jjg@1127 627 case EXEC:
mcimadamore@820 628 JCTree.JCExpressionStatement execTree =
mcimadamore@820 629 (JCTree.JCExpressionStatement)env.next.tree;
mcimadamore@820 630 restype = (TreeInfo.skipParens(execTree.expr) == env.tree) ?
mcimadamore@820 631 syms.voidType :
mcimadamore@820 632 syms.objectType;
mcimadamore@820 633 break;
mcimadamore@820 634 default:
mcimadamore@820 635 restype = syms.objectType;
mcimadamore@674 636 }
mcimadamore@674 637
mcimadamore@674 638 List<Type> paramtypes = Type.map(argtypes, implicitArgType);
mcimadamore@674 639 List<Type> exType = spMethod != null ?
mcimadamore@674 640 spMethod.getThrownTypes() :
mcimadamore@674 641 List.of(syms.throwableType); // make it throw all exceptions
mcimadamore@674 642
mcimadamore@674 643 MethodType mtype = new MethodType(paramtypes,
mcimadamore@674 644 restype,
mcimadamore@674 645 exType,
mcimadamore@674 646 syms.methodClass);
mcimadamore@674 647 return mtype;
mcimadamore@674 648 }
mcimadamore@674 649 //where
mcimadamore@674 650 Mapping implicitArgType = new Mapping ("implicitArgType") {
mcimadamore@674 651 public Type apply(Type t) {
mcimadamore@674 652 t = types.erasure(t);
mcimadamore@674 653 if (t.tag == BOT)
mcimadamore@674 654 // nulls type as the marker type Null (which has no instances)
mcimadamore@674 655 // infer as java.lang.Void for now
mcimadamore@674 656 t = types.boxedClass(syms.voidType).type;
mcimadamore@674 657 return t;
mcimadamore@674 658 }
mcimadamore@674 659 };
mcimadamore@895 660 }

mercurial