From 7478143e5f6e351c6862b393fa3357d672380b34 Mon Sep 17 00:00:00 2001 From: Nicholas Shahan Date: Mon, 13 Jul 2020 22:45:19 +0000 Subject: [PATCH] [ddc] Inline the sound null safety flag Now that the sound null safety mode is a compile time flag instead of a runtime flag there is no need to set the value in the bootstrapping code before running main(). The sound and weak versions of the sdk now have it already set. Add compileTimeFlag() method that will inline the constant value directly into the generated output. Change-Id: I5b9243c47cffc421067ac820ef49342b9d0efff9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/154100 Reviewed-by: Mark Zhou Reviewed-by: Sigmund Cherem Commit-Queue: Nicholas Shahan --- pkg/dev_compiler/lib/src/kernel/compiler.dart | 8 ++++ pkg/dev_compiler/test/modular_suite.dart | 2 - pkg/dev_compiler/test/modular_suite_nnbd.dart | 1 - pkg/dev_compiler/tool/ddb | 3 -- pkg/test_runner/lib/src/browser.dart | 1 - .../js_dev_runtime/patch/internal_patch.dart | 3 +- .../private/ddc_runtime/operations.dart | 12 +++--- .../private/ddc_runtime/types.dart | 42 +++++++------------ 8 files changed, 32 insertions(+), 40 deletions(-) diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart index 4ed43fadc9a..23cc2bae20c 100644 --- a/pkg/dev_compiler/lib/src/kernel/compiler.dart +++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart @@ -4849,6 +4849,14 @@ class ProgramCompiler extends ComputeOnceConstantVisitor if (name == 'extensionSymbol' && firstArg is StringLiteral) { return getExtensionSymbolInternal(firstArg.value); } + + if (name == 'compileTimeFlag' && firstArg is StringLiteral) { + var flagName = firstArg.value; + if (flagName == 'soundNullSafety') { + return js.boolean(_options.soundNullSafety); + } + throw UnsupportedError('Invalid flag in call to $name: $flagName'); + } } else if (node.arguments.positional.length == 2) { var firstArg = node.arguments.positional[0]; var secondArg = node.arguments.positional[1]; diff --git a/pkg/dev_compiler/test/modular_suite.dart b/pkg/dev_compiler/test/modular_suite.dart index ab721cb4629..3d47edc45b5 100644 --- a/pkg/dev_compiler/test/modular_suite.dart +++ b/pkg/dev_compiler/test/modular_suite.dart @@ -259,8 +259,6 @@ class RunD8 implements IOModularStep { var runjs = ''' import { dart, _isolate_helper } from 'dart_sdk.js'; import { main } from 'main.js'; - // Run with weak null safety. - dart.nullSafety(false); _isolate_helper.startRootIsolate(() => {}, []); main.main(); '''; diff --git a/pkg/dev_compiler/test/modular_suite_nnbd.dart b/pkg/dev_compiler/test/modular_suite_nnbd.dart index 0970e54f635..66774655e90 100644 --- a/pkg/dev_compiler/test/modular_suite_nnbd.dart +++ b/pkg/dev_compiler/test/modular_suite_nnbd.dart @@ -263,7 +263,6 @@ class RunD8 implements IOModularStep { var runjs = ''' import { dart, _isolate_helper } from 'dart_sdk.js'; import { main } from 'main.js'; - dart.nullSafety(false); _isolate_helper.startRootIsolate(() => {}, []); main.main(); '''; diff --git a/pkg/dev_compiler/tool/ddb b/pkg/dev_compiler/tool/ddb index c7cd1caa938..2fbe99e1d65 100755 --- a/pkg/dev_compiler/tool/ddb +++ b/pkg/dev_compiler/tool/ddb @@ -276,7 +276,6 @@ void main(List args) async { function(sdk, app) { 'use strict'; if ($nnbd) { - sdk.dart.nullSafety($soundNullSafety); sdk.dart.weakNullSafetyWarnings(!$soundNullSafety); sdk.dart.nonNullAsserts($nonNullAsserts); } @@ -310,7 +309,6 @@ let sdk = require(\"dart_sdk\"); let main = require(\"./$basename\").$libname.main; try { if ($nnbd) { - sdk.dart.nullSafety($soundNullSafety); sdk.dart.weakNullSafetyWarnings(!$soundNullSafety); sdk.dart.nonNullAsserts($nonNullAsserts); } @@ -345,7 +343,6 @@ import { $libname } from '$basename.js'; let main = $libname.main; try { if ($nnbd) { - dart.nullSafety($soundNullSafety); dart.weakNullSafetyWarnings(!$soundNullSafety); dart.nonNullAsserts($nonNullAsserts); } diff --git a/pkg/test_runner/lib/src/browser.dart b/pkg/test_runner/lib/src/browser.dart index bb0297a78b7..67238df3c8c 100644 --- a/pkg/test_runner/lib/src/browser.dart +++ b/pkg/test_runner/lib/src/browser.dart @@ -233,7 +233,6 @@ requirejs(["$testName", "dart_sdk", "async_helper"], }; if ($isNnbd) { - sdk.dart.nullSafety($isNnbdStrong); sdk.dart.weakNullSafetyWarnings(!$isNnbdStrong); sdk.dart.nonNullAsserts($nonNullAsserts); } 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 2e605a291b8..66c6bb14d51 100644 --- a/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart +++ b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart @@ -11,7 +11,8 @@ import 'dart:_foreign_helper' show JS; import 'dart:_runtime' as dart; @patch -bool typeAcceptsNull() => !dart.strictNullSafety || null is T; +bool typeAcceptsNull() => + !dart.compileTimeFlag('soundNullSafety') || null is T; @patch class Symbol implements core.Symbol { diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart index fefa3b8252f..fde8fe75016 100644 --- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart +++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart @@ -185,7 +185,7 @@ String? _argumentErrors(FunctionType type, List actuals, namedActuals) { if (missingRequired.isNotEmpty) { var error = "Dynamic call with missing required named arguments: " "${missingRequired.join(', ')}."; - if (!strictNullSafety) { + if (!compileTimeFlag('soundNullSafety')) { _nullWarn(error); } else { return error; @@ -430,7 +430,7 @@ bool instanceOf(obj, type) { cast(obj, type) { // We hoist the common case where null is checked against another type here // for better performance. - if (obj == null && !strictNullSafety) { + if (obj == null && !compileTimeFlag('soundNullSafety')) { // Check the null comparison cache to avoid emitting repeated warnings. _nullWarnOnType(type); return obj; @@ -450,7 +450,9 @@ bool test(bool? obj) { bool dtest(obj) { // Only throw an AssertionError in weak mode for compatibility. Strong mode // should throw a TypeError. - if (obj is! bool) booleanConversionFailed(strictNullSafety ? obj : test(obj)); + if (obj is! bool) + booleanConversionFailed( + compileTimeFlag('soundNullSafety') ? obj : test(obj)); return obj; } @@ -462,7 +464,7 @@ void booleanConversionFailed(obj) { asInt(obj) { // Note: null (and undefined) will fail this test. if (JS('!', 'Math.floor(#) != #', obj, obj)) { - if (obj == null && !strictNullSafety) { + if (obj == null && !compileTimeFlag('soundNullSafety')) { _nullWarnOnType(JS('', '#', int)); return null; } else { @@ -498,7 +500,7 @@ _notNull(x) { /// variants of the same type. nullCast(x, type) { if (x == null) { - if (!strictNullSafety) { + if (!compileTimeFlag('soundNullSafety')) { _nullWarnOnType(type); } else { castError(x, type); diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart index 9a2b72f2468..2a6c61e38a6 100644 --- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart +++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart @@ -5,32 +5,17 @@ /// This library defines the representation of runtime types. part of dart._runtime; +/// Returns the state of [flag] that is determined at compile time. +/// +/// The constant value itself is inlined by the compiler in place of the call +/// to this method. +@notNull +external bool compileTimeFlag(String flag); + _throwNullSafetyWarningError() => throw UnsupportedError( 'Null safety errors cannot be shown as warnings when running with sound ' 'null safety.'); -@notNull -bool _setNullSafety = false; - -@notNull -bool strictNullSafety = false; - -/// Sets the mode of the runtime subtype checks. -/// -/// Changing the mode after the application has started running is not -/// supported. -void nullSafety(bool soundNullSafety) { - if (_setNullSafety) { - throw UnsupportedError('The Null Safety mode can only be set once.'); - } - - if (soundNullSafety && _weakNullSafetyWarnings) - _throwNullSafetyWarningError(); - - strictNullSafety = soundNullSafety; - _setNullSafety = true; -} - @notNull bool _weakNullSafetyWarnings = false; @@ -40,7 +25,9 @@ bool _weakNullSafetyWarnings = false; /// is enabled. Showing warnings while running with sound null safety is not /// supported (they will be errors). void weakNullSafetyWarnings(bool showWarnings) { - if (showWarnings && strictNullSafety) _throwNullSafetyWarningError(); + if (showWarnings && compileTimeFlag('soundNullSafety')) { + _throwNullSafetyWarningError(); + } _weakNullSafetyWarnings = showWarnings; } @@ -910,7 +897,7 @@ class GenericFunctionTypeIdentifier extends AbstractFunctionType { var bound = typeBounds[i]; if (_equalType(bound, dynamic) || JS('!', '# === #', bound, nullable(unwrapType(Object))) || - (!strictNullSafety && _equalType(bound, Object))) { + (!compileTimeFlag('soundNullSafety') && _equalType(bound, Object))) { // Do not print the bound when it is a top type. In weak mode the bounds // of Object and Object* will also be elided. continue; @@ -1009,7 +996,8 @@ class GenericFunctionType extends AbstractFunctionType { // difference is rare. if (_equalType(type, dynamic)) return true; if (_jsInstanceOf(type, NullableType) || - (!strictNullSafety && _jsInstanceOf(type, LegacyType))) { + (!compileTimeFlag('soundNullSafety') && + _jsInstanceOf(type, LegacyType))) { return _equalType(JS('!', '#.type', type), Object); } return false; @@ -1301,7 +1289,7 @@ bool isSubtypeOf(@notNull Object t1, @notNull Object t2) { if (JS('!', '# !== void 0', result)) return result; var validSubtype = _isSubtype(t1, t2, true); - if (!validSubtype && !strictNullSafety) { + if (!validSubtype && !compileTimeFlag('soundNullSafety')) { validSubtype = _isSubtype(t1, t2, false); if (validSubtype) { // TODO(nshahan) Need more information to be helpful here. @@ -1757,7 +1745,7 @@ class _TypeInferrer { var supertypeRequiredNamed = supertype.getRequiredNamedParameters(); var subtypeNamed = supertype.getNamedParameters(); var subtypeRequiredNamed = supertype.getRequiredNamedParameters(); - if (!strictNullSafety) { + if (!compileTimeFlag('soundNullSafety')) { // In weak mode, treat required named params as optional named params. supertypeNamed = {...supertypeNamed, ...supertypeRequiredNamed}; subtypeNamed = {...subtypeNamed, ...subtypeRequiredNamed};