504 * type argument. |
504 * type argument. |
505 * @param pos Position to be used for error reporting. |
505 * @param pos Position to be used for error reporting. |
506 * @param a The type that should be bounded by bs. |
506 * @param a The type that should be bounded by bs. |
507 * @param bs The bound. |
507 * @param bs The bound. |
508 */ |
508 */ |
509 private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) { |
509 private boolean checkExtends(Type a, TypeVar bs) { |
510 if (a.isUnbound()) { |
510 if (a.isUnbound()) { |
511 return; |
511 return true; |
512 } else if (a.tag != WILDCARD) { |
512 } else if (a.tag != WILDCARD) { |
513 a = types.upperBound(a); |
513 a = types.upperBound(a); |
514 for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) { |
514 return types.isSubtype(a, bs.bound); |
515 if (!types.isSubtype(a, l.head)) { |
|
516 log.error(pos, "not.within.bounds", a); |
|
517 return; |
|
518 } |
|
519 } |
|
520 } else if (a.isExtendsBound()) { |
515 } else if (a.isExtendsBound()) { |
521 if (!types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings)) |
516 return types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings); |
522 log.error(pos, "not.within.bounds", a); |
|
523 } else if (a.isSuperBound()) { |
517 } else if (a.isSuperBound()) { |
524 if (types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound())) |
518 return !types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound()); |
525 log.error(pos, "not.within.bounds", a); |
|
526 } |
519 } |
527 } |
520 return true; |
528 |
|
529 /** Check that a type is within some bounds. |
|
530 * |
|
531 * Used in TypeApply to verify that, e.g., X in V<X> is a valid |
|
532 * type argument. |
|
533 * @param pos Position to be used for error reporting. |
|
534 * @param a The type that should be bounded by bs. |
|
535 * @param bs The bound. |
|
536 */ |
|
537 private void checkCapture(JCTypeApply tree) { |
|
538 List<JCExpression> args = tree.getTypeArguments(); |
|
539 for (Type arg : types.capture(tree.type).getTypeArguments()) { |
|
540 if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) { |
|
541 log.error(args.head.pos, "not.within.bounds", args.head.type); |
|
542 break; |
|
543 } |
|
544 args = args.tail; |
|
545 } |
|
546 } |
521 } |
547 |
522 |
548 /** Check that type is different from 'void'. |
523 /** Check that type is different from 'void'. |
549 * @param pos Position to be used for error reporting. |
524 * @param pos Position to be used for error reporting. |
550 * @param t The type to be checked. |
525 * @param t The type to be checked. |
772 warnUnchecked(pos, |
747 warnUnchecked(pos, |
773 "unchecked.generic.array.creation", |
748 "unchecked.generic.array.creation", |
774 argtype); |
749 argtype); |
775 } |
750 } |
776 } |
751 } |
|
752 |
|
753 /** |
|
754 * Check that type 't' is a valid instantiation of a generic class |
|
755 * (see JLS 4.5) |
|
756 * |
|
757 * @param t class type to be checked |
|
758 * @return true if 't' is well-formed |
|
759 */ |
|
760 public boolean checkValidGenericType(Type t) { |
|
761 return firstIncompatibleTypeArg(t) == null; |
|
762 } |
|
763 //WHERE |
|
764 private Type firstIncompatibleTypeArg(Type type) { |
|
765 List<Type> formals = type.tsym.type.allparams(); |
|
766 List<Type> actuals = type.allparams(); |
|
767 List<Type> args = type.getTypeArguments(); |
|
768 List<Type> forms = type.tsym.type.getTypeArguments(); |
|
769 ListBuffer<Type> tvars_buf = new ListBuffer<Type>(); |
|
770 |
|
771 // For matching pairs of actual argument types `a' and |
|
772 // formal type parameters with declared bound `b' ... |
|
773 while (args.nonEmpty() && forms.nonEmpty()) { |
|
774 // exact type arguments needs to know their |
|
775 // bounds (for upper and lower bound |
|
776 // calculations). So we create new TypeVars with |
|
777 // bounds substed with actuals. |
|
778 tvars_buf.append(types.substBound(((TypeVar)forms.head), |
|
779 formals, |
|
780 actuals)); |
|
781 args = args.tail; |
|
782 forms = forms.tail; |
|
783 } |
|
784 |
|
785 args = type.getTypeArguments(); |
|
786 List<Type> tvars_cap = types.substBounds(formals, |
|
787 formals, |
|
788 types.capture(type).allparams()); |
|
789 while (args.nonEmpty() && tvars_cap.nonEmpty()) { |
|
790 // Let the actual arguments know their bound |
|
791 args.head.withTypeVar((TypeVar)tvars_cap.head); |
|
792 args = args.tail; |
|
793 tvars_cap = tvars_cap.tail; |
|
794 } |
|
795 |
|
796 args = type.getTypeArguments(); |
|
797 List<Type> tvars = tvars_buf.toList(); |
|
798 |
|
799 while (args.nonEmpty() && tvars.nonEmpty()) { |
|
800 Type actual = types.subst(args.head, |
|
801 type.tsym.type.getTypeArguments(), |
|
802 tvars_buf.toList()); |
|
803 if (!checkExtends(actual, (TypeVar)tvars.head)) { |
|
804 return args.head; |
|
805 } |
|
806 args = args.tail; |
|
807 tvars = tvars.tail; |
|
808 } |
|
809 |
|
810 args = type.getTypeArguments(); |
|
811 |
|
812 for (Type arg : types.capture(type).getTypeArguments()) { |
|
813 if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) { |
|
814 return args.head; |
|
815 } |
|
816 } |
|
817 |
|
818 return null; |
|
819 } |
777 |
820 |
778 /** Check that given modifiers are legal for given symbol and |
821 /** Check that given modifiers are legal for given symbol and |
779 * return modifiers together with any implicit modififiers for that symbol. |
822 * return modifiers together with any implicit modififiers for that symbol. |
780 * Warning: we can't use flags() here since this method |
823 * Warning: we can't use flags() here since this method |
781 * is called during class enter, when flags() would cause a premature |
824 * is called during class enter, when flags() would cause a premature |
985 } |
1028 } |
986 |
1029 |
987 @Override |
1030 @Override |
988 public void visitTypeApply(JCTypeApply tree) { |
1031 public void visitTypeApply(JCTypeApply tree) { |
989 if (tree.type.tag == CLASS) { |
1032 if (tree.type.tag == CLASS) { |
990 List<Type> formals = tree.type.tsym.type.allparams(); |
|
991 List<Type> actuals = tree.type.allparams(); |
|
992 List<JCExpression> args = tree.arguments; |
1033 List<JCExpression> args = tree.arguments; |
993 List<Type> forms = tree.type.tsym.type.getTypeArguments(); |
1034 List<Type> forms = tree.type.tsym.type.getTypeArguments(); |
994 ListBuffer<Type> tvars_buf = new ListBuffer<Type>(); |
1035 |
|
1036 Type incompatibleArg = firstIncompatibleTypeArg(tree.type); |
|
1037 if (incompatibleArg != null) { |
|
1038 for (JCTree arg : tree.arguments) { |
|
1039 if (arg.type == incompatibleArg) { |
|
1040 log.error(arg, "not.within.bounds", incompatibleArg); |
|
1041 } |
|
1042 } |
|
1043 } |
995 |
1044 |
996 boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class; |
1045 boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class; |
997 |
1046 |
998 // For matching pairs of actual argument types `a' and |
1047 // For matching pairs of actual argument types `a' and |
999 // formal type parameters with declared bound `b' ... |
1048 // formal type parameters with declared bound `b' ... |
1000 while (args.nonEmpty() && forms.nonEmpty()) { |
1049 while (args.nonEmpty() && forms.nonEmpty()) { |
1001 validateTree(args.head, |
1050 validateTree(args.head, |
1002 !(isOuter && is_java_lang_Class), |
1051 !(isOuter && is_java_lang_Class), |
1003 false); |
1052 false); |
1004 |
|
1005 // exact type arguments needs to know their |
|
1006 // bounds (for upper and lower bound |
|
1007 // calculations). So we create new TypeVars with |
|
1008 // bounds substed with actuals. |
|
1009 tvars_buf.append(types.substBound(((TypeVar)forms.head), |
|
1010 formals, |
|
1011 actuals)); |
|
1012 |
|
1013 args = args.tail; |
1053 args = args.tail; |
1014 forms = forms.tail; |
1054 forms = forms.tail; |
1015 } |
1055 } |
1016 |
|
1017 args = tree.arguments; |
|
1018 List<Type> tvars_cap = types.substBounds(formals, |
|
1019 formals, |
|
1020 types.capture(tree.type).allparams()); |
|
1021 while (args.nonEmpty() && tvars_cap.nonEmpty()) { |
|
1022 // Let the actual arguments know their bound |
|
1023 args.head.type.withTypeVar((TypeVar)tvars_cap.head); |
|
1024 args = args.tail; |
|
1025 tvars_cap = tvars_cap.tail; |
|
1026 } |
|
1027 |
|
1028 args = tree.arguments; |
|
1029 List<Type> tvars = tvars_buf.toList(); |
|
1030 |
|
1031 while (args.nonEmpty() && tvars.nonEmpty()) { |
|
1032 Type actual = types.subst(args.head.type, |
|
1033 tree.type.tsym.type.getTypeArguments(), |
|
1034 tvars_buf.toList()); |
|
1035 checkExtends(args.head.pos(), |
|
1036 actual, |
|
1037 (TypeVar)tvars.head); |
|
1038 args = args.tail; |
|
1039 tvars = tvars.tail; |
|
1040 } |
|
1041 |
|
1042 checkCapture(tree); |
|
1043 |
1056 |
1044 // Check that this type is either fully parameterized, or |
1057 // Check that this type is either fully parameterized, or |
1045 // not parameterized at all. |
1058 // not parameterized at all. |
1046 if (tree.type.getEnclosingType().isRaw()) |
1059 if (tree.type.getEnclosingType().isRaw()) |
1047 log.error(tree.pos(), "improperly.formed.type.inner.raw.param"); |
1060 log.error(tree.pos(), "improperly.formed.type.inner.raw.param"); |