646 |
643 |
647 if (useVarargs) { |
644 if (useVarargs) { |
648 //note: if applicability check is triggered by most specific test, |
645 //note: if applicability check is triggered by most specific test, |
649 //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5) |
646 //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5) |
650 Type elt = types.elemtype(varargsFormal); |
647 Type elt = types.elemtype(varargsFormal); |
651 Type eltUndet = infer.asUndetType(elt, undetvars); |
|
652 while (argtypes.nonEmpty()) { |
648 while (argtypes.nonEmpty()) { |
653 Type capturedActual = types.capture(argtypes.head); |
649 ResultInfo resultInfo = methodCheckResult(elt, allowBoxing, true, undetvars, handler, warn); |
654 if (!types.isConvertible(capturedActual, eltUndet, warn)) { |
650 checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head)); |
655 throw handler.argumentMismatch(true, argtypes.head, elt); |
|
656 } |
|
657 checkedArgs.append(capturedActual); |
|
658 argtypes = argtypes.tail; |
651 argtypes = argtypes.tail; |
659 } |
652 } |
660 //check varargs element type accessibility |
653 //check varargs element type accessibility |
661 if (undetvars.isEmpty() && !isAccessible(env, elt)) { |
654 if (undetvars.isEmpty() && !isAccessible(env, elt)) { |
662 Symbol location = env.enclClass.sym; |
655 Symbol location = env.enclClass.sym; |
663 throw handler.inaccessibleVarargs(location, elt); |
656 throw handler.inaccessibleVarargs(location, elt); |
664 } |
657 } |
665 } |
658 } |
666 return checkedArgs.toList(); |
659 return checkedArgs.toList(); |
667 } |
660 } |
668 // where |
661 |
669 public static class InapplicableMethodException extends RuntimeException { |
662 /** |
670 private static final long serialVersionUID = 0; |
663 * Check context to be used during method applicability checks. A method check |
671 |
664 * context might contain inference variables. |
672 JCDiagnostic diagnostic; |
665 */ |
673 JCDiagnostic.Factory diags; |
666 abstract class MethodCheckContext implements CheckContext { |
674 |
667 |
675 InapplicableMethodException(JCDiagnostic.Factory diags) { |
668 MethodCheckHandler handler; |
676 this.diagnostic = null; |
669 boolean useVarargs; |
677 this.diags = diags; |
670 List<Type> undetvars; |
678 } |
671 Warner rsWarner; |
679 InapplicableMethodException setMessage() { |
672 |
680 this.diagnostic = null; |
673 public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) { |
681 return this; |
674 this.handler = handler; |
682 } |
675 this.useVarargs = useVarargs; |
683 InapplicableMethodException setMessage(String key) { |
676 this.undetvars = undetvars; |
684 this.diagnostic = key != null ? diags.fragment(key) : null; |
677 this.rsWarner = rsWarner; |
685 return this; |
678 } |
686 } |
679 |
687 InapplicableMethodException setMessage(String key, Object... args) { |
680 public void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details) { |
688 this.diagnostic = key != null ? diags.fragment(key, args) : null; |
681 throw handler.argumentMismatch(useVarargs, found, req); |
689 return this; |
682 } |
690 } |
683 |
691 InapplicableMethodException setMessage(JCDiagnostic diag) { |
684 public Type rawInstantiatePoly(ForAll found, Type req, Warner warn) { |
692 this.diagnostic = diag; |
685 throw new AssertionError("ForAll in argument position"); |
693 return this; |
686 } |
694 } |
687 |
695 |
688 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { |
696 public JCDiagnostic getDiagnostic() { |
689 return rsWarner; |
697 return diagnostic; |
690 } |
698 } |
691 } |
699 } |
692 |
700 private final InapplicableMethodException inapplicableMethodException; |
693 /** |
|
694 * Subclass of method check context class that implements strict method conversion. |
|
695 * Strict method conversion checks compatibility between types using subtyping tests. |
|
696 */ |
|
697 class StrictMethodContext extends MethodCheckContext { |
|
698 |
|
699 public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) { |
|
700 super(handler, useVarargs, undetvars, rsWarner); |
|
701 } |
|
702 |
|
703 public boolean compatible(Type found, Type req, Warner warn) { |
|
704 return types.isSubtypeUnchecked(found, infer.asUndetType(req, undetvars), warn); |
|
705 } |
|
706 } |
|
707 |
|
708 /** |
|
709 * Subclass of method check context class that implements loose method conversion. |
|
710 * Loose method conversion checks compatibility between types using method conversion tests. |
|
711 */ |
|
712 class LooseMethodContext extends MethodCheckContext { |
|
713 |
|
714 public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) { |
|
715 super(handler, useVarargs, undetvars, rsWarner); |
|
716 } |
|
717 |
|
718 public boolean compatible(Type found, Type req, Warner warn) { |
|
719 return types.isConvertible(found, infer.asUndetType(req, undetvars), warn); |
|
720 } |
|
721 } |
|
722 |
|
723 /** |
|
724 * Create a method check context to be used during method applicability check |
|
725 */ |
|
726 ResultInfo methodCheckResult(Type to, boolean allowBoxing, boolean useVarargs, |
|
727 List<Type> undetvars, MethodCheckHandler methodHandler, Warner rsWarner) { |
|
728 MethodCheckContext checkContext = allowBoxing ? |
|
729 new LooseMethodContext(methodHandler, useVarargs, undetvars, rsWarner) : |
|
730 new StrictMethodContext(methodHandler, useVarargs, undetvars, rsWarner); |
|
731 return attr.new ResultInfo(VAL, to, checkContext) { |
|
732 @Override |
|
733 protected Type check(DiagnosticPosition pos, Type found) { |
|
734 return super.check(pos, chk.checkNonVoid(pos, types.capture(types.upperBound(found)))); |
|
735 } |
|
736 }; |
|
737 } |
|
738 |
|
739 public static class InapplicableMethodException extends RuntimeException { |
|
740 private static final long serialVersionUID = 0; |
|
741 |
|
742 JCDiagnostic diagnostic; |
|
743 JCDiagnostic.Factory diags; |
|
744 |
|
745 InapplicableMethodException(JCDiagnostic.Factory diags) { |
|
746 this.diagnostic = null; |
|
747 this.diags = diags; |
|
748 } |
|
749 InapplicableMethodException setMessage() { |
|
750 this.diagnostic = null; |
|
751 return this; |
|
752 } |
|
753 InapplicableMethodException setMessage(String key) { |
|
754 this.diagnostic = key != null ? diags.fragment(key) : null; |
|
755 return this; |
|
756 } |
|
757 InapplicableMethodException setMessage(String key, Object... args) { |
|
758 this.diagnostic = key != null ? diags.fragment(key, args) : null; |
|
759 return this; |
|
760 } |
|
761 InapplicableMethodException setMessage(JCDiagnostic diag) { |
|
762 this.diagnostic = diag; |
|
763 return this; |
|
764 } |
|
765 |
|
766 public JCDiagnostic getDiagnostic() { |
|
767 return diagnostic; |
|
768 } |
|
769 } |
|
770 private final InapplicableMethodException inapplicableMethodException; |
701 |
771 |
702 /* *************************************************************************** |
772 /* *************************************************************************** |
703 * Symbol lookup |
773 * Symbol lookup |
704 * the following naming conventions for arguments are used |
774 * the following naming conventions for arguments are used |
705 * |
775 * |