422 * @param pos Position to be used for error reporting. |
422 * @param pos Position to be used for error reporting. |
423 * @param a The type that should be bounded by bs. |
423 * @param a The type that should be bounded by bs. |
424 * @param bs The bound. |
424 * @param bs The bound. |
425 */ |
425 */ |
426 private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) { |
426 private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) { |
427 if (a.tag == TYPEVAR && ((TypeVar)a).isCaptured()) { |
427 if (a.isUnbound()) { |
428 CapturedType ct = (CapturedType)a; |
428 return; |
429 boolean ok; |
429 } else if (a.tag != WILDCARD) { |
430 if (ct.bound.isErroneous()) {//capture doesn't exist |
430 a = types.upperBound(a); |
431 ok = false; |
431 for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) { |
432 } |
432 if (!types.isSubtype(a, l.head)) { |
433 else { |
433 log.error(pos, "not.within.bounds", a); |
434 switch (ct.wildcard.kind) { |
434 return; |
435 case EXTENDS: |
435 } |
436 ok = types.isCastable(bs.getUpperBound(), |
436 } |
437 types.upperBound(a), |
437 } else if (a.isExtendsBound()) { |
438 Warner.noWarnings); |
438 if (!types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings)) |
439 break; |
439 log.error(pos, "not.within.bounds", a); |
440 case SUPER: |
440 } else if (a.isSuperBound()) { |
441 ok = !types.notSoftSubtype(types.lowerBound(a), |
441 if (types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound())) |
442 bs.getUpperBound()); |
442 log.error(pos, "not.within.bounds", a); |
443 break; |
443 } |
444 case UNBOUND: |
444 } |
445 ok = true; |
445 |
446 break; |
446 /** Check that a type is within some bounds. |
447 default: |
447 * |
448 throw new AssertionError("Invalid bound kind"); |
448 * Used in TypeApply to verify that, e.g., X in V<X> is a valid |
449 } |
449 * type argument. |
450 } |
450 * @param pos Position to be used for error reporting. |
451 if (!ok) |
451 * @param a The type that should be bounded by bs. |
452 log.error(pos, "not.within.bounds", a); |
452 * @param bs The bound. |
453 } |
453 */ |
454 else { |
454 private void checkCapture(JCTypeApply tree) { |
455 a = types.upperBound(a); |
455 List<JCExpression> args = tree.getTypeArguments(); |
456 for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) { |
456 for (Type arg : types.capture(tree.type).getTypeArguments()) { |
457 if (!types.isSubtype(a, l.head)) { |
457 if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) { |
458 log.error(pos, "not.within.bounds", a); |
458 log.error(args.head.pos, "not.within.bounds", args.head.type); |
459 return; |
459 break; |
460 } |
460 } |
461 } |
461 args = args.tail; |
462 } |
462 } |
463 } |
463 } |
464 |
464 |
465 /** Check that type is different from 'void'. |
465 /** Check that type is different from 'void'. |
466 * @param pos Position to be used for error reporting. |
466 * @param pos Position to be used for error reporting. |
467 * @param t The type to be checked. |
467 * @param t The type to be checked. |
468 */ |
468 */ |
801 } |
801 } |
802 |
802 |
803 public void visitTypeApply(JCTypeApply tree) { |
803 public void visitTypeApply(JCTypeApply tree) { |
804 if (tree.type.tag == CLASS) { |
804 if (tree.type.tag == CLASS) { |
805 List<Type> formals = tree.type.tsym.type.getTypeArguments(); |
805 List<Type> formals = tree.type.tsym.type.getTypeArguments(); |
806 List<Type> actuals = types.capture(tree.type).getTypeArguments(); |
806 List<Type> actuals = tree.type.getTypeArguments(); |
807 List<JCExpression> args = tree.arguments; |
807 List<JCExpression> args = tree.arguments; |
808 List<Type> forms = formals; |
808 List<Type> forms = formals; |
809 ListBuffer<TypeVar> tvars_buf = new ListBuffer<TypeVar>(); |
809 ListBuffer<TypeVar> tvars_buf = new ListBuffer<TypeVar>(); |
810 |
810 |
811 // For matching pairs of actual argument types `a' and |
811 // For matching pairs of actual argument types `a' and |
824 args = args.tail; |
824 args = args.tail; |
825 forms = forms.tail; |
825 forms = forms.tail; |
826 } |
826 } |
827 |
827 |
828 args = tree.arguments; |
828 args = tree.arguments; |
|
829 List<Type> tvars_cap = types.substBounds(formals, |
|
830 formals, |
|
831 types.capture(tree.type).getTypeArguments()); |
|
832 while (args.nonEmpty() && tvars_cap.nonEmpty()) { |
|
833 // Let the actual arguments know their bound |
|
834 args.head.type.withTypeVar((TypeVar)tvars_cap.head); |
|
835 args = args.tail; |
|
836 tvars_cap = tvars_cap.tail; |
|
837 } |
|
838 |
|
839 args = tree.arguments; |
829 List<TypeVar> tvars = tvars_buf.toList(); |
840 List<TypeVar> tvars = tvars_buf.toList(); |
830 while (args.nonEmpty() && tvars.nonEmpty()) { |
841 |
831 // Let the actual arguments know their bound |
|
832 args.head.type.withTypeVar(tvars.head); |
|
833 args = args.tail; |
|
834 tvars = tvars.tail; |
|
835 } |
|
836 |
|
837 args = tree.arguments; |
|
838 tvars = tvars_buf.toList(); |
|
839 while (args.nonEmpty() && tvars.nonEmpty()) { |
842 while (args.nonEmpty() && tvars.nonEmpty()) { |
840 checkExtends(args.head.pos(), |
843 checkExtends(args.head.pos(), |
841 actuals.head, |
844 args.head.type, |
842 tvars.head); |
845 tvars.head); |
843 args = args.tail; |
846 args = args.tail; |
844 tvars = tvars.tail; |
847 tvars = tvars.tail; |
845 actuals = actuals.tail; |
848 } |
846 } |
849 |
|
850 checkCapture(tree); |
847 |
851 |
848 // Check that this type is either fully parameterized, or |
852 // Check that this type is either fully parameterized, or |
849 // not parameterized at all. |
853 // not parameterized at all. |
850 if (tree.type.getEnclosingType().isRaw()) |
854 if (tree.type.getEnclosingType().isRaw()) |
851 log.error(tree.pos(), "improperly.formed.type.inner.raw.param"); |
855 log.error(tree.pos(), "improperly.formed.type.inner.raw.param"); |