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

changeset 1510
7873d37f5b37
parent 1479
38d3d1027f5a
child 1519
97bd5e7151bc
equal deleted inserted replaced
1509:1985e35e97b2 1510:7873d37f5b37
64 Resolve rs; 64 Resolve rs;
65 DeferredAttr deferredAttr; 65 DeferredAttr deferredAttr;
66 Log log; 66 Log log;
67 JCDiagnostic.Factory diags; 67 JCDiagnostic.Factory diags;
68 68
69 /** Should we inject return-type constraints earlier? */
70 boolean allowEarlyReturnConstraints;
71
69 public static Infer instance(Context context) { 72 public static Infer instance(Context context) {
70 Infer instance = context.get(inferKey); 73 Infer instance = context.get(inferKey);
71 if (instance == null) 74 if (instance == null)
72 instance = new Infer(context); 75 instance = new Infer(context);
73 return instance; 76 return instance;
81 deferredAttr = DeferredAttr.instance(context); 84 deferredAttr = DeferredAttr.instance(context);
82 log = Log.instance(context); 85 log = Log.instance(context);
83 chk = Check.instance(context); 86 chk = Check.instance(context);
84 diags = JCDiagnostic.Factory.instance(context); 87 diags = JCDiagnostic.Factory.instance(context);
85 inferenceException = new InferenceException(diags); 88 inferenceException = new InferenceException(diags);
89 allowEarlyReturnConstraints = Source.instance(context).allowEarlyReturnConstraints();
86 } 90 }
87 91
88 /** 92 /**
89 * This exception class is design to store a list of diagnostics corresponding 93 * This exception class is design to store a list of diagnostics corresponding
90 * to inference errors that can arise during a method applicability check. 94 * to inference errors that can arise during a method applicability check.
186 public void instantiateUninferred(DiagnosticPosition pos, 190 public void instantiateUninferred(DiagnosticPosition pos,
187 InferenceContext inferenceContext, 191 InferenceContext inferenceContext,
188 MethodType mtype, 192 MethodType mtype,
189 Attr.ResultInfo resultInfo, 193 Attr.ResultInfo resultInfo,
190 Warner warn) throws InferenceException { 194 Warner warn) throws InferenceException {
191 Type to = resultInfo.pt;
192 if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
193 to = mtype.getReturnType().isPrimitiveOrVoid() ?
194 mtype.getReturnType() : syms.objectType;
195 }
196 Type qtype1 = inferenceContext.asFree(mtype.getReturnType(), types);
197 if (!types.isSubtype(qtype1,
198 qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to)) {
199 throw inferenceException
200 .setMessage("infer.no.conforming.instance.exists",
201 inferenceContext.restvars(), mtype.getReturnType(), to);
202 }
203
204 while (true) { 195 while (true) {
205 boolean stuck = true; 196 boolean stuck = true;
206 for (Type t : inferenceContext.undetvars) { 197 for (Type t : inferenceContext.undetvars) {
207 UndetVar uv = (UndetVar)t; 198 UndetVar uv = (UndetVar)t;
208 if (uv.inst == null && (uv.getBounds(InferenceBound.EQ).nonEmpty() || 199 if (uv.inst == null && (uv.getBounds(InferenceBound.EQ).nonEmpty() ||
281 resolveContext.deferredAttrContext(msym, inferenceContext); 272 resolveContext.deferredAttrContext(msym, inferenceContext);
282 273
283 try { 274 try {
284 methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn); 275 methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn);
285 276
277 if (resultInfo != null && allowEarlyReturnConstraints &&
278 !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
279 generateReturnConstraints(mt, inferenceContext, resultInfo);
280 }
281
286 deferredAttrContext.complete(); 282 deferredAttrContext.complete();
287 283
288 // minimize as yet undetermined type variables 284 // minimize as yet undetermined type variables
289 for (Type t : inferenceContext.undetvars) { 285 for (Type t : inferenceContext.undetvars) {
290 minimizeInst((UndetVar)t, warn); 286 minimizeInst((UndetVar)t, warn);
296 292
297 List<Type> restvars = inferenceContext.restvars(); 293 List<Type> restvars = inferenceContext.restvars();
298 294
299 if (!restvars.isEmpty()) { 295 if (!restvars.isEmpty()) {
300 if (resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { 296 if (resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
297 if (!allowEarlyReturnConstraints) {
298 generateReturnConstraints(mt, inferenceContext, resultInfo);
299 }
301 instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn); 300 instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn);
302 checkWithinBounds(inferenceContext, warn); 301 checkWithinBounds(inferenceContext, warn);
303 mt = (MethodType)inferenceContext.asInstType(mt, types); 302 mt = (MethodType)inferenceContext.asInstType(mt, types);
304 if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) { 303 if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
305 log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt); 304 log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
311 return mt; 310 return mt;
312 } finally { 311 } finally {
313 inferenceContext.notifyChange(types); 312 inferenceContext.notifyChange(types);
314 } 313 }
315 } 314 }
315 //where
316 void generateReturnConstraints(Type mt, InferenceContext inferenceContext, Attr.ResultInfo resultInfo) {
317 if (resultInfo != null) {
318 Type to = resultInfo.pt;
319 if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
320 to = mt.getReturnType().isPrimitiveOrVoid() ?
321 mt.getReturnType() : syms.objectType;
322 }
323 Type qtype1 = inferenceContext.asFree(mt.getReturnType(), types);
324 if (!types.isSubtype(qtype1,
325 qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to)) {
326 throw inferenceException
327 .setMessage("infer.no.conforming.instance.exists",
328 inferenceContext.restvars(), mt.getReturnType(), to);
329 }
330 }
331 }
316 332
317 /** check that type parameters are within their bounds. 333 /** check that type parameters are within their bounds.
318 */ 334 */
319 void checkWithinBounds(InferenceContext inferenceContext, 335 void checkWithinBounds(InferenceContext inferenceContext,
320 Warner warn) throws InferenceException { 336 Warner warn) throws InferenceException {
459 return funcInterface; 475 return funcInterface;
460 } else { 476 } else {
461 Type formalInterface = funcInterface.tsym.type; 477 Type formalInterface = funcInterface.tsym.type;
462 InferenceContext funcInterfaceContext = 478 InferenceContext funcInterfaceContext =
463 new InferenceContext(funcInterface.tsym.type.getTypeArguments(), this, false); 479 new InferenceContext(funcInterface.tsym.type.getTypeArguments(), this, false);
464 if (paramTypes != null) { 480 Assert.check(paramTypes != null);
465 //get constraints from explicit params (this is done by 481 //get constraints from explicit params (this is done by
466 //checking that explicit param types are equal to the ones 482 //checking that explicit param types are equal to the ones
467 //in the functional interface descriptors) 483 //in the functional interface descriptors)
468 List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes(); 484 List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
469 if (descParameterTypes.size() != paramTypes.size()) { 485 if (descParameterTypes.size() != paramTypes.size()) {
470 checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda")); 486 checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
487 return types.createErrorType(funcInterface);
488 }
489 for (Type p : descParameterTypes) {
490 if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) {
491 checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
471 return types.createErrorType(funcInterface); 492 return types.createErrorType(funcInterface);
472 } 493 }
473 for (Type p : descParameterTypes) { 494 paramTypes = paramTypes.tail;
474 if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) { 495 }
475 checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
476 return types.createErrorType(funcInterface);
477 }
478 paramTypes = paramTypes.tail;
479 }
480 for (Type t : funcInterfaceContext.undetvars) {
481 UndetVar uv = (UndetVar)t;
482 minimizeInst(uv, types.noWarnings);
483 if (uv.inst == null &&
484 Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
485 maximizeInst(uv, types.noWarnings);
486 }
487 }
488
489 formalInterface = funcInterfaceContext.asInstType(formalInterface, types);
490 }
491 ListBuffer<Type> typeargs = ListBuffer.lb();
492 List<Type> actualTypeargs = funcInterface.getTypeArguments(); 496 List<Type> actualTypeargs = funcInterface.getTypeArguments();
493 //for remaining uninferred type-vars in the functional interface type, 497 for (Type t : funcInterfaceContext.undetvars) {
494 //simply replace the wildcards with its bound 498 UndetVar uv = (UndetVar)t;
495 for (Type t : formalInterface.getTypeArguments()) { 499 minimizeInst(uv, types.noWarnings);
496 if (actualTypeargs.head.hasTag(WILDCARD)) { 500 if (uv.inst == null &&
497 WildcardType wt = (WildcardType)actualTypeargs.head; 501 Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
498 typeargs.append(wt.type); 502 maximizeInst(uv, types.noWarnings);
499 } else { 503 }
500 typeargs.append(actualTypeargs.head); 504 if (uv.inst == null) {
505 uv.inst = actualTypeargs.head;
501 } 506 }
502 actualTypeargs = actualTypeargs.tail; 507 actualTypeargs = actualTypeargs.tail;
503 } 508 }
504 Type owntype = types.subst(formalInterface, funcInterfaceContext.inferenceVars(), typeargs.toList()); 509 Type owntype = funcInterfaceContext.asInstType(formalInterface, types);
505 if (!chk.checkValidGenericType(owntype)) { 510 if (!chk.checkValidGenericType(owntype)) {
506 //if the inferred functional interface type is not well-formed, 511 //if the inferred functional interface type is not well-formed,
507 //or if it's not a subtype of the original target, issue an error 512 //or if it's not a subtype of the original target, issue an error
508 checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); 513 checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
509 return types.createErrorType(funcInterface);
510 } 514 }
511 return owntype; 515 return owntype;
512 } 516 }
513 } 517 }
514 // </editor-fold> 518 // </editor-fold>

mercurial