1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Fri Jan 14 09:45:04 2011 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Fri Jan 14 09:45:52 2011 +0000 1.3 @@ -506,43 +506,18 @@ 1.4 * @param a The type that should be bounded by bs. 1.5 * @param bs The bound. 1.6 */ 1.7 - private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) { 1.8 + private boolean checkExtends(Type a, TypeVar bs) { 1.9 if (a.isUnbound()) { 1.10 - return; 1.11 + return true; 1.12 } else if (a.tag != WILDCARD) { 1.13 a = types.upperBound(a); 1.14 - for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) { 1.15 - if (!types.isSubtype(a, l.head)) { 1.16 - log.error(pos, "not.within.bounds", a); 1.17 - return; 1.18 - } 1.19 - } 1.20 + return types.isSubtype(a, bs.bound); 1.21 } else if (a.isExtendsBound()) { 1.22 - if (!types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings)) 1.23 - log.error(pos, "not.within.bounds", a); 1.24 + return types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings); 1.25 } else if (a.isSuperBound()) { 1.26 - if (types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound())) 1.27 - log.error(pos, "not.within.bounds", a); 1.28 + return !types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound()); 1.29 } 1.30 - } 1.31 - 1.32 - /** Check that a type is within some bounds. 1.33 - * 1.34 - * Used in TypeApply to verify that, e.g., X in V<X> is a valid 1.35 - * type argument. 1.36 - * @param pos Position to be used for error reporting. 1.37 - * @param a The type that should be bounded by bs. 1.38 - * @param bs The bound. 1.39 - */ 1.40 - private void checkCapture(JCTypeApply tree) { 1.41 - List<JCExpression> args = tree.getTypeArguments(); 1.42 - for (Type arg : types.capture(tree.type).getTypeArguments()) { 1.43 - if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) { 1.44 - log.error(args.head.pos, "not.within.bounds", args.head.type); 1.45 - break; 1.46 - } 1.47 - args = args.tail; 1.48 - } 1.49 + return true; 1.50 } 1.51 1.52 /** Check that type is different from 'void'. 1.53 @@ -775,6 +750,74 @@ 1.54 } 1.55 } 1.56 1.57 + /** 1.58 + * Check that type 't' is a valid instantiation of a generic class 1.59 + * (see JLS 4.5) 1.60 + * 1.61 + * @param t class type to be checked 1.62 + * @return true if 't' is well-formed 1.63 + */ 1.64 + public boolean checkValidGenericType(Type t) { 1.65 + return firstIncompatibleTypeArg(t) == null; 1.66 + } 1.67 + //WHERE 1.68 + private Type firstIncompatibleTypeArg(Type type) { 1.69 + List<Type> formals = type.tsym.type.allparams(); 1.70 + List<Type> actuals = type.allparams(); 1.71 + List<Type> args = type.getTypeArguments(); 1.72 + List<Type> forms = type.tsym.type.getTypeArguments(); 1.73 + ListBuffer<Type> tvars_buf = new ListBuffer<Type>(); 1.74 + 1.75 + // For matching pairs of actual argument types `a' and 1.76 + // formal type parameters with declared bound `b' ... 1.77 + while (args.nonEmpty() && forms.nonEmpty()) { 1.78 + // exact type arguments needs to know their 1.79 + // bounds (for upper and lower bound 1.80 + // calculations). So we create new TypeVars with 1.81 + // bounds substed with actuals. 1.82 + tvars_buf.append(types.substBound(((TypeVar)forms.head), 1.83 + formals, 1.84 + actuals)); 1.85 + args = args.tail; 1.86 + forms = forms.tail; 1.87 + } 1.88 + 1.89 + args = type.getTypeArguments(); 1.90 + List<Type> tvars_cap = types.substBounds(formals, 1.91 + formals, 1.92 + types.capture(type).allparams()); 1.93 + while (args.nonEmpty() && tvars_cap.nonEmpty()) { 1.94 + // Let the actual arguments know their bound 1.95 + args.head.withTypeVar((TypeVar)tvars_cap.head); 1.96 + args = args.tail; 1.97 + tvars_cap = tvars_cap.tail; 1.98 + } 1.99 + 1.100 + args = type.getTypeArguments(); 1.101 + List<Type> tvars = tvars_buf.toList(); 1.102 + 1.103 + while (args.nonEmpty() && tvars.nonEmpty()) { 1.104 + Type actual = types.subst(args.head, 1.105 + type.tsym.type.getTypeArguments(), 1.106 + tvars_buf.toList()); 1.107 + if (!checkExtends(actual, (TypeVar)tvars.head)) { 1.108 + return args.head; 1.109 + } 1.110 + args = args.tail; 1.111 + tvars = tvars.tail; 1.112 + } 1.113 + 1.114 + args = type.getTypeArguments(); 1.115 + 1.116 + for (Type arg : types.capture(type).getTypeArguments()) { 1.117 + if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) { 1.118 + return args.head; 1.119 + } 1.120 + } 1.121 + 1.122 + return null; 1.123 + } 1.124 + 1.125 /** Check that given modifiers are legal for given symbol and 1.126 * return modifiers together with any implicit modififiers for that symbol. 1.127 * Warning: we can't use flags() here since this method 1.128 @@ -987,11 +1030,17 @@ 1.129 @Override 1.130 public void visitTypeApply(JCTypeApply tree) { 1.131 if (tree.type.tag == CLASS) { 1.132 - List<Type> formals = tree.type.tsym.type.allparams(); 1.133 - List<Type> actuals = tree.type.allparams(); 1.134 List<JCExpression> args = tree.arguments; 1.135 List<Type> forms = tree.type.tsym.type.getTypeArguments(); 1.136 - ListBuffer<Type> tvars_buf = new ListBuffer<Type>(); 1.137 + 1.138 + Type incompatibleArg = firstIncompatibleTypeArg(tree.type); 1.139 + if (incompatibleArg != null) { 1.140 + for (JCTree arg : tree.arguments) { 1.141 + if (arg.type == incompatibleArg) { 1.142 + log.error(arg, "not.within.bounds", incompatibleArg); 1.143 + } 1.144 + } 1.145 + } 1.146 1.147 boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class; 1.148 1.149 @@ -1001,46 +1050,10 @@ 1.150 validateTree(args.head, 1.151 !(isOuter && is_java_lang_Class), 1.152 false); 1.153 - 1.154 - // exact type arguments needs to know their 1.155 - // bounds (for upper and lower bound 1.156 - // calculations). So we create new TypeVars with 1.157 - // bounds substed with actuals. 1.158 - tvars_buf.append(types.substBound(((TypeVar)forms.head), 1.159 - formals, 1.160 - actuals)); 1.161 - 1.162 args = args.tail; 1.163 forms = forms.tail; 1.164 } 1.165 1.166 - args = tree.arguments; 1.167 - List<Type> tvars_cap = types.substBounds(formals, 1.168 - formals, 1.169 - types.capture(tree.type).allparams()); 1.170 - while (args.nonEmpty() && tvars_cap.nonEmpty()) { 1.171 - // Let the actual arguments know their bound 1.172 - args.head.type.withTypeVar((TypeVar)tvars_cap.head); 1.173 - args = args.tail; 1.174 - tvars_cap = tvars_cap.tail; 1.175 - } 1.176 - 1.177 - args = tree.arguments; 1.178 - List<Type> tvars = tvars_buf.toList(); 1.179 - 1.180 - while (args.nonEmpty() && tvars.nonEmpty()) { 1.181 - Type actual = types.subst(args.head.type, 1.182 - tree.type.tsym.type.getTypeArguments(), 1.183 - tvars_buf.toList()); 1.184 - checkExtends(args.head.pos(), 1.185 - actual, 1.186 - (TypeVar)tvars.head); 1.187 - args = args.tail; 1.188 - tvars = tvars.tail; 1.189 - } 1.190 - 1.191 - checkCapture(tree); 1.192 - 1.193 // Check that this type is either fully parameterized, or 1.194 // not parameterized at all. 1.195 if (tree.type.getEnclosingType().isRaw())