463 if (!restvars.isEmpty()) { |
463 if (!restvars.isEmpty()) { |
464 // if there are uninstantiated variables, |
464 // if there are uninstantiated variables, |
465 // quantify result type with them |
465 // quantify result type with them |
466 final List<Type> inferredTypes = insttypes.toList(); |
466 final List<Type> inferredTypes = insttypes.toList(); |
467 final List<Type> all_tvars = tvars; //this is the wrong tvars |
467 final List<Type> all_tvars = tvars; //this is the wrong tvars |
468 final MethodType mt2 = new MethodType(mt.argtypes, null, mt.thrown, syms.methodClass); |
468 return new UninferredMethodType(mt, restvars.toList()) { |
469 mt2.restype = new ForAll(restvars.toList(), mt.restype) { |
|
470 @Override |
469 @Override |
471 public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) { |
470 List<Type> getConstraints(TypeVar tv, ConstraintKind ck) { |
472 for (Type t : restundet.toList()) { |
471 for (Type t : restundet.toList()) { |
473 UndetVar uv = (UndetVar)t; |
472 UndetVar uv = (UndetVar)t; |
474 if (uv.qtype == tv) { |
473 if (uv.qtype == tv) { |
475 switch (ck) { |
474 switch (ck) { |
476 case EXTENDS: return uv.hibounds.appendList(types.subst(types.getBounds(tv), all_tvars, inferredTypes)); |
475 case EXTENDS: return uv.hibounds.appendList(types.subst(types.getBounds(tv), all_tvars, inferredTypes)); |
479 } |
478 } |
480 } |
479 } |
481 } |
480 } |
482 return List.nil(); |
481 return List.nil(); |
483 } |
482 } |
484 |
|
485 @Override |
483 @Override |
486 public Type inst(List<Type> inferred, Types types) throws NoInstanceException { |
484 void check(List<Type> inferred, Types types) throws NoInstanceException { |
487 List<Type> formals = types.subst(mt2.argtypes, tvars, inferred); |
|
488 // check that actuals conform to inferred formals |
485 // check that actuals conform to inferred formals |
489 checkArgumentsAcceptable(env, capturedArgs, formals, allowBoxing, useVarargs, warn); |
486 checkArgumentsAcceptable(env, capturedArgs, getParameterTypes(), allowBoxing, useVarargs, warn); |
490 // check that inferred bounds conform to their bounds |
487 // check that inferred bounds conform to their bounds |
491 checkWithinBounds(all_tvars, |
488 checkWithinBounds(all_tvars, |
492 types.subst(inferredTypes, tvars, inferred), warn); |
489 types.subst(inferredTypes, tvars, inferred), warn); |
493 if (useVarargs) { |
490 if (useVarargs) { |
494 chk.checkVararg(env.tree.pos(), formals, msym); |
491 chk.checkVararg(env.tree.pos(), getParameterTypes(), msym); |
495 } |
492 } |
496 return super.inst(inferred, types); |
|
497 }}; |
493 }}; |
498 return mt2; |
|
499 } |
494 } |
500 else { |
495 else { |
501 // check that actuals conform to inferred formals |
496 // check that actuals conform to inferred formals |
502 checkArgumentsAcceptable(env, capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn); |
497 checkArgumentsAcceptable(env, capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn); |
503 // return instantiated version of method type |
498 // return instantiated version of method type |
504 return mt; |
499 return mt; |
505 } |
500 } |
506 } |
501 } |
507 //where |
502 //where |
508 |
503 |
|
504 /** |
|
505 * A delegated type representing a partially uninferred method type. |
|
506 * The return type of a partially uninferred method type is a ForAll |
|
507 * type - when the return type is instantiated (see Infer.instantiateExpr) |
|
508 * the underlying method type is also updated. |
|
509 */ |
|
510 static abstract class UninferredMethodType extends DelegatedType { |
|
511 |
|
512 final List<Type> tvars; |
|
513 |
|
514 public UninferredMethodType(MethodType mtype, List<Type> tvars) { |
|
515 super(METHOD, new MethodType(mtype.argtypes, null, mtype.thrown, mtype.tsym)); |
|
516 this.tvars = tvars; |
|
517 asMethodType().restype = new UninferredReturnType(tvars, mtype.restype); |
|
518 } |
|
519 |
|
520 @Override |
|
521 public MethodType asMethodType() { |
|
522 return qtype.asMethodType(); |
|
523 } |
|
524 |
|
525 @Override |
|
526 public Type map(Mapping f) { |
|
527 return qtype.map(f); |
|
528 } |
|
529 |
|
530 void instantiateReturnType(Type restype, List<Type> inferred, Types types) throws NoInstanceException { |
|
531 //update method type with newly inferred type-arguments |
|
532 qtype = new MethodType(types.subst(getParameterTypes(), tvars, inferred), |
|
533 restype, |
|
534 types.subst(UninferredMethodType.this.getThrownTypes(), tvars, inferred), |
|
535 UninferredMethodType.this.qtype.tsym); |
|
536 check(inferred, types); |
|
537 } |
|
538 |
|
539 abstract void check(List<Type> inferred, Types types) throws NoInstanceException; |
|
540 |
|
541 abstract List<Type> getConstraints(TypeVar tv, ConstraintKind ck); |
|
542 |
|
543 class UninferredReturnType extends ForAll { |
|
544 public UninferredReturnType(List<Type> tvars, Type restype) { |
|
545 super(tvars, restype); |
|
546 } |
|
547 @Override |
|
548 public Type inst(List<Type> actuals, Types types) { |
|
549 Type newRestype = super.inst(actuals, types); |
|
550 instantiateReturnType(newRestype, actuals, types); |
|
551 return newRestype; |
|
552 } |
|
553 @Override |
|
554 public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) { |
|
555 return UninferredMethodType.this.getConstraints(tv, ck); |
|
556 } |
|
557 } |
|
558 } |
|
559 |
509 private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals, |
560 private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals, |
510 boolean allowBoxing, boolean useVarargs, Warner warn) { |
561 boolean allowBoxing, boolean useVarargs, Warner warn) { |
511 try { |
562 try { |
512 rs.checkRawArgumentsAcceptable(env, actuals, formals, |
563 rs.checkRawArgumentsAcceptable(env, actuals, formals, |
513 allowBoxing, useVarargs, warn); |
564 allowBoxing, useVarargs, warn); |
516 // inferred method is not applicable |
567 // inferred method is not applicable |
517 throw invalidInstanceException.setMessage(ex.getDiagnostic()); |
568 throw invalidInstanceException.setMessage(ex.getDiagnostic()); |
518 } |
569 } |
519 } |
570 } |
520 |
571 |
521 /** Try to instantiate argument type `that' to given type `to'. |
572 /** Try to instantiate argument type `that' to given type `to'. |
522 * If this fails, try to insantiate `that' to `to' where |
573 * If this fails, try to insantiate `that' to `to' where |
523 * every occurrence of a type variable in `tvars' is replaced |
574 * every occurrence of a type variable in `tvars' is replaced |
524 * by an unknown type. |
575 * by an unknown type. |
525 */ |
576 */ |
526 private Type instantiateArg(ForAll that, |
577 private Type instantiateArg(ForAll that, |
527 Type to, |
578 Type to, |
528 List<Type> tvars, |
579 List<Type> tvars, |
529 Warner warn) throws InferenceException { |
580 Warner warn) throws InferenceException { |
530 List<Type> targs; |
581 List<Type> targs; |
531 try { |
582 try { |
532 return instantiateExpr(that, to, warn); |
583 return instantiateExpr(that, to, warn); |
533 } catch (NoInstanceException ex) { |
584 } catch (NoInstanceException ex) { |
534 Type to1 = to; |
585 Type to1 = to; |
535 for (List<Type> l = tvars; l.nonEmpty(); l = l.tail) |
586 for (List<Type> l = tvars; l.nonEmpty(); l = l.tail) |
536 to1 = types.subst(to1, List.of(l.head), List.of(syms.unknownType)); |
587 to1 = types.subst(to1, List.of(l.head), List.of(syms.unknownType)); |
537 return instantiateExpr(that, to1, warn); |
588 return instantiateExpr(that, to1, warn); |
538 } |
589 } |
539 } |
590 } |
540 |
591 |
541 /** check that type parameters are within their bounds. |
592 /** check that type parameters are within their bounds. |
542 */ |
593 */ |
543 void checkWithinBounds(List<Type> tvars, |
594 void checkWithinBounds(List<Type> tvars, |
544 List<Type> arguments, |
595 List<Type> arguments, |