mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 10:18:13 +00:00
[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 <markzipan@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com> Commit-Queue: Nicholas Shahan <nshahan@google.com>
This commit is contained in:
parent
69d11907ec
commit
7478143e5f
|
@ -4849,6 +4849,14 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
|
|||
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];
|
||||
|
|
|
@ -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();
|
||||
''';
|
||||
|
|
|
@ -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();
|
||||
''';
|
||||
|
|
|
@ -276,7 +276,6 @@ void main(List<String> 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);
|
||||
}
|
||||
|
|
|
@ -233,7 +233,6 @@ requirejs(["$testName", "dart_sdk", "async_helper"],
|
|||
};
|
||||
|
||||
if ($isNnbd) {
|
||||
sdk.dart.nullSafety($isNnbdStrong);
|
||||
sdk.dart.weakNullSafetyWarnings(!$isNnbdStrong);
|
||||
sdk.dart.nonNullAsserts($nonNullAsserts);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ import 'dart:_foreign_helper' show JS;
|
|||
import 'dart:_runtime' as dart;
|
||||
|
||||
@patch
|
||||
bool typeAcceptsNull<T>() => !dart.strictNullSafety || null is T;
|
||||
bool typeAcceptsNull<T>() =>
|
||||
!dart.compileTimeFlag('soundNullSafety') || null is T;
|
||||
|
||||
@patch
|
||||
class Symbol implements core.Symbol {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<bool>('!', '# === #', 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};
|
||||
|
|
Loading…
Reference in a new issue