Make TypeError no longer implement AssertionError.

This means that TypeError no longer inherits a spurious `message` member.
The message of a platform-thrown TypeError is still available as `toString()`.

Fixes #40317

Bug: http://dartbug.com/40317
Change-Id: I77312859ebae3f92c2e56aeea6283b075b71c8d5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136129
Commit-Queue: Lasse R.H. Nielsen <lrn@google.com>
Reviewed-by: Erik Ernst <eernst@google.com>
This commit is contained in:
Lasse R.H. Nielsen 2020-02-21 14:02:57 +00:00 committed by commit-bot@chromium.org
parent a739002cfa
commit 98b4635aa9
13 changed files with 89 additions and 88 deletions

View file

@ -6,6 +6,14 @@
### Core libraries
#### `dart:core`
* The class `TypeError` no longer extends `AssertionError`.
This also means that it no longer inherits the spurious `message` getter
which was added to `AssertionError` when the second operand to `assert`
was allowed. The value of that getter on a `TypeError` was the same
string as returned by `toString`, so it is still available.
#### `dart:html`
* **Breaking Change**: Changed the return type of several html native methods

View file

@ -1,6 +1,6 @@
ERROR|COMPILE_TIME_ERROR|BODY_MAY_COMPLETE_NORMALLY|lib/_internal/js_runtime/lib/js_helper.dart|2688|17|17|The body might complete normally, which would cause 'null' to be returned, but the return type is a potentially non-nullable type.
ERROR|COMPILE_TIME_ERROR|BODY_MAY_COMPLETE_NORMALLY|lib/_internal/js_runtime/lib/js_helper.dart|3632|5|11|The body might complete normally, which would cause 'null' to be returned, but the return type is a potentially non-nullable type.
ERROR|COMPILE_TIME_ERROR|BODY_MAY_COMPLETE_NORMALLY|lib/_internal/js_runtime/lib/js_helper.dart|3660|5|6|The body might complete normally, which would cause 'null' to be returned, but the return type is a potentially non-nullable type.
ERROR|COMPILE_TIME_ERROR|BODY_MAY_COMPLETE_NORMALLY|lib/_internal/js_runtime/lib/js_helper.dart|3628|5|11|The body might complete normally, which would cause 'null' to be returned, but the return type is a potentially non-nullable type.
ERROR|COMPILE_TIME_ERROR|BODY_MAY_COMPLETE_NORMALLY|lib/_internal/js_runtime/lib/js_helper.dart|3656|5|6|The body might complete normally, which would cause 'null' to be returned, but the return type is a potentially non-nullable type.
ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1637|7|5|Superinterfaces don't have a valid override for '&': int.& (int Function(int)), JSNumber.& (num Function(num)).
ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1637|7|5|Superinterfaces don't have a valid override for '<<': int.<< (int Function(int)), JSNumber.<< (num Function(num)).
ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1637|7|5|Superinterfaces don't have a valid override for '>>': int.>> (int Function(int)), JSNumber.>> (num Function(num)).

View file

@ -704,25 +704,22 @@ class JSName {
*/
abstract class JavaScriptIndexingBehavior<E> {}
// TODO(lrn): These exceptions should be implemented in core.
// When they are, remove the 'Implementation' here.
/// Thrown by type assertions that fail.
class TypeErrorImpl extends Error implements TypeError {
final String message;
final String _message;
TypeErrorImpl(this.message);
TypeErrorImpl(this._message);
String toString() => message;
String toString() => _message;
}
/// Thrown by the 'as' operator if the cast isn't valid.
class CastErrorImpl extends Error implements CastError {
final String message;
final String _message;
CastErrorImpl(this.message);
CastErrorImpl(this._message);
String toString() => message;
String toString() => _message;
}
class FallThroughErrorImplementation extends FallThroughError {

View file

@ -3087,34 +3087,30 @@ void checkDeferredIsLoaded(String loadId) {
/// visible to anyone, and is only injected into special libraries.
abstract class JavaScriptIndexingBehavior<E> extends JSMutableIndexable<E> {}
// TODO(lrn): These exceptions should be implemented in core.
// When they are, remove the 'Implementation' here.
/// Thrown by type assertions that fail.
class TypeErrorImplementation extends Error implements TypeError {
final String message;
final String _message;
/// Normal type error caused by a failed subtype test.
TypeErrorImplementation(Object value, String type)
: message = "TypeError: ${Error.safeToString(value)}: type "
: _message = "TypeError: ${Error.safeToString(value)}: type "
"'${_typeDescription(value)}' is not a subtype of type '$type'";
TypeErrorImplementation.fromMessage(String this.message);
TypeErrorImplementation.fromMessage(String this._message);
String toString() => message;
String toString() => _message;
}
/// Thrown by the 'as' operator if the cast isn't valid.
class CastErrorImplementation extends Error implements CastError {
// TODO(lrn): Rename to CastError (and move implementation into core).
final String message;
final String _message;
/// Normal cast error caused by a failed type cast.
CastErrorImplementation(Object value, Object type)
: message = "CastError: ${Error.safeToString(value)}: type "
: _message = "CastError: ${Error.safeToString(value)}: type "
"'${_typeDescription(value)}' is not a subtype of type '$type'";
String toString() => message;
String toString() => _message;
}
String _typeDescription(value) {

View file

@ -82,15 +82,19 @@ class _AssertionError extends Error implements AssertionError {
final Object message;
}
class _TypeError extends _AssertionError implements TypeError {
class _TypeError extends Error implements TypeError {
@pragma("vm:entry-point")
_TypeError._create(String url, int line, int column, String errorMsg)
: super._create("is assignable", url, line, column, errorMsg);
_TypeError._create(this._url, this._line, this._column, this._message);
static _throwNew(int location, Object src_value, _Type dst_type,
String dst_name) native "TypeError_throwNew";
String toString() => super.message;
String toString() => _message;
final String _url;
final int _line;
final int _column;
final Object _message;
}
class _CastError extends Error implements CastError {

View file

@ -112,9 +112,9 @@ class AssertionError extends Error {
}
/**
* Error thrown by the runtime system when a type assertion fails.
* Error thrown by the runtime system when a dynamic type error happens.
*/
class TypeError extends AssertionError {}
class TypeError extends Error {}
/**
* Error thrown by the runtime system when a cast operation fails.

View file

@ -704,25 +704,22 @@ class JSName {
*/
abstract class JavaScriptIndexingBehavior<E> {}
// TODO(lrn): These exceptions should be implemented in core.
// When they are, remove the 'Implementation' here.
/// Thrown by type assertions that fail.
class TypeErrorImpl extends Error implements TypeError {
final String message;
final String _message;
TypeErrorImpl(this.message);
TypeErrorImpl(this._message);
String toString() => message;
String toString() => _message;
}
/// Thrown by the 'as' operator if the cast isn't valid.
class CastErrorImpl extends Error implements CastError {
final String message;
final String _message;
CastErrorImpl(this.message);
CastErrorImpl(this._message);
String toString() => message;
String toString() => _message;
}
class FallThroughErrorImplementation extends FallThroughError {

View file

@ -3086,34 +3086,30 @@ void checkDeferredIsLoaded(String loadId) {
/// visible to anyone, and is only injected into special libraries.
abstract class JavaScriptIndexingBehavior<E> extends JSMutableIndexable<E> {}
// TODO(lrn): These exceptions should be implemented in core.
// When they are, remove the 'Implementation' here.
/// Thrown by type assertions that fail.
class TypeErrorImplementation extends Error implements TypeError {
final String message;
final String _message;
/// Normal type error caused by a failed subtype test.
TypeErrorImplementation(Object value, String type)
: message = "TypeError: ${Error.safeToString(value)}: type "
: _message = "TypeError: ${Error.safeToString(value)}: type "
"'${_typeDescription(value)}' is not a subtype of type '$type'";
TypeErrorImplementation.fromMessage(String this.message);
TypeErrorImplementation.fromMessage(String this._message);
String toString() => message;
String toString() => _message;
}
/// Thrown by the 'as' operator if the cast isn't valid.
class CastErrorImplementation extends Error implements CastError {
// TODO(lrn): Rename to CastError (and move implementation into core).
final String message;
final String _message;
/// Normal cast error caused by a failed type cast.
CastErrorImplementation(Object value, Object type)
: message = "CastError: ${Error.safeToString(value)}: type "
: _message = "CastError: ${Error.safeToString(value)}: type "
"'${_typeDescription(value)}' is not a subtype of type '$type'";
String toString() => message;
String toString() => _message;
}
String _typeDescription(value) {

View file

@ -81,15 +81,19 @@ class _AssertionError extends Error implements AssertionError {
final Object? message;
}
class _TypeError extends _AssertionError implements TypeError {
class _TypeError extends Error implements TypeError {
@pragma("vm:entry-point")
_TypeError._create(String url, int line, int column, String errorMsg)
: super._create("is assignable", url, line, column, errorMsg);
_TypeError._create(this._url, this._line, this._column, this._message);
static _throwNew(int location, Object srcValue, _Type dstType, String dstName)
native "TypeError_throwNew";
String toString() => super.message as String;
String toString() => _message;
final String _url;
final int _line;
final int _column;
final String _message;
}
class _CastError extends Error implements CastError {

View file

@ -110,9 +110,9 @@ class AssertionError extends Error {
}
/**
* Error thrown by the runtime system when a type assertion fails.
* Error thrown by the runtime system when a dynamic type error happens.
*/
class TypeError extends AssertionError {}
class TypeError extends Error {}
/**
* Error thrown by the runtime system when a cast operation fails.

View file

@ -8,7 +8,7 @@
import "package:expect/expect.dart";
testTrue() {
int testTrue() {
int i = 0;
try {
assert(true);
@ -18,7 +18,7 @@ testTrue() {
return i;
}
testFalse() {
int testFalse() {
int i = 0;
try {
assert(false);
@ -32,7 +32,7 @@ unknown(dynamic a) {
return a ? true : false;
}
testBoolean(bool value) {
int testBoolean(bool value) {
int i = 0;
try {
assert(value);
@ -42,7 +42,7 @@ testBoolean(bool value) {
return i;
}
testDynamic(dynamic value) {
int testDynamic(dynamic value) {
int i = 0;
try {
assert(value);
@ -56,11 +56,10 @@ testMessage(value, message) {
try {
assert(value, message);
return null;
} catch (error) {
// Catch any type to allow the Boolean conversion to throw either
// AssertionError or TypeError.
} on AssertionError catch (error) {
return error;
}
return null;
}
main() {
@ -72,20 +71,20 @@ main() {
Expect.equals(1, testBoolean(false));
Expect.equals(1, testDynamic(unknown(false)));
Expect.equals(1, testDynamic(null));
Expect.equals(1, testDynamic(42));
Expect.equals(1, testDynamic(() => true));
Expect.equals(1, testDynamic(() => false));
Expect.equals(1, testDynamic(() => 42));
Expect.equals(1, testDynamic(() => null));
Expect.throwsTypeError(() => testDynamic(null));
Expect.throwsTypeError(() => testDynamic(42));
Expect.throwsTypeError(() => testDynamic(() => true));
Expect.throwsTypeError(() => testDynamic(() => false));
Expect.throwsTypeError(() => testDynamic(() => 42));
Expect.throwsTypeError(() => testDynamic(() => null));
Expect.equals(1234, testMessage(false, 1234).message);
Expect.equals('hi', testMessage(false, 'hi').message);
// These errors do not have the message because boolean conversion failed.
Expect.notEquals(1234, testMessage(null, 1234).message);
Expect.notEquals('hi', testMessage(null, 'hi').message);
Expect.notEquals('hi', testMessage(() => null, 'hi').message);
Expect.notEquals('hi', testMessage(() => false, 'hi').message);
Expect.notEquals('hi', testMessage(() => true, 'hi').message);
// These assertions throw a type error because boolean conversion failed.
Expect.throwsTypeError(() => testMessage(null, 1234));
Expect.throwsTypeError(() => testMessage(null, 'hi'));
Expect.throwsTypeError(() => testMessage(() => null, 'hi'));
Expect.throwsTypeError(() => testMessage(() => false, 'hi'));
Expect.throwsTypeError(() => testMessage(() => true, 'hi'));
}

View file

@ -8,7 +8,7 @@
import "package:expect/expect.dart";
testTrue() {
int testTrue() {
int i = 0;
try {
assert(true);
@ -18,7 +18,7 @@ testTrue() {
return i;
}
testFalse() {
int testFalse() {
int i = 0;
try {
assert(false);
@ -28,11 +28,11 @@ testFalse() {
return i;
}
unknown(dynamic a) {
dynamic unknown(dynamic a) {
return a ? true : false;
}
testBoolean(bool value) {
int testBoolean(bool value) {
int i = 0;
try {
assert(value);
@ -42,7 +42,7 @@ testBoolean(bool value) {
return i;
}
testDynamic(dynamic value) {
int testDynamic(dynamic value) {
int i = 0;
try {
assert(value);
@ -52,13 +52,13 @@ testDynamic(dynamic value) {
return i;
}
testMessage(value, message) {
AssertionError testMessage(value, message) {
try {
assert(value, message);
return null;
} on AssertionError catch (error) {
return error;
}
return null;
}
main() {
@ -70,13 +70,13 @@ main() {
Expect.equals(1, testBoolean(false));
Expect.equals(1, testDynamic(unknown(false)));
Expect.equals(1, testBoolean(null));
Expect.equals(1, testDynamic(null));
Expect.equals(1, testDynamic(42));
Expect.equals(1, testDynamic(() => true));
Expect.equals(1, testDynamic(() => false));
Expect.equals(1, testDynamic(() => 42));
Expect.equals(1, testDynamic(() => null));
Expect.throwsTypeError(() => testBoolean(null));
Expect.throwsTypeError(() => testDynamic(null));
Expect.throwsTypeError(() => testDynamic(42));
Expect.throwsTypeError(() => testDynamic(() => true));
Expect.throwsTypeError(() => testDynamic(() => false));
Expect.throwsTypeError(() => testDynamic(() => 42));
Expect.throwsTypeError(() => testDynamic(() => null));
Expect.equals(1234, testMessage(false, 1234).message);
Expect.equals('hi', testMessage(false, 'hi').message);

View file

@ -20,7 +20,7 @@ main() {
dynamic y = 3;
Expect.throws(() => new Bar().foo(i: x, a: y), (e) {
if (e is TypeError) {
var m = e.message.toString();
var m = e.toString();
return m.contains("is not a subtype of type 'int'") ||
m.contains(
"Expected a value of type 'int', but got one of type 'String'");