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 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 // production mode and checked mode, because the finalized type may be written | 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 | 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 | 622 // snapshot in production mode and then use the unchecked type in checked mode |
623 // after reading it from the snapshot. | 623 // after reading it from the snapshot. |
624 // However, we do not immediately report a bound error, which would be wrong | 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. | 625 // in production mode, but simply postpone the bound checking to runtime. |
626 const intptr_t num_type_params = cls.NumTypeParameters(); | 626 const intptr_t num_type_params = cls.NumTypeParameters(); |
627 const intptr_t offset = cls.NumTypeArguments() - num_type_params; | 627 const intptr_t offset = cls.NumTypeArguments() - num_type_params; |
628 AbstractType& type_arg = AbstractType::Handle(); | 628 AbstractType& type_arg = AbstractType::Handle(); |
629 AbstractType& cls_type_param = AbstractType::Handle(); | 629 AbstractType& cls_type_param = AbstractType::Handle(); |
630 AbstractType& bound = AbstractType::Handle(); | 630 AbstractType& declared_bound = AbstractType::Handle(); |
| 631 AbstractType& instantiated_bound = AbstractType::Handle(); |
631 const TypeArguments& cls_type_params = | 632 const TypeArguments& cls_type_params = |
632 TypeArguments::Handle(cls.type_parameters()); | 633 TypeArguments::Handle(cls.type_parameters()); |
633 ASSERT((cls_type_params.IsNull() && (num_type_params == 0)) || | 634 ASSERT((cls_type_params.IsNull() && (num_type_params == 0)) || |
634 (cls_type_params.Length() == num_type_params)); | 635 (cls_type_params.Length() == num_type_params)); |
635 for (intptr_t i = 0; i < num_type_params; i++) { | 636 for (intptr_t i = 0; i < num_type_params; i++) { |
636 type_arg = arguments.TypeAt(offset + i); | 637 type_arg = arguments.TypeAt(offset + i); |
637 if (type_arg.IsDynamicType()) { | 638 if (type_arg.IsDynamicType()) { |
638 continue; | 639 continue; |
639 } | 640 } |
640 cls_type_param = cls_type_params.TypeAt(i); | 641 cls_type_param = cls_type_params.TypeAt(i); |
641 const TypeParameter& type_param = TypeParameter::Cast(cls_type_param); | 642 const TypeParameter& type_param = TypeParameter::Cast(cls_type_param); |
642 ASSERT(type_param.IsFinalized()); | 643 ASSERT(type_param.IsFinalized()); |
643 bound = type_param.bound(); | 644 declared_bound = type_param.bound(); |
644 if (!bound.IsObjectType() && !bound.IsDynamicType()) { | 645 if (!declared_bound.IsObjectType() && !declared_bound.IsDynamicType()) { |
645 Error& malformed_error = Error::Handle(); | 646 Error& malformed_error = Error::Handle(); |
646 // Note that the bound may be malformed, in which case the bound check | 647 // 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 // 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 // Note also that the bound may still be unfinalized. |
649 if (!bound.IsFinalized()) { | 650 if (!declared_bound.IsFinalized()) { |
650 ASSERT(bound.IsBeingFinalized()); | 651 ASSERT(declared_bound.IsBeingFinalized()); |
651 // The bound refers to type parameters, creating a cycle; postpone | 652 // The bound refers to type parameters, creating a cycle; postpone |
652 // bound check to run time, when the bound will be finalized. | 653 // bound check to run time, when the bound will be finalized. |
653 // TODO(regis): Do we need to instantiate an uninstantiated bound here? | 654 // TODO(regis): Do we need to instantiate an uninstantiated bound here? |
654 type_arg = BoundedType::New(type_arg, bound, type_param); | 655 type_arg = BoundedType::New(type_arg, declared_bound, type_param); |
655 arguments.SetTypeAt(offset + i, type_arg); | 656 arguments.SetTypeAt(offset + i, type_arg); |
656 continue; | 657 continue; |
657 } | 658 } |
658 if (!bound.IsInstantiated()) { | 659 if (declared_bound.IsInstantiated()) { |
659 bound = bound.InstantiateFrom(arguments, &malformed_error); | 660 instantiated_bound = declared_bound.raw(); |
| 661 } else { |
| 662 instantiated_bound = |
| 663 declared_bound.InstantiateFrom(arguments, &malformed_error); |
660 } | 664 } |
661 // TODO(regis): We could simplify this code if we could differentiate | 665 // 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 | 666 // between a failed bound check and a bound check that is undecidable at |
663 // compile time. | 667 // compile time. |
664 if (malformed_error.IsNull()) { | 668 // Shortcut the special case where we check a type parameter against its |
665 type_param.CheckBound(type_arg, bound, &malformed_error); | 669 // declared upper bound. |
| 670 if (malformed_error.IsNull() && |
| 671 (!type_arg.Equals(type_param) || |
| 672 !instantiated_bound.Equals(declared_bound))) { |
| 673 type_param.CheckBound(type_arg, instantiated_bound, &malformed_error); |
666 } | 674 } |
667 if (!malformed_error.IsNull()) { | 675 if (!malformed_error.IsNull()) { |
668 if (!type_arg.IsInstantiated() || !bound.IsInstantiated()) { | 676 if (!type_arg.IsInstantiated() || |
669 type_arg = BoundedType::New(type_arg, bound, type_param); | 677 !instantiated_bound.IsInstantiated()) { |
| 678 type_arg = BoundedType::New(type_arg, instantiated_bound, type_param); |
670 arguments.SetTypeAt(offset + i, type_arg); | 679 arguments.SetTypeAt(offset + i, type_arg); |
671 } else if (bound_error->IsNull()) { | 680 } else if (bound_error->IsNull()) { |
672 *bound_error = malformed_error.raw(); | 681 *bound_error = malformed_error.raw(); |
673 } | 682 } |
674 } | 683 } |
675 } | 684 } |
676 } | 685 } |
677 AbstractType& super_type = AbstractType::Handle(cls.super_type()); | 686 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
678 if (!super_type.IsNull()) { | 687 if (!super_type.IsNull()) { |
679 const Class& super_class = Class::Handle(super_type.type_class()); | 688 const Class& super_class = Class::Handle(super_type.type_class()); |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1014 const intptr_t num_type_params = cls.NumTypeParameters(); | 1023 const intptr_t num_type_params = cls.NumTypeParameters(); |
1015 TypeParameter& type_param = TypeParameter::Handle(); | 1024 TypeParameter& type_param = TypeParameter::Handle(); |
1016 AbstractType& bound = AbstractType::Handle(); | 1025 AbstractType& bound = AbstractType::Handle(); |
1017 const AbstractTypeArguments& type_params = | 1026 const AbstractTypeArguments& type_params = |
1018 AbstractTypeArguments::Handle(cls.type_parameters()); | 1027 AbstractTypeArguments::Handle(cls.type_parameters()); |
1019 ASSERT((type_params.IsNull() && (num_type_params == 0)) || | 1028 ASSERT((type_params.IsNull() && (num_type_params == 0)) || |
1020 (type_params.Length() == num_type_params)); | 1029 (type_params.Length() == num_type_params)); |
1021 for (intptr_t i = 0; i < num_type_params; i++) { | 1030 for (intptr_t i = 0; i < num_type_params; i++) { |
1022 type_param ^= type_params.TypeAt(i); | 1031 type_param ^= type_params.TypeAt(i); |
1023 bound = type_param.bound(); | 1032 bound = type_param.bound(); |
1024 if (bound.IsFinalized()) { | 1033 if (bound.IsFinalized() || bound.IsBeingFinalized()) { |
| 1034 // A bound involved in F-bounded quantification may form a cycle. |
1025 continue; | 1035 continue; |
1026 } | 1036 } |
1027 ResolveType(cls, bound, kCanonicalize); | 1037 ResolveType(cls, bound, kCanonicalize); |
1028 bound = FinalizeType(cls, bound, kCanonicalize); | 1038 bound = FinalizeType(cls, bound, kCanonicalize); |
1029 type_param.set_bound(bound); | 1039 type_param.set_bound(bound); |
1030 } | 1040 } |
1031 } | 1041 } |
1032 | 1042 |
1033 | 1043 |
1034 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { | 1044 void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) { |
(...skipping 950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1985 void ClassFinalizer::ReportError(const char* format, ...) { | 1995 void ClassFinalizer::ReportError(const char* format, ...) { |
1986 va_list args; | 1996 va_list args; |
1987 va_start(args, format); | 1997 va_start(args, format); |
1988 const Error& error = Error::Handle( | 1998 const Error& error = Error::Handle( |
1989 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); | 1999 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); |
1990 va_end(args); | 2000 va_end(args); |
1991 ReportError(error); | 2001 ReportError(error); |
1992 } | 2002 } |
1993 | 2003 |
1994 } // namespace dart | 2004 } // namespace dart |
OLD | NEW |