OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/class_finalizer.h" | 5 #include "vm/class_finalizer.h" |
6 | 6 |
7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
8 #include "vm/heap.h" | 8 #include "vm/heap.h" |
9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 ASSERT(!function.IsNull()); | 58 ASSERT(!function.IsNull()); |
59 if (function.HasOptimizedCode()) { | 59 if (function.HasOptimizedCode()) { |
60 function.SwitchToUnoptimizedCode(); | 60 function.SwitchToUnoptimizedCode(); |
61 } | 61 } |
62 } | 62 } |
63 } | 63 } |
64 #endif | 64 #endif |
65 } | 65 } |
66 | 66 |
67 | 67 |
68 void AddSuperType(const Type& type, | 68 void AddSuperType(const AbstractType& type, |
69 GrowableArray<intptr_t>* finalized_super_classes) { | 69 GrowableArray<intptr_t>* finalized_super_classes) { |
70 ASSERT(type.HasResolvedTypeClass()); | 70 ASSERT(type.HasResolvedTypeClass()); |
71 if (type.IsObjectType()) { | 71 if (type.IsObjectType()) { |
72 return; | 72 return; |
73 } | 73 } |
74 const Class& cls = Class::Handle(type.type_class()); | 74 const Class& cls = Class::Handle(type.type_class()); |
75 ASSERT(cls.is_finalized()); | 75 ASSERT(cls.is_finalized()); |
76 const intptr_t cid = cls.id(); | 76 const intptr_t cid = cls.id(); |
77 for (intptr_t i = 0; i < finalized_super_classes->length(); i++) { | 77 for (intptr_t i = 0; i < finalized_super_classes->length(); i++) { |
78 if ((*finalized_super_classes)[i] == cid) { | 78 if ((*finalized_super_classes)[i] == cid) { |
79 // Already added. | 79 // Already added. |
80 return; | 80 return; |
81 } | 81 } |
82 } | 82 } |
83 finalized_super_classes->Add(cid); | 83 finalized_super_classes->Add(cid); |
84 const Type& super_type = Type::Handle(cls.super_type()); | 84 const AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
85 AddSuperType(super_type, finalized_super_classes); | 85 AddSuperType(super_type, finalized_super_classes); |
86 } | 86 } |
87 | 87 |
88 | 88 |
89 // Use array instead of set since we expect very few subclassed classes | 89 // Use array instead of set since we expect very few subclassed classes |
90 // to occur. | 90 // to occur. |
91 static void CollectFinalizedSuperClasses( | 91 static void CollectFinalizedSuperClasses( |
92 const GrowableObjectArray& pending_classes, | 92 const GrowableObjectArray& pending_classes, |
93 GrowableArray<intptr_t>* finalized_super_classes) { | 93 GrowableArray<intptr_t>* finalized_super_classes) { |
94 Class& cls = Class::Handle(); | 94 Class& cls = Class::Handle(); |
95 Type& super_type = Type::Handle(); | 95 AbstractType& super_type = Type::Handle(); |
96 for (intptr_t i = 0; i < pending_classes.Length(); i++) { | 96 for (intptr_t i = 0; i < pending_classes.Length(); i++) { |
97 cls ^= pending_classes.At(i); | 97 cls ^= pending_classes.At(i); |
98 ASSERT(!cls.is_finalized()); | 98 ASSERT(!cls.is_finalized()); |
99 super_type ^= cls.super_type(); | 99 super_type = cls.super_type(); |
100 if (!super_type.IsNull()) { | 100 if (!super_type.IsNull()) { |
101 if (!super_type.IsMalformed() && | 101 if (!super_type.IsMalformed() && |
102 super_type.HasResolvedTypeClass() && | 102 super_type.HasResolvedTypeClass() && |
103 Class::Handle(super_type.type_class()).is_finalized()) { | 103 Class::Handle(super_type.type_class()).is_finalized()) { |
104 AddSuperType(super_type, finalized_super_classes); | 104 AddSuperType(super_type, finalized_super_classes); |
105 } | 105 } |
106 } | 106 } |
107 } | 107 } |
108 } | 108 } |
109 | 109 |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 Type& target_type = Type::Handle(target.RedirectionType()); | 427 Type& target_type = Type::Handle(target.RedirectionType()); |
428 Function& target_target = Function::Handle(target.RedirectionTarget()); | 428 Function& target_target = Function::Handle(target.RedirectionTarget()); |
429 if (target_target.IsNull()) { | 429 if (target_target.IsNull()) { |
430 ASSERT(target_type.IsMalformed()); | 430 ASSERT(target_type.IsMalformed()); |
431 } else { | 431 } else { |
432 // If the target type refers to type parameters, substitute them with the | 432 // If the target type refers to type parameters, substitute them with the |
433 // type arguments of the redirection type. | 433 // type arguments of the redirection type. |
434 if (!target_type.IsInstantiated()) { | 434 if (!target_type.IsInstantiated()) { |
435 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle( | 435 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle( |
436 type.arguments()); | 436 type.arguments()); |
437 target_type ^= target_type.InstantiateFrom(type_args); | 437 Error& malformed_error = Error::Handle(); |
438 // TODO(regis): Check bounds in checked mode. | 438 target_type ^= target_type.InstantiateFrom(type_args, &malformed_error); |
439 target_type ^= FinalizeType(cls, target_type, kCanonicalize); | 439 if (malformed_error.IsNull()) { |
440 if (target_type.IsMalformed()) { | 440 target_type ^= FinalizeType(cls, target_type, kCanonicalize); |
| 441 } else { |
| 442 FinalizeMalformedType(malformed_error, |
| 443 cls, target_type, kFinalize, |
| 444 "cannot resolve redirecting factory"); |
441 target_target = Function::null(); | 445 target_target = Function::null(); |
442 } | 446 } |
443 } | 447 } |
444 } | 448 } |
445 factory.SetRedirectionType(target_type); | 449 factory.SetRedirectionType(target_type); |
446 factory.SetRedirectionTarget(target_target); | 450 factory.SetRedirectionTarget(target_target); |
447 } | 451 } |
448 | 452 |
449 | 453 |
450 void ClassFinalizer::ResolveType(const Class& cls, | 454 void ClassFinalizer::ResolveType(const Class& cls, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 AbstractType& type_argument = AbstractType::Handle(); | 501 AbstractType& type_argument = AbstractType::Handle(); |
498 for (intptr_t i = 0; i < num_arguments; i++) { | 502 for (intptr_t i = 0; i < num_arguments; i++) { |
499 type_argument = arguments.TypeAt(i); | 503 type_argument = arguments.TypeAt(i); |
500 ResolveType(cls, type_argument, finalization); | 504 ResolveType(cls, type_argument, finalization); |
501 } | 505 } |
502 } | 506 } |
503 } | 507 } |
504 | 508 |
505 | 509 |
506 void ClassFinalizer::FinalizeTypeParameters(const Class& cls) { | 510 void ClassFinalizer::FinalizeTypeParameters(const Class& cls) { |
| 511 // The type parameter bounds are not finalized here. |
507 const TypeArguments& type_parameters = | 512 const TypeArguments& type_parameters = |
508 TypeArguments::Handle(cls.type_parameters()); | 513 TypeArguments::Handle(cls.type_parameters()); |
509 if (!type_parameters.IsNull()) { | 514 if (!type_parameters.IsNull()) { |
510 TypeParameter& type_parameter = TypeParameter::Handle(); | 515 TypeParameter& type_parameter = TypeParameter::Handle(); |
511 const intptr_t num_types = type_parameters.Length(); | 516 const intptr_t num_types = type_parameters.Length(); |
512 for (intptr_t i = 0; i < num_types; i++) { | 517 for (intptr_t i = 0; i < num_types; i++) { |
513 type_parameter ^= type_parameters.TypeAt(i); | 518 type_parameter ^= type_parameters.TypeAt(i); |
514 type_parameter ^= FinalizeType(cls, | 519 type_parameter ^= FinalizeType(cls, |
515 type_parameter, | 520 type_parameter, |
516 kCanonicalizeWellFormed); | 521 kCanonicalizeWellFormed); |
(...skipping 13 matching lines...) Expand all Loading... |
530 // Example: | 535 // Example: |
531 // Declared: class C<K, V> extends B<V> { ... } | 536 // Declared: class C<K, V> extends B<V> { ... } |
532 // class B<T> extends A<int> { ... } | 537 // class B<T> extends A<int> { ... } |
533 // Input: C<String, double> expressed as | 538 // Input: C<String, double> expressed as |
534 // cls = C, arguments = [null, null, String, double], | 539 // cls = C, arguments = [null, null, String, double], |
535 // i.e. cls_args = [String, double], offset = 2, length = 2. | 540 // i.e. cls_args = [String, double], offset = 2, length = 2. |
536 // Output: arguments = [int, double, String, double] | 541 // Output: arguments = [int, double, String, double] |
537 void ClassFinalizer::FinalizeTypeArguments( | 542 void ClassFinalizer::FinalizeTypeArguments( |
538 const Class& cls, | 543 const Class& cls, |
539 const AbstractTypeArguments& arguments, | 544 const AbstractTypeArguments& arguments, |
540 FinalizationKind finalization) { | 545 FinalizationKind finalization, |
| 546 Error* bound_error) { |
541 ASSERT(arguments.Length() >= cls.NumTypeArguments()); | 547 ASSERT(arguments.Length() >= cls.NumTypeArguments()); |
542 if (!cls.is_finalized()) { | 548 if (!cls.is_finalized()) { |
543 FinalizeTypeParameters(cls); | 549 FinalizeTypeParameters(cls); |
544 } | 550 } |
545 Type& super_type = Type::Handle(cls.super_type()); | 551 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
546 if (!super_type.IsNull()) { | 552 if (!super_type.IsNull()) { |
547 const Class& super_class = Class::Handle(super_type.type_class()); | 553 const Class& super_class = Class::Handle(super_type.type_class()); |
548 AbstractTypeArguments& super_type_args = AbstractTypeArguments::Handle(); | 554 AbstractTypeArguments& super_type_args = AbstractTypeArguments::Handle(); |
549 if (super_type.IsBeingFinalized()) { | 555 if (super_type.IsBeingFinalized()) { |
550 // This type references itself via its type arguments. This is legal, but | 556 // This type references itself via its type arguments. This is legal, but |
551 // we must avoid endless recursion. We therefore map the innermost | 557 // we must avoid endless recursion. We therefore map the innermost |
552 // super type to dynamic. | 558 // super type to dynamic. |
553 // Note that a direct self-reference via the super class chain is illegal | 559 // Note that a direct self-reference via the super class chain is illegal |
554 // and reported as an error earlier. | 560 // and reported as an error earlier. |
555 // Such legal self-references occur with F-bounded quantification. | 561 // Such legal self-references occur with F-bounded quantification. |
(...skipping 13 matching lines...) Expand all Loading... |
569 } | 575 } |
570 const intptr_t num_super_type_params = super_class.NumTypeParameters(); | 576 const intptr_t num_super_type_params = super_class.NumTypeParameters(); |
571 const intptr_t offset = super_class.NumTypeArguments(); | 577 const intptr_t offset = super_class.NumTypeArguments(); |
572 const intptr_t super_offset = offset - num_super_type_params; | 578 const intptr_t super_offset = offset - num_super_type_params; |
573 ASSERT(offset == (cls.NumTypeArguments() - cls.NumTypeParameters())); | 579 ASSERT(offset == (cls.NumTypeArguments() - cls.NumTypeParameters())); |
574 AbstractType& super_type_arg = AbstractType::Handle(Type::DynamicType()); | 580 AbstractType& super_type_arg = AbstractType::Handle(Type::DynamicType()); |
575 for (intptr_t i = 0; i < num_super_type_params; i++) { | 581 for (intptr_t i = 0; i < num_super_type_params; i++) { |
576 if (!super_type_args.IsNull()) { | 582 if (!super_type_args.IsNull()) { |
577 super_type_arg = super_type_args.TypeAt(super_offset + i); | 583 super_type_arg = super_type_args.TypeAt(super_offset + i); |
578 if (!super_type_arg.IsInstantiated()) { | 584 if (!super_type_arg.IsInstantiated()) { |
579 super_type_arg = super_type_arg.InstantiateFrom(arguments); | 585 Error& malformed_error = Error::Handle(); |
| 586 super_type_arg = super_type_arg.InstantiateFrom(arguments, |
| 587 &malformed_error); |
| 588 if (!malformed_error.IsNull()) { |
| 589 if (!super_type_arg.IsInstantiated()) { |
| 590 // CheckTypeArgumentBounds will insert a BoundedType. |
| 591 } else if (bound_error->IsNull()) { |
| 592 *bound_error = malformed_error.raw(); |
| 593 } |
| 594 } |
580 } | 595 } |
581 if (finalization >= kCanonicalize) { | 596 if (finalization >= kCanonicalize) { |
582 super_type_arg = super_type_arg.Canonicalize(); | 597 super_type_arg = super_type_arg.Canonicalize(); |
583 } | 598 } |
584 } | 599 } |
585 arguments.SetTypeAt(super_offset + i, super_type_arg); | 600 arguments.SetTypeAt(super_offset + i, super_type_arg); |
586 } | 601 } |
587 FinalizeTypeArguments(super_class, arguments, finalization); | 602 FinalizeTypeArguments(super_class, arguments, finalization, bound_error); |
| 603 } |
| 604 } |
| 605 |
| 606 |
| 607 // Check the type argument vector 'arguments' against the corresponding bounds |
| 608 // of the type parameters of class 'cls' and, recursively, of its superclasses. |
| 609 // Replace a type argument that cannot be checked at compile time by a |
| 610 // BoundedType, thereby postponing the bound check to run time. |
| 611 // Return a bound error if a type argument is not within bound at compile time. |
| 612 void ClassFinalizer::CheckTypeArgumentBounds( |
| 613 const Class& cls, |
| 614 const AbstractTypeArguments& arguments, |
| 615 Error* bound_error) { |
| 616 if (!cls.is_finalized()) { |
| 617 ResolveAndFinalizeUpperBounds(cls); |
| 618 } |
| 619 // Note that when finalizing a type, we need to verify the bounds in both |
| 620 // production mode and checked mode, because the finalized type may be written |
| 621 // to a snapshot. It would be wrong to ignore bounds when generating the |
| 622 // snapshot in production mode and then use the unchecked type in checked mode |
| 623 // after reading it from the snapshot. |
| 624 // However, we do not immediately report a bound error, which would be wrong |
| 625 // in production mode, but simply postpone the bound checking to runtime. |
| 626 const intptr_t num_type_params = cls.NumTypeParameters(); |
| 627 const intptr_t offset = cls.NumTypeArguments() - num_type_params; |
| 628 AbstractType& type_arg = AbstractType::Handle(); |
| 629 AbstractType& cls_type_param = AbstractType::Handle(); |
| 630 AbstractType& bound = AbstractType::Handle(); |
| 631 const TypeArguments& cls_type_params = |
| 632 TypeArguments::Handle(cls.type_parameters()); |
| 633 ASSERT((cls_type_params.IsNull() && (num_type_params == 0)) || |
| 634 (cls_type_params.Length() == num_type_params)); |
| 635 for (intptr_t i = 0; i < num_type_params; i++) { |
| 636 type_arg = arguments.TypeAt(offset + i); |
| 637 if (type_arg.IsDynamicType()) { |
| 638 continue; |
| 639 } |
| 640 cls_type_param = cls_type_params.TypeAt(i); |
| 641 const TypeParameter& type_param = TypeParameter::Cast(cls_type_param); |
| 642 ASSERT(type_param.IsFinalized()); |
| 643 bound = type_param.bound(); |
| 644 if (!bound.IsObjectType() && !bound.IsDynamicType()) { |
| 645 Error& malformed_error = Error::Handle(); |
| 646 // Note that the bound may be malformed, in which case the bound check |
| 647 // will return an error and the bound check will be postponed to run time. |
| 648 // Note also that the bound may still be unfinalized. |
| 649 if (!bound.IsFinalized()) { |
| 650 ASSERT(bound.IsBeingFinalized()); |
| 651 // The bound refers to type parameters, creating a cycle; postpone |
| 652 // bound check to run time, when the bound will be finalized. |
| 653 // TODO(regis): Do we need to instantiate an uninstantiated bound here? |
| 654 type_arg = BoundedType::New(type_arg, bound, type_param); |
| 655 arguments.SetTypeAt(offset + i, type_arg); |
| 656 continue; |
| 657 } |
| 658 if (!bound.IsInstantiated()) { |
| 659 bound = bound.InstantiateFrom(arguments, &malformed_error); |
| 660 } |
| 661 // TODO(regis): We could simplify this code if we could differentiate |
| 662 // between a failed bound check and a bound check that is undecidable at |
| 663 // compile time. |
| 664 if (malformed_error.IsNull()) { |
| 665 type_param.CheckBound(type_arg, bound, &malformed_error); |
| 666 } |
| 667 if (!malformed_error.IsNull()) { |
| 668 if (!type_arg.IsInstantiated() || !bound.IsInstantiated()) { |
| 669 type_arg = BoundedType::New(type_arg, bound, type_param); |
| 670 arguments.SetTypeAt(offset + i, type_arg); |
| 671 } else if (bound_error->IsNull()) { |
| 672 *bound_error = malformed_error.raw(); |
| 673 } |
| 674 } |
| 675 } |
| 676 } |
| 677 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
| 678 if (!super_type.IsNull()) { |
| 679 const Class& super_class = Class::Handle(super_type.type_class()); |
| 680 CheckTypeArgumentBounds(super_class, arguments, bound_error); |
588 } | 681 } |
589 } | 682 } |
590 | 683 |
591 | 684 |
592 RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls, | 685 RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls, |
593 const AbstractType& type, | 686 const AbstractType& type, |
594 FinalizationKind finalization) { | 687 FinalizationKind finalization) { |
595 if (type.IsFinalized()) { | 688 if (type.IsFinalized()) { |
596 // Ensure type is canonical if canonicalization is requested, unless type is | 689 // Ensure type is canonical if canonicalization is requested, unless type is |
597 // malformed. | 690 // malformed. |
(...skipping 22 matching lines...) Expand all Loading... |
620 ASSERT(!parameterized_class.IsNull()); | 713 ASSERT(!parameterized_class.IsNull()); |
621 // The index must reflect the position of this type parameter in the type | 714 // The index must reflect the position of this type parameter in the type |
622 // arguments vector of its parameterized class. The offset to add is the | 715 // arguments vector of its parameterized class. The offset to add is the |
623 // number of type arguments in the super type, which is equal to the | 716 // number of type arguments in the super type, which is equal to the |
624 // difference in number of type arguments and type parameters of the | 717 // difference in number of type arguments and type parameters of the |
625 // parameterized class. | 718 // parameterized class. |
626 const intptr_t offset = parameterized_class.NumTypeArguments() - | 719 const intptr_t offset = parameterized_class.NumTypeArguments() - |
627 parameterized_class.NumTypeParameters(); | 720 parameterized_class.NumTypeParameters(); |
628 type_parameter.set_index(type_parameter.index() + offset); | 721 type_parameter.set_index(type_parameter.index() + offset); |
629 type_parameter.set_is_finalized(); | 722 type_parameter.set_is_finalized(); |
630 // TODO(regis): We are not able to finalize the bound here without getting | |
631 // into cycles. Revisit. | |
632 // We do not canonicalize type parameters. | 723 // We do not canonicalize type parameters. |
633 return type_parameter.raw(); | 724 return type_parameter.raw(); |
634 } | 725 } |
635 | 726 |
636 // At this point, we can only have a parameterized_type. | 727 // At this point, we can only have a parameterized_type. |
637 const Type& parameterized_type = Type::Cast(type); | 728 const Type& parameterized_type = Type::Cast(type); |
638 | 729 |
639 if (parameterized_type.IsBeingFinalized()) { | 730 if (parameterized_type.IsBeingFinalized()) { |
640 // Self reference detected. The type is malformed. | 731 // Self reference detected. The type is malformed. |
641 FinalizeMalformedType( | 732 FinalizeMalformedType( |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
711 Error::Handle(), // No previous error. | 802 Error::Handle(), // No previous error. |
712 cls, parameterized_type, finalization, | 803 cls, parameterized_type, finalization, |
713 "wrong number of type arguments in type '%s'", | 804 "wrong number of type arguments in type '%s'", |
714 String::Handle(parameterized_type.UserVisibleName()).ToCString()); | 805 String::Handle(parameterized_type.UserVisibleName()).ToCString()); |
715 return parameterized_type.raw(); | 806 return parameterized_type.raw(); |
716 } | 807 } |
717 // The full type argument vector consists of the type arguments of the | 808 // The full type argument vector consists of the type arguments of the |
718 // super types of type_class, which may be initialized from the parsed | 809 // super types of type_class, which may be initialized from the parsed |
719 // type arguments, followed by the parsed type arguments. | 810 // type arguments, followed by the parsed type arguments. |
720 TypeArguments& full_arguments = TypeArguments::Handle(); | 811 TypeArguments& full_arguments = TypeArguments::Handle(); |
| 812 Error& bound_error = Error::Handle(); |
721 if (num_type_arguments > 0) { | 813 if (num_type_arguments > 0) { |
722 // If no type arguments were parsed and if the super types do not prepend | 814 // If no type arguments were parsed and if the super types do not prepend |
723 // type arguments to the vector, we can leave the vector as null. | 815 // type arguments to the vector, we can leave the vector as null. |
724 if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) { | 816 if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) { |
725 full_arguments = TypeArguments::New(num_type_arguments); | 817 full_arguments = TypeArguments::New(num_type_arguments); |
726 // Copy the parsed type arguments at the correct offset in the full type | 818 // Copy the parsed type arguments at the correct offset in the full type |
727 // argument vector. | 819 // argument vector. |
728 const intptr_t offset = num_type_arguments - num_type_parameters; | 820 const intptr_t offset = num_type_arguments - num_type_parameters; |
729 AbstractType& type_arg = AbstractType::Handle(Type::DynamicType()); | 821 AbstractType& type_arg = AbstractType::Handle(Type::DynamicType()); |
730 for (intptr_t i = 0; i < num_type_parameters; i++) { | 822 for (intptr_t i = 0; i < num_type_parameters; i++) { |
(...skipping 11 matching lines...) Expand all Loading... |
742 // of its signature function and no super type is involved. | 834 // of its signature function and no super type is involved. |
743 // If the signature class is canonical (not an alias), the owner of its | 835 // If the signature class is canonical (not an alias), the owner of its |
744 // signature function may either be an alias or the enclosing class of a | 836 // signature function may either be an alias or the enclosing class of a |
745 // local function, in which case the super type of the enclosing class is | 837 // local function, in which case the super type of the enclosing class is |
746 // also considered when filling up the argument vector. | 838 // also considered when filling up the argument vector. |
747 if (type_class.IsSignatureClass()) { | 839 if (type_class.IsSignatureClass()) { |
748 const Function& signature_fun = | 840 const Function& signature_fun = |
749 Function::Handle(type_class.signature_function()); | 841 Function::Handle(type_class.signature_function()); |
750 ASSERT(!signature_fun.is_static()); | 842 ASSERT(!signature_fun.is_static()); |
751 const Class& sig_fun_owner = Class::Handle(signature_fun.Owner()); | 843 const Class& sig_fun_owner = Class::Handle(signature_fun.Owner()); |
752 FinalizeTypeArguments(sig_fun_owner, full_arguments, finalization); | 844 FinalizeTypeArguments( |
| 845 sig_fun_owner, full_arguments, finalization, &bound_error); |
| 846 CheckTypeArgumentBounds(sig_fun_owner, full_arguments, &bound_error); |
753 } else { | 847 } else { |
754 FinalizeTypeArguments(type_class, full_arguments, finalization); | 848 FinalizeTypeArguments( |
| 849 type_class, full_arguments, finalization, &bound_error); |
| 850 CheckTypeArgumentBounds(type_class, full_arguments, &bound_error); |
755 } | 851 } |
756 if (full_arguments.IsRaw(num_type_arguments)) { | 852 if (full_arguments.IsRaw(num_type_arguments)) { |
757 // The parameterized_type is raw. Set its argument vector to null, which | 853 // The parameterized_type is raw. Set its argument vector to null, which |
758 // is more efficient in type tests. | 854 // is more efficient in type tests. |
759 full_arguments = TypeArguments::null(); | 855 full_arguments = TypeArguments::null(); |
760 } else if (finalization >= kCanonicalize) { | 856 } else if (finalization >= kCanonicalize) { |
761 // FinalizeTypeArguments can modify 'full_arguments', | 857 // FinalizeTypeArguments can modify 'full_arguments', |
762 // canonicalize afterwards. | 858 // canonicalize afterwards. |
763 full_arguments ^= full_arguments.Canonicalize(); | 859 full_arguments ^= full_arguments.Canonicalize(); |
764 } | 860 } |
765 parameterized_type.set_arguments(full_arguments); | 861 parameterized_type.set_arguments(full_arguments); |
766 } else { | 862 } else { |
767 ASSERT(full_arguments.IsNull()); // Use null vector for raw type. | 863 ASSERT(full_arguments.IsNull()); // Use null vector for raw type. |
768 } | 864 } |
769 } | 865 } |
770 | 866 |
771 // Self referencing types may get finalized indirectly. | 867 // Self referencing types may get finalized indirectly. |
772 if (!parameterized_type.IsFinalized()) { | 868 if (!parameterized_type.IsFinalized()) { |
773 // Mark the type as finalized. | 869 // Mark the type as finalized. |
774 parameterized_type.SetIsFinalized(); | 870 parameterized_type.SetIsFinalized(); |
775 } | 871 } |
776 | 872 |
777 // Upper bounds of the finalized type arguments are only verified in checked | |
778 // mode, since bound errors are never reported by the vm in production mode. | |
779 if (FLAG_enable_type_checks && | |
780 !full_arguments.IsNull() && | |
781 full_arguments.IsInstantiated()) { | |
782 ResolveAndFinalizeUpperBounds(type_class); | |
783 Error& malformed_error = Error::Handle(); | |
784 // Pass the full type argument vector as the bounds instantiator. | |
785 if (!full_arguments.IsWithinBoundsOf(type_class, | |
786 full_arguments, | |
787 &malformed_error)) { | |
788 ASSERT(!malformed_error.IsNull()); | |
789 // The type argument vector of the type is not within bounds. The type | |
790 // is malformed. Prepend malformed_error to new malformed type error in | |
791 // order to report both locations. | |
792 // Note that malformed bounds never result in a compile time error, even | |
793 // in checked mode. Therefore, overwrite finalization with kFinalize | |
794 // when finalizing the malformed type. | |
795 FinalizeMalformedType( | |
796 malformed_error, | |
797 cls, parameterized_type, kFinalize, | |
798 "type arguments of type '%s' are not within bounds", | |
799 String::Handle(parameterized_type.UserVisibleName()).ToCString()); | |
800 return parameterized_type.raw(); | |
801 } | |
802 } | |
803 | |
804 // If the type class is a signature class, we are currently finalizing a | 873 // If the type class is a signature class, we are currently finalizing a |
805 // signature type, i.e. finalizing the result type and parameter types of the | 874 // signature type, i.e. finalizing the result type and parameter types of the |
806 // signature function of this signature type. | 875 // signature function of this signature type. |
807 // We do this after marking this type as finalized in order to allow a | 876 // We do this after marking this type as finalized in order to allow a |
808 // function type to refer to itself via its parameter types and result type. | 877 // function type to refer to itself via its parameter types and result type. |
809 if (type_class.IsSignatureClass()) { | 878 if (type_class.IsSignatureClass()) { |
810 // The class may be created while parsing a function body, after all | 879 // The class may be created while parsing a function body, after all |
811 // pending classes have already been finalized. | 880 // pending classes have already been finalized. |
812 FinalizeClass(type_class); | 881 FinalizeClass(type_class); |
813 } | 882 } |
814 | 883 |
| 884 // If a bound error occurred, return a BoundedType with a malformed bound. |
| 885 // The malformed bound will be ignored in production mode. |
| 886 if (!bound_error.IsNull()) { |
| 887 FinalizationKind bound_finalization = kTryResolve; // No compile error. |
| 888 if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) { |
| 889 bound_finalization = finalization; |
| 890 } |
| 891 const String& parameterized_type_name = String::Handle( |
| 892 parameterized_type.UserVisibleName()); |
| 893 const Type& malformed_bound = Type::Handle( |
| 894 NewFinalizedMalformedType(bound_error, |
| 895 cls, |
| 896 parameterized_type.token_pos(), |
| 897 bound_finalization, |
| 898 "type '%s' has an out of bound type argument", |
| 899 parameterized_type_name.ToCString())); |
| 900 return BoundedType::New(parameterized_type, |
| 901 malformed_bound, |
| 902 TypeParameter::Handle()); |
| 903 } |
| 904 |
815 if (finalization >= kCanonicalize) { | 905 if (finalization >= kCanonicalize) { |
816 return parameterized_type.Canonicalize(); | 906 return parameterized_type.Canonicalize(); |
817 } else { | 907 } else { |
818 return parameterized_type.raw(); | 908 return parameterized_type.raw(); |
819 } | 909 } |
820 } | 910 } |
821 | 911 |
822 | 912 |
823 void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls, | 913 void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls, |
824 const Function& function) { | 914 const Function& function) { |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1101 const Class& mixin_cls = Class::Handle(mixin_type.type_class()); | 1191 const Class& mixin_cls = Class::Handle(mixin_type.type_class()); |
1102 | 1192 |
1103 if (FLAG_trace_class_finalization) { | 1193 if (FLAG_trace_class_finalization) { |
1104 OS::Print("Applying mixin '%s' to '%s'\n", | 1194 OS::Print("Applying mixin '%s' to '%s'\n", |
1105 String::Handle(mixin_cls.Name()).ToCString(), | 1195 String::Handle(mixin_cls.Name()).ToCString(), |
1106 cls.ToCString()); | 1196 cls.ToCString()); |
1107 } | 1197 } |
1108 | 1198 |
1109 // Check that the super class of the mixin class is extending | 1199 // Check that the super class of the mixin class is extending |
1110 // class Object. | 1200 // class Object. |
1111 const Type& mixin_super_type = Type::Handle(mixin_cls.super_type()); | 1201 const AbstractType& mixin_super_type = |
| 1202 AbstractType::Handle(mixin_cls.super_type()); |
1112 if (!mixin_super_type.IsObjectType()) { | 1203 if (!mixin_super_type.IsObjectType()) { |
1113 const Script& script = Script::Handle(cls.script()); | 1204 const Script& script = Script::Handle(cls.script()); |
1114 const String& class_name = String::Handle(mixin_cls.Name()); | 1205 const String& class_name = String::Handle(mixin_cls.Name()); |
1115 ReportError(script, cls.token_pos(), | 1206 ReportError(script, cls.token_pos(), |
1116 "mixin class %s must extend class Object", | 1207 "mixin class %s must extend class Object", |
1117 class_name.ToCString()); | 1208 class_name.ToCString()); |
1118 } | 1209 } |
1119 | 1210 |
1120 // Copy the type parameters of the mixin class to the mixin | 1211 // Copy the type parameters of the mixin class to the mixin |
1121 // application class. | 1212 // application class. |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1217 } | 1308 } |
1218 if (cls.mixin() != Type::null()) { | 1309 if (cls.mixin() != Type::null()) { |
1219 // Copy instance methods and fields from the mixin class. | 1310 // Copy instance methods and fields from the mixin class. |
1220 // This has to happen before the check whether the methods of | 1311 // This has to happen before the check whether the methods of |
1221 // the class conflict with inherited methods. | 1312 // the class conflict with inherited methods. |
1222 ApplyMixin(cls); | 1313 ApplyMixin(cls); |
1223 } | 1314 } |
1224 // Finalize type parameters before finalizing the super type. | 1315 // Finalize type parameters before finalizing the super type. |
1225 FinalizeTypeParameters(cls); | 1316 FinalizeTypeParameters(cls); |
1226 // Finalize super type. | 1317 // Finalize super type. |
1227 Type& super_type = Type::Handle(cls.super_type()); | 1318 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
1228 if (!super_type.IsNull()) { | 1319 if (!super_type.IsNull()) { |
1229 super_type ^= FinalizeType(cls, super_type, kCanonicalizeWellFormed); | 1320 // In case of a bound error in the super type in production mode, the |
| 1321 // finalized super type will be a BoundedType with a malformed bound. |
| 1322 // It should not be a problem if the class is written to a snapshot and |
| 1323 // later executed in checked mode. Note that the finalized type argument |
| 1324 // vector of any type of the base class will contain a BoundedType for the |
| 1325 // out of bound type argument. |
| 1326 super_type = FinalizeType(cls, super_type, kCanonicalizeWellFormed); |
1230 cls.set_super_type(super_type); | 1327 cls.set_super_type(super_type); |
1231 } | 1328 } |
1232 if (cls.IsSignatureClass()) { | 1329 if (cls.IsSignatureClass()) { |
1233 // Check for illegal self references. | 1330 // Check for illegal self references. |
1234 GrowableArray<intptr_t> visited_aliases; | 1331 GrowableArray<intptr_t> visited_aliases; |
1235 if (!IsAliasCycleFree(cls, &visited_aliases)) { | 1332 if (!IsAliasCycleFree(cls, &visited_aliases)) { |
1236 const String& name = String::Handle(cls.Name()); | 1333 const String& name = String::Handle(cls.Name()); |
1237 const Script& script = Script::Handle(cls.script()); | 1334 const Script& script = Script::Handle(cls.script()); |
1238 ReportError(script, cls.token_pos(), | 1335 ReportError(script, cls.token_pos(), |
1239 "typedef '%s' illegally refers to itself", | 1336 "typedef '%s' illegally refers to itself", |
1240 name.ToCString()); | 1337 name.ToCString()); |
1241 } | 1338 } |
1242 cls.Finalize(); | 1339 cls.Finalize(); |
1243 // Signature classes extend Object. No need to add this class to the direct | 1340 // Signature classes extend Object. No need to add this class to the direct |
1244 // subclasses of Object. | 1341 // subclasses of Object. |
1245 ASSERT(super_type.IsNull() || super_type.IsObjectType()); | 1342 ASSERT(super_type.IsNull() || super_type.IsObjectType()); |
1246 | 1343 |
| 1344 // The type parameters of signature classes may have bounds. |
| 1345 ResolveAndFinalizeUpperBounds(cls); |
| 1346 |
1247 // Resolve and finalize the result and parameter types of the signature | 1347 // Resolve and finalize the result and parameter types of the signature |
1248 // function of this signature class. | 1348 // function of this signature class. |
1249 const Function& sig_function = Function::Handle(cls.signature_function()); | 1349 const Function& sig_function = Function::Handle(cls.signature_function()); |
1250 ResolveAndFinalizeSignature(cls, sig_function); | 1350 ResolveAndFinalizeSignature(cls, sig_function); |
1251 | 1351 |
1252 // Resolve and finalize the signature type of this signature class. | 1352 // Resolve and finalize the signature type of this signature class. |
1253 const Type& sig_type = Type::Handle(cls.SignatureType()); | 1353 const Type& sig_type = Type::Handle(cls.SignatureType()); |
1254 FinalizeType(cls, sig_type, kCanonicalizeWellFormed); | 1354 FinalizeType(cls, sig_type, kCanonicalizeWellFormed); |
1255 return; | 1355 return; |
1256 } | 1356 } |
1257 // Finalize interface types (but not necessarily interface classes). | 1357 // Finalize interface types (but not necessarily interface classes). |
1258 Array& interface_types = Array::Handle(cls.interfaces()); | 1358 Array& interface_types = Array::Handle(cls.interfaces()); |
1259 AbstractType& interface_type = AbstractType::Handle(); | 1359 AbstractType& interface_type = AbstractType::Handle(); |
1260 for (intptr_t i = 0; i < interface_types.Length(); i++) { | 1360 for (intptr_t i = 0; i < interface_types.Length(); i++) { |
1261 interface_type ^= interface_types.At(i); | 1361 interface_type ^= interface_types.At(i); |
1262 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); | 1362 interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed); |
1263 interface_types.SetAt(i, interface_type); | 1363 interface_types.SetAt(i, interface_type); |
1264 } | 1364 } |
1265 // Mark as finalized before resolving type parameter upper bounds and member | 1365 // Mark as finalized before resolving type parameter upper bounds and member |
1266 // types in order to break cycles. | 1366 // types in order to break cycles. |
1267 cls.Finalize(); | 1367 cls.Finalize(); |
| 1368 // Finalize bounds even if running in production mode, so that a snapshot |
| 1369 // contains them. |
1268 ResolveAndFinalizeUpperBounds(cls); | 1370 ResolveAndFinalizeUpperBounds(cls); |
1269 ResolveAndFinalizeMemberTypes(cls); | 1371 ResolveAndFinalizeMemberTypes(cls); |
1270 // Run additional checks after all types are finalized. | 1372 // Run additional checks after all types are finalized. |
1271 if (cls.is_const()) { | 1373 if (cls.is_const()) { |
1272 CheckForLegalConstClass(cls); | 1374 CheckForLegalConstClass(cls); |
1273 } | 1375 } |
1274 // Add this class to the direct subclasses of the superclass, unless the | 1376 // Add this class to the direct subclasses of the superclass, unless the |
1275 // superclass is Object. | 1377 // superclass is Object. |
1276 if (!super_type.IsNull() && !super_type.IsObjectType()) { | 1378 if (!super_type.IsNull() && !super_type.IsObjectType()) { |
1277 ASSERT(!super_class.IsNull()); | 1379 ASSERT(!super_class.IsNull()); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1366 const String& class_name = String::Handle(cls.Name()); | 1468 const String& class_name = String::Handle(cls.Name()); |
1367 const Script& script = Script::Handle(cls.script()); | 1469 const Script& script = Script::Handle(cls.script()); |
1368 ReportError(script, cls.token_pos(), | 1470 ReportError(script, cls.token_pos(), |
1369 "cyclic reference found for class '%s'", | 1471 "cyclic reference found for class '%s'", |
1370 class_name.ToCString()); | 1472 class_name.ToCString()); |
1371 } | 1473 } |
1372 } | 1474 } |
1373 | 1475 |
1374 // If the class/interface has no explicit super class/interfaces | 1476 // If the class/interface has no explicit super class/interfaces |
1375 // and is not a mixin application, we are done. | 1477 // and is not a mixin application, we are done. |
1376 Type& super_type = Type::Handle(cls.super_type()); | 1478 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
1377 Type& mixin_type = Type::Handle(cls.mixin()); | 1479 Type& mixin_type = Type::Handle(cls.mixin()); |
1378 Array& super_interfaces = Array::Handle(cls.interfaces()); | 1480 Array& super_interfaces = Array::Handle(cls.interfaces()); |
1379 if ((super_type.IsNull() || super_type.IsObjectType()) && | 1481 if ((super_type.IsNull() || super_type.IsObjectType()) && |
1380 (super_interfaces.Length() == 0) && | 1482 (super_interfaces.Length() == 0) && |
1381 (mixin_type.IsNull())) { | 1483 (mixin_type.IsNull())) { |
1382 return; | 1484 return; |
1383 } | 1485 } |
1384 | 1486 |
1385 if (!mixin_type.IsNull()) { | 1487 if (!mixin_type.IsNull()) { |
1386 ResolveType(cls, mixin_type, kCanonicalizeWellFormed); | 1488 ResolveType(cls, mixin_type, kCanonicalizeWellFormed); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1546 const String& class_name = String::Handle(cls.Name()); | 1648 const String& class_name = String::Handle(cls.Name()); |
1547 OS::Print("class '%s'", class_name.ToCString()); | 1649 OS::Print("class '%s'", class_name.ToCString()); |
1548 const Library& library = Library::Handle(cls.library()); | 1650 const Library& library = Library::Handle(cls.library()); |
1549 if (!library.IsNull()) { | 1651 if (!library.IsNull()) { |
1550 OS::Print(" library '%s%s':\n", | 1652 OS::Print(" library '%s%s':\n", |
1551 String::Handle(library.url()).ToCString(), | 1653 String::Handle(library.url()).ToCString(), |
1552 String::Handle(library.private_key()).ToCString()); | 1654 String::Handle(library.private_key()).ToCString()); |
1553 } else { | 1655 } else { |
1554 OS::Print(" (null library):\n"); | 1656 OS::Print(" (null library):\n"); |
1555 } | 1657 } |
1556 const Type& super_type = Type::Handle(cls.super_type()); | 1658 const AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
1557 if (super_type.IsNull()) { | 1659 if (super_type.IsNull()) { |
1558 OS::Print(" Super: NULL"); | 1660 OS::Print(" Super: NULL"); |
1559 } else { | 1661 } else { |
1560 const String& super_name = String::Handle(super_type.Name()); | 1662 const String& super_name = String::Handle(super_type.Name()); |
1561 OS::Print(" Super: %s", super_name.ToCString()); | 1663 OS::Print(" Super: %s", super_name.ToCString()); |
1562 } | 1664 } |
1563 const Array& interfaces_array = Array::Handle(cls.interfaces()); | 1665 const Array& interfaces_array = Array::Handle(cls.interfaces()); |
1564 if (interfaces_array.Length() > 0) { | 1666 if (interfaces_array.Length() > 0) { |
1565 OS::Print("; interfaces: "); | 1667 OS::Print("; interfaces: "); |
1566 AbstractType& interface = AbstractType::Handle(); | 1668 AbstractType& interface = AbstractType::Handle(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1605 script, type.token_pos(), "Error", format, args); | 1707 script, type.token_pos(), "Error", format, args); |
1606 } else { | 1708 } else { |
1607 error ^= Parser::FormatErrorWithAppend( | 1709 error ^= Parser::FormatErrorWithAppend( |
1608 prev_error, script, type.token_pos(), "Error", format, args); | 1710 prev_error, script, type.token_pos(), "Error", format, args); |
1609 } | 1711 } |
1610 if ((finalization == kCanonicalizeWellFormed) || | 1712 if ((finalization == kCanonicalizeWellFormed) || |
1611 FLAG_error_on_malformed_type) { | 1713 FLAG_error_on_malformed_type) { |
1612 ReportError(error); | 1714 ReportError(error); |
1613 } | 1715 } |
1614 } | 1716 } |
| 1717 // In checked mode, always mark the type as malformed. |
| 1718 // In production mode, mark the type as malformed only if its type class is |
| 1719 // not resolved. |
| 1720 // In both mode, make the type raw, since it may not be possible to |
| 1721 // properly finalize its type arguments. |
1615 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { | 1722 if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { |
1616 // In check mode, always mark the type as malformed. | |
1617 // In production mode, mark the type as malformed only if its type class is | |
1618 // not resolved. | |
1619 type.set_malformed_error(error); | 1723 type.set_malformed_error(error); |
1620 if (!type.HasResolvedTypeClass()) { | |
1621 // We do not want an unresolved class to end up in a snapshot. | |
1622 type.set_type_class(Object::Handle(Object::null_class())); | |
1623 } | |
1624 } else { | |
1625 // In production mode, do not mark the type with a resolved type class as | |
1626 // malformed, but make it raw. | |
1627 type.set_arguments(AbstractTypeArguments::Handle()); | |
1628 } | 1724 } |
1629 ASSERT(type.HasResolvedTypeClass()); | 1725 type.set_arguments(AbstractTypeArguments::Handle()); |
1630 if (!type.IsFinalized()) { | 1726 if (!type.IsFinalized()) { |
1631 type.SetIsFinalized(); | 1727 type.SetIsFinalized(); |
1632 // Do not canonicalize malformed types, since they may not be resolved. | 1728 // Do not canonicalize malformed types, since they may not be resolved. |
1633 } else { | 1729 } else { |
1634 // The only case where the malformed type was already finalized is when its | 1730 // The only case where the malformed type was already finalized is when its |
1635 // type arguments are not within bounds. In that case, we have a prev_error. | 1731 // type arguments are not within bounds. In that case, we have a prev_error. |
1636 ASSERT(!prev_error.IsNull()); | 1732 ASSERT(!prev_error.IsNull()); |
1637 } | 1733 } |
1638 } | 1734 } |
1639 | 1735 |
1640 | 1736 |
1641 RawType* ClassFinalizer::NewFinalizedMalformedType( | 1737 RawType* ClassFinalizer::NewFinalizedMalformedType( |
1642 const Error& prev_error, | 1738 const Error& prev_error, |
1643 const Class& cls, | 1739 const Class& cls, |
1644 intptr_t type_pos, | 1740 intptr_t type_pos, |
1645 FinalizationKind finalization, | 1741 FinalizationKind finalization, |
1646 const char* format, ...) { | 1742 const char* format, ...) { |
1647 va_list args; | 1743 va_list args; |
1648 va_start(args, format); | 1744 va_start(args, format); |
1649 const UnresolvedClass& unresolved_class = UnresolvedClass::Handle( | 1745 const UnresolvedClass& unresolved_class = UnresolvedClass::Handle( |
1650 UnresolvedClass::New(LibraryPrefix::Handle(), | 1746 UnresolvedClass::New(LibraryPrefix::Handle(), |
1651 Symbols::Empty(), | 1747 Symbols::Empty(), |
1652 type_pos)); | 1748 type_pos)); |
1653 const Type& type = Type::Handle( | 1749 const Type& type = Type::Handle( |
1654 Type::New(unresolved_class, TypeArguments::Handle(), type_pos)); | 1750 Type::New(unresolved_class, TypeArguments::Handle(), type_pos)); |
1655 ReportMalformedType(prev_error, cls, type, finalization, format, args); | 1751 ReportMalformedType(prev_error, cls, type, finalization, format, args); |
1656 va_end(args); | 1752 va_end(args); |
1657 ASSERT(type.IsMalformed()); | 1753 ASSERT(type.IsMalformed()); |
| 1754 ASSERT(type.IsFinalized()); |
1658 return type.raw(); | 1755 return type.raw(); |
1659 } | 1756 } |
1660 | 1757 |
1661 | 1758 |
1662 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, | 1759 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, |
1663 const Class& cls, | 1760 const Class& cls, |
1664 const Type& type, | 1761 const Type& type, |
1665 FinalizationKind finalization, | 1762 FinalizationKind finalization, |
1666 const char* format, ...) { | 1763 const char* format, ...) { |
1667 va_list args; | 1764 va_list args; |
(...skipping 24 matching lines...) Expand all Loading... |
1692 void ClassFinalizer::ReportError(const char* format, ...) { | 1789 void ClassFinalizer::ReportError(const char* format, ...) { |
1693 va_list args; | 1790 va_list args; |
1694 va_start(args, format); | 1791 va_start(args, format); |
1695 const Error& error = Error::Handle( | 1792 const Error& error = Error::Handle( |
1696 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1793 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
1697 va_end(args); | 1794 va_end(args); |
1698 ReportError(error); | 1795 ReportError(error); |
1699 } | 1796 } |
1700 | 1797 |
1701 } // namespace dart | 1798 } // namespace dart |
OLD | NEW |