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

changeset 1268
af6a4c24f4e3
parent 1251
6f0ed5a89c25
child 1296
cddc2c894cc6
equal deleted inserted replaced
1267:f43aded513e7 1268:af6a4c24f4e3
212 * If a maximal instantiation exists which makes this type 212 * If a maximal instantiation exists which makes this type
213 * a subtype of type `to', return the instantiated type. 213 * a subtype of type `to', return the instantiated type.
214 * If no instantiation exists, or if several incomparable 214 * If no instantiation exists, or if several incomparable
215 * best instantiations exist throw a NoInstanceException. 215 * best instantiations exist throw a NoInstanceException.
216 */ 216 */
217 public Type instantiateExpr(ForAll that, 217 public List<Type> instantiateUninferred(DiagnosticPosition pos,
218 Type to, 218 List<Type> undetvars,
219 List<Type> tvars,
220 MethodType mtype,
221 Attr.ResultInfo resultInfo,
219 Warner warn) throws InferenceException { 222 Warner warn) throws InferenceException {
220 List<Type> undetvars = that.undetvars(); 223 Type to = resultInfo.pt;
221 Type qtype1 = types.subst(that.qtype, that.tvars, undetvars); 224 if (to.tag == NONE) {
225 to = mtype.getReturnType().tag <= VOID ?
226 mtype.getReturnType() : syms.objectType;
227 }
228 Type qtype1 = types.subst(mtype.getReturnType(), tvars, undetvars);
222 if (!types.isSubtype(qtype1, 229 if (!types.isSubtype(qtype1,
223 qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) { 230 qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) {
224 throw unambiguousNoInstanceException 231 throw unambiguousNoInstanceException
225 .setMessage("infer.no.conforming.instance.exists", 232 .setMessage("infer.no.conforming.instance.exists",
226 that.tvars, that.qtype, to); 233 tvars, mtype.getReturnType(), to);
227 } 234 }
228 235
229 List<Type> insttypes; 236 List<Type> insttypes;
230 while (true) { 237 while (true) {
231 boolean stuck = true; 238 boolean stuck = true;
232 insttypes = List.nil(); 239 insttypes = List.nil();
233 for (Type t : undetvars) { 240 for (Type t : undetvars) {
234 UndetVar uv = (UndetVar)t; 241 UndetVar uv = (UndetVar)t;
235 if (uv.inst == null && (uv.eq.nonEmpty() || !Type.containsAny(uv.hibounds, that.tvars))) { 242 if (uv.inst == null && (uv.eq.nonEmpty() || !Type.containsAny(uv.hibounds, tvars))) {
236 maximizeInst((UndetVar)t, warn); 243 maximizeInst((UndetVar)t, warn);
237 stuck = false; 244 stuck = false;
238 } 245 }
239 insttypes = insttypes.append(uv.inst == null ? uv.qtype : uv.inst); 246 insttypes = insttypes.append(uv.inst == null ? uv.qtype : uv.inst);
240 } 247 }
241 if (!Type.containsAny(insttypes, that.tvars)) { 248 if (!Type.containsAny(insttypes, tvars)) {
242 //all variables have been instantiated - exit 249 //all variables have been instantiated - exit
243 break; 250 break;
244 } else if (stuck) { 251 } else if (stuck) {
245 //some variables could not be instantiated because of cycles in 252 //some variables could not be instantiated because of cycles in
246 //upper bounds - provide a (possibly recursive) default instantiation 253 //upper bounds - provide a (possibly recursive) default instantiation
247 insttypes = types.subst(insttypes, 254 insttypes = types.subst(insttypes,
248 that.tvars, 255 tvars,
249 instantiateAsUninferredVars(undetvars, that.tvars)); 256 instantiateAsUninferredVars(undetvars, tvars));
250 break; 257 break;
251 } else { 258 } else {
252 //some variables have been instantiated - replace newly instantiated 259 //some variables have been instantiated - replace newly instantiated
253 //variables in remaining upper bounds and continue 260 //variables in remaining upper bounds and continue
254 for (Type t : undetvars) { 261 for (Type t : undetvars) {
255 UndetVar uv = (UndetVar)t; 262 UndetVar uv = (UndetVar)t;
256 uv.hibounds = types.subst(uv.hibounds, that.tvars, insttypes); 263 uv.hibounds = types.subst(uv.hibounds, tvars, insttypes);
257 } 264 }
258 } 265 }
259 } 266 }
260 return that.inst(insttypes, types); 267 return insttypes;
261 } 268 }
262 269
263 /** 270 /**
264 * Infer cyclic inference variables as described in 15.12.2.8. 271 * Infer cyclic inference variables as described in 15.12.2.8.
265 */ 272 */
294 } 301 }
295 302
296 /** Instantiate method type `mt' by finding instantiations of 303 /** Instantiate method type `mt' by finding instantiations of
297 * `tvars' so that method can be applied to `argtypes'. 304 * `tvars' so that method can be applied to `argtypes'.
298 */ 305 */
299 public Type instantiateMethod(final Env<AttrContext> env, 306 public Type instantiateMethod(Env<AttrContext> env,
300 List<Type> tvars, 307 List<Type> tvars,
301 MethodType mt, 308 MethodType mt,
302 final Symbol msym, 309 Attr.ResultInfo resultInfo,
303 final List<Type> argtypes, 310 Symbol msym,
304 final boolean allowBoxing, 311 List<Type> argtypes,
305 final boolean useVarargs, 312 boolean allowBoxing,
306 final Warner warn) throws InferenceException { 313 boolean useVarargs,
314 Warner warn) throws InferenceException {
307 //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG 315 //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
308 final List<Type> undetvars = makeUndetvars(tvars); 316 List<Type> undetvars = makeUndetvars(tvars);
309 317
310 final List<Type> capturedArgs = 318 List<Type> capturedArgs =
311 rs.checkRawArgumentsAcceptable(env, undetvars, argtypes, mt.getParameterTypes(), 319 rs.checkRawArgumentsAcceptable(env, undetvars, argtypes, mt.getParameterTypes(),
312 allowBoxing, useVarargs, warn, new InferenceCheckHandler(undetvars)); 320 allowBoxing, useVarargs, warn, new InferenceCheckHandler(undetvars));
313 321
314 // minimize as yet undetermined type variables 322 // minimize as yet undetermined type variables
315 for (Type t : undetvars) 323 for (Type t : undetvars)
342 } 350 }
343 checkWithinBounds(tvars, undetvars, insttypes.toList(), warn); 351 checkWithinBounds(tvars, undetvars, insttypes.toList(), warn);
344 352
345 mt = (MethodType)types.subst(mt, tvars, insttypes.toList()); 353 mt = (MethodType)types.subst(mt, tvars, insttypes.toList());
346 354
347 if (!restvars.isEmpty()) { 355 if (!restvars.isEmpty() && resultInfo != null) {
348 // if there are uninstantiated variables, 356 List<Type> restInferred =
349 // quantify result type with them 357 instantiateUninferred(env.tree.pos(), restundet.toList(), restvars.toList(), mt, resultInfo, warn);
350 final List<Type> inferredTypes = insttypes.toList(); 358 checkWithinBounds(tvars, undetvars,
351 final List<Type> all_tvars = tvars; //this is the wrong tvars 359 types.subst(insttypes.toList(), restvars.toList(), restInferred), warn);
352 return new UninferredMethodType(env.tree.pos(), msym, mt, restvars.toList()) { 360 mt = (MethodType)types.subst(mt, restvars.toList(), restInferred);
353 @Override 361 if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
354 List<Type> undetvars() { 362 log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
355 return restundet.toList(); 363 }
356 } 364 }
357 @Override 365
358 void instantiateReturnType(Type restype, List<Type> inferred, Types types) throws NoInstanceException { 366 if (restvars.isEmpty() || resultInfo != null) {
359 Type owntype = new MethodType(types.subst(getParameterTypes(), tvars, inferred),
360 restype,
361 types.subst(getThrownTypes(), tvars, inferred),
362 qtype.tsym);
363 // check that actuals conform to inferred formals
364 warn.clear();
365 checkArgumentsAcceptable(env, capturedArgs, owntype.getParameterTypes(), allowBoxing, useVarargs, warn);
366 // check that inferred bounds conform to their bounds
367 checkWithinBounds(all_tvars, undetvars,
368 types.subst(inferredTypes, tvars, inferred), warn);
369 qtype = chk.checkMethod(owntype, msym, env, TreeInfo.args(env.tree), capturedArgs, useVarargs, warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED));
370 }
371 };
372 }
373 else {
374 // check that actuals conform to inferred formals 367 // check that actuals conform to inferred formals
375 checkArgumentsAcceptable(env, capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn); 368 checkArgumentsAcceptable(env, capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn);
376 // return instantiated version of method type 369 }
377 return mt; 370 // return instantiated version of method type
378 } 371 return mt;
379 } 372 }
380 //where 373 //where
381 374
382 /** inference check handler **/ 375 /** inference check handler **/
383 class InferenceCheckHandler implements Resolve.MethodCheckHandler { 376 class InferenceCheckHandler implements Resolve.MethodCheckHandler {
399 inferenceVars(undetvars), found, expected); 392 inferenceVars(undetvars), found, expected);
400 } 393 }
401 public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) { 394 public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
402 return unambiguousNoInstanceException.setMessage("inaccessible.varargs.type", 395 return unambiguousNoInstanceException.setMessage("inaccessible.varargs.type",
403 expected, Kinds.kindName(location), location); 396 expected, Kinds.kindName(location), location);
404 }
405 }
406
407 /**
408 * A delegated type representing a partially uninferred method type.
409 * The return type of a partially uninferred method type is a ForAll
410 * type - when the return type is instantiated (see Infer.instantiateExpr)
411 * the underlying method type is also updated.
412 */
413 abstract class UninferredMethodType extends DelegatedType {
414
415 final List<Type> tvars;
416 final Symbol msym;
417 final DiagnosticPosition pos;
418
419 public UninferredMethodType(DiagnosticPosition pos, Symbol msym, MethodType mtype, List<Type> tvars) {
420 super(METHOD, new MethodType(mtype.argtypes, null, mtype.thrown, mtype.tsym));
421 this.tvars = tvars;
422 this.msym = msym;
423 this.pos = pos;
424 asMethodType().restype = new UninferredReturnType(tvars, mtype.restype);
425 }
426
427 @Override
428 public MethodType asMethodType() {
429 return qtype.asMethodType();
430 }
431
432 @Override
433 public Type map(Mapping f) {
434 return qtype.map(f);
435 }
436
437 abstract void instantiateReturnType(Type restype, List<Type> inferred, Types types);
438
439 abstract List<Type> undetvars();
440
441 class UninferredReturnType extends ForAll {
442 public UninferredReturnType(List<Type> tvars, Type restype) {
443 super(tvars, restype);
444 }
445 @Override
446 public Type inst(List<Type> actuals, Types types) {
447 Type newRestype = super.inst(actuals, types);
448 instantiateReturnType(newRestype, actuals, types);
449 if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
450 log.note(pos, "deferred.method.inst", msym, UninferredMethodType.this.qtype, newRestype);
451 }
452 return UninferredMethodType.this.qtype.getReturnType();
453 }
454 @Override
455 public List<Type> undetvars() {
456 return UninferredMethodType.this.undetvars();
457 }
458 } 397 }
459 } 398 }
460 399
461 private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals, 400 private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
462 boolean allowBoxing, boolean useVarargs, Warner warn) { 401 boolean allowBoxing, boolean useVarargs, Warner warn) {

mercurial