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

changeset 1238
e28a06a3c5d9
parent 1237
568e70bbd9aa
child 1239
2827076dbf64
equal deleted inserted replaced
1237:568e70bbd9aa 1238:e28a06a3c5d9
267 if (ex instanceof ClassReader.BadClassFile 267 if (ex instanceof ClassReader.BadClassFile
268 && !suppressAbortOnBadClassFile) throw new Abort(); 268 && !suppressAbortOnBadClassFile) throw new Abort();
269 else return syms.errType; 269 else return syms.errType;
270 } 270 }
271 271
272 /** Report a type error.
273 * @param pos Position to be used for error reporting.
274 * @param problem A string describing the error.
275 * @param found The type that was found.
276 * @param req The type that was required.
277 */
278 Type typeError(DiagnosticPosition pos, Object problem, Type found, Type req) {
279 log.error(pos, "prob.found.req",
280 problem, found, req);
281 return types.createErrorType(found);
282 }
283
284 Type typeError(DiagnosticPosition pos, String problem, Type found, Type req, Object explanation) {
285 log.error(pos, "prob.found.req.1", problem, found, req, explanation);
286 return types.createErrorType(found);
287 }
288
289 /** Report an error that wrong type tag was found. 272 /** Report an error that wrong type tag was found.
290 * @param pos Position to be used for error reporting. 273 * @param pos Position to be used for error reporting.
291 * @param required An internationalized string describing the type tag 274 * @param required An internationalized string describing the type tag
292 * required. 275 * required.
293 * @param found The type that was found. 276 * @param found The type that was found.
428 411
429 /* ************************************************************************* 412 /* *************************************************************************
430 * Type Checking 413 * Type Checking
431 **************************************************************************/ 414 **************************************************************************/
432 415
416 /**
417 * A check context is an object that can be used to perform compatibility
418 * checks - depending on the check context, meaning of 'compatibility' might
419 * vary significantly.
420 */
421 interface CheckContext {
422 /**
423 * Is type 'found' compatible with type 'req' in given context
424 */
425 boolean compatible(Type found, Type req, Warner warn);
426 /**
427 * Instantiate a ForAll type against a given target type 'req' in given context
428 */
429 Type rawInstantiatePoly(ForAll found, Type req, Warner warn);
430 /**
431 * Report a check error
432 */
433 void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details);
434 /**
435 * Obtain a warner for this check context
436 */
437 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req);
438 }
439
440 /**
441 * This class represent a check context that is nested within another check
442 * context - useful to check sub-expressions. The default behavior simply
443 * redirects all method calls to the enclosing check context leveraging
444 * the forwarding pattern.
445 */
446 static class NestedCheckContext implements CheckContext {
447 CheckContext enclosingContext;
448
449 NestedCheckContext(CheckContext enclosingContext) {
450 this.enclosingContext = enclosingContext;
451 }
452
453 public boolean compatible(Type found, Type req, Warner warn) {
454 return enclosingContext.compatible(found, req, warn);
455 }
456
457 public Type rawInstantiatePoly(ForAll found, Type req, Warner warn) {
458 return enclosingContext.rawInstantiatePoly(found, req, warn);
459 }
460
461 public void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details) {
462 enclosingContext.report(pos, found, req, details);
463 }
464
465 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
466 return enclosingContext.checkWarner(pos, found, req);
467 }
468 }
469
470 /**
471 * Check context to be used when evaluating assignment/return statements
472 */
473 CheckContext basicHandler = new CheckContext() {
474 public void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details) {
475 if (details == null) {
476 log.error(pos, "prob.found.req", found, req);
477 } else {
478 log.error(pos, "prob.found.req.1", details);
479 }
480 }
481 public boolean compatible(Type found, Type req, Warner warn) {
482 return types.isAssignable(found, req, warn);
483 }
484
485 public Type rawInstantiatePoly(ForAll found, Type req, Warner warn) {
486 if (req.tag == NONE)
487 req = found.qtype.tag <= VOID ? found.qtype : syms.objectType;
488 return infer.instantiateExpr(found, req, warn);
489 }
490
491 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
492 return convertWarner(pos, found, req);
493 }
494 };
495
433 /** Check that a given type is assignable to a given proto-type. 496 /** Check that a given type is assignable to a given proto-type.
434 * If it is, return the type, otherwise return errType. 497 * If it is, return the type, otherwise return errType.
435 * @param pos Position to be used for error reporting. 498 * @param pos Position to be used for error reporting.
436 * @param found The type that was found. 499 * @param found The type that was found.
437 * @param req The type that was required. 500 * @param req The type that was required.
438 */ 501 */
439 Type checkType(DiagnosticPosition pos, Type found, Type req) { 502 Type checkType(DiagnosticPosition pos, Type found, Type req) {
440 return checkType(pos, found, req, "incompatible.types"); 503 return checkType(pos, found, req, basicHandler);
441 } 504 }
442 505
443 Type checkType(DiagnosticPosition pos, Type found, Type req, String errKey) { 506 Type checkType(final DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) {
444 if (req.tag == ERROR) 507 if (req.tag == ERROR)
445 return req; 508 return req;
446 if (found.tag == FORALL) 509 if (found.tag == FORALL) {
447 return instantiatePoly(pos, (ForAll)found, req, convertWarner(pos, found, req)); 510 ForAll fa = (ForAll)found;
511 Type owntype = instantiatePoly(pos, checkContext, fa, req, checkContext.checkWarner(pos, found, req));
512 return checkType(pos, owntype, req, checkContext);
513 }
448 if (req.tag == NONE) 514 if (req.tag == NONE)
449 return found; 515 return found;
450 if (types.isAssignable(found, req, convertWarner(pos, found, req))) 516 if (checkContext.compatible(found, req, checkContext.checkWarner(pos, found, req))) {
451 return found; 517 return found;
452 if (found.tag <= DOUBLE && req.tag <= DOUBLE) 518 } else {
453 return typeError(pos, diags.fragment("possible.loss.of.precision"), found, req); 519 if (found.tag <= DOUBLE && req.tag <= DOUBLE) {
454 if (found.isSuperBound()) { 520 checkContext.report(pos, found, req, diags.fragment("possible.loss.of.precision"));
455 log.error(pos, "assignment.from.super-bound", found); 521 return types.createErrorType(found);
522 }
523 checkContext.report(pos, found, req, null);
456 return types.createErrorType(found); 524 return types.createErrorType(found);
457 } 525 }
458 if (req.isExtendsBound()) {
459 log.error(pos, "assignment.to.extends-bound", req);
460 return types.createErrorType(found);
461 }
462 return typeError(pos, diags.fragment(errKey), found, req);
463 } 526 }
464 527
465 /** Instantiate polymorphic type to some prototype, unless 528 /** Instantiate polymorphic type to some prototype, unless
466 * prototype is `anyPoly' in which case polymorphic type 529 * prototype is `anyPoly' in which case polymorphic type
467 * is returned unchanged. 530 * is returned unchanged.
468 */ 531 */
469 Type instantiatePoly(DiagnosticPosition pos, ForAll t, Type pt, Warner warn) throws Infer.NoInstanceException { 532 Type instantiatePoly(DiagnosticPosition pos, CheckContext checkContext, ForAll t, Type pt, Warner warn) throws Infer.NoInstanceException {
470 if (pt == Infer.anyPoly && complexInference) { 533 try {
471 return t; 534 return checkContext.rawInstantiatePoly(t, pt, warn);
472 } else if (pt == Infer.anyPoly || pt.tag == NONE) { 535 } catch (final Infer.NoInstanceException ex) {
473 Type newpt = t.qtype.tag <= VOID ? t.qtype : syms.objectType; 536 JCDiagnostic d = ex.getDiagnostic();
474 return instantiatePoly(pos, t, newpt, warn); 537 if (d != null) {
475 } else if (pt.tag == ERROR) {
476 return pt;
477 } else {
478 try {
479 return infer.instantiateExpr(t, pt, warn);
480 } catch (Infer.NoInstanceException ex) {
481 if (ex.isAmbiguous) { 538 if (ex.isAmbiguous) {
482 JCDiagnostic d = ex.getDiagnostic(); 539 d = diags.fragment("undetermined.type", t, d);
483 log.error(pos, 540 }
484 "undetermined.type" + (d!=null ? ".1" : ""), 541 }
485 t, d); 542 checkContext.report(pos, t, pt, d);
486 return types.createErrorType(pt); 543 return types.createErrorType(pt);
487 } else { 544 } catch (Infer.InvalidInstanceException ex) {
488 JCDiagnostic d = ex.getDiagnostic(); 545 JCDiagnostic d = ex.getDiagnostic();
489 return typeError(pos, 546 if (d != null) {
490 diags.fragment("incompatible.types" + (d!=null ? ".1" : ""), d), 547 d = diags.fragment("invalid.inferred.types", t.tvars, d);
491 t, pt); 548 }
492 } 549 checkContext.report(pos, t, pt, d);
493 } catch (Infer.InvalidInstanceException ex) { 550 return types.createErrorType(pt);
494 JCDiagnostic d = ex.getDiagnostic();
495 log.error(pos, "invalid.inferred.types", t.tvars, d);
496 return types.createErrorType(pt);
497 }
498 } 551 }
499 } 552 }
500 553
501 /** Check that a given type can be cast to a given target type. 554 /** Check that a given type can be cast to a given target type.
502 * Return the result of the cast. 555 * Return the result of the cast.
503 * @param pos Position to be used for error reporting. 556 * @param pos Position to be used for error reporting.
504 * @param found The type that is being cast. 557 * @param found The type that is being cast.
505 * @param req The target type of the cast. 558 * @param req The target type of the cast.
506 */ 559 */
507 Type checkCastable(DiagnosticPosition pos, Type found, Type req) { 560 Type checkCastable(DiagnosticPosition pos, Type found, Type req) {
561 return checkCastable(pos, found, req, basicHandler);
562 }
563 Type checkCastable(DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) {
508 if (found.tag == FORALL) { 564 if (found.tag == FORALL) {
509 instantiatePoly(pos, (ForAll) found, req, castWarner(pos, found, req)); 565 instantiatePoly(pos, basicHandler, (ForAll) found, req, castWarner(pos, found, req));
510 return req; 566 return req;
511 } else if (types.isCastable(found, req, castWarner(pos, found, req))) { 567 } else if (types.isCastable(found, req, castWarner(pos, found, req))) {
512 return req; 568 return req;
513 } else { 569 } else {
514 return typeError(pos, 570 checkContext.report(pos, found, req, diags.fragment("inconvertible.types", found, req));
515 diags.fragment("inconvertible.types"), 571 return types.createErrorType(found);
516 found, req);
517 } 572 }
518 } 573 }
519 574
520 /** Check for redundant casts (i.e. where source type is a subtype of target type) 575 /** Check for redundant casts (i.e. where source type is a subtype of target type)
521 * The problem should only be reported for non-292 cast 576 * The problem should only be reported for non-292 cast
865 920
866 if (formal.isCompound() 921 if (formal.isCompound()
867 && types.isSubtype(actual, types.supertype(formal)) 922 && types.isSubtype(actual, types.supertype(formal))
868 && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn)) 923 && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn))
869 return; 924 return;
870
871 if (false) {
872 // TODO: make assertConvertible work
873 typeError(tree.pos(), diags.fragment("incompatible.types"), actual, formal);
874 throw new AssertionError("Tree: " + tree
875 + " actual:" + actual
876 + " formal: " + formal);
877 }
878 } 925 }
879 926
880 /** 927 /**
881 * Check that type 't' is a valid instantiation of a generic class 928 * Check that type 't' is a valid instantiation of a generic class
882 * (see JLS 4.5) 929 * (see JLS 4.5)

mercurial