Version 2.11.0-216.0.dev

Merge commit '1d6eac5ebf0c57be373c7f551c637a57e6f108cb' into 'dev'
diff --git a/pkg/front_end/analysis_options_no_lints.yaml b/pkg/front_end/analysis_options_no_lints.yaml
index 6bbd1ac..25f50ec 100644
--- a/pkg/front_end/analysis_options_no_lints.yaml
+++ b/pkg/front_end/analysis_options_no_lints.yaml
@@ -4,16 +4,17 @@
 
 analyzer:
   exclude:
-    - test/analyser_ignored/**
-    - test/extensions/data/**
     - parser_testcases/**
-    - testcases/**
+    - test/analyser_ignored/**
+    - test/enable_non_nullable/data/**
+    - test/extensions/data/**
     - test/id_testing/data/**
     - test/language_versioning/data/**
     - test/patching/data/**
     - test/predicates/data/**
     - test/static_types/data/**
     - test/text_representation/data/**
+    - testcases/**
   errors:
     # Allow having TODOs in the code
     todo: ignore
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 23cf4a1..7914ed3 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -24,6 +24,9 @@
         expiredExperimentalFlags,
         parseExperimentalFlag;
 
+import 'experimental_flags.dart' as flags
+    show getExperimentEnabledVersionInLibrary, isExperimentEnabledInLibrary;
+
 import 'file_system.dart' show FileSystem;
 
 import 'standard_file_system.dart' show StandardFileSystem;
@@ -132,6 +135,7 @@
   /// Features not mentioned in the map will have their default value.
   Map<ExperimentalFlag, bool> experimentalFlags = <ExperimentalFlag, bool>{};
 
+  Map<ExperimentalFlag, bool> defaultExperimentFlagsForTesting;
   AllowedExperimentalFlags allowedExperimentalFlagsForTesting;
   Map<ExperimentalFlag, Version> experimentEnabledVersionForTesting;
   Map<ExperimentalFlag, Version> experimentReleasedVersionForTesting;
@@ -248,6 +252,23 @@
   /// compiling the platform dill.
   bool emitDeps = true;
 
+  bool isExperimentEnabledInLibrary(ExperimentalFlag flag, Uri importUri) {
+    return flags.isExperimentEnabledInLibrary(flag, importUri,
+        defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
+        experimentalFlags: experimentalFlags,
+        allowedExperimentalFlags: allowedExperimentalFlagsForTesting);
+  }
+
+  Version getExperimentEnabledVersionInLibrary(
+      ExperimentalFlag flag, Uri importUri) {
+    return flags.getExperimentEnabledVersionInLibrary(flag, importUri,
+        defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting,
+        allowedExperimentalFlags: allowedExperimentalFlagsForTesting,
+        experimentEnabledVersionForTesting: experimentEnabledVersionForTesting,
+        experimentReleasedVersionForTesting:
+            experimentReleasedVersionForTesting);
+  }
+
   bool equivalent(CompilerOptions other,
       {bool ignoreOnDiagnostic: true,
       bool ignoreVerbose: true,
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
index 582b79e..9e21c12 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
@@ -83,7 +83,8 @@
 /// defines the identity of a library, for instance `dart:core`, `package:foo`,
 /// or `file:///path/dir/file.dart`.
 bool isExperimentEnabledInLibrary(ExperimentalFlag flag, Uri canonicalUri,
-    {Map<ExperimentalFlag, bool> experimentalFlags,
+    {Map<ExperimentalFlag, bool> defaultExperimentFlagsForTesting,
+    Map<ExperimentalFlag, bool> experimentalFlags,
     AllowedExperimentalFlags allowedExperimentalFlags}) {
   assert(defaultExperimentalFlags.containsKey(flag),
       "No default value for $flag.");
@@ -96,6 +97,9 @@
   if (experimentalFlags != null) {
     enabled = experimentalFlags[flag];
   }
+  if (defaultExperimentFlagsForTesting != null) {
+    enabled ??= defaultExperimentFlagsForTesting[flag];
+  }
   enabled ??= defaultExperimentalFlags[flag];
   if (!enabled) {
     allowedExperimentalFlags ??= defaultAllowedExperimentalFlags;
@@ -119,13 +123,51 @@
   return enabled;
 }
 
-Version getExperimentEnabledVersion(ExperimentalFlag flag,
-    {Map<ExperimentalFlag, Version> experimentReleasedVersionForTesting}) {
-  Version version;
-  if (experimentReleasedVersionForTesting != null) {
-    version = experimentReleasedVersionForTesting[flag];
+/// Returns the version in which [flag] is enabled for the library with the
+/// [canonicalUri].
+Version getExperimentEnabledVersionInLibrary(
+    ExperimentalFlag flag, Uri canonicalUri,
+    {AllowedExperimentalFlags allowedExperimentalFlags,
+    Map<ExperimentalFlag, bool> defaultExperimentFlagsForTesting,
+    Map<ExperimentalFlag, Version> experimentEnabledVersionForTesting,
+    Map<ExperimentalFlag, Version> experimentReleasedVersionForTesting}) {
+  allowedExperimentalFlags ??= defaultAllowedExperimentalFlags;
+
+  Set<ExperimentalFlag> allowedFlags;
+  if (canonicalUri.scheme == 'dart') {
+    allowedFlags = allowedExperimentalFlags.forSdkLibrary(canonicalUri.path);
+  } else if (canonicalUri.scheme == 'package') {
+    int index = canonicalUri.path.indexOf('/');
+    String packageName;
+    if (index >= 0) {
+      packageName = canonicalUri.path.substring(0, index);
+    } else {
+      packageName = canonicalUri.path;
+    }
+    allowedFlags = allowedExperimentalFlags.forPackage(packageName);
   }
-  version ??= experimentReleasedVersion[flag];
-  assert(version != null, "No version for enabling $flag.");
+  Version version;
+  bool enabledByDefault;
+  if (defaultExperimentFlagsForTesting != null) {
+    enabledByDefault = defaultExperimentFlagsForTesting[flag];
+  }
+  enabledByDefault ??= defaultExperimentalFlags[flag];
+  if (!enabledByDefault ||
+      allowedFlags != null && allowedFlags.contains(flag)) {
+    // If the feature is not enabled by default or is enabled by the allowed
+    // list use the experiment release version.
+    if (experimentReleasedVersionForTesting != null) {
+      version = experimentReleasedVersionForTesting[flag];
+    }
+    version ??= experimentReleasedVersion[flag];
+  } else {
+    // If the feature is enabled by default and is not enabled by the allowed
+    // list use the enabled version.
+    if (experimentEnabledVersionForTesting != null) {
+      version = experimentEnabledVersionForTesting[flag];
+    }
+    version ??= experimentEnabledVersion[flag];
+  }
+  assert(version != null, "No version for enabling $flag in $canonicalUri.");
   return version;
 }
diff --git a/pkg/front_end/lib/src/api_prototype/language_version.dart b/pkg/front_end/lib/src/api_prototype/language_version.dart
index a77b716..02db78f 100644
--- a/pkg/front_end/lib/src/api_prototype/language_version.dart
+++ b/pkg/front_end/lib/src/api_prototype/language_version.dart
@@ -23,8 +23,7 @@
 
 import 'compiler_options.dart' show CompilerOptions;
 
-import 'experimental_flags.dart'
-    show ExperimentalFlag, experimentReleasedVersion;
+import 'experimental_flags.dart' show ExperimentalFlag;
 import 'file_system.dart' show FileSystem, FileSystemException;
 
 /// Gets the language version for a specific URI.
@@ -34,7 +33,8 @@
 /// specifies a language version that's too high).
 ///
 /// The language version returned is valid though.
-Future<Version> languageVersionForUri(Uri uri, CompilerOptions options) async {
+Future<VersionAndPackageUri> languageVersionForUri(
+    Uri uri, CompilerOptions options) async {
   return await CompilerContext.runWithOptions(
       new ProcessedOptions(options: options, inputs: [uri]), (context) async {
     // Get largest valid version / default version.
@@ -65,6 +65,13 @@
       fileUri = uri;
       package = uriTranslator.packages.packageOf(uri);
     }
+    Uri packageUri = uri;
+    if (packageUri.scheme != 'dart' &&
+        packageUri.scheme != 'package' &&
+        package != null &&
+        package.name != null) {
+      packageUri = new Uri(scheme: 'package', path: package.name);
+    }
 
     // Check file content for @dart annotation.
     int major;
@@ -102,7 +109,7 @@
     }
     if (major != null && minor != null) {
       // The file decided. Return result.
-      return new Version(major, minor);
+      return new VersionAndPackageUri(new Version(major, minor), packageUri);
     }
 
     // Check package.
@@ -119,11 +126,13 @@
     }
     if (major != null && minor != null) {
       // The package decided. Return result.
-      return new Version(major, minor);
+      return new VersionAndPackageUri(new Version(major, minor), packageUri);
     }
 
     // Return default.
-    return new Version(currentSdkVersionMajor, currentSdkVersionMinor);
+    return new VersionAndPackageUri(
+        new Version(currentSdkVersionMajor, currentSdkVersionMinor),
+        packageUri);
   });
 }
 
@@ -134,6 +143,16 @@
   // This method is here in order to use the opt out hack here for test
   // sources.
   if (SourceLibraryBuilder.isOptOutTest(uri)) return true;
-  Version uriVersion = await languageVersionForUri(uri, options);
-  return (uriVersion < experimentReleasedVersion[ExperimentalFlag.nonNullable]);
+  VersionAndPackageUri versionAndLibraryUri =
+      await languageVersionForUri(uri, options);
+  return (versionAndLibraryUri.version <
+      options.getExperimentEnabledVersionInLibrary(
+          ExperimentalFlag.nonNullable, versionAndLibraryUri.packageUri));
+}
+
+class VersionAndPackageUri {
+  final Version version;
+  final Uri packageUri;
+
+  VersionAndPackageUri(this.version, this.packageUri);
 }
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 6682c79..1c158cd 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -353,15 +353,12 @@
   /// the 'allowed_experiments.json' file for this library.
   bool isExperimentEnabledInLibrary(
       flags.ExperimentalFlag flag, Uri importUri) {
-    return flags.isExperimentEnabledInLibrary(flag, importUri,
-        experimentalFlags: _raw.experimentalFlags,
-        allowedExperimentalFlags: _raw.allowedExperimentalFlagsForTesting);
+    return _raw.isExperimentEnabledInLibrary(flag, importUri);
   }
 
-  Version getExperimentEnabledVersion(flags.ExperimentalFlag flag) {
-    return flags.getExperimentEnabledVersion(flag,
-        experimentReleasedVersionForTesting:
-            _raw.experimentReleasedVersionForTesting);
+  Version getExperimentEnabledVersionInLibrary(
+      flags.ExperimentalFlag flag, Uri importUri) {
+    return _raw.getExperimentEnabledVersionInLibrary(flag, importUri);
   }
 
   Component _validateNullSafetyMode(Component component) {
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 607bf99..4f7945b 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -327,6 +327,7 @@
     _fieldEncoding.registerMembers(library, this, f);
   }
 
+  /// Builds the core AST structures for this field as needed for the outline.
   void build(SourceLibraryBuilder libraryBuilder) {
     if (type != null) {
       // notInstanceContext is set to true for extension fields as they
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 05c1bc4..fef6b53 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -149,6 +149,7 @@
   @override
   void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes) {}
 
+  /// Builds the core AST structures for this member as needed for the outline.
   void buildMembers(
       LibraryBuilder library, void Function(Member, BuiltMemberKind) f);
 
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 0bd7da5..7942b40 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -332,13 +332,12 @@
         importUri.scheme != 'dart' || _packageUri == null,
         "Package uri '$_packageUri' set on dart: library with import uri "
         "'${importUri}'.");
-    updateLibraryNNBDSettings();
   }
 
   bool _enableVarianceInLibrary;
   bool _enableNonfunctionTypeAliasesInLibrary;
   bool _enableNonNullableInLibrary;
-  Version _enableNonNullableVersionCache;
+  Version _enableNonNullableVersionInLibrary;
   bool _enableTripleShiftInLibrary;
   bool _enableExtensionMethodsInLibrary;
 
@@ -360,8 +359,10 @@
       loader.target.isExperimentEnabledInLibrary(
           ExperimentalFlag.nonNullable, _packageUri ?? importUri);
 
-  Version get _enableNonNullableVersion => _enableNonNullableVersionCache ??=
-      loader.target.getExperimentEnabledVersion(ExperimentalFlag.nonNullable);
+  Version get enableNonNullableVersionInLibrary =>
+      _enableNonNullableVersionInLibrary ??= loader.target
+          .getExperimentEnabledVersionInLibrary(
+              ExperimentalFlag.nonNullable, _packageUri ?? importUri);
 
   bool get enableTripleShiftInLibrary => _enableTripleShiftInLibrary ??=
       loader.target.isExperimentEnabledInLibrary(
@@ -434,10 +435,30 @@
     return type;
   }
 
+  bool _isNonNullableByDefault;
+
   @override
-  bool get isNonNullableByDefault =>
+  bool get isNonNullableByDefault {
+    assert(
+        _isNonNullableByDefault == null ||
+            _isNonNullableByDefault == _computeIsNonNullableByDefault(),
+        "Unstable isNonNullableByDefault property, changed "
+        "from ${_isNonNullableByDefault} to "
+        "${_computeIsNonNullableByDefault()}");
+    return _ensureIsNonNullableByDefault();
+  }
+
+  bool _ensureIsNonNullableByDefault() {
+    if (_isNonNullableByDefault == null) {
+      _isNonNullableByDefault = _computeIsNonNullableByDefault();
+      updateLibraryNNBDSettings();
+    }
+    return _isNonNullableByDefault;
+  }
+
+  bool _computeIsNonNullableByDefault() =>
       enableNonNullableInLibrary &&
-      languageVersion.version >= _enableNonNullableVersion &&
+      languageVersion.version >= enableNonNullableVersionInLibrary &&
       !isOptOutTest(library.importUri);
 
   static bool isOptOutTest(Uri uri) {
@@ -480,6 +501,7 @@
       }
     }
     _languageVersion.isFinal = true;
+    _ensureIsNonNullableByDefault();
   }
 
   @override
@@ -904,6 +926,7 @@
     return true;
   }
 
+  /// Builds the core AST structure of this library as needed for the outline.
   Library build(LibraryBuilder coreLibrary, {bool modifyTarget}) {
     assert(implementationBuilders.isEmpty);
     canAddImplementationBuilders = true;
@@ -955,8 +978,6 @@
           reference: referenceFrom?.reference));
     }
 
-    // TODO(CFE Team): Is this really needed in two places?
-    updateLibraryNNBDSettings();
     return library;
   }
 
@@ -2552,6 +2573,7 @@
     MetadataBuilder.buildAnnotations(library, metadata, this, null, null);
   }
 
+  /// Builds the core AST structures for [declaration] needed for the outline.
   void buildBuilder(Builder declaration, LibraryBuilder coreLibrary) {
     String findDuplicateSuffix(Builder declaration) {
       if (declaration.next != null) {
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 14803dd..50dcccf 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -251,7 +251,7 @@
         configuration: new ScannerConfiguration(
             enableTripleShift: library.enableTripleShiftInLibrary,
             enableExtensionMethods: library.enableExtensionMethodsInLibrary,
-            enableNonNullable: library.isNonNullableByDefault),
+            enableNonNullable: library.enableNonNullableInLibrary),
         languageVersionChanged:
             (Scanner scanner, LanguageVersionToken version) {
       if (!suppressLexicalErrors) {
@@ -346,8 +346,7 @@
       // libraries with no corresponding package config we generate a message
       // per library.
       Map<String, List<LibraryBuilder>> libraryByPackage = {};
-      Version enableNonNullableVersion =
-          target.getExperimentEnabledVersion(ExperimentalFlag.nonNullable);
+      Map<Package, Version> enableNonNullableVersionByPackage = {};
       for (LibraryBuilder libraryBuilder in _strongOptOutLibraries) {
         Package package =
             target.uriTranslator.getPackage(libraryBuilder.importUri);
@@ -355,6 +354,11 @@
         if (package != null &&
             package.languageVersion != null &&
             package.languageVersion is! InvalidLanguageVersion) {
+          Version enableNonNullableVersion =
+              enableNonNullableVersionByPackage[package] ??=
+                  target.getExperimentEnabledVersionInLibrary(
+                      ExperimentalFlag.nonNullable,
+                      new Uri(scheme: 'package', path: package.name));
           Version version = new Version(
               package.languageVersion.major, package.languageVersion.minor);
           if (version < enableNonNullableVersion) {
@@ -908,6 +912,7 @@
     return handleHierarchyCycles(objectClass);
   }
 
+  /// Builds the core AST structure needed for the outline of the component.
   void buildComponent() {
     builders.forEach((Uri uri, LibraryBuilder library) {
       if (library.loader == this) {
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart b/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
index ba35905..0e6a737 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
@@ -14,7 +14,7 @@
 import 'package:front_end/src/api_prototype/experimental_flags.dart';
 
 import 'package:kernel/ast.dart'
-    show AsyncMarker, Expression, FunctionNode, TreeNode, Version;
+    show AsyncMarker, Expression, FunctionNode, TreeNode;
 
 import '../fasta_codes.dart';
 
@@ -90,13 +90,11 @@
   void reportMissingNonNullableSupport(Token token) {
     assert(!libraryBuilder.isNonNullableByDefault);
     assert(token != null);
-    Version enableNonNullableVersion = libraryBuilder.loader.target
-        .getExperimentEnabledVersion(ExperimentalFlag.nonNullable);
     if (libraryBuilder.enableNonNullableInLibrary) {
       if (libraryBuilder.languageVersion.isExplicit) {
         addProblem(
-            templateNonNullableOptOutExplicit
-                .withArguments(enableNonNullableVersion.toText()),
+            templateNonNullableOptOutExplicit.withArguments(
+                libraryBuilder.enableNonNullableVersionInLibrary.toText()),
             token.charOffset,
             token.charCount,
             context: <LocatedMessage>[
@@ -107,17 +105,19 @@
             ]);
       } else {
         addProblem(
-            templateNonNullableOptOutImplicit
-                .withArguments(enableNonNullableVersion.toText()),
+            templateNonNullableOptOutImplicit.withArguments(
+                libraryBuilder.enableNonNullableVersionInLibrary.toText()),
             token.charOffset,
             token.charCount);
       }
     } else if (!libraryBuilder.loader.target
         .isExperimentEnabledGlobally(ExperimentalFlag.nonNullable)) {
-      if (libraryBuilder.languageVersion.version < enableNonNullableVersion) {
+      if (libraryBuilder.languageVersion.version <
+          libraryBuilder.enableNonNullableVersionInLibrary) {
         addProblem(
             templateExperimentNotEnabledNoFlagInvalidLanguageVersion
-                .withArguments(enableNonNullableVersion.toText()),
+                .withArguments(
+                    libraryBuilder.enableNonNullableVersionInLibrary.toText()),
             token.offset,
             noLength);
       } else {
@@ -125,8 +125,8 @@
       }
     } else {
       addProblem(
-          templateExperimentNotEnabled.withArguments(
-              'non-nullable', enableNonNullableVersion.toText()),
+          templateExperimentNotEnabled.withArguments('non-nullable',
+              libraryBuilder.enableNonNullableVersionInLibrary.toText()),
           token.offset,
           noLength);
     }
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index ebacbfc..57a4369 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -61,8 +61,9 @@
     return _options.isExperimentEnabledInLibrary(flag, importUri);
   }
 
-  Version getExperimentEnabledVersion(ExperimentalFlag flag) {
-    return _options.getExperimentEnabledVersion(flag);
+  Version getExperimentEnabledVersionInLibrary(
+      ExperimentalFlag flag, Uri importUri) {
+    return _options.getExperimentEnabledVersionInLibrary(flag, importUri);
   }
 
   bool isExperimentEnabledGlobally(ExperimentalFlag flag) {
diff --git a/pkg/front_end/test/enable_non_nullable/data/.dart_tool/package_config.json b/pkg/front_end/test/enable_non_nullable/data/.dart_tool/package_config.json
new file mode 100644
index 0000000..bc435fb
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/.dart_tool/package_config.json
@@ -0,0 +1,18 @@
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "allowed_package",
+      "rootUri": "../allowed_package/",
+      "packageUri": "lib/",
+      "languageVersion": "2.9"
+    },
+    {
+      "name": "not_allowed_package",
+      "rootUri": "../not_allowed_package/",
+      "packageUri": "lib/",
+      "languageVersion": "2.9"
+    }
+
+  ]
+}
\ No newline at end of file
diff --git a/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/unversioned_lib.dart b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/unversioned_lib.dart
new file mode 100644
index 0000000..a08c72e
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/unversioned_lib.dart
@@ -0,0 +1,3 @@
+// 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.
diff --git a/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_10_lib.dart b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_10_lib.dart
new file mode 100644
index 0000000..5f60217
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_10_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+// @dart=2.10
diff --git a/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_11_lib.dart b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_11_lib.dart
new file mode 100644
index 0000000..8de228b
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_11_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+// @dart=2.11
diff --git a/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_8_lib.dart b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_8_lib.dart
new file mode 100644
index 0000000..e7d43c5
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_8_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+// @dart=2.8
diff --git a/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_9_lib.dart b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_9_lib.dart
new file mode 100644
index 0000000..c2de893
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/allowed_package/lib/versioned_2_9_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+// @dart=2.9
diff --git a/pkg/front_end/test/enable_non_nullable/data/main.dart b/pkg/front_end/test/enable_non_nullable/data/main.dart
new file mode 100644
index 0000000..cc333b0
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/main.dart
@@ -0,0 +1,21 @@
+// 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.
+
+import 'package:allowed_package/unversioned_lib.dart';
+import 'package:allowed_package/versioned_2_8_lib.dart';
+import 'package:allowed_package/versioned_2_9_lib.dart';
+import 'package:allowed_package/versioned_2_10_lib.dart';
+import 'package:allowed_package/versioned_2_11_lib.dart';
+import 'package:not_allowed_package/unversioned_lib.dart';
+import 'package:not_allowed_package/versioned_2_8_lib.dart';
+import 'package:not_allowed_package/versioned_2_9_lib.dart';
+import 'package:not_allowed_package/versioned_2_10_lib.dart';
+import 'package:not_allowed_package/versioned_2_11_lib.dart';
+import 'unversioned_lib.dart';
+import 'versioned_2_8_lib.dart';
+import 'versioned_2_9_lib.dart';
+import 'versioned_2_10_lib.dart';
+import 'versioned_2_11_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/unversioned_lib.dart b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/unversioned_lib.dart
new file mode 100644
index 0000000..a08c72e
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/unversioned_lib.dart
@@ -0,0 +1,3 @@
+// 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.
diff --git a/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_10_lib.dart b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_10_lib.dart
new file mode 100644
index 0000000..5f60217
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_10_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+// @dart=2.10
diff --git a/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_11_lib.dart b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_11_lib.dart
new file mode 100644
index 0000000..8de228b
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_11_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+// @dart=2.11
diff --git a/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_8_lib.dart b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_8_lib.dart
new file mode 100644
index 0000000..e7d43c5
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_8_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+// @dart=2.8
diff --git a/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_9_lib.dart b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_9_lib.dart
new file mode 100644
index 0000000..c2de893
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/not_allowed_package/lib/versioned_2_9_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+// @dart=2.9
diff --git a/pkg/front_end/test/enable_non_nullable/data/unversioned_lib.dart b/pkg/front_end/test/enable_non_nullable/data/unversioned_lib.dart
new file mode 100644
index 0000000..a08c72e
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/unversioned_lib.dart
@@ -0,0 +1,3 @@
+// 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.
diff --git a/pkg/front_end/test/enable_non_nullable/data/versioned_2_10_lib.dart b/pkg/front_end/test/enable_non_nullable/data/versioned_2_10_lib.dart
new file mode 100644
index 0000000..5f60217
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/versioned_2_10_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+// @dart=2.10
diff --git a/pkg/front_end/test/enable_non_nullable/data/versioned_2_11_lib.dart b/pkg/front_end/test/enable_non_nullable/data/versioned_2_11_lib.dart
new file mode 100644
index 0000000..8de228b
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/versioned_2_11_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+// @dart=2.11
diff --git a/pkg/front_end/test/enable_non_nullable/data/versioned_2_8_lib.dart b/pkg/front_end/test/enable_non_nullable/data/versioned_2_8_lib.dart
new file mode 100644
index 0000000..e7d43c5
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/versioned_2_8_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+// @dart=2.8
diff --git a/pkg/front_end/test/enable_non_nullable/data/versioned_2_9_lib.dart b/pkg/front_end/test/enable_non_nullable/data/versioned_2_9_lib.dart
new file mode 100644
index 0000000..c2de893
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/data/versioned_2_9_lib.dart
@@ -0,0 +1,5 @@
+// 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.
+
+// @dart=2.9
diff --git a/pkg/front_end/test/enable_non_nullable/enable_non_nullable_test.dart b/pkg/front_end/test/enable_non_nullable/enable_non_nullable_test.dart
new file mode 100644
index 0000000..d6feb1d
--- /dev/null
+++ b/pkg/front_end/test/enable_non_nullable/enable_non_nullable_test.dart
@@ -0,0 +1,128 @@
+// Copyright (c) 2019, 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.md file.
+
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+import 'package:front_end/src/api_prototype/compiler_options.dart';
+import 'package:front_end/src/api_prototype/experimental_flags.dart';
+import 'package:front_end/src/api_prototype/kernel_generator.dart';
+import 'package:front_end/src/api_prototype/language_version.dart';
+import 'package:front_end/src/compute_platform_binaries_location.dart';
+import 'package:kernel/ast.dart';
+
+/// The version used in this test as the experiment release version.
+const Version experimentReleaseVersion = const Version(2, 9);
+
+/// The version used in this test as the experiment enabled version.
+const Version experimentEnabledVersion = const Version(2, 10);
+
+main() async {
+  print('--------------------------------------------------------------------');
+  print('Test off-by-default with command-line flag');
+  print('--------------------------------------------------------------------');
+  await test(
+      enableNonNullableByDefault: false,
+      // When the flag is off by default, the experiment release version should
+      // be used as the opt-in criterion for all libraries.
+      versionImpliesOptIn: experimentReleaseVersion,
+      versionOptsInAllowed: experimentReleaseVersion);
+
+  print('--------------------------------------------------------------------');
+  print('Test on-by-default');
+  print('--------------------------------------------------------------------');
+  await test(
+      enableNonNullableByDefault: true,
+      // When the flag is on by default, the experiment release version should
+      // be used as the opt-in criterion only for libraries in allowed packages
+      // and the experiment enabled version should be used as the opt-in
+      // criterion for all other libraries.
+      versionImpliesOptIn: experimentEnabledVersion,
+      versionOptsInAllowed: experimentReleaseVersion);
+}
+
+test(
+    {bool enableNonNullableByDefault,
+    Version versionImpliesOptIn,
+    Version versionOptsInAllowed}) async {
+  CompilerOptions options = new CompilerOptions();
+  if (enableNonNullableByDefault) {
+    // Pretend non-nullable is on by default.
+    options.defaultExperimentFlagsForTesting = {
+      ExperimentalFlag.nonNullable: true
+    };
+  } else {
+    // Pretend non-nullable is off by default but enabled on command-line.
+    options
+      ..defaultExperimentFlagsForTesting = {ExperimentalFlag.nonNullable: false}
+      ..experimentalFlags = {ExperimentalFlag.nonNullable: true};
+  }
+
+  Uri sdkSummary = computePlatformBinariesLocation(forceBuildDir: true)
+      .resolve('vm_platform_strong.dill');
+  options
+    ..sdkSummary = sdkSummary
+    // Pretend current version is 2.11
+    ..currentSdkVersion = '2.11'
+    ..allowedExperimentalFlagsForTesting = new AllowedExperimentalFlags(
+        sdkDefaultExperiments:
+            defaultAllowedExperimentalFlags.sdkDefaultExperiments,
+        sdkLibraryExperiments:
+            defaultAllowedExperimentalFlags.sdkLibraryExperiments,
+        packageExperiments: {
+          ...defaultAllowedExperimentalFlags.packageExperiments,
+          'allowed_package': {ExperimentalFlag.nonNullable}
+        })
+    ..experimentReleasedVersionForTesting = const {
+      // Pretend non-nullable is released in version 2.9.
+      ExperimentalFlag.nonNullable: experimentReleaseVersion
+    }
+    ..experimentEnabledVersionForTesting = const {
+      // Pretend non-nullable is enabled in version 2.10.
+      ExperimentalFlag.nonNullable: experimentEnabledVersion
+    };
+
+  Directory directory = new Directory.fromUri(
+      Uri.base.resolve('pkg/front_end/test/enable_non_nullable/data/'));
+  CompilerResult result = await kernelForProgramInternal(
+      directory.uri.resolve('main.dart'), options,
+      retainDataForTesting: true);
+  for (Library library in result.component.libraries) {
+    if (library.importUri.scheme != 'dart') {
+      bool usesLegacy =
+          await uriUsesLegacyLanguageVersion(library.fileUri, options);
+      VersionAndPackageUri versionAndPackageUri =
+          await languageVersionForUri(library.fileUri, options);
+      bool isNonNullableByDefault = library.isNonNullableByDefault;
+      print('${library.fileUri}:');
+      print(' version=${versionAndPackageUri.version}');
+      print(' (package) uri=${versionAndPackageUri.packageUri}');
+      print(' isNonNullableByDefault=${isNonNullableByDefault}');
+      print(' uriUsesLegacyLanguageVersion=${usesLegacy}');
+      Expect.equals(library.languageVersion, versionAndPackageUri.version,
+          "Language version mismatch for ${library.importUri}");
+      Expect.equals(
+          !usesLegacy,
+          isNonNullableByDefault,
+          "Unexpected null-safe state for ${library.importUri}:"
+          " isNonNullableByDefault=$isNonNullableByDefault,"
+          " uriUsesLegacyLanguageVersion=$usesLegacy. "
+          "Computed version=${versionAndPackageUri.version},"
+          " (package) uri=${versionAndPackageUri.packageUri}");
+      Expect.isTrue(
+          library.languageVersion < versionImpliesOptIn ||
+              library.isNonNullableByDefault,
+          "Expected library ${library.importUri} with version "
+          "${library.languageVersion} to be opted in.");
+      Expect.isTrue(
+          versionAndPackageUri.packageUri.scheme != 'package' ||
+              !versionAndPackageUri.packageUri.path
+                  .startsWith('allowed_package') ||
+              library.languageVersion < versionOptsInAllowed ||
+              library.isNonNullableByDefault,
+          "Expected allowed library ${library.importUri} with version "
+          "${library.languageVersion} to be opted in.");
+    }
+  }
+}
diff --git a/pkg/front_end/test/language_versioning/language_versioning_test.dart b/pkg/front_end/test/language_versioning/language_versioning_test.dart
index 4146239..b44c90d 100644
--- a/pkg/front_end/test/language_versioning/language_versioning_test.dart
+++ b/pkg/front_end/test/language_versioning/language_versioning_test.dart
@@ -87,9 +87,11 @@
     for (Library library in component.libraries) {
       if (library.importUri.scheme == "dart") continue;
       Version lvFile =
-          await lv.languageVersionForUri(library.fileUri, stashedOptions);
+          (await lv.languageVersionForUri(library.fileUri, stashedOptions))
+              .version;
       Version lvImportUri =
-          await lv.languageVersionForUri(library.importUri, stashedOptions);
+          (await lv.languageVersionForUri(library.importUri, stashedOptions))
+              .version;
       if ((lvFile != lvImportUri || lvFile != library.languageVersion)) {
         throw """
 Language version disagreement:
diff --git a/pkg/front_end/test/lint_test.status b/pkg/front_end/test/lint_test.status
index cc1e0e3..10f7b68 100644
--- a/pkg/front_end/test/lint_test.status
+++ b/pkg/front_end/test/lint_test.status
@@ -8,6 +8,7 @@
 _fe_analyzer_shared/lib/src/scanner/string_scanner/ImportsTwice: Fail
 _fe_analyzer_shared/lib/src/scanner/token_impl/ImportsTwice: Fail
 _fe_analyzer_shared/lib/src/scanner/utf8_bytes_scanner/ImportsTwice: Fail
+front_end/lib/src/api_prototype/compiler_options/ImportsTwice: Fail
 front_end/lib/src/api_prototype/compiler_options/Exports: Fail
 front_end/lib/src/api_prototype/constant_evaluator/Exports: Fail
 front_end/lib/src/api_prototype/front_end/Exports: Fail
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_bound_access.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_bound_access.dart.weak.expect
index 080ff9e..dec49a6 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_bound_access.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_bound_access.dart.weak.expect
@@ -13,7 +13,7 @@
 class DynamicClass<T extends dynamic = dynamic, S extends self::DynamicClass::T* = dynamic> extends core::Object {
   generic-covariant-impl field self::DynamicClass::T* field1;
   generic-covariant-impl field self::DynamicClass::T* field2;
-  constructor •(self::DynamicClass::T* field1, self::DynamicClass::T* field2) → self::DynamicClass<self::DynamicClass::T%, self::DynamicClass::S*>*
+  constructor •(self::DynamicClass::T* field1, self::DynamicClass::T* field2) → self::DynamicClass<self::DynamicClass::T*, self::DynamicClass::S*>*
     : self::DynamicClass::field1 = field1, self::DynamicClass::field2 = field2, super core::Object::•()
     ;
   method method() → dynamic
diff --git a/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/not_allowed_package/lib/versioned_2_9_lib.dart b/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/not_allowed_package/lib/versioned_2_9_lib.dart
index 43a931e..ff693f6 100644
--- a/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/not_allowed_package/lib/versioned_2_9_lib.dart
+++ b/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/not_allowed_package/lib/versioned_2_9_lib.dart
@@ -4,4 +4,4 @@
 
 // @dart=2.9
 
-int? versioned_2_9_AllowedPackage; // ok
\ No newline at end of file
+int? versioned_2_9_AllowedPackage; // error
\ No newline at end of file
diff --git a/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/versioned_2_9_lib.dart b/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/versioned_2_9_lib.dart
index 6df385a..7a9a3ee 100644
--- a/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/versioned_2_9_lib.dart
+++ b/pkg/front_end/testcases/nnbd_mixed/experiment_release_version/versioned_2_9_lib.dart
@@ -4,4 +4,4 @@
 
 // @dart=2.9
 
-int? versioned_2_9_Library; // ok
\ No newline at end of file
+int? versioned_2_9_Library; // error
\ No newline at end of file
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 47f67ff..deda925 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -480,6 +480,7 @@
     "exclude": [
       "^pkg/analysis_server/lib/src/analysis_server\\.dart",
       "test/analyser_ignored/",
+      "test/enable_non_nullable/data/",
       "test/extensions/data/",
       "test/id_testing/data/",
       "test/language_versioning/data/",
diff --git a/tools/VERSION b/tools/VERSION
index 82fc3c8..8436a26 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 11
 PATCH 0
-PRERELEASE 215
+PRERELEASE 216
 PRERELEASE_PATCH 0
\ No newline at end of file