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

changeset 1238
e28a06a3c5d9
parent 1237
568e70bbd9aa
child 1239
2827076dbf64
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Mar 26 15:27:51 2012 +0100
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Mar 26 15:28:22 2012 +0100
     1.3 @@ -269,23 +269,6 @@
     1.4          else return syms.errType;
     1.5      }
     1.6  
     1.7 -    /** Report a type error.
     1.8 -     *  @param pos        Position to be used for error reporting.
     1.9 -     *  @param problem    A string describing the error.
    1.10 -     *  @param found      The type that was found.
    1.11 -     *  @param req        The type that was required.
    1.12 -     */
    1.13 -    Type typeError(DiagnosticPosition pos, Object problem, Type found, Type req) {
    1.14 -        log.error(pos, "prob.found.req",
    1.15 -                  problem, found, req);
    1.16 -        return types.createErrorType(found);
    1.17 -    }
    1.18 -
    1.19 -    Type typeError(DiagnosticPosition pos, String problem, Type found, Type req, Object explanation) {
    1.20 -        log.error(pos, "prob.found.req.1", problem, found, req, explanation);
    1.21 -        return types.createErrorType(found);
    1.22 -    }
    1.23 -
    1.24      /** Report an error that wrong type tag was found.
    1.25       *  @param pos        Position to be used for error reporting.
    1.26       *  @param required   An internationalized string describing the type tag
    1.27 @@ -430,6 +413,86 @@
    1.28   * Type Checking
    1.29   **************************************************************************/
    1.30  
    1.31 +    /**
    1.32 +     * A check context is an object that can be used to perform compatibility
    1.33 +     * checks - depending on the check context, meaning of 'compatibility' might
    1.34 +     * vary significantly.
    1.35 +     */
    1.36 +    interface CheckContext {
    1.37 +        /**
    1.38 +         * Is type 'found' compatible with type 'req' in given context
    1.39 +         */
    1.40 +        boolean compatible(Type found, Type req, Warner warn);
    1.41 +        /**
    1.42 +         * Instantiate a ForAll type against a given target type 'req' in given context
    1.43 +         */
    1.44 +        Type rawInstantiatePoly(ForAll found, Type req, Warner warn);
    1.45 +        /**
    1.46 +         * Report a check error
    1.47 +         */
    1.48 +        void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details);
    1.49 +        /**
    1.50 +         * Obtain a warner for this check context
    1.51 +         */
    1.52 +        public Warner checkWarner(DiagnosticPosition pos, Type found, Type req);
    1.53 +    }
    1.54 +
    1.55 +    /**
    1.56 +     * This class represent a check context that is nested within another check
    1.57 +     * context - useful to check sub-expressions. The default behavior simply
    1.58 +     * redirects all method calls to the enclosing check context leveraging
    1.59 +     * the forwarding pattern.
    1.60 +     */
    1.61 +    static class NestedCheckContext implements CheckContext {
    1.62 +        CheckContext enclosingContext;
    1.63 +
    1.64 +        NestedCheckContext(CheckContext enclosingContext) {
    1.65 +            this.enclosingContext = enclosingContext;
    1.66 +        }
    1.67 +
    1.68 +        public boolean compatible(Type found, Type req, Warner warn) {
    1.69 +            return enclosingContext.compatible(found, req, warn);
    1.70 +        }
    1.71 +
    1.72 +        public Type rawInstantiatePoly(ForAll found, Type req, Warner warn) {
    1.73 +            return enclosingContext.rawInstantiatePoly(found, req, warn);
    1.74 +        }
    1.75 +
    1.76 +        public void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details) {
    1.77 +            enclosingContext.report(pos, found, req, details);
    1.78 +        }
    1.79 +
    1.80 +        public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
    1.81 +            return enclosingContext.checkWarner(pos, found, req);
    1.82 +        }
    1.83 +    }
    1.84 +
    1.85 +    /**
    1.86 +     * Check context to be used when evaluating assignment/return statements
    1.87 +     */
    1.88 +    CheckContext basicHandler = new CheckContext() {
    1.89 +        public void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details) {
    1.90 +            if (details == null) {
    1.91 +                log.error(pos, "prob.found.req", found, req);
    1.92 +            } else {
    1.93 +                log.error(pos, "prob.found.req.1", details);
    1.94 +            }
    1.95 +        }
    1.96 +        public boolean compatible(Type found, Type req, Warner warn) {
    1.97 +            return types.isAssignable(found, req, warn);
    1.98 +        }
    1.99 +
   1.100 +        public Type rawInstantiatePoly(ForAll found, Type req, Warner warn) {
   1.101 +            if (req.tag == NONE)
   1.102 +                req = found.qtype.tag <= VOID ? found.qtype : syms.objectType;
   1.103 +            return infer.instantiateExpr(found, req, warn);
   1.104 +        }
   1.105 +
   1.106 +        public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
   1.107 +            return convertWarner(pos, found, req);
   1.108 +        }
   1.109 +    };
   1.110 +
   1.111      /** Check that a given type is assignable to a given proto-type.
   1.112       *  If it is, return the type, otherwise return errType.
   1.113       *  @param pos        Position to be used for error reporting.
   1.114 @@ -437,64 +500,54 @@
   1.115       *  @param req        The type that was required.
   1.116       */
   1.117      Type checkType(DiagnosticPosition pos, Type found, Type req) {
   1.118 -        return checkType(pos, found, req, "incompatible.types");
   1.119 +        return checkType(pos, found, req, basicHandler);
   1.120      }
   1.121  
   1.122 -    Type checkType(DiagnosticPosition pos, Type found, Type req, String errKey) {
   1.123 +    Type checkType(final DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) {
   1.124          if (req.tag == ERROR)
   1.125              return req;
   1.126 -        if (found.tag == FORALL)
   1.127 -            return instantiatePoly(pos, (ForAll)found, req, convertWarner(pos, found, req));
   1.128 +        if (found.tag == FORALL) {
   1.129 +            ForAll fa = (ForAll)found;
   1.130 +            Type owntype = instantiatePoly(pos, checkContext, fa, req, checkContext.checkWarner(pos, found, req));
   1.131 +            return checkType(pos, owntype, req, checkContext);
   1.132 +        }
   1.133          if (req.tag == NONE)
   1.134              return found;
   1.135 -        if (types.isAssignable(found, req, convertWarner(pos, found, req)))
   1.136 +        if (checkContext.compatible(found, req, checkContext.checkWarner(pos, found, req))) {
   1.137              return found;
   1.138 -        if (found.tag <= DOUBLE && req.tag <= DOUBLE)
   1.139 -            return typeError(pos, diags.fragment("possible.loss.of.precision"), found, req);
   1.140 -        if (found.isSuperBound()) {
   1.141 -            log.error(pos, "assignment.from.super-bound", found);
   1.142 +        } else {
   1.143 +            if (found.tag <= DOUBLE && req.tag <= DOUBLE) {
   1.144 +                checkContext.report(pos, found, req, diags.fragment("possible.loss.of.precision"));
   1.145 +                return types.createErrorType(found);
   1.146 +            }
   1.147 +            checkContext.report(pos, found, req, null);
   1.148              return types.createErrorType(found);
   1.149          }
   1.150 -        if (req.isExtendsBound()) {
   1.151 -            log.error(pos, "assignment.to.extends-bound", req);
   1.152 -            return types.createErrorType(found);
   1.153 -        }
   1.154 -        return typeError(pos, diags.fragment(errKey), found, req);
   1.155      }
   1.156  
   1.157      /** Instantiate polymorphic type to some prototype, unless
   1.158       *  prototype is `anyPoly' in which case polymorphic type
   1.159       *  is returned unchanged.
   1.160       */
   1.161 -    Type instantiatePoly(DiagnosticPosition pos, ForAll t, Type pt, Warner warn) throws Infer.NoInstanceException {
   1.162 -        if (pt == Infer.anyPoly && complexInference) {
   1.163 -            return t;
   1.164 -        } else if (pt == Infer.anyPoly || pt.tag == NONE) {
   1.165 -            Type newpt = t.qtype.tag <= VOID ? t.qtype : syms.objectType;
   1.166 -            return instantiatePoly(pos, t, newpt, warn);
   1.167 -        } else if (pt.tag == ERROR) {
   1.168 -            return pt;
   1.169 -        } else {
   1.170 -            try {
   1.171 -                return infer.instantiateExpr(t, pt, warn);
   1.172 -            } catch (Infer.NoInstanceException ex) {
   1.173 +    Type instantiatePoly(DiagnosticPosition pos, CheckContext checkContext, ForAll t, Type pt, Warner warn) throws Infer.NoInstanceException {
   1.174 +        try {
   1.175 +            return checkContext.rawInstantiatePoly(t, pt, warn);
   1.176 +        } catch (final Infer.NoInstanceException ex) {
   1.177 +            JCDiagnostic d = ex.getDiagnostic();
   1.178 +            if (d != null) {
   1.179                  if (ex.isAmbiguous) {
   1.180 -                    JCDiagnostic d = ex.getDiagnostic();
   1.181 -                    log.error(pos,
   1.182 -                              "undetermined.type" + (d!=null ? ".1" : ""),
   1.183 -                              t, d);
   1.184 -                    return types.createErrorType(pt);
   1.185 -                } else {
   1.186 -                    JCDiagnostic d = ex.getDiagnostic();
   1.187 -                    return typeError(pos,
   1.188 -                                     diags.fragment("incompatible.types" + (d!=null ? ".1" : ""), d),
   1.189 -                                     t, pt);
   1.190 +                    d = diags.fragment("undetermined.type", t, d);
   1.191                  }
   1.192 -            } catch (Infer.InvalidInstanceException ex) {
   1.193 -                JCDiagnostic d = ex.getDiagnostic();
   1.194 -                log.error(pos, "invalid.inferred.types", t.tvars, d);
   1.195 -                return types.createErrorType(pt);
   1.196              }
   1.197 +            checkContext.report(pos, t, pt, d);
   1.198 +            return types.createErrorType(pt);
   1.199 +        } catch (Infer.InvalidInstanceException ex) {
   1.200 +            JCDiagnostic d = ex.getDiagnostic();
   1.201 +            if (d != null) {
   1.202 +                d = diags.fragment("invalid.inferred.types", t.tvars, d);
   1.203 +            }
   1.204 +            checkContext.report(pos, t, pt, d);
   1.205 +            return types.createErrorType(pt);
   1.206          }
   1.207      }
   1.208  
   1.209 @@ -505,15 +558,17 @@
   1.210       *  @param req        The target type of the cast.
   1.211       */
   1.212      Type checkCastable(DiagnosticPosition pos, Type found, Type req) {
   1.213 +        return checkCastable(pos, found, req, basicHandler);
   1.214 +    }
   1.215 +    Type checkCastable(DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) {
   1.216          if (found.tag == FORALL) {
   1.217 -            instantiatePoly(pos, (ForAll) found, req, castWarner(pos, found, req));
   1.218 +            instantiatePoly(pos, basicHandler, (ForAll) found, req, castWarner(pos, found, req));
   1.219              return req;
   1.220          } else if (types.isCastable(found, req, castWarner(pos, found, req))) {
   1.221              return req;
   1.222          } else {
   1.223 -            return typeError(pos,
   1.224 -                             diags.fragment("inconvertible.types"),
   1.225 -                             found, req);
   1.226 +            checkContext.report(pos, found, req, diags.fragment("inconvertible.types", found, req));
   1.227 +            return types.createErrorType(found);
   1.228          }
   1.229      }
   1.230  
   1.231 @@ -867,14 +922,6 @@
   1.232                  && types.isSubtype(actual, types.supertype(formal))
   1.233                  && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn))
   1.234                  return;
   1.235 -
   1.236 -            if (false) {
   1.237 -                // TODO: make assertConvertible work
   1.238 -                typeError(tree.pos(), diags.fragment("incompatible.types"), actual, formal);
   1.239 -                throw new AssertionError("Tree: " + tree
   1.240 -                                         + " actual:" + actual
   1.241 -                                         + " formal: " + formal);
   1.242 -            }
   1.243          }
   1.244  
   1.245      /**

mercurial