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

changeset 821
c8d312dd17bc
parent 816
7c537f4298fb
child 828
19c900c703c6
equal deleted inserted replaced
820:2d5aff89aaa3 821:c8d312dd17bc
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");

mercurial