mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
Reland "[vm/nnbd] Auto-detect null-safety from entry point in kernel compilers"
This is a reland of fd19c8cc25
No changes were made to the original CL.
The following fixes landed separately:
* Flutter tests which use --enable-experiment=non-nullable are
disabled in https://github.com/flutter/flutter/pull/57235.
* Auto-detection of null-safety mode from dill file in gen_snapshot is
implemented in https://dart-review.googlesource.com/c/sdk/+/148152.
Original change's description:
> [vm/nnbd] Auto-detect null-safety from entry point in kernel compilers
>
> If --null-safety flag is not specified, tools should infer null safety
> mode from a legacy status of an entry point script.
> This change adds such auto-detection to kernel compilers (front-end
> server and gen_kernel).
>
> Issue: https://github.com/dart-lang/sdk/issues/41206
> Change-Id: If78491d08390c28b98e86857ec7d61520433dee9
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/148024
> Reviewed-by: Ryan Macnak <rmacnak@google.com>
> Reviewed-by: Alexander Aprelev <aam@google.com>
> Commit-Queue: Alexander Markov <alexmarkov@google.com>
Change-Id: Ibc185caa6975087a35c89ff69faf3f6c11fcf14c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/148201
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
a6148714f0
commit
bbe469eabd
6 changed files with 88 additions and 21 deletions
|
@ -152,7 +152,7 @@ ArgParser argParser = ArgParser(allowTrailingOptions: true)
|
|||
..addFlag('null-safety',
|
||||
help:
|
||||
'Respect the nullability of types at runtime in casts and instance checks.',
|
||||
defaultsTo: false)
|
||||
defaultsTo: null)
|
||||
..addMultiOption('enable-experiment',
|
||||
help: 'Comma separated list of experimental features, eg set-literals.',
|
||||
hide: true)
|
||||
|
@ -385,7 +385,8 @@ class FrontendCompiler implements CompilerInterface {
|
|||
..experimentalFlags = parseExperimentalFlags(
|
||||
parseExperimentalArguments(options['enable-experiment']),
|
||||
onError: (msg) => errors.add(msg))
|
||||
..nnbdMode = options['null-safety'] ? NnbdMode.Strong : NnbdMode.Weak
|
||||
..nnbdMode =
|
||||
(options['null-safety'] == true) ? NnbdMode.Strong : NnbdMode.Weak
|
||||
..onDiagnostic = (DiagnosticMessage message) {
|
||||
bool printMessage;
|
||||
switch (message.severity) {
|
||||
|
@ -446,6 +447,11 @@ class FrontendCompiler implements CompilerInterface {
|
|||
}
|
||||
}
|
||||
|
||||
if (options['null-safety'] == null &&
|
||||
compilerOptions.experimentalFlags[ExperimentalFlag.nonNullable]) {
|
||||
await autoDetectNullSafetyMode(_mainSource, compilerOptions);
|
||||
}
|
||||
|
||||
compilerOptions.bytecode = options['gen-bytecode'];
|
||||
final BytecodeOptions bytecodeOptions = BytecodeOptions(
|
||||
enableAsserts: options['enable-asserts'],
|
||||
|
@ -459,7 +465,7 @@ class FrontendCompiler implements CompilerInterface {
|
|||
compilerOptions.target = createFrontEndTarget(
|
||||
options['target'],
|
||||
trackWidgetCreation: options['track-widget-creation'],
|
||||
nullSafety: options['null-safety'],
|
||||
nullSafety: compilerOptions.nnbdMode == NnbdMode.Strong,
|
||||
);
|
||||
if (compilerOptions.target == null) {
|
||||
print('Failed to create front-end target ${options['target']}.');
|
||||
|
|
|
@ -31,7 +31,6 @@ import 'package:build_integration/file_system/multi_root.dart';
|
|||
import 'package:front_end/src/api_prototype/experimental_flags.dart';
|
||||
import 'package:front_end/src/api_prototype/front_end.dart' as fe
|
||||
show CompilerResult;
|
||||
import 'package:front_end/src/api_prototype/language_version.dart';
|
||||
import 'package:front_end/src/api_prototype/memory_file_system.dart';
|
||||
import 'package:front_end/src/api_unstable/vm.dart';
|
||||
import 'package:kernel/binary/ast_to_binary.dart';
|
||||
|
@ -46,7 +45,10 @@ import 'package:vm/bytecode/gen_bytecode.dart'
|
|||
import 'package:vm/bytecode/options.dart' show BytecodeOptions;
|
||||
import 'package:vm/incremental_compiler.dart';
|
||||
import 'package:vm/kernel_front_end.dart'
|
||||
show createLoadedLibrariesSet, runWithFrontEndCompilerContext;
|
||||
show
|
||||
autoDetectNullSafetyMode,
|
||||
createLoadedLibrariesSet,
|
||||
runWithFrontEndCompilerContext;
|
||||
import 'package:vm/http_filesystem.dart';
|
||||
import 'package:vm/target/vm.dart' show VmTarget;
|
||||
import 'package:front_end/src/api_prototype/compiler_options.dart'
|
||||
|
@ -90,12 +92,6 @@ const int kNullSafetyOptionUnspecified = 0;
|
|||
const int kNullSafetyOptionWeak = 1;
|
||||
const int kNullSafetyOptionStrong = 2;
|
||||
|
||||
Future<void> autoDetectNullSafetyMode(
|
||||
Uri script, CompilerOptions options) async {
|
||||
var isLegacy = await uriUsesLegacyLanguageVersion(script, options);
|
||||
options.nnbdMode = isLegacy ? NnbdMode.Weak : NnbdMode.Strong;
|
||||
}
|
||||
|
||||
abstract class Compiler {
|
||||
final int isolateId;
|
||||
final FileSystem fileSystem;
|
||||
|
|
|
@ -15,6 +15,9 @@ import 'package:build_integration/file_system/multi_root.dart'
|
|||
|
||||
import 'package:crypto/crypto.dart';
|
||||
|
||||
import 'package:front_end/src/api_prototype/language_version.dart'
|
||||
show uriUsesLegacyLanguageVersion;
|
||||
|
||||
import 'package:front_end/src/api_unstable/vm.dart'
|
||||
show
|
||||
CompilerContext,
|
||||
|
@ -22,6 +25,7 @@ import 'package:front_end/src/api_unstable/vm.dart'
|
|||
CompilerResult,
|
||||
DiagnosticMessage,
|
||||
DiagnosticMessageHandler,
|
||||
ExperimentalFlag,
|
||||
FileSystem,
|
||||
FileSystemEntity,
|
||||
FileSystemException,
|
||||
|
@ -110,7 +114,7 @@ void declareCompilerOptions(ArgParser args) {
|
|||
args.addFlag('null-safety',
|
||||
help:
|
||||
'Respect the nullability of types at runtime in casts and instance checks.',
|
||||
defaultsTo: false);
|
||||
defaultsTo: null);
|
||||
args.addFlag('split-output-by-packages',
|
||||
help:
|
||||
'Split resulting kernel file into multiple files (one per package).',
|
||||
|
@ -200,12 +204,6 @@ Future<int> runCompiler(ArgResults options, String usage) async {
|
|||
aot: aot,
|
||||
)..parseCommandLineFlags(options['bytecode-options']);
|
||||
|
||||
final target = createFrontEndTarget(targetName, nullSafety: nullSafety);
|
||||
if (target == null) {
|
||||
print('Failed to create front-end target $targetName.');
|
||||
return badUsageExitCode;
|
||||
}
|
||||
|
||||
final fileSystem =
|
||||
createFrontEndFileSystem(fileSystemScheme, fileSystemRoots);
|
||||
|
||||
|
@ -227,19 +225,30 @@ Future<int> runCompiler(ArgResults options, String usage) async {
|
|||
|
||||
final CompilerOptions compilerOptions = new CompilerOptions()
|
||||
..sdkSummary = platformKernelUri
|
||||
..target = target
|
||||
..fileSystem = fileSystem
|
||||
..additionalDills = additionalDills
|
||||
..packagesFileUri = packagesUri
|
||||
..experimentalFlags = parseExperimentalFlags(
|
||||
parseExperimentalArguments(experimentalFlags),
|
||||
onError: print)
|
||||
..nnbdMode = nullSafety ? NnbdMode.Strong : NnbdMode.Weak
|
||||
..nnbdMode = (nullSafety == true) ? NnbdMode.Strong : NnbdMode.Weak
|
||||
..onDiagnostic = (DiagnosticMessage m) {
|
||||
errorDetector(m);
|
||||
}
|
||||
..embedSourceText = embedSources;
|
||||
|
||||
if (nullSafety == null &&
|
||||
compilerOptions.experimentalFlags[ExperimentalFlag.nonNullable]) {
|
||||
await autoDetectNullSafetyMode(mainUri, compilerOptions);
|
||||
}
|
||||
|
||||
compilerOptions.target = createFrontEndTarget(targetName,
|
||||
nullSafety: compilerOptions.nnbdMode == NnbdMode.Strong);
|
||||
if (compilerOptions.target == null) {
|
||||
print('Failed to create front-end target $targetName.');
|
||||
return badUsageExitCode;
|
||||
}
|
||||
|
||||
final results = await compileToKernel(mainUri, compilerOptions,
|
||||
includePlatform: additionalDills.isNotEmpty,
|
||||
aot: aot,
|
||||
|
@ -558,6 +567,13 @@ bool parseCommandLineDefines(
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Detect null safety mode from an entry point and set [options.nnbdMode].
|
||||
Future<void> autoDetectNullSafetyMode(
|
||||
Uri script, CompilerOptions options) async {
|
||||
var isLegacy = await uriUsesLegacyLanguageVersion(script, options);
|
||||
options.nnbdMode = isLegacy ? NnbdMode.Weak : NnbdMode.Strong;
|
||||
}
|
||||
|
||||
/// Create front-end target with given name.
|
||||
Target createFrontEndTarget(String targetName,
|
||||
{bool trackWidgetCreation = false, bool nullSafety = false}) {
|
||||
|
|
|
@ -8,7 +8,6 @@ import 'package:path/path.dart' as path;
|
|||
import 'package:test/test.dart';
|
||||
|
||||
import 'package:vm/snapshot/instruction_sizes.dart' as instruction_sizes;
|
||||
import 'package:vm/snapshot/name.dart';
|
||||
|
||||
void main() async {
|
||||
if (!Platform.executable.contains('dart-sdk')) {
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// Tests auto-detection of null safety mode in gen_kernel tool.
|
||||
|
||||
import 'dart:io' show File, Platform;
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'snapshot_test_helper.dart';
|
||||
|
||||
compileAndRunTest(String comment, String expectedOutput) async {
|
||||
await withTempDir((String temp) async {
|
||||
final testScriptPath = path.join(temp, 'test.dart');
|
||||
File(testScriptPath).writeAsStringSync('''
|
||||
// $comment
|
||||
|
||||
void main() {
|
||||
try {
|
||||
null as int;
|
||||
print('weak mode');
|
||||
} on TypeError {
|
||||
print('strong mode');
|
||||
}
|
||||
}
|
||||
''');
|
||||
|
||||
final testDillPath = path.join(temp, 'test.dill');
|
||||
await runGenKernel('BUILD DILL FILE', [
|
||||
'--enable-experiment=non-nullable',
|
||||
'--output=$testDillPath',
|
||||
testScriptPath,
|
||||
]);
|
||||
|
||||
final result = await runBinary(
|
||||
'RUN TEST FROM DILL', Platform.executable, [testDillPath]);
|
||||
expectOutput(expectedOutput, result);
|
||||
});
|
||||
}
|
||||
|
||||
main() async {
|
||||
await compileAndRunTest('', 'strong mode');
|
||||
await compileAndRunTest('@dart=2.7', 'weak mode');
|
||||
}
|
|
@ -17,6 +17,7 @@ dart/data_uri_import_test/none: SkipByDesign
|
|||
dart/emit_aot_size_info_flag_test: Pass, Slow # Spawns several subprocesses
|
||||
dart/minimal_kernel_bytecode_test: Pass, Slow # Spawns several subprocesses
|
||||
dart/minimal_kernel_test: Pass, Slow # Spawns several subprocesses
|
||||
dart/null_safety_autodetection_in_kernel_compiler_test: Pass, Slow # Spawns several subprocesses
|
||||
dart/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
|
||||
dart/snapshot_version_test: Skip # This test is a Dart1 test (script snapshot)
|
||||
dart/stack_overflow_shared_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
|
||||
|
@ -52,6 +53,7 @@ dart/appjit*: SkipByDesign # Test needs to a particular opt-counter value
|
|||
dart/kernel_determinism_test: SkipSlow
|
||||
dart/minimal_kernel_bytecode_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
|
||||
dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
|
||||
dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
|
||||
|
||||
[ $builder_tag == tsan ]
|
||||
dart/appjit_cha_deopt_test: SkipSlow
|
||||
|
@ -79,6 +81,7 @@ cc/VerifyImplicit_Crash: Crash # Negative tests of VerifiedMemory should crash i
|
|||
dart/appjit_cha_deopt_test: Pass, Slow # Quite slow in debug mode, uses --optimization-counter-threshold=100
|
||||
dart/minimal_kernel_bytecode_test: SkipSlow # gen_kernel is too slow in debug mode
|
||||
dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow in debug mode
|
||||
dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in debug mode
|
||||
dart/spawn_shutdown_test: Pass, Slow # VM Shutdown test, It can take some time for all the isolates to shutdown in a Debug build.
|
||||
|
||||
[ $mode == product ]
|
||||
|
@ -141,6 +144,7 @@ dart/bytecode_and_ast_mix_test: SkipByDesign # Test needs to run from source
|
|||
dart/kernel_determinism_test: SkipByDesign # Test needs to run from source
|
||||
dart/minimal_kernel_bytecode_test: SkipByDesign # Test needs to run from source
|
||||
dart/minimal_kernel_test: SkipByDesign # Test needs to run from source
|
||||
dart/null_safety_autodetection_in_kernel_compiler_test: SkipByDesign # Test needs to run from source
|
||||
dart/snapshot_depfile_test: SkipByDesign # Test needs to run from source
|
||||
|
||||
[ $compiler == dartkp && ($runtime == dart_precompiled || $runtime == vm) ]
|
||||
|
@ -202,6 +206,7 @@ dart/appjit*: SkipSlow # DFE too slow
|
|||
dart/data_uri_spawn_test: Skip # Please triage.
|
||||
dart/minimal_kernel_bytecode_test: SkipSlow # gen_kernel is too slow on simulated architectures
|
||||
dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow on simulated architectures
|
||||
dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow on simulated architectures
|
||||
dart/snapshot_version_test: RuntimeError # Please triage.
|
||||
|
||||
[ $hot_reload || $hot_reload_rollback ]
|
||||
|
@ -302,6 +307,7 @@ dart/disassemble_determinism_test: SkipSlow # Runs expensive fibonacci(32) compu
|
|||
dart/issue_31959_31960_test: SkipSlow
|
||||
dart/minimal_kernel_bytecode_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
|
||||
dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
|
||||
dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
|
||||
dart/print_flow_graph_determinism_test: SkipSlow
|
||||
dart/slow_path_shared_stub_test: SkipSlow # Too slow with --shared-slow-path-triggers-gc flag and not relevant outside precompiled.
|
||||
dart/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it reloads.
|
||||
|
|
Loading…
Reference in a new issue