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

Thu, 02 Aug 2012 18:24:01 +0100

author
mcimadamore
date
Thu, 02 Aug 2012 18:24:01 +0100
changeset 1298
2d75e7c952b8
parent 1296
cddc2c894cc6
child 1337
2eca84194807
permissions
-rw-r--r--

7187104: Inference cleanup: remove redundant exception classes in Infer.java
Summary: Remove unused exception classes in Infer.java
Reviewed-by: jjg

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@299 35 import com.sun.tools.javac.code.Symbol.*;
mcimadamore@1186 36 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
mcimadamore@1114 37 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
mcimadamore@1114 38 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
duke@1 39
duke@1 40 import static com.sun.tools.javac.code.TypeTags.*;
duke@1 41
duke@1 42 /** Helper class for type parameter inference, used by the attribution phase.
duke@1 43 *
jjg@581 44 * <p><b>This is NOT part of any supported API.
jjg@581 45 * If you write code that depends on this, you do so at your own risk.
duke@1 46 * This code and its internal interfaces are subject to change or
duke@1 47 * deletion without notice.</b>
duke@1 48 */
duke@1 49 public class Infer {
duke@1 50 protected static final Context.Key<Infer> inferKey =
duke@1 51 new Context.Key<Infer>();
duke@1 52
duke@1 53 /** A value for prototypes that admit any type, including polymorphic ones. */
duke@1 54 public static final Type anyPoly = new Type(NONE, null);
duke@1 55
duke@1 56 Symtab syms;
duke@1 57 Types types;
mcimadamore@396 58 Check chk;
mcimadamore@299 59 Resolve rs;
mcimadamore@1114 60 Log log;
mcimadamore@89 61 JCDiagnostic.Factory diags;
duke@1 62
duke@1 63 public static Infer instance(Context context) {
duke@1 64 Infer instance = context.get(inferKey);
duke@1 65 if (instance == null)
duke@1 66 instance = new Infer(context);
duke@1 67 return instance;
duke@1 68 }
duke@1 69
duke@1 70 protected Infer(Context context) {
duke@1 71 context.put(inferKey, this);
duke@1 72 syms = Symtab.instance(context);
duke@1 73 types = Types.instance(context);
mcimadamore@299 74 rs = Resolve.instance(context);
mcimadamore@1114 75 log = Log.instance(context);
mcimadamore@396 76 chk = Check.instance(context);
mcimadamore@89 77 diags = JCDiagnostic.Factory.instance(context);
mcimadamore@1298 78 inferenceException = new InferenceException(diags);
mcimadamore@299 79
duke@1 80 }
duke@1 81
mcimadamore@1186 82 public static class InferenceException extends InapplicableMethodException {
duke@1 83 private static final long serialVersionUID = 0;
duke@1 84
mcimadamore@299 85 InferenceException(JCDiagnostic.Factory diags) {
mcimadamore@689 86 super(diags);
duke@1 87 }
mcimadamore@299 88 }
mcimadamore@299 89
mcimadamore@1298 90 private final InferenceException inferenceException;
duke@1 91
duke@1 92 /***************************************************************************
duke@1 93 * Auxiliary type values and classes
duke@1 94 ***************************************************************************/
duke@1 95
duke@1 96 /** A mapping that turns type variables into undetermined type variables.
duke@1 97 */
mcimadamore@1251 98 List<Type> makeUndetvars(List<Type> tvars) {
mcimadamore@1251 99 List<Type> undetvars = Type.map(tvars, fromTypeVarFun);
mcimadamore@1251 100 for (Type t : undetvars) {
mcimadamore@1251 101 UndetVar uv = (UndetVar)t;
mcimadamore@1251 102 uv.hibounds = types.getBounds((TypeVar)uv.qtype);
mcimadamore@1251 103 }
mcimadamore@1251 104 return undetvars;
mcimadamore@1251 105 }
mcimadamore@1251 106 //where
mcimadamore@1251 107 Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") {
mcimadamore@1251 108 public Type apply(Type t) {
mcimadamore@1251 109 if (t.tag == TYPEVAR) return new UndetVar(t);
mcimadamore@1251 110 else return t.map(this);
duke@1 111 }
mcimadamore@1251 112 };
duke@1 113
duke@1 114 /***************************************************************************
duke@1 115 * Mini/Maximization of UndetVars
duke@1 116 ***************************************************************************/
duke@1 117
duke@1 118 /** Instantiate undetermined type variable to its minimal upper bound.
duke@1 119 * Throw a NoInstanceException if this not possible.
duke@1 120 */
mcimadamore@1298 121 void maximizeInst(UndetVar that, Warner warn) throws InferenceException {
mcimadamore@828 122 List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
mcimadamore@1251 123 if (that.eq.isEmpty()) {
mcimadamore@828 124 if (hibounds.isEmpty())
duke@1 125 that.inst = syms.objectType;
mcimadamore@828 126 else if (hibounds.tail.isEmpty())
mcimadamore@828 127 that.inst = hibounds.head;
mcimadamore@210 128 else
mcimadamore@828 129 that.inst = types.glb(hibounds);
mcimadamore@1251 130 } else {
mcimadamore@1251 131 that.inst = that.eq.head;
duke@1 132 }
mcimadamore@210 133 if (that.inst == null ||
mcimadamore@298 134 that.inst.isErroneous())
mcimadamore@1298 135 throw inferenceException
mcimadamore@210 136 .setMessage("no.unique.maximal.instance.exists",
mcimadamore@828 137 that.qtype, hibounds);
duke@1 138 }
duke@1 139
mcimadamore@828 140 private Filter<Type> errorFilter = new Filter<Type>() {
mcimadamore@828 141 @Override
mcimadamore@828 142 public boolean accepts(Type t) {
mcimadamore@828 143 return !t.isErroneous();
mcimadamore@828 144 }
mcimadamore@828 145 };
mcimadamore@828 146
jjg@110 147 /** Instantiate undetermined type variable to the lub of all its lower bounds.
duke@1 148 * Throw a NoInstanceException if this not possible.
duke@1 149 */
mcimadamore@1298 150 void minimizeInst(UndetVar that, Warner warn) throws InferenceException {
mcimadamore@828 151 List<Type> lobounds = Type.filter(that.lobounds, errorFilter);
mcimadamore@1251 152 if (that.eq.isEmpty()) {
mcimadamore@828 153 if (lobounds.isEmpty())
duke@1 154 that.inst = syms.botType;
mcimadamore@828 155 else if (lobounds.tail.isEmpty())
mcimadamore@828 156 that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head;
duke@1 157 else {
mcimadamore@828 158 that.inst = types.lub(lobounds);
mcimadamore@5 159 }
jjg@110 160 if (that.inst == null || that.inst.tag == ERROR)
mcimadamore@1298 161 throw inferenceException
duke@1 162 .setMessage("no.unique.minimal.instance.exists",
mcimadamore@828 163 that.qtype, lobounds);
mcimadamore@1251 164 } else {
mcimadamore@1251 165 that.inst = that.eq.head;
duke@1 166 }
duke@1 167 }
duke@1 168
mcimadamore@1186 169 Type asUndetType(Type t, List<Type> undetvars) {
mcimadamore@1186 170 return types.subst(t, inferenceVars(undetvars), undetvars);
mcimadamore@1186 171 }
mcimadamore@1186 172
mcimadamore@1186 173 List<Type> inferenceVars(List<Type> undetvars) {
mcimadamore@1186 174 ListBuffer<Type> tvars = ListBuffer.lb();
mcimadamore@1186 175 for (Type uv : undetvars) {
mcimadamore@1186 176 tvars.append(((UndetVar)uv).qtype);
mcimadamore@1186 177 }
mcimadamore@1186 178 return tvars.toList();
mcimadamore@1186 179 }
mcimadamore@1186 180
duke@1 181 /***************************************************************************
duke@1 182 * Exported Methods
duke@1 183 ***************************************************************************/
duke@1 184
duke@1 185 /** Try to instantiate expression type `that' to given type `to'.
duke@1 186 * If a maximal instantiation exists which makes this type
duke@1 187 * a subtype of type `to', return the instantiated type.
duke@1 188 * If no instantiation exists, or if several incomparable
duke@1 189 * best instantiations exist throw a NoInstanceException.
duke@1 190 */
mcimadamore@1268 191 public List<Type> instantiateUninferred(DiagnosticPosition pos,
mcimadamore@1268 192 List<Type> undetvars,
mcimadamore@1268 193 List<Type> tvars,
mcimadamore@1268 194 MethodType mtype,
mcimadamore@1268 195 Attr.ResultInfo resultInfo,
mcimadamore@299 196 Warner warn) throws InferenceException {
mcimadamore@1268 197 Type to = resultInfo.pt;
mcimadamore@1268 198 if (to.tag == NONE) {
mcimadamore@1268 199 to = mtype.getReturnType().tag <= VOID ?
mcimadamore@1268 200 mtype.getReturnType() : syms.objectType;
mcimadamore@1268 201 }
mcimadamore@1268 202 Type qtype1 = types.subst(mtype.getReturnType(), tvars, undetvars);
mcimadamore@753 203 if (!types.isSubtype(qtype1,
mcimadamore@753 204 qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) {
mcimadamore@1298 205 throw inferenceException
mcimadamore@689 206 .setMessage("infer.no.conforming.instance.exists",
mcimadamore@1268 207 tvars, mtype.getReturnType(), to);
duke@1 208 }
duke@1 209
mcimadamore@1251 210 List<Type> insttypes;
mcimadamore@1251 211 while (true) {
mcimadamore@1251 212 boolean stuck = true;
mcimadamore@1251 213 insttypes = List.nil();
mcimadamore@1251 214 for (Type t : undetvars) {
mcimadamore@1251 215 UndetVar uv = (UndetVar)t;
mcimadamore@1268 216 if (uv.inst == null && (uv.eq.nonEmpty() || !Type.containsAny(uv.hibounds, tvars))) {
mcimadamore@1251 217 maximizeInst((UndetVar)t, warn);
mcimadamore@1251 218 stuck = false;
mcimadamore@1251 219 }
mcimadamore@1251 220 insttypes = insttypes.append(uv.inst == null ? uv.qtype : uv.inst);
mcimadamore@1251 221 }
mcimadamore@1268 222 if (!Type.containsAny(insttypes, tvars)) {
mcimadamore@1251 223 //all variables have been instantiated - exit
mcimadamore@1251 224 break;
mcimadamore@1251 225 } else if (stuck) {
mcimadamore@1251 226 //some variables could not be instantiated because of cycles in
mcimadamore@1251 227 //upper bounds - provide a (possibly recursive) default instantiation
mcimadamore@1251 228 insttypes = types.subst(insttypes,
mcimadamore@1268 229 tvars,
mcimadamore@1268 230 instantiateAsUninferredVars(undetvars, tvars));
mcimadamore@1251 231 break;
mcimadamore@1251 232 } else {
mcimadamore@1251 233 //some variables have been instantiated - replace newly instantiated
mcimadamore@1251 234 //variables in remaining upper bounds and continue
mcimadamore@1251 235 for (Type t : undetvars) {
mcimadamore@1251 236 UndetVar uv = (UndetVar)t;
mcimadamore@1268 237 uv.hibounds = types.subst(uv.hibounds, tvars, insttypes);
mcimadamore@1251 238 }
mcimadamore@1251 239 }
mcimadamore@635 240 }
mcimadamore@1268 241 return insttypes;
duke@1 242 }
mcimadamore@1251 243
mcimadamore@1251 244 /**
mcimadamore@1251 245 * Infer cyclic inference variables as described in 15.12.2.8.
mcimadamore@1251 246 */
mcimadamore@1178 247 private List<Type> instantiateAsUninferredVars(List<Type> undetvars, List<Type> tvars) {
mcimadamore@1178 248 Assert.check(undetvars.length() == tvars.length());
mcimadamore@1251 249 ListBuffer<Type> insttypes = ListBuffer.lb();
mcimadamore@1251 250 ListBuffer<Type> todo = ListBuffer.lb();
mcimadamore@1251 251 //step 1 - create fresh tvars
mcimadamore@635 252 for (Type t : undetvars) {
mcimadamore@635 253 UndetVar uv = (UndetVar)t;
mcimadamore@1251 254 if (uv.inst == null) {
mcimadamore@1251 255 TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner);
mcimadamore@1251 256 fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.hibounds), null);
mcimadamore@1251 257 todo.append(uv);
mcimadamore@1251 258 uv.inst = fresh_tvar.type;
mcimadamore@1251 259 }
mcimadamore@1251 260 insttypes.append(uv.inst);
mcimadamore@635 261 }
mcimadamore@1251 262 //step 2 - replace fresh tvars in their bounds
mcimadamore@1178 263 List<Type> formals = tvars;
mcimadamore@1251 264 for (Type t : todo) {
mcimadamore@1251 265 UndetVar uv = (UndetVar)t;
mcimadamore@1251 266 TypeVar ct = (TypeVar)uv.inst;
mcimadamore@1251 267 ct.bound = types.glb(types.subst(types.getBounds(ct), tvars, insttypes.toList()));
mcimadamore@1251 268 if (ct.bound.isErroneous()) {
mcimadamore@1251 269 //report inference error if glb fails
mcimadamore@1251 270 reportBoundError(uv, BoundErrorKind.BAD_UPPER);
mcimadamore@1251 271 }
mcimadamore@1178 272 formals = formals.tail;
mcimadamore@635 273 }
mcimadamore@1251 274 return insttypes.toList();
mcimadamore@635 275 }
duke@1 276
duke@1 277 /** Instantiate method type `mt' by finding instantiations of
duke@1 278 * `tvars' so that method can be applied to `argtypes'.
duke@1 279 */
mcimadamore@1268 280 public Type instantiateMethod(Env<AttrContext> env,
mcimadamore@547 281 List<Type> tvars,
duke@1 282 MethodType mt,
mcimadamore@1268 283 Attr.ResultInfo resultInfo,
mcimadamore@1268 284 Symbol msym,
mcimadamore@1268 285 List<Type> argtypes,
mcimadamore@1268 286 boolean allowBoxing,
mcimadamore@1268 287 boolean useVarargs,
mcimadamore@1268 288 Warner warn) throws InferenceException {
duke@1 289 //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
mcimadamore@1268 290 List<Type> undetvars = makeUndetvars(tvars);
mcimadamore@689 291
mcimadamore@1268 292 List<Type> capturedArgs =
mcimadamore@1186 293 rs.checkRawArgumentsAcceptable(env, undetvars, argtypes, mt.getParameterTypes(),
mcimadamore@1186 294 allowBoxing, useVarargs, warn, new InferenceCheckHandler(undetvars));
duke@1 295
duke@1 296 // minimize as yet undetermined type variables
duke@1 297 for (Type t : undetvars)
duke@1 298 minimizeInst((UndetVar) t, warn);
duke@1 299
duke@1 300 /** Type variables instantiated to bottom */
duke@1 301 ListBuffer<Type> restvars = new ListBuffer<Type>();
duke@1 302
mcimadamore@396 303 /** Undet vars instantiated to bottom */
mcimadamore@396 304 final ListBuffer<Type> restundet = new ListBuffer<Type>();
mcimadamore@396 305
duke@1 306 /** Instantiated types or TypeVars if under-constrained */
duke@1 307 ListBuffer<Type> insttypes = new ListBuffer<Type>();
duke@1 308
duke@1 309 /** Instantiated types or UndetVars if under-constrained */
duke@1 310 ListBuffer<Type> undettypes = new ListBuffer<Type>();
duke@1 311
duke@1 312 for (Type t : undetvars) {
duke@1 313 UndetVar uv = (UndetVar)t;
duke@1 314 if (uv.inst.tag == BOT) {
duke@1 315 restvars.append(uv.qtype);
mcimadamore@396 316 restundet.append(uv);
duke@1 317 insttypes.append(uv.qtype);
duke@1 318 undettypes.append(uv);
duke@1 319 uv.inst = null;
duke@1 320 } else {
duke@1 321 insttypes.append(uv.inst);
duke@1 322 undettypes.append(uv.inst);
duke@1 323 }
duke@1 324 }
mcimadamore@1251 325 checkWithinBounds(tvars, undetvars, insttypes.toList(), warn);
duke@1 326
mcimadamore@299 327 mt = (MethodType)types.subst(mt, tvars, insttypes.toList());
mcimadamore@299 328
mcimadamore@1268 329 if (!restvars.isEmpty() && resultInfo != null) {
mcimadamore@1268 330 List<Type> restInferred =
mcimadamore@1268 331 instantiateUninferred(env.tree.pos(), restundet.toList(), restvars.toList(), mt, resultInfo, warn);
mcimadamore@1268 332 checkWithinBounds(tvars, undetvars,
mcimadamore@1268 333 types.subst(insttypes.toList(), restvars.toList(), restInferred), warn);
mcimadamore@1268 334 mt = (MethodType)types.subst(mt, restvars.toList(), restInferred);
mcimadamore@1268 335 if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
mcimadamore@1268 336 log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
mcimadamore@1268 337 }
duke@1 338 }
mcimadamore@1268 339
mcimadamore@1268 340 if (restvars.isEmpty() || resultInfo != null) {
mcimadamore@845 341 // check that actuals conform to inferred formals
mcimadamore@845 342 checkArgumentsAcceptable(env, capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn);
mcimadamore@299 343 }
mcimadamore@1268 344 // return instantiated version of method type
mcimadamore@1268 345 return mt;
duke@1 346 }
duke@1 347 //where
duke@1 348
mcimadamore@1186 349 /** inference check handler **/
mcimadamore@1186 350 class InferenceCheckHandler implements Resolve.MethodCheckHandler {
mcimadamore@1186 351
mcimadamore@1186 352 List<Type> undetvars;
mcimadamore@1186 353
mcimadamore@1186 354 public InferenceCheckHandler(List<Type> undetvars) {
mcimadamore@1186 355 this.undetvars = undetvars;
mcimadamore@1186 356 }
mcimadamore@1186 357
mcimadamore@1186 358 public InapplicableMethodException arityMismatch() {
mcimadamore@1298 359 return inferenceException.setMessage("infer.arg.length.mismatch", inferenceVars(undetvars));
mcimadamore@1186 360 }
mcimadamore@1296 361 public InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details) {
mcimadamore@1186 362 String key = varargs ?
mcimadamore@1296 363 "infer.varargs.argument.mismatch" :
mcimadamore@1296 364 "infer.no.conforming.assignment.exists";
mcimadamore@1298 365 return inferenceException.setMessage(key,
mcimadamore@1296 366 inferenceVars(undetvars), details);
mcimadamore@1186 367 }
mcimadamore@1186 368 public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
mcimadamore@1298 369 return inferenceException.setMessage("inaccessible.varargs.type",
mcimadamore@1186 370 expected, Kinds.kindName(location), location);
mcimadamore@1186 371 }
mcimadamore@1186 372 }
mcimadamore@1186 373
mcimadamore@845 374 private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
mcimadamore@845 375 boolean allowBoxing, boolean useVarargs, Warner warn) {
mcimadamore@845 376 try {
mcimadamore@845 377 rs.checkRawArgumentsAcceptable(env, actuals, formals,
mcimadamore@845 378 allowBoxing, useVarargs, warn);
mcimadamore@845 379 }
mcimadamore@1186 380 catch (InapplicableMethodException ex) {
mcimadamore@845 381 // inferred method is not applicable
mcimadamore@1298 382 throw inferenceException.setMessage(ex.getDiagnostic());
mcimadamore@845 383 }
mcimadamore@845 384 }
mcimadamore@845 385
mcimadamore@1251 386 /** check that type parameters are within their bounds.
mcimadamore@895 387 */
mcimadamore@1251 388 void checkWithinBounds(List<Type> tvars,
mcimadamore@1251 389 List<Type> undetvars,
mcimadamore@1251 390 List<Type> arguments,
mcimadamore@1251 391 Warner warn)
mcimadamore@1298 392 throws InferenceException {
mcimadamore@1251 393 List<Type> args = arguments;
mcimadamore@1251 394 for (Type t : undetvars) {
mcimadamore@1251 395 UndetVar uv = (UndetVar)t;
mcimadamore@1251 396 uv.hibounds = types.subst(uv.hibounds, tvars, arguments);
mcimadamore@1251 397 uv.lobounds = types.subst(uv.lobounds, tvars, arguments);
mcimadamore@1251 398 uv.eq = types.subst(uv.eq, tvars, arguments);
mcimadamore@1251 399 checkCompatibleUpperBounds(uv, tvars);
mcimadamore@1251 400 if (args.head.tag != TYPEVAR || !args.head.containsAny(tvars)) {
mcimadamore@1251 401 Type inst = args.head;
mcimadamore@1251 402 for (Type u : uv.hibounds) {
mcimadamore@1251 403 if (!types.isSubtypeUnchecked(inst, types.subst(u, tvars, undetvars), warn)) {
mcimadamore@1251 404 reportBoundError(uv, BoundErrorKind.UPPER);
mcimadamore@1251 405 }
mcimadamore@1251 406 }
mcimadamore@1251 407 for (Type l : uv.lobounds) {
mcimadamore@1251 408 if (!types.isSubtypeUnchecked(types.subst(l, tvars, undetvars), inst, warn)) {
mcimadamore@1251 409 reportBoundError(uv, BoundErrorKind.LOWER);
mcimadamore@1251 410 }
mcimadamore@1251 411 }
mcimadamore@1251 412 for (Type e : uv.eq) {
mcimadamore@1251 413 if (!types.isSameType(inst, types.subst(e, tvars, undetvars))) {
mcimadamore@1251 414 reportBoundError(uv, BoundErrorKind.EQ);
mcimadamore@1251 415 }
mcimadamore@1251 416 }
mcimadamore@1251 417 }
mcimadamore@1251 418 args = args.tail;
duke@1 419 }
mcimadamore@895 420 }
duke@1 421
mcimadamore@1251 422 void checkCompatibleUpperBounds(UndetVar uv, List<Type> tvars) {
mcimadamore@1251 423 // VGJ: sort of inlined maximizeInst() below. Adding
mcimadamore@1251 424 // bounds can cause lobounds that are above hibounds.
mcimadamore@1251 425 ListBuffer<Type> hiboundsNoVars = ListBuffer.lb();
mcimadamore@1251 426 for (Type t : Type.filter(uv.hibounds, errorFilter)) {
mcimadamore@1251 427 if (!t.containsAny(tvars)) {
mcimadamore@1251 428 hiboundsNoVars.append(t);
mcimadamore@1251 429 }
duke@1 430 }
mcimadamore@1251 431 List<Type> hibounds = hiboundsNoVars.toList();
mcimadamore@1251 432 Type hb = null;
mcimadamore@1251 433 if (hibounds.isEmpty())
mcimadamore@1251 434 hb = syms.objectType;
mcimadamore@1251 435 else if (hibounds.tail.isEmpty())
mcimadamore@1251 436 hb = hibounds.head;
mcimadamore@1251 437 else
mcimadamore@1251 438 hb = types.glb(hibounds);
mcimadamore@1251 439 if (hb == null || hb.isErroneous())
mcimadamore@1251 440 reportBoundError(uv, BoundErrorKind.BAD_UPPER);
mcimadamore@1251 441 }
mcimadamore@1251 442
mcimadamore@1251 443 enum BoundErrorKind {
mcimadamore@1251 444 BAD_UPPER() {
mcimadamore@1251 445 @Override
mcimadamore@1251 446 InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
mcimadamore@1251 447 return ex.setMessage("incompatible.upper.bounds", uv.qtype, uv.hibounds);
mcimadamore@1251 448 }
mcimadamore@1251 449 },
mcimadamore@1251 450 UPPER() {
mcimadamore@1251 451 @Override
mcimadamore@1251 452 InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
mcimadamore@1251 453 return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst, uv.hibounds);
mcimadamore@1251 454 }
mcimadamore@1251 455 },
mcimadamore@1251 456 LOWER() {
mcimadamore@1251 457 @Override
mcimadamore@1251 458 InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
mcimadamore@1251 459 return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst, uv.lobounds);
mcimadamore@1251 460 }
mcimadamore@1251 461 },
mcimadamore@1251 462 EQ() {
mcimadamore@1251 463 @Override
mcimadamore@1251 464 InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
mcimadamore@1251 465 return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst, uv.eq);
mcimadamore@1251 466 }
mcimadamore@1251 467 };
mcimadamore@1251 468
mcimadamore@1251 469 abstract InapplicableMethodException setMessage(InferenceException ex, UndetVar uv);
mcimadamore@1251 470 }
mcimadamore@1251 471 //where
mcimadamore@1251 472 void reportBoundError(UndetVar uv, BoundErrorKind bk) {
mcimadamore@1298 473 throw bk.setMessage(inferenceException, uv);
duke@1 474 }
mcimadamore@674 475
mcimadamore@674 476 /**
mcimadamore@674 477 * Compute a synthetic method type corresponding to the requested polymorphic
mcimadamore@820 478 * method signature. The target return type is computed from the immediately
mcimadamore@820 479 * enclosing scope surrounding the polymorphic-signature call.
mcimadamore@674 480 */
mcimadamore@1239 481 Type instantiatePolymorphicSignatureInstance(Env<AttrContext> env,
mcimadamore@674 482 MethodSymbol spMethod, // sig. poly. method or null if none
mcimadamore@820 483 List<Type> argtypes) {
mcimadamore@674 484 final Type restype;
mcimadamore@716 485
mcimadamore@820 486 //The return type for a polymorphic signature call is computed from
mcimadamore@820 487 //the enclosing tree E, as follows: if E is a cast, then use the
mcimadamore@820 488 //target type of the cast expression as a return type; if E is an
mcimadamore@820 489 //expression statement, the return type is 'void' - otherwise the
mcimadamore@820 490 //return type is simply 'Object'. A correctness check ensures that
mcimadamore@820 491 //env.next refers to the lexically enclosing environment in which
mcimadamore@820 492 //the polymorphic signature call environment is nested.
mcimadamore@820 493
mcimadamore@820 494 switch (env.next.tree.getTag()) {
jjg@1127 495 case TYPECAST:
mcimadamore@820 496 JCTypeCast castTree = (JCTypeCast)env.next.tree;
mcimadamore@820 497 restype = (TreeInfo.skipParens(castTree.expr) == env.tree) ?
mcimadamore@820 498 castTree.clazz.type :
mcimadamore@820 499 syms.objectType;
mcimadamore@820 500 break;
jjg@1127 501 case EXEC:
mcimadamore@820 502 JCTree.JCExpressionStatement execTree =
mcimadamore@820 503 (JCTree.JCExpressionStatement)env.next.tree;
mcimadamore@820 504 restype = (TreeInfo.skipParens(execTree.expr) == env.tree) ?
mcimadamore@820 505 syms.voidType :
mcimadamore@820 506 syms.objectType;
mcimadamore@820 507 break;
mcimadamore@820 508 default:
mcimadamore@820 509 restype = syms.objectType;
mcimadamore@674 510 }
mcimadamore@674 511
mcimadamore@674 512 List<Type> paramtypes = Type.map(argtypes, implicitArgType);
mcimadamore@674 513 List<Type> exType = spMethod != null ?
mcimadamore@674 514 spMethod.getThrownTypes() :
mcimadamore@674 515 List.of(syms.throwableType); // make it throw all exceptions
mcimadamore@674 516
mcimadamore@674 517 MethodType mtype = new MethodType(paramtypes,
mcimadamore@674 518 restype,
mcimadamore@674 519 exType,
mcimadamore@674 520 syms.methodClass);
mcimadamore@674 521 return mtype;
mcimadamore@674 522 }
mcimadamore@674 523 //where
mcimadamore@674 524 Mapping implicitArgType = new Mapping ("implicitArgType") {
mcimadamore@674 525 public Type apply(Type t) {
mcimadamore@674 526 t = types.erasure(t);
mcimadamore@674 527 if (t.tag == BOT)
mcimadamore@674 528 // nulls type as the marker type Null (which has no instances)
mcimadamore@674 529 // infer as java.lang.Void for now
mcimadamore@674 530 t = types.boxedClass(syms.voidType).type;
mcimadamore@674 531 return t;
mcimadamore@674 532 }
mcimadamore@674 533 };
mcimadamore@895 534 }

mercurial