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) { |