diff --git a/pkg/front_end/testcases/general/external_import.dart.weak.expect b/pkg/front_end/testcases/general/external_import.dart.weak.expect index 0d7662ffa80..5e7e2df62e6 100644 --- a/pkg/front_end/testcases/general/external_import.dart.weak.expect +++ b/pkg/front_end/testcases/general/external_import.dart.weak.expect @@ -37,5 +37,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///external_import.dart: -- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9) +- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect b/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect index 0d7662ffa80..5e7e2df62e6 100644 --- a/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect +++ b/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect @@ -37,5 +37,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///external_import.dart: -- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9) +- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect b/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect index 0d7662ffa80..5e7e2df62e6 100644 --- a/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect +++ b/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect @@ -37,5 +37,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///external_import.dart: -- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9) +- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect index 7670aed4785..b24cb955388 100644 --- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect +++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect @@ -42,5 +42,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///native_is_illegal.dart: -- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9) +- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect index 7670aed4785..b24cb955388 100644 --- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect +++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect @@ -42,5 +42,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///native_is_illegal.dart: -- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9) +- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect index 7670aed4785..b24cb955388 100644 --- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect +++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect @@ -42,5 +42,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///native_is_illegal.dart: -- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9) +- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart index f4ab5561d59..ca3bd4f699e 100644 --- a/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart +++ b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart @@ -62,3 +62,6 @@ T createSentinel() => throw UnsupportedError('createSentinel'); @patch bool isSentinel(dynamic value) => throw UnsupportedError('isSentinel'); + +@patch +T unsafeCast(dynamic v) => v; diff --git a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart b/sdk/lib/_internal/js_runtime/lib/internal_patch.dart index 9bf6da67f66..ef27959937c 100644 --- a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart +++ b/sdk/lib/_internal/js_runtime/lib/internal_patch.dart @@ -73,3 +73,7 @@ T createSentinel() => createJsSentinel(); @patch @pragma('dart2js:tryInline') bool isSentinel(dynamic value) => isJsSentinel(value); + +@patch +@pragma('dart2js:tryInline') +T unsafeCast(dynamic v) => v; diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart index b8141d68112..3d7a3cd8f5a 100644 --- a/sdk/lib/_internal/vm/lib/internal_patch.dart +++ b/sdk/lib/_internal/vm/lib/internal_patch.dart @@ -156,13 +156,9 @@ Int32List _growRegExpStack(Int32List stack) { return newStack; } -// This function can be used to skip implicit or explicit checked down casts in -// the parts of the core library implementation where we know by construction the -// type of a value. -// -// Important: this is unsafe and must be used with care. +@patch @pragma("vm:external-name", "Internal_unsafeCast") -external T unsafeCast(Object? v); +external T unsafeCast(dynamic v); // This function can be used to keep an object alive till that point. @pragma("vm:recognized", "other") diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart index 0b16dae3492..ca05fc66a65 100644 --- a/sdk/lib/async/async.dart +++ b/sdk/lib/async/async.dart @@ -114,7 +114,8 @@ import "dart:_internal" printToZone, printToConsole, Since, - typeAcceptsNull; + typeAcceptsNull, + unsafeCast; part 'async_error.dart'; part 'broadcast_stream_controller.dart'; diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart index 4d13cc819f2..26cfecd514f 100644 --- a/sdk/lib/async/future_impl.dart +++ b/sdk/lib/async/future_impl.dart @@ -4,15 +4,6 @@ part of dart.async; -/// The onValue and onError handlers return either a value or a future -typedef FutureOr _FutureOnValue(S value); - -/// Test used by [Future.catchError] to handle skip some errors. -typedef bool _FutureErrorTest(Object error); - -/// Used by [WhenFuture]. -typedef dynamic _FutureAction(); - abstract class _Completer implements Completer { final _Future future = new _Future(); @@ -106,7 +97,7 @@ class _FutureListener { state = (errorCallback == null) ? stateThen : stateThenOnerror; _FutureListener.thenAwait( - this.result, _FutureOnValue onValue, Function errorCallback) + this.result, FutureOr Function(S) onValue, Function errorCallback) : callback = onValue, errorCallback = errorCallback, state = stateThenOnerror; @@ -127,19 +118,19 @@ class _FutureListener { FutureOr Function(S) get _onValue { assert(handlesValue); - return callback as dynamic; + return unsafeCast Function(S)>(callback); } Function? get _onError => errorCallback; - _FutureErrorTest get _errorTest { + bool Function(Object) get _errorTest { assert(hasErrorTest); - return callback as dynamic; + return unsafeCast(callback); } - _FutureAction get _whenCompleteAction { + dynamic Function() get _whenCompleteAction { assert(handlesComplete); - return callback as dynamic; + return unsafeCast(callback); } /// Whether this listener has an error callback. diff --git a/sdk/lib/internal/internal.dart b/sdk/lib/internal/internal.dart index 5d38bd8917e..a7a7eda1b06 100644 --- a/sdk/lib/internal/internal.dart +++ b/sdk/lib/internal/internal.dart @@ -35,6 +35,23 @@ part 'symbol.dart'; // execution mode. external bool typeAcceptsNull(); +/// Unsafely treats [value] as type [T]. +/// +/// An unsafe cast allows casting any value to any type, +/// without any runtime type checks. +/// +/// Can be used internally in platform library implementations of +/// data structures, where a value is known to have a type different +/// from its static type (like knowing that a string is definitely +/// a "_OneByteString" or that the value stored into a heterogenous +/// list is really a value of the surrounding map). +/// +/// Must only be used for casts which would definitely *succeed* +/// as a normal cast. +/// +/// Should only be used for performance in performance critical code. +external T unsafeCast(dynamic value); + // Powers of 10 up to 10^22 are representable as doubles. // Powers of 10 above that are only approximate due to lack of precission. // Used by double-parsing.