Add experimental feature flag sound-flow-analysis.

All work on https://github.com/dart-lang/language/issues/3100 (Change
flow analysis to assume sound null safety once unsound null safety
support is fully removed) will be guarded by this flag.

Bug: https://github.com/dart-lang/language/issues/3100
Change-Id: I0a6e7b732520ed70944141b4bb02832b7d0d969b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/417906
Reviewed-by: Kevin Moore <kevmoo@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
Paul Berry
2025-03-27 15:19:31 -07:00
committed by Commit Queue
parent 8d0037ddc3
commit 82420ba66c
5 changed files with 70 additions and 9 deletions
@@ -220,6 +220,13 @@ enum ExperimentalFlag {
experimentEnabledVersion: const Version(2, 0),
experimentReleasedVersion: const Version(2, 0)),
soundFlowAnalysis(
name: 'sound-flow-analysis',
isEnabledByDefault: false,
isExpired: false,
experimentEnabledVersion: defaultLanguageVersion,
experimentReleasedVersion: defaultLanguageVersion),
spreadCollections(
name: 'spread-collections',
isEnabledByDefault: true,
@@ -100,7 +100,7 @@ import 'package:meta/meta.dart';
// TODO(scheglov): Clean up the list of implicitly analyzed files.
class AnalysisDriver {
/// The version of data format, should be incremented on every format change.
static const int DATA_VERSION = 449;
static const int DATA_VERSION = 450;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.
@@ -50,6 +50,7 @@ final _knownFeatures = <String, ExperimentalFeature>{
EnableString.records: ExperimentalFeatures.records,
EnableString.sealed_class: ExperimentalFeatures.sealed_class,
EnableString.set_literals: ExperimentalFeatures.set_literals,
EnableString.sound_flow_analysis: ExperimentalFeatures.sound_flow_analysis,
EnableString.spread_collections: ExperimentalFeatures.spread_collections,
EnableString.super_parameters: ExperimentalFeatures.super_parameters,
EnableString.test_experiment: ExperimentalFeatures.test_experiment,
@@ -153,6 +154,9 @@ class EnableString {
/// String to enable the experiment "set-literals"
static const String set_literals = 'set-literals';
/// String to enable the experiment "sound-flow-analysis"
static const String sound_flow_analysis = 'sound-flow-analysis';
/// String to enable the experiment "spread-collections"
static const String spread_collections = 'spread-collections';
@@ -516,8 +520,20 @@ class ExperimentalFeatures {
channels: ["stable", "beta", "dev", "main"],
);
static final spread_collections = ExperimentalFeature(
static final sound_flow_analysis = ExperimentalFeature(
index: 30,
enableString: EnableString.sound_flow_analysis,
isEnabledByDefault: IsEnabledByDefault.sound_flow_analysis,
isExpired: IsExpired.sound_flow_analysis,
documentation:
'Assume sound null safety when computing type promotion, reachability, and definite assignment.',
experimentalReleaseVersion: null,
releaseVersion: null,
channels: ["stable", "beta", "dev", "main"],
);
static final spread_collections = ExperimentalFeature(
index: 31,
enableString: EnableString.spread_collections,
isEnabledByDefault: IsEnabledByDefault.spread_collections,
isExpired: IsExpired.spread_collections,
@@ -528,7 +544,7 @@ class ExperimentalFeatures {
);
static final super_parameters = ExperimentalFeature(
index: 31,
index: 32,
enableString: EnableString.super_parameters,
isEnabledByDefault: IsEnabledByDefault.super_parameters,
isExpired: IsExpired.super_parameters,
@@ -539,7 +555,7 @@ class ExperimentalFeatures {
);
static final test_experiment = ExperimentalFeature(
index: 32,
index: 33,
enableString: EnableString.test_experiment,
isEnabledByDefault: IsEnabledByDefault.test_experiment,
isExpired: IsExpired.test_experiment,
@@ -551,7 +567,7 @@ class ExperimentalFeatures {
);
static final triple_shift = ExperimentalFeature(
index: 33,
index: 34,
enableString: EnableString.triple_shift,
isEnabledByDefault: IsEnabledByDefault.triple_shift,
isExpired: IsExpired.triple_shift,
@@ -562,7 +578,7 @@ class ExperimentalFeatures {
);
static final unnamed_libraries = ExperimentalFeature(
index: 34,
index: 35,
enableString: EnableString.unnamed_libraries,
isEnabledByDefault: IsEnabledByDefault.unnamed_libraries,
isExpired: IsExpired.unnamed_libraries,
@@ -573,7 +589,7 @@ class ExperimentalFeatures {
);
static final unquoted_imports = ExperimentalFeature(
index: 35,
index: 36,
enableString: EnableString.unquoted_imports,
isEnabledByDefault: IsEnabledByDefault.unquoted_imports,
isExpired: IsExpired.unquoted_imports,
@@ -584,7 +600,7 @@ class ExperimentalFeatures {
);
static final variance = ExperimentalFeature(
index: 36,
index: 37,
enableString: EnableString.variance,
isEnabledByDefault: IsEnabledByDefault.variance,
isExpired: IsExpired.variance,
@@ -595,7 +611,7 @@ class ExperimentalFeatures {
);
static final wildcard_variables = ExperimentalFeature(
index: 37,
index: 38,
enableString: EnableString.wildcard_variables,
isEnabledByDefault: IsEnabledByDefault.wildcard_variables,
isExpired: IsExpired.wildcard_variables,
@@ -700,6 +716,9 @@ class IsEnabledByDefault {
/// Default state of the experiment "set-literals"
static const bool set_literals = true;
/// Default state of the experiment "sound-flow-analysis"
static const bool sound_flow_analysis = false;
/// Default state of the experiment "spread-collections"
static const bool spread_collections = true;
@@ -819,6 +838,9 @@ class IsExpired {
/// Expiration status of the experiment "set-literals"
static const bool set_literals = true;
/// Expiration status of the experiment "sound-flow-analysis"
static const bool sound_flow_analysis = false;
/// Expiration status of the experiment "spread-collections"
static const bool spread_collections = true;
@@ -948,6 +970,10 @@ mixin _CurrentState {
/// Current state for the flag "set-literals"
bool get set_literals => isEnabled(ExperimentalFeatures.set_literals);
/// Current state for the flag "sound-flow-analysis"
bool get sound_flow_analysis =>
isEnabled(ExperimentalFeatures.sound_flow_analysis);
/// Current state for the flag "spread-collections"
bool get spread_collections =>
isEnabled(ExperimentalFeatures.spread_collections);
@@ -299,6 +299,14 @@ class ExperimentalFlag {
experimentEnabledVersion: const Version(2, 0),
experimentReleasedVersion: const Version(2, 0));
static const ExperimentalFlag soundFlowAnalysis = const ExperimentalFlag(
name: 'sound-flow-analysis',
isEnabledByDefault: false,
isExpired: false,
enabledVersion: defaultLanguageVersion,
experimentEnabledVersion: defaultLanguageVersion,
experimentReleasedVersion: defaultLanguageVersion);
static const ExperimentalFlag spreadCollections = const ExperimentalFlag(
name: 'spread-collections',
isEnabledByDefault: true,
@@ -534,6 +542,10 @@ class GlobalFeatures {
GlobalFeature get setLiterals =>
_setLiterals ??= _computeGlobalFeature(ExperimentalFlag.setLiterals);
GlobalFeature? _soundFlowAnalysis;
GlobalFeature get soundFlowAnalysis => _soundFlowAnalysis ??=
_computeGlobalFeature(ExperimentalFlag.soundFlowAnalysis);
GlobalFeature? _spreadCollections;
GlobalFeature get spreadCollections => _spreadCollections ??=
_computeGlobalFeature(ExperimentalFlag.spreadCollections);
@@ -740,6 +752,11 @@ class LibraryFeatures {
_setLiterals ??= globalFeatures._computeLibraryFeature(
ExperimentalFlag.setLiterals, canonicalUri, libraryVersion);
LibraryFeature? _soundFlowAnalysis;
LibraryFeature get soundFlowAnalysis =>
_soundFlowAnalysis ??= globalFeatures._computeLibraryFeature(
ExperimentalFlag.soundFlowAnalysis, canonicalUri, libraryVersion);
LibraryFeature? _spreadCollections;
LibraryFeature get spreadCollections =>
_spreadCollections ??= globalFeatures._computeLibraryFeature(
@@ -844,6 +861,8 @@ class LibraryFeatures {
return sealedClass;
case shared.ExperimentalFlag.setLiterals:
return setLiterals;
case shared.ExperimentalFlag.soundFlowAnalysis:
return soundFlowAnalysis;
case shared.ExperimentalFlag.spreadCollections:
return spreadCollections;
case shared.ExperimentalFlag.superParameters:
@@ -928,6 +947,8 @@ ExperimentalFlag? parseExperimentalFlag(String flag) {
return ExperimentalFlag.sealedClass;
case "set-literals":
return ExperimentalFlag.setLiterals;
case "sound-flow-analysis":
return ExperimentalFlag.soundFlowAnalysis;
case "spread-collections":
return ExperimentalFlag.spreadCollections;
case "super-parameters":
@@ -1003,6 +1024,8 @@ final Map<ExperimentalFlag, bool> defaultExperimentalFlags = {
ExperimentalFlag.records: ExperimentalFlag.records.isEnabledByDefault,
ExperimentalFlag.sealedClass: ExperimentalFlag.sealedClass.isEnabledByDefault,
ExperimentalFlag.setLiterals: ExperimentalFlag.setLiterals.isEnabledByDefault,
ExperimentalFlag.soundFlowAnalysis:
ExperimentalFlag.soundFlowAnalysis.isEnabledByDefault,
ExperimentalFlag.spreadCollections:
ExperimentalFlag.spreadCollections.isEnabledByDefault,
ExperimentalFlag.superParameters:
@@ -1065,6 +1088,7 @@ const Map<shared.ExperimentalFlag, ExperimentalFlag> sharedExperimentalFlags = {
shared.ExperimentalFlag.records: ExperimentalFlag.records,
shared.ExperimentalFlag.sealedClass: ExperimentalFlag.sealedClass,
shared.ExperimentalFlag.setLiterals: ExperimentalFlag.setLiterals,
shared.ExperimentalFlag.soundFlowAnalysis: ExperimentalFlag.soundFlowAnalysis,
shared.ExperimentalFlag.spreadCollections: ExperimentalFlag.spreadCollections,
shared.ExperimentalFlag.superParameters: ExperimentalFlag.superParameters,
shared.ExperimentalFlag.testExperiment: ExperimentalFlag.testExperiment,
+4
View File
@@ -151,6 +151,10 @@ features:
getter-setter-error:
help: "Stop reporting errors about mismatching types in a getter/setter pair."
sound-flow-analysis:
# See https://github.com/dart-lang/language/issues/3100
help: "Assume sound null safety when computing type promotion, reachability, and definite assignment."
# Experiment flag only used for testing.
test-experiment:
help: >-