Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(732)

Side by Side Diff: runtime/vm/object.cc

Issue 66033006: Check type bounds of redirecting factories (issue 14699). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 4825 matching lines...) Expand 10 before | Expand all | Expand 10 after
4836 const char* Function::ToFullyQualifiedCString() const { 4836 const char* Function::ToFullyQualifiedCString() const {
4837 char* chars = NULL; 4837 char* chars = NULL;
4838 ConstructFunctionFullyQualifiedCString(*this, &chars, 0); 4838 ConstructFunctionFullyQualifiedCString(*this, &chars, 0);
4839 return chars; 4839 return chars;
4840 } 4840 }
4841 4841
4842 4842
4843 bool Function::HasCompatibleParametersWith(const Function& other, 4843 bool Function::HasCompatibleParametersWith(const Function& other,
4844 Error* bound_error) const { 4844 Error* bound_error) const {
4845 ASSERT(FLAG_error_on_bad_override); 4845 ASSERT(FLAG_error_on_bad_override);
4846 ASSERT((bound_error != NULL) && bound_error->IsNull());
4846 // Check that this function's signature type is a subtype of the other 4847 // Check that this function's signature type is a subtype of the other
4847 // function's signature type. 4848 // function's signature type.
4848 if (!TypeTest(kIsSubtypeOf, Object::null_abstract_type_arguments(), 4849 if (!TypeTest(kIsSubtypeOf, Object::null_abstract_type_arguments(),
4849 other, Object::null_abstract_type_arguments(), bound_error)) { 4850 other, Object::null_abstract_type_arguments(), bound_error)) {
4850 // For more informative error reporting, use the location of the other 4851 // For more informative error reporting, use the location of the other
4851 // function here, since the caller will use the location of this function. 4852 // function here, since the caller will use the location of this function.
4852 *bound_error = FormatError( 4853 *bound_error = FormatError(
4853 *bound_error, // A bound error if non null. 4854 *bound_error, // A bound error if non null.
4854 Script::Handle(other.script()), 4855 Script::Handle(other.script()),
4855 other.token_pos(), 4856 other.token_pos(),
(...skipping 6444 matching lines...) Expand 10 before | Expand all | Expand 10 after
11300 11301
11301 RawAbstractType* AbstractType::Canonicalize() const { 11302 RawAbstractType* AbstractType::Canonicalize() const {
11302 // AbstractType is an abstract class. 11303 // AbstractType is an abstract class.
11303 UNREACHABLE(); 11304 UNREACHABLE();
11304 return NULL; 11305 return NULL;
11305 } 11306 }
11306 11307
11307 11308
11308 RawString* AbstractType::BuildName(NameVisibility name_visibility) const { 11309 RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
11309 if (IsBoundedType()) { 11310 if (IsBoundedType()) {
11310 // TODO(regis): Should the bound be visible in the name for debug purposes
11311 // if name_visibility is kInternalName?
11312 const AbstractType& type = AbstractType::Handle( 11311 const AbstractType& type = AbstractType::Handle(
11313 BoundedType::Cast(*this).type()); 11312 BoundedType::Cast(*this).type());
11314 return type.BuildName(name_visibility); 11313 if (name_visibility == kUserVisibleName) {
11314 return type.BuildName(kUserVisibleName);
11315 }
11316 String& type_name = String::Handle(type.BuildName(kInternalName));
11317 type_name = String::Concat(type_name, Symbols::SpaceExtendsSpace());
11318 // Building the bound name may lead into cycles.
11319 const AbstractType& bound = AbstractType::Handle(
11320 BoundedType::Cast(*this).bound());
11321 String& bound_name = String::Handle();
11322 if (bound.IsTypeParameter()) {
11323 bound_name = TypeParameter::Cast(bound).name();
11324 } else if (bound.IsType()) {
11325 const Class& cls = Class::Handle(Type::Cast(bound).type_class());
11326 bound_name = cls.Name();
11327 if (Type::Cast(bound).arguments() != AbstractTypeArguments::null()) {
11328 bound_name = String::Concat(bound_name, Symbols::OptimizedOut());
11329 }
11330 } else {
11331 bound_name = String::New(Symbols::OptimizedOut());
11332 }
11333 type_name = String::Concat(type_name, bound_name);
11334 return Symbols::New(type_name);
11315 } 11335 }
11316 if (IsTypeParameter()) { 11336 if (IsTypeParameter()) {
11317 return TypeParameter::Cast(*this).name(); 11337 return TypeParameter::Cast(*this).name();
11318 } 11338 }
11319 // If the type is still being finalized, we may be reporting an error about 11339 // If the type is still being finalized, we may be reporting an error about
11320 // a malformed type, so proceed with caution. 11340 // a malformed type, so proceed with caution.
11321 const AbstractTypeArguments& args = 11341 const AbstractTypeArguments& args =
11322 AbstractTypeArguments::Handle(arguments()); 11342 AbstractTypeArguments::Handle(arguments());
11323 const intptr_t num_args = args.IsNull() ? 0 : args.Length(); 11343 const intptr_t num_args = args.IsNull() ? 0 : args.Length();
11324 String& class_name = String::Handle(); 11344 String& class_name = String::Handle();
(...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after
12063 } 12083 }
12064 12084
12065 12085
12066 RawAbstractType* TypeParameter::InstantiateFrom( 12086 RawAbstractType* TypeParameter::InstantiateFrom(
12067 const AbstractTypeArguments& instantiator_type_arguments, 12087 const AbstractTypeArguments& instantiator_type_arguments,
12068 Error* bound_error) const { 12088 Error* bound_error) const {
12069 ASSERT(IsFinalized()); 12089 ASSERT(IsFinalized());
12070 if (instantiator_type_arguments.IsNull()) { 12090 if (instantiator_type_arguments.IsNull()) {
12071 return Type::DynamicType(); 12091 return Type::DynamicType();
12072 } 12092 }
12073 // Bound checks may appear in the instantiator type arguments, as is the case 12093 return instantiator_type_arguments.TypeAt(index());
12074 // with a pair of type parameters of the same class referring to each other
12075 // via their bounds.
12076 AbstractType& type_arg = AbstractType::Handle(
12077 instantiator_type_arguments.TypeAt(index()));
12078 if (type_arg.IsBoundedType()) {
12079 const BoundedType& bounded_type = BoundedType::Cast(type_arg);
12080 // Bounds checking of a type is postponed to run time if the type is still
12081 // uninstantiated at compile time, or if the bound and the type are mutually
12082 // recursive. In the latter case, the type may already be instantiated.
12083 if (!bounded_type.IsInstantiated()) {
12084 ASSERT(AbstractType::Handle(bounded_type.bound()).IsInstantiated());
12085 type_arg = bounded_type.InstantiateFrom(AbstractTypeArguments::Handle(),
12086 bound_error);
12087 }
12088 }
12089 return type_arg.raw();
12090 } 12094 }
12091 12095
12092 12096
12093 bool TypeParameter::CheckBound(const AbstractType& bounded_type, 12097 bool TypeParameter::CheckBound(const AbstractType& bounded_type,
12094 const AbstractType& upper_bound, 12098 const AbstractType& upper_bound,
12095 Error* bound_error) const { 12099 Error* bound_error) const {
12096 ASSERT((bound_error == NULL) || bound_error->IsNull()); 12100 ASSERT((bound_error != NULL) && bound_error->IsNull());
12097 ASSERT(bounded_type.IsFinalized()); 12101 ASSERT(bounded_type.IsFinalized());
12098 ASSERT(upper_bound.IsFinalized()); 12102 ASSERT(upper_bound.IsFinalized());
12099 ASSERT(!bounded_type.IsMalformed()); 12103 ASSERT(!bounded_type.IsMalformed());
12100 if (bounded_type.IsSubtypeOf(upper_bound, bound_error)) { 12104 if (bounded_type.IsSubtypeOf(upper_bound, bound_error)) {
12101 return true; 12105 return true;
12102 } 12106 }
12103 if ((bound_error != NULL) && bound_error->IsNull()) { 12107 if (bound_error->IsNull()) {
12104 // Report the bound error. 12108 // Report the bound error only if both the bounded type and the upper bound
12105 const String& bounded_type_name = String::Handle( 12109 // are instantiated. Otherwise, we cannot tell yet it is a bound error.
12106 bounded_type.UserVisibleName()); 12110 if (bounded_type.IsInstantiated() && upper_bound.IsInstantiated()) {
12107 const String& upper_bound_name = String::Handle( 12111 const String& bounded_type_name = String::Handle(
12108 upper_bound.UserVisibleName()); 12112 bounded_type.UserVisibleName());
12109 const AbstractType& declared_bound = AbstractType::Handle(bound()); 12113 const String& upper_bound_name = String::Handle(
12110 const String& declared_bound_name = String::Handle( 12114 upper_bound.UserVisibleName());
12111 declared_bound.UserVisibleName()); 12115 const AbstractType& declared_bound = AbstractType::Handle(bound());
12112 const String& type_param_name = String::Handle(UserVisibleName()); 12116 const String& declared_bound_name = String::Handle(
12113 const Class& cls = Class::Handle(parameterized_class()); 12117 declared_bound.UserVisibleName());
12114 const String& class_name = String::Handle(cls.Name()); 12118 const String& type_param_name = String::Handle(UserVisibleName());
12115 const Script& script = Script::Handle(cls.script()); 12119 const Class& cls = Class::Handle(parameterized_class());
12116 // Since the bound may have been canonicalized, its token index is 12120 const String& class_name = String::Handle(cls.Name());
12117 // meaningless, therefore use the token index of this type parameter. 12121 const Script& script = Script::Handle(cls.script());
12118 *bound_error = FormatError( 12122 // Since the bound may have been canonicalized, its token index is
12119 *bound_error, 12123 // meaningless, therefore use the token index of this type parameter.
12120 script, 12124 *bound_error = FormatError(
12121 token_pos(), 12125 *bound_error,
12122 "type parameter '%s' of class '%s' must extend bound '%s', " 12126 script,
12123 "but type argument '%s' is not a subtype of '%s'\n", 12127 token_pos(),
12124 type_param_name.ToCString(), 12128 "type parameter '%s' of class '%s' must extend bound '%s', "
12125 class_name.ToCString(), 12129 "but type argument '%s' is not a subtype of '%s'\n",
12126 declared_bound_name.ToCString(), 12130 type_param_name.ToCString(),
12127 bounded_type_name.ToCString(), 12131 class_name.ToCString(),
12128 upper_bound_name.ToCString()); 12132 declared_bound_name.ToCString(),
12133 bounded_type_name.ToCString(),
12134 upper_bound_name.ToCString());
12135 }
12129 } 12136 }
12130 return false; 12137 return false;
12131 } 12138 }
12132 12139
12133 12140
12134 RawAbstractType* TypeParameter::CloneUnfinalized() const { 12141 RawAbstractType* TypeParameter::CloneUnfinalized() const {
12135 if (IsFinalized()) { 12142 if (IsFinalized()) {
12136 return raw(); 12143 return raw();
12137 } 12144 }
12138 // No need to clone bound, as it is not part of the finalization state. 12145 // No need to clone bound, as it is not part of the finalization state.
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
12211 JSONObject jsobj(stream); 12218 JSONObject jsobj(stream);
12212 } 12219 }
12213 12220
12214 12221
12215 bool BoundedType::IsMalformed() const { 12222 bool BoundedType::IsMalformed() const {
12216 return AbstractType::Handle(type()).IsMalformed(); 12223 return AbstractType::Handle(type()).IsMalformed();
12217 } 12224 }
12218 12225
12219 12226
12220 bool BoundedType::IsMalboundedWithError(Error* bound_error) const { 12227 bool BoundedType::IsMalboundedWithError(Error* bound_error) const {
12221 if (!FLAG_enable_type_checks && !FLAG_error_on_bad_type) { 12228 if (FLAG_enable_type_checks || FLAG_error_on_bad_type) {
12222 return false; 12229 const AbstractType& upper_bound = AbstractType::Handle(bound());
12230 if (upper_bound.IsMalformed()) {
12231 if (bound_error != NULL) {
12232 *bound_error = upper_bound.malformed_error();
12233 ASSERT(!bound_error->IsNull());
12234 }
12235 return true;
12236 }
12223 } 12237 }
12224 const AbstractType& upper_bound = AbstractType::Handle(bound()); 12238 return AbstractType::Handle(type()).IsMalboundedWithError(bound_error);
12225 if (upper_bound.IsMalformed()) {
12226 if (bound_error != NULL) {
12227 *bound_error = upper_bound.malformed_error();
12228 ASSERT(!bound_error->IsNull());
12229 }
12230 return true;
12231 }
12232 return false;
12233 } 12239 }
12234 12240
12235 12241
12236 RawError* BoundedType::malformed_error() const { 12242 RawError* BoundedType::malformed_error() const {
12237 return AbstractType::Handle(type()).malformed_error(); 12243 return AbstractType::Handle(type()).malformed_error();
12238 } 12244 }
12239 12245
12240 12246
12241 bool BoundedType::Equals(const Instance& other) const { 12247 bool BoundedType::Equals(const Instance& other) const {
12242 // BoundedType are not canonicalized, because their bound may get finalized 12248 // BoundedType are not canonicalized, because their bound may get finalized
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
12308 // Avoid endless recursion while checking and instantiating bound. 12314 // Avoid endless recursion while checking and instantiating bound.
12309 set_is_being_checked(true); 12315 set_is_being_checked(true);
12310 AbstractType& upper_bound = AbstractType::Handle(bound()); 12316 AbstractType& upper_bound = AbstractType::Handle(bound());
12311 ASSERT(!upper_bound.IsObjectType() && !upper_bound.IsDynamicType()); 12317 ASSERT(!upper_bound.IsObjectType() && !upper_bound.IsDynamicType());
12312 const TypeParameter& type_param = TypeParameter::Handle(type_parameter()); 12318 const TypeParameter& type_param = TypeParameter::Handle(type_parameter());
12313 if (!upper_bound.IsInstantiated()) { 12319 if (!upper_bound.IsInstantiated()) {
12314 upper_bound = upper_bound.InstantiateFrom(instantiator_type_arguments, 12320 upper_bound = upper_bound.InstantiateFrom(instantiator_type_arguments,
12315 bound_error); 12321 bound_error);
12316 } 12322 }
12317 if (bound_error->IsNull()) { 12323 if (bound_error->IsNull()) {
12318 type_param.CheckBound(bounded_type, upper_bound, bound_error); 12324 if (!type_param.CheckBound(bounded_type, upper_bound, bound_error) &&
12325 bound_error->IsNull()) {
12326 // We cannot determine yet whether the bounded_type is below the
12327 // upper_bound, because one or both of them is still uninstantiated.
12328 ASSERT(!bounded_type.IsInstantiated() || !upper_bound.IsInstantiated());
12329 // Postpone bound check by returning a new BoundedType with partially
12330 // instantiated bounded_type and upper_bound, but keeping type_param.
12331 bounded_type = BoundedType::New(bounded_type, upper_bound, type_param);
12332 }
12319 } 12333 }
12320 set_is_being_checked(false); 12334 set_is_being_checked(false);
12321 } 12335 }
12322 return bounded_type.raw(); 12336 return bounded_type.raw();
12323 } 12337 }
12324 12338
12325 12339
12326 RawAbstractType* BoundedType::CloneUnfinalized() const { 12340 RawAbstractType* BoundedType::CloneUnfinalized() const {
12327 if (IsFinalized()) { 12341 if (IsFinalized()) {
12328 return raw(); 12342 return raw();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
12366 const BoundedType& result = BoundedType::Handle(BoundedType::New()); 12380 const BoundedType& result = BoundedType::Handle(BoundedType::New());
12367 result.set_type(type); 12381 result.set_type(type);
12368 result.set_bound(bound); 12382 result.set_bound(bound);
12369 result.set_type_parameter(type_parameter); 12383 result.set_type_parameter(type_parameter);
12370 result.set_is_being_checked(false); 12384 result.set_is_being_checked(false);
12371 return result.raw(); 12385 return result.raw();
12372 } 12386 }
12373 12387
12374 12388
12375 const char* BoundedType::ToCString() const { 12389 const char* BoundedType::ToCString() const {
12376 const char* format = "BoundedType: type %s; bound: %s; class: %s"; 12390 const char* format = "BoundedType: type %s; bound: %s; type param: %s of %s";
12377 const char* type_cstr = String::Handle(AbstractType::Handle( 12391 const char* type_cstr = String::Handle(AbstractType::Handle(
12378 type()).Name()).ToCString(); 12392 type()).Name()).ToCString();
12379 const char* bound_cstr = String::Handle(AbstractType::Handle( 12393 const char* bound_cstr = String::Handle(AbstractType::Handle(
12380 bound()).Name()).ToCString(); 12394 bound()).Name()).ToCString();
12395 const char* type_param_cstr = String::Handle(TypeParameter::Handle(
12396 type_parameter()).name()).ToCString();
12381 const Class& cls = Class::Handle(TypeParameter::Handle( 12397 const Class& cls = Class::Handle(TypeParameter::Handle(
12382 type_parameter()).parameterized_class()); 12398 type_parameter()).parameterized_class());
12383 const char* cls_cstr = 12399 const char* cls_cstr =
12384 cls.IsNull() ? " null" : String::Handle(cls.Name()).ToCString(); 12400 cls.IsNull() ? " null" : String::Handle(cls.Name()).ToCString();
12385 intptr_t len = OS::SNPrint( 12401 intptr_t len = OS::SNPrint(
12386 NULL, 0, format, type_cstr, bound_cstr, cls_cstr) + 1; 12402 NULL, 0, format, type_cstr, bound_cstr, type_param_cstr, cls_cstr) + 1;
12387 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 12403 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
12388 OS::SNPrint(chars, len, format, type_cstr, bound_cstr, cls_cstr); 12404 OS::SNPrint(
12405 chars, len, format, type_cstr, bound_cstr, type_param_cstr, cls_cstr);
12389 return chars; 12406 return chars;
12390 } 12407 }
12391 12408
12392 12409
12393 void BoundedType::PrintToJSONStream(JSONStream* stream, bool ref) const { 12410 void BoundedType::PrintToJSONStream(JSONStream* stream, bool ref) const {
12394 JSONObject jsobj(stream); 12411 JSONObject jsobj(stream);
12395 } 12412 }
12396 12413
12397 12414
12398 intptr_t MixinAppType::token_pos() const { 12415 intptr_t MixinAppType::token_pos() const {
(...skipping 3348 matching lines...) Expand 10 before | Expand all | Expand 10 after
15747 return "_MirrorReference"; 15764 return "_MirrorReference";
15748 } 15765 }
15749 15766
15750 15767
15751 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { 15768 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const {
15752 JSONObject jsobj(stream); 15769 JSONObject jsobj(stream);
15753 } 15770 }
15754 15771
15755 15772
15756 } // namespace dart 15773 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698