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

changeset 821
c8d312dd17bc
parent 816
7c537f4298fb
child 828
19c900c703c6
     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())

mercurial