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

Unified Diff: runtime/vm/object.cc

Issue 22685007: Implement updated method overriding rules in the vm. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 4 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/object_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
===================================================================
--- runtime/vm/object.cc (revision 26025)
+++ runtime/vm/object.cc (working copy)
@@ -58,6 +58,7 @@
DECLARE_FLAG(bool, trace_compiler);
DECLARE_FLAG(bool, eliminate_type_checks);
DECLARE_FLAG(bool, enable_type_checks);
+DECLARE_FLAG(bool, error_on_bad_override);
static const char* kGetterPrefix = "get:";
static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix);
@@ -1925,17 +1926,24 @@
}
-static const char* FormatPatchError(const char* format, const Object& obj) {
- const char* msg = obj.ToCString();
- intptr_t len = OS::SNPrint(NULL, 0, format, msg) + 1;
- char* result = Isolate::Current()->current_zone()->Alloc<char>(len);
- OS::SNPrint(result, len, format, msg);
- return result;
+static RawError* FormatError(const Error& prev_error,
+ const Script& script,
+ intptr_t token_pos,
+ const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ if (prev_error.IsNull()) {
+ return Parser::FormatError(script, token_pos, "Error", format, args);
+ } else {
+ return Parser::FormatErrorWithAppend(prev_error, script, token_pos,
+ "Error", format, args);
+ }
}
// Apply the members from the patch class to the original class.
-const char* Class::ApplyPatch(const Class& patch) const {
+bool Class::ApplyPatch(const Class& patch, Error* error) const {
+ ASSERT(error != NULL);
ASSERT(!is_finalized());
// Shared handles used during the iteration.
String& member_name = String::Handle();
@@ -1975,11 +1983,14 @@
if (orig_func.raw() != orig_implicit_ctor.raw()) {
new_functions.Add(orig_func);
}
- } else if (!func.HasCompatibleParametersWith(orig_func) &&
- !(func.IsFactory() && orig_func.IsConstructor() &&
- (func.num_fixed_parameters() + 1 ==
- orig_func.num_fixed_parameters()))) {
- return FormatPatchError("mismatched parameters: %s", member_name);
+ } else if (func.UserVisibleSignature() !=
+ orig_func.UserVisibleSignature()) {
+ // Compare user visible signatures to ignore different implicit parameters
+ // when patching a constructor with a factory.
+ *error = FormatError(*error, // No previous error.
+ Script::Handle(patch.script()), func.token_pos(),
+ "signature mismatch: '%s'", member_name.ToCString());
+ return false;
}
}
for (intptr_t i = 0; i < patch_len; i++) {
@@ -2017,7 +2028,10 @@
// Verify no duplicate additions.
orig_field ^= LookupField(member_name);
if (!orig_field.IsNull()) {
- return FormatPatchError("duplicate field: %s", member_name);
+ *error = FormatError(*error, // No previous error.
+ Script::Handle(patch.script()), field.token_pos(),
+ "duplicate field: %s", member_name.ToCString());
+ return false;
}
new_list.SetAt(i, field);
}
@@ -2030,7 +2044,7 @@
// The functions and fields in the patch class are no longer needed.
patch.SetFunctions(Object::empty_array());
patch.SetFields(Object::empty_array());
- return NULL;
+ return true;
}
@@ -3138,21 +3152,6 @@
}
-static RawError* FormatError(const Error& prev_error,
- const Script& script,
- intptr_t token_pos,
- const char* format, ...) {
- va_list args;
- va_start(args, format);
- if (prev_error.IsNull()) {
- return Parser::FormatError(script, token_pos, "Error", format, args);
- } else {
- return Parser::FormatErrorWithAppend(prev_error, script, token_pos,
- "Error", format, args);
- }
-}
-
-
bool AbstractTypeArguments::TypeTest(TypeTestKind test_kind,
const AbstractTypeArguments& other,
intptr_t len,
@@ -4372,24 +4371,33 @@
}
-bool Function::HasCompatibleParametersWith(const Function& other) const {
- const intptr_t num_fixed_params = num_fixed_parameters();
- const intptr_t num_opt_pos_params = NumOptionalPositionalParameters();
- const intptr_t other_num_fixed_params = other.num_fixed_parameters();
- const intptr_t other_num_opt_pos_params =
- other.NumOptionalPositionalParameters();
- // A generative constructor may be compared to a redirecting factory and be
- // compatible although it has an additional phase parameter.
- const intptr_t num_ignored_params =
- (other.IsRedirectingFactory() && IsConstructor()) ? 1 : 0;
- // The default values of optional parameters can differ.
- // This function requires the same arguments or less and accepts the same
- // arguments or more.
- if (((num_fixed_params - num_ignored_params) > other_num_fixed_params) ||
- ((num_fixed_params - num_ignored_params) + num_opt_pos_params <
- other_num_fixed_params + other_num_opt_pos_params)) {
+bool Function::HasCompatibleParametersWith(const Function& other,
+ Error* error) const {
+ ASSERT(FLAG_error_on_bad_override);
+ // Check that this function's signature type is a subtype of the other
+ // function's signature type.
+ if (!TypeTest(kIsSubtypeOf, Object::null_abstract_type_arguments(),
+ other, Object::null_abstract_type_arguments(), error)) {
+ // For more informative error reporting, use the location of the other
+ // function here, since the caller will use the location of this function.
+ *error = FormatError(
+ *error, // A malformed error if non null.
+ Script::Handle(other.script()),
+ other.token_pos(),
+ "signature type '%s' of function '%s' is not a subtype of signature "
+ "type '%s' of function '%s'",
+ String::Handle(UserVisibleSignature()).ToCString(),
+ String::Handle(UserVisibleName()).ToCString(),
+ String::Handle(other.UserVisibleSignature()).ToCString(),
+ String::Handle(other.UserVisibleName()).ToCString());
return false;
}
+ // We should also check that if the other function explicitly specifies a
+ // default value for a formal parameter, this function does not specify a
+ // different default value for the same parameter. However, this check is not
+ // possible in the current implementation, because the default parameter
+ // values are not stored in the Function object, but discarded after a
+ // function is compiled.
return true;
}
@@ -4459,9 +4467,16 @@
other.NumOptionalNamedParameters();
// This function requires the same arguments or less and accepts the same
// arguments or more.
- if ((num_fixed_params > other_num_fixed_params) ||
- (num_fixed_params + num_opt_pos_params <
- other_num_fixed_params + other_num_opt_pos_params) ||
+ // A generative constructor may be compared to a redirecting factory and be
+ // compatible although it has an additional phase parameter.
+ // More generally, we can ignore implicit parameters.
+ const intptr_t num_ignored_params = NumImplicitParameters();
+ const intptr_t other_num_ignored_params = other.NumImplicitParameters();
+ if (((num_fixed_params - num_ignored_params) >
+ (other_num_fixed_params - other_num_ignored_params)) ||
+ ((num_fixed_params - num_ignored_params + num_opt_pos_params) <
+ (other_num_fixed_params - other_num_ignored_params +
+ other_num_opt_pos_params)) ||
(num_opt_named_params < other_num_opt_named_params)) {
return false;
}
@@ -4494,10 +4509,11 @@
}
}
// Check the types of fixed and optional positional parameters.
- for (intptr_t i = 0;
- i < other_num_fixed_params + other_num_opt_pos_params; i++) {
+ for (intptr_t i = 0; i < (other_num_fixed_params - other_num_ignored_params +
+ other_num_opt_pos_params); i++) {
if (!TestParameterType(test_kind,
- i, i, type_arguments, other, other_type_arguments,
+ i + num_ignored_params, i + other_num_ignored_params,
+ type_arguments, other, other_type_arguments,
malformed_error)) {
return false;
}
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/object_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698