422 /** |
422 /** |
423 * Is type 'found' compatible with type 'req' in given context |
423 * Is type 'found' compatible with type 'req' in given context |
424 */ |
424 */ |
425 boolean compatible(Type found, Type req, Warner warn); |
425 boolean compatible(Type found, Type req, Warner warn); |
426 /** |
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 |
427 * Report a check error |
432 */ |
428 */ |
433 void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details); |
429 void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details); |
434 /** |
430 /** |
435 * Obtain a warner for this check context |
431 * Obtain a warner for this check context |
452 |
448 |
453 public boolean compatible(Type found, Type req, Warner warn) { |
449 public boolean compatible(Type found, Type req, Warner warn) { |
454 return enclosingContext.compatible(found, req, warn); |
450 return enclosingContext.compatible(found, req, warn); |
455 } |
451 } |
456 |
452 |
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) { |
453 public void report(DiagnosticPosition pos, Type found, Type req, JCDiagnostic details) { |
462 enclosingContext.report(pos, found, req, details); |
454 enclosingContext.report(pos, found, req, details); |
463 } |
455 } |
464 |
456 |
465 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { |
457 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { |
480 } |
472 } |
481 public boolean compatible(Type found, Type req, Warner warn) { |
473 public boolean compatible(Type found, Type req, Warner warn) { |
482 return types.isAssignable(found, req, warn); |
474 return types.isAssignable(found, req, warn); |
483 } |
475 } |
484 |
476 |
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) { |
477 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) { |
492 return convertWarner(pos, found, req); |
478 return convertWarner(pos, found, req); |
493 } |
479 } |
494 }; |
480 }; |
495 |
481 |
504 } |
490 } |
505 |
491 |
506 Type checkType(final DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) { |
492 Type checkType(final DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) { |
507 if (req.tag == ERROR) |
493 if (req.tag == ERROR) |
508 return req; |
494 return req; |
509 if (found.tag == FORALL) { |
|
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 } |
|
514 if (req.tag == NONE) |
495 if (req.tag == NONE) |
515 return found; |
496 return found; |
516 if (checkContext.compatible(found, req, checkContext.checkWarner(pos, found, req))) { |
497 if (checkContext.compatible(found, req, checkContext.checkWarner(pos, found, req))) { |
517 return found; |
498 return found; |
518 } else { |
499 } else { |
523 checkContext.report(pos, found, req, null); |
504 checkContext.report(pos, found, req, null); |
524 return types.createErrorType(found); |
505 return types.createErrorType(found); |
525 } |
506 } |
526 } |
507 } |
527 |
508 |
528 /** Instantiate polymorphic type to some prototype, unless |
|
529 * prototype is `anyPoly' in which case polymorphic type |
|
530 * is returned unchanged. |
|
531 */ |
|
532 Type instantiatePoly(DiagnosticPosition pos, CheckContext checkContext, ForAll t, Type pt, Warner warn) throws Infer.NoInstanceException { |
|
533 try { |
|
534 return checkContext.rawInstantiatePoly(t, pt, warn); |
|
535 } catch (final Infer.NoInstanceException ex) { |
|
536 JCDiagnostic d = ex.getDiagnostic(); |
|
537 if (d != null) { |
|
538 if (ex.isAmbiguous) { |
|
539 d = diags.fragment("undetermined.type", t, d); |
|
540 } |
|
541 } |
|
542 checkContext.report(pos, t, pt, d); |
|
543 return types.createErrorType(pt); |
|
544 } catch (Infer.InvalidInstanceException ex) { |
|
545 JCDiagnostic d = ex.getDiagnostic(); |
|
546 if (d != null) { |
|
547 d = diags.fragment("invalid.inferred.types", t.tvars, d); |
|
548 } |
|
549 checkContext.report(pos, t, pt, d); |
|
550 return types.createErrorType(pt); |
|
551 } |
|
552 } |
|
553 |
|
554 /** Check that a given type can be cast to a given target type. |
509 /** Check that a given type can be cast to a given target type. |
555 * Return the result of the cast. |
510 * Return the result of the cast. |
556 * @param pos Position to be used for error reporting. |
511 * @param pos Position to be used for error reporting. |
557 * @param found The type that is being cast. |
512 * @param found The type that is being cast. |
558 * @param req The target type of the cast. |
513 * @param req The target type of the cast. |
559 */ |
514 */ |
560 Type checkCastable(DiagnosticPosition pos, Type found, Type req) { |
515 Type checkCastable(DiagnosticPosition pos, Type found, Type req) { |
561 return checkCastable(pos, found, req, basicHandler); |
516 return checkCastable(pos, found, req, basicHandler); |
562 } |
517 } |
563 Type checkCastable(DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) { |
518 Type checkCastable(DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) { |
564 if (found.tag == FORALL) { |
519 if (types.isCastable(found, req, castWarner(pos, found, req))) { |
565 instantiatePoly(pos, basicHandler, (ForAll) found, req, castWarner(pos, found, req)); |
|
566 return req; |
|
567 } else if (types.isCastable(found, req, castWarner(pos, found, req))) { |
|
568 return req; |
520 return req; |
569 } else { |
521 } else { |
570 checkContext.report(pos, found, req, diags.fragment("inconvertible.types", found, req)); |
522 checkContext.report(pos, found, req, diags.fragment("inconvertible.types", found, req)); |
571 return types.createErrorType(found); |
523 return types.createErrorType(found); |
572 } |
524 } |