Version 2.10.0-40.0.dev

Merge commit 'd2057a0b5785a526e6f73b8f5f0c49004499d767' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 3136266..515b734 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2020-08-13T10:20:32.864803",
+  "generated": "2020-08-17T14:05:33.104579",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -202,7 +202,7 @@
       "name": "dart_internal",
       "rootUri": "../pkg/dart_internal",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.10"
     },
     {
       "name": "dart_style",
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index 1a89506..37ee42d 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -313,7 +313,7 @@
   /// left operand has the type [leftType] and whose right operand has the type
   /// [rightType], given that resolution has so far produced the [currentType].
   DartType refineBinaryExpressionType(DartType leftType, TokenType operator,
-      DartType rightType, DartType currentType);
+      DartType rightType, DartType currentType, MethodElement operatorElement);
 
   @override
   DartType resolveToBound(DartType type) {
@@ -1346,7 +1346,7 @@
 
   @override
   DartType refineBinaryExpressionType(DartType leftType, TokenType operator,
-      DartType rightType, DartType currentType) {
+      DartType rightType, DartType currentType, MethodElement operatorElement) {
     if (isNonNullableByDefault) {
       return _refineBinaryExpressionTypeNullSafe(
           leftType, operator, rightType, currentType);
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 70cc4ba..b9ce65f 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -20,7 +20,7 @@
    */
   static const HintCode CAN_BE_NULL_AFTER_NULL_AWARE = HintCode(
       'CAN_BE_NULL_AFTER_NULL_AWARE',
-      "The target expression uses '?.', so its value can be null.",
+      "The receiver uses '?.', so its value can be null.",
       correction: "Replace the '.' with a '?.' in the invocation.");
 
   /**
@@ -1533,10 +1533,9 @@
    */
   static const HintCode RECEIVER_OF_TYPE_NEVER = HintCode(
       'RECEIVER_OF_TYPE_NEVER',
-      'The receiver expression is of type Never, and will never complete '
-          'with a value.',
-      correction: 'Try checking for throw expressions or type errors in the'
-          ' target expression');
+      "The receiver is of type 'Never', and will never complete with a value.",
+      correction: "Try checking for throw expressions or type errors in the "
+          "receiver");
 
   /**
    * No parameters.
diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
index dcfb6a0..4490f2a 100644
--- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -313,6 +313,7 @@
         operator,
         rightType,
         type,
+        operatorElement,
       );
       _inferenceHelper.recordStaticType(node, type);
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
index db0d9c9..ccc0ab7 100644
--- a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
@@ -363,6 +363,7 @@
         node.operator.type,
         node.rightOperand.staticType,
         staticType,
+        node.staticElement,
       );
     }
     _inferenceHelper.recordStaticType(node, staticType);
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index a0b721c..11d59aa 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -2788,7 +2788,7 @@
   // #### Description
   //
   // The analyzer produces this diagnostic when an extension override is the
-  // target of the invocation of a static member. Similar to static members in
+  // receiver of the invocation of a static member. Similar to static members in
   // classes, the static members of an extension should be accessed using the
   // name of the extension, not an extension override.
   //
@@ -2867,8 +2867,8 @@
   // ```
   //
   // If there's a different extension that's valid for the type of the argument,
-  // then either replace the name of the extension or unwrap the target so that
-  // the correct extension is found.
+  // then either replace the name of the extension or unwrap the argument so
+  // that the correct extension is found.
   static const CompileTimeErrorCode EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE =
       CompileTimeErrorCode(
           'EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE',
@@ -2882,8 +2882,8 @@
   // #### Description
   //
   // The analyzer produces this diagnostic when an extension override is used as
-  // the target of a cascade expression. The value of a cascade expression
-  // `e..m` is the value of the target `e`, but extension overrides aren't
+  // the receiver of a cascade expression. The value of a cascade expression
+  // `e..m` is the value of the receiver `e`, but extension overrides aren't
   // expressions and don't have a value.
   //
   // #### Examples
@@ -2919,7 +2919,7 @@
       CompileTimeErrorCode(
           'EXTENSION_OVERRIDE_WITH_CASCADE',
           "Extension overrides have no value so they can't be used as the "
-              "target of a cascade expression.",
+              "receiver of a cascade expression.",
           correction: "Try using '.' instead of '..'.",
           hasPublishedDocs: true);
 
@@ -2963,7 +2963,7 @@
   // }
   // ```
   //
-  // If you don't want to invoke a member, then unwrap the target:
+  // If you don't want to invoke a member, then unwrap the argument:
   //
   // ```dart
   // extension E on int {
@@ -3544,8 +3544,8 @@
   static const CompileTimeErrorCode GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND =
       CompileTimeErrorCode('GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND',
           "Generic function types can't be used as type parameter bounds",
-          correction: "Try making the free variable in the function type part"
-              " of the larger declaration signature");
+          correction: "Try making the free variable in the function type part "
+              "of the larger declaration signature");
 
   /**
    * It is a compile-time error if a generic function type is used as an actual
@@ -5862,12 +5862,12 @@
   static const CompileTimeErrorCode NO_GENERATIVE_CONSTRUCTORS_IN_SUPERCLASS =
       CompileTimeErrorCode(
           'NO_GENERATIVE_CONSTRUCTOR_IN_SUPERCLASS',
-          "The class '{0}' cannot extend '{1}' because '{1}' only has factory"
-              " constructors (no generative constructors), and '{0}' has at"
-              ' least one generative constructor.',
-          correction: 'Try implementing the class instead, adding a generative'
-              " (not factory) constructor to the superclass {0}, or a factory"
-              ' constructor to the subclass.');
+          "The class '{0}' cannot extend '{1}' because '{1}' only has factory "
+              "constructors (no generative constructors), and '{0}' has at "
+              "least one generative constructor.",
+          correction: "Try implementing the class instead, adding a generative "
+              "(not factory) constructor to the superclass {0}, or a factory "
+              "constructor to the subclass.");
 
   /**
    * Parameters:
@@ -6608,8 +6608,8 @@
   static const CompileTimeErrorCode NON_GENERATIVE_CONSTRUCTOR =
       CompileTimeErrorCode(
           'NON_GENERATIVE_CONSTRUCTOR',
-          "The constructor '{0}' is a factory constructor, but must be a"
-              " generative constructor to be a valid superinitializer.",
+          "The constructor '{0}' is a factory constructor, but must be a "
+              "generative constructor to be a valid superinitializer.",
           correction:
               "Try calling a different constructor of the superclass, or "
               "making the called constructor not be a factory constructor.");
@@ -6627,12 +6627,12 @@
   static const CompileTimeErrorCode NON_GENERATIVE_IMPLICIT_CONSTRUCTOR =
       CompileTimeErrorCode(
           'NON_GENERATIVE_IMPLICIT_CONSTRUCTOR',
-          "The default constructor of superclass '{0}' (called by the implicit"
-              " default constructor of '{1}') must be a generative constructor,"
-              " but factory found.",
-          correction: 'Try adding an explicit constructor that has a different'
-              " superinitializer or changing the superclass constructor '{2}'"
-              " to not be a factory constructor.");
+          "The default constructor of superclass '{0}' (called by the implicit "
+              "default constructor of '{1}') must be a generative constructor, "
+              "but factory found.",
+          correction: "Try adding an explicit constructor that has a different "
+              "superinitializer or changing the superclass constructor '{2}' "
+              "to not be a factory constructor.");
 
   static const CompileTimeErrorCode NON_SYNC_FACTORY = CompileTimeErrorCode(
       'NON_SYNC_FACTORY',
@@ -7483,8 +7483,8 @@
           "Library is unnamed. Expected a URI not a library name '{0}' in the "
               "part-of directive.",
           correction:
-              "Try changing the part-of directive to a URI, or try including a"
-              " different part.");
+              "Try changing the part-of directive to a URI, or try including a "
+              "different part.");
 
   /**
    * 14.1 Imports: It is a compile-time error if the current library declares a
@@ -9493,7 +9493,7 @@
   // ```
   //
   // If a subclass adds a parameter with the name in question, then cast the
-  // target to the subclass:
+  // receiver to the subclass:
   //
   // ```dart
   // class C {
@@ -10259,8 +10259,8 @@
     'WRONG_TYPE_PARAMETER_VARIANCE_POSITION',
     "The '{0}' type parameter '{1}' can't be used in an '{2}' position.",
     correction: "Try removing the type parameter or change the explicit "
-        "variance modifier declaration for the type parameter to another one of"
-        " 'in', 'out', or 'inout'.",
+        "variance modifier declaration for the type parameter to another one "
+        "of 'in', 'out', or 'inout'.",
   );
 
   /**
@@ -10450,7 +10450,7 @@
   // #### Description
   //
   // The analyzer produces this diagnostic when a null-aware operator (`?.`,
-  // `?..`, `?[`, `?..[`, or `...?`) is used on a target that's known to be
+  // `?..`, `?[`, `?..[`, or `...?`) is used on a receiver that's known to be
   // non-nullable.
   //
   // #### Example
@@ -10489,8 +10489,8 @@
   static const StaticWarningCode INVALID_NULL_AWARE_OPERATOR =
       StaticWarningCode(
           'INVALID_NULL_AWARE_OPERATOR',
-          "The target expression can't be null, so the null-aware operator "
-              "'{0}' can't be used.",
+          "The receiver can't be null, so the null-aware operator '{0}' can't "
+              "be used.",
           correction: "Try replacing the operator '{0}' with '{1}'.",
           hasPublishedDocs: true);
 
@@ -10504,8 +10504,8 @@
       StaticWarningCodeWithUniqueName(
           'INVALID_NULL_AWARE_OPERATOR',
           'INVALID_NULL_AWARE_OPERATOR_AFTER_SHORT_CIRCUIT',
-          "The target expression can't be null because of short-circuiting, so "
-              "the null-aware operator '{0}' can't be used.",
+          "The receiver can't be null because of short-circuiting, so the "
+              "null-aware operator '{0}' can't be used.",
           correction: "Try replacing the operator '{0}' with '{1}'.",
           hasPublishedDocs: true);
 
@@ -10638,12 +10638,9 @@
   // }
   // ```
   static const StaticWarningCode UNNECESSARY_NON_NULL_ASSERTION =
-      StaticWarningCode(
-          'UNNECESSARY_NON_NULL_ASSERTION',
-          "The '!' will have no effect because the target expression can't be"
-              " null.",
-          correction: "Try removing the '!' operator.",
-          hasPublishedDocs: true);
+      StaticWarningCode('UNNECESSARY_NON_NULL_ASSERTION',
+          "The '!' will have no effect because the receiver can't be null.",
+          correction: "Try removing the '!' operator.", hasPublishedDocs: true);
 
   /**
    * Initialize a newly created error code to have the given [name]. The message
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 33db715..f036ec1 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -629,6 +629,7 @@
         op,
         rhsType,
         functionType.returnType,
+        methodElement,
       );
 
       // Check the argument for an implicit cast.
@@ -749,6 +750,7 @@
           TokenType.PLUS,
           rhsType,
           functionType.returnType,
+          element,
         );
 
         // Skip the argument check - `int` cannot be downcast.
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 8d007fc..28e0d25 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -2214,7 +2214,7 @@
 #### Description
 
 The analyzer produces this diagnostic when an extension override is the
-target of the invocation of a static member. Similar to static members in
+receiver of the invocation of a static member. Similar to static members in
 classes, the static members of an extension should be accessed using the
 name of the extension, not an extension override.
 
@@ -2286,8 +2286,8 @@
 {% endprettify %}
 
 If there's a different extension that's valid for the type of the argument,
-then either replace the name of the extension or unwrap the target so that
-the correct extension is found.
+then either replace the name of the extension or unwrap the argument so
+that the correct extension is found.
 
 ### extension_override_without_access
 
@@ -2330,7 +2330,7 @@
 }
 {% endprettify %}
 
-If you don't want to invoke a member, then unwrap the target:
+If you don't want to invoke a member, then unwrap the argument:
 
 {% prettify dart tag=pre+code %}
 extension E on int {
@@ -2344,14 +2344,14 @@
 
 ### extension_override_with_cascade
 
-_Extension overrides have no value so they can't be used as the target of a
+_Extension overrides have no value so they can't be used as the receiver of a
 cascade expression._
 
 #### Description
 
 The analyzer produces this diagnostic when an extension override is used as
-the target of a cascade expression. The value of a cascade expression
-`e..m` is the value of the target `e`, but extension overrides aren't
+the receiver of a cascade expression. The value of a cascade expression
+`e..m` is the value of the receiver `e`, but extension overrides aren't
 expressions and don't have a value.
 
 #### Examples
@@ -3445,16 +3445,15 @@
 
 ### invalid_null_aware_operator
 
-_The target expression can't be null because of short-circuiting, so the
-null-aware operator '{0}' can't be used._
+_The receiver can't be null because of short-circuiting, so the null-aware
+operator '{0}' can't be used._
 
-_The target expression can't be null, so the null-aware operator '{0}' can't be
-used._
+_The receiver can't be null, so the null-aware operator '{0}' can't be used._
 
 #### Description
 
 The analyzer produces this diagnostic when a null-aware operator (`?.`,
-`?..`, `?[`, `?..[`, or `...?`) is used on a target that's known to be
+`?..`, `?[`, `?..[`, or `...?`) is used on a receiver that's known to be
 non-nullable.
 
 #### Example
@@ -7646,7 +7645,7 @@
 {% endprettify %}
 
 If a subclass adds a parameter with the name in question, then cast the
-target to the subclass:
+receiver to the subclass:
 
 {% prettify dart tag=pre+code %}
 class C {
@@ -7895,7 +7894,7 @@
 
 ### unnecessary_non_null_assertion
 
-_The '!' will have no effect because the target expression can't be null._
+_The '!' will have no effect because the receiver can't be null._
 
 #### Description
 
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 2871956..f4bc3a6 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -250,6 +250,10 @@
   /// operate with a stronger guarantee.
   bool enableNullAssertions = false;
 
+  /// Whether to generate code asserting that non-nullable return values of
+  /// `@Native` methods are checked for being non-null.
+  bool enableNativeReturnNullAssertions = false;
+
   /// Whether to generate a source-map file together with the output program.
   bool generateSourceMap = true;
 
@@ -616,6 +620,11 @@
 
     if (_deferClassTypes) deferClassTypes = true;
     if (_noDeferClassTypes) deferClassTypes = false;
+
+    if (enableNullAssertions) {
+      // TODO(sra): Add a command-line flag to control this independently.
+      enableNativeReturnNullAssertions = true;
+    }
   }
 
   /// Returns `true` if warnings and hints are shown for all packages.
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 24104e5..dfc216c 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -1540,8 +1540,18 @@
 
       push(HInvokeExternal(targetElement, inputs, returnType, nativeBehavior,
           sourceInformation: null));
-      // TODO(johnniwinther): Provide source information.
       HInstruction value = pop();
+      // TODO(johnniwinther): Provide source information.
+      if (options.enableNativeReturnNullAssertions) {
+        if (_isNonNullableByDefault(functionNode)) {
+          DartType type = _getDartTypeIfValid(functionNode.returnType);
+          if (dartTypes.isNonNullableIfSound(type)) {
+            push(HNullCheck(value, _abstractValueDomain.excludeNull(returnType),
+                sticky: true));
+            value = pop();
+          }
+        }
+      }
       if (targetElement.isSetter) {
         _closeAndGotoExit(HGoto(_abstractValueDomain));
       } else {
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 661962a..7c50116 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -8,6 +8,7 @@
 import 'package:front_end/src/api_unstable/dart2js.dart' show Link;
 
 import '../common.dart';
+import '../common/metrics.dart';
 import '../common/names.dart';
 import '../common/codegen.dart' show CodegenRegistry;
 import '../common/tasks.dart' show Measurer, CompilerTask;
@@ -52,6 +53,7 @@
 class SsaCodeGeneratorTask extends CompilerTask {
   final CompilerOptions _options;
   final SourceInformationStrategy sourceInformationStrategy;
+  final _CodegenMetrics _metrics = _CodegenMetrics();
 
   SsaCodeGeneratorTask(
       Measurer measurer, this._options, this.sourceInformationStrategy)
@@ -60,6 +62,9 @@
   @override
   String get name => 'SSA code generator';
 
+  @override
+  Metrics get metrics => _metrics;
+
   js.Fun buildJavaScriptFunction(bool needsAsyncRewrite, FunctionEntity element,
       List<js.Parameter> parameters, js.Block body) {
     js.Fun finish(js.AsyncModifier asyncModifier) {
@@ -115,6 +120,7 @@
       SsaCodeGenerator codeGenerator = SsaCodeGenerator(
           this,
           _options,
+          _metrics,
           emitter,
           codegen.rtiSubstitutions,
           codegen.rtiRecipeEncoder,
@@ -143,6 +149,7 @@
       SsaCodeGenerator codeGenerator = SsaCodeGenerator(
           this,
           _options,
+          _metrics,
           emitter,
           codegen.rtiSubstitutions,
           codegen.rtiRecipeEncoder,
@@ -158,6 +165,34 @@
   }
 }
 
+class _CodegenMetrics extends MetricsBase {
+  int countHIf = 0;
+  int countHIfConstant = 0;
+  final countHInterceptor = CountMetric('count.HInterceptor');
+  final countHInterceptorGet = CountMetric('count.HInterceptor.getInterceptor');
+  final countHInterceptorOneshot = CountMetric('count.HInterceptor.oneShot');
+  final countHInterceptorConditionalConstant =
+      CountMetric('count.HInterceptor.conditionalConstant');
+
+  _CodegenMetrics();
+
+  @override
+  String get namespace => 'codegen';
+
+  @override
+  Iterable<Metric> get primary => [];
+
+  @override
+  Iterable<Metric> get secondary => [
+        CountMetric('count.HIf')..add(countHIf),
+        CountMetric('count.HIf.constant')..add(countHIfConstant),
+        countHInterceptor,
+        countHInterceptorGet,
+        countHInterceptorConditionalConstant,
+        countHInterceptorOneshot
+      ];
+}
+
 class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
   /// Returned by [expressionType] to tell how code can be generated for
   /// a subgraph.
@@ -186,6 +221,7 @@
   final Tracer _tracer;
   final JClosedWorld _closedWorld;
   final CodegenRegistry _registry;
+  final _CodegenMetrics _metrics;
 
   final Set<HInstruction> generateAtUseSite;
   final Set<HInstruction> controlFlowOperators;
@@ -232,6 +268,7 @@
   SsaCodeGenerator(
       this._codegenTask,
       this._options,
+      this._metrics,
       this._emitter,
       this._rtiSubstitutions,
       this._rtiRecipeEncoder,
@@ -1791,9 +1828,12 @@
 
   @override
   visitIf(HIf node) {
+    _metrics.countHIf++;
+    HInstruction condition = node.inputs[0];
+    if (condition.isConstant()) _metrics.countHIfConstant++;
+
     if (tryControlFlowOperation(node)) return;
 
-    HInstruction condition = node.inputs[0];
     HIfBlockInformation info = node.blockInformation.body;
 
     if (condition.isConstant()) {
@@ -1827,7 +1867,9 @@
 
   @override
   void visitInterceptor(HInterceptor node) {
+    _metrics.countHInterceptor.add();
     if (node.isConditionalConstantInterceptor) {
+      _metrics.countHInterceptorConditionalConstant.add();
       assert(node.inputs.length == 2);
       use(node.receiver);
       js.Expression receiverExpression = pop();
@@ -1835,6 +1877,7 @@
       js.Expression constant = pop();
       push(js.js('# && #', [receiverExpression, constant]));
     } else {
+      _metrics.countHInterceptorGet.add();
       assert(node.inputs.length == 1);
       _registry.registerSpecializedGetInterceptor(node.interceptedClasses);
       js.Name name = _namer.nameForGetInterceptor(node.interceptedClasses);
@@ -1922,6 +1965,8 @@
 
   @override
   void visitOneShotInterceptor(HOneShotInterceptor node) {
+    _metrics.countHInterceptor.add();
+    _metrics.countHInterceptorOneshot.add();
     List<js.Expression> arguments = visitArguments(node.inputs);
     js.Expression isolate =
         _namer.readGlobalObjectForLibrary(_commonElements.interceptorsLibrary);
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 9e5cdc5..72631d5 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -1548,18 +1548,20 @@
       : super(inputs, type);
 }
 
-/// A [HCheck] instruction is an instruction that might do a dynamic
-/// check at runtime on another instruction. To have proper instruction
-/// dependencies in the graph, instructions that depend on the check
-/// being done reference the [HCheck] instruction instead of the
-/// instruction itself.
+/// A [HCheck] instruction is an instruction that might do a dynamic check at
+/// runtime on an input instruction. To have proper instruction dependencies in
+/// the graph, instructions that depend on the check being done reference the
+/// [HCheck] instruction instead of the input instruction.
 abstract class HCheck extends HInstruction {
   HCheck(inputs, type) : super(inputs, type) {
     setUseGvn();
   }
+
   HInstruction get checkedInput => inputs[0];
+
   @override
   bool isJsStatement() => true;
+
   @override
   bool canThrow(AbstractValueDomain domain) => true;
 
@@ -3607,10 +3609,12 @@
 /// field getter or setter when the receiver might be null. In these cases, the
 /// [selector] and [field] members are assigned.
 class HNullCheck extends HCheck {
+  // A sticky check is not optimized away on the basis of the input type.
+  final bool sticky;
   Selector selector;
   FieldEntity field;
 
-  HNullCheck(HInstruction input, AbstractValue type)
+  HNullCheck(HInstruction input, AbstractValue type, {this.sticky = false})
       : super(<HInstruction>[input], type);
 
   @override
@@ -3632,6 +3636,7 @@
   bool dataEquals(HNullCheck other) => true;
 
   bool isRedundant(JClosedWorld closedWorld) {
+    if (sticky) return false;
     AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
     AbstractValue inputType = checkedInput.instructionType;
     return abstractValueDomain.isNull(inputType).isDefinitelyFalse;
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 9ff7388..0d00347 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -908,7 +908,7 @@
         AbstractValueFactory.fromNativeBehavior(nativeBehavior, _closedWorld);
     HInstruction receiver = node.inputs.last; // Drop interceptor.
     receiver = maybeGuardWithNullCheck(receiver, node, null);
-    HInvokeExternal result = HInvokeExternal(
+    HInstruction result = HInvokeExternal(
         method, [receiver], returnType, nativeBehavior,
         sourceInformation: node.sourceInformation);
     _registry.registerStaticUse(StaticUse.methodInlining(method, null));
@@ -919,7 +919,25 @@
     result.sideEffects.setDependsOnSomething();
     result.sideEffects.clearAllSideEffects();
     result.setUseGvn();
-    return result;
+
+    return maybeAddNativeReturnNullCheck(node, result, method);
+  }
+
+  HInstruction maybeAddNativeReturnNullCheck(
+      HInstruction node, HInstruction replacement, FunctionEntity method) {
+    if (_options.enableNativeReturnNullAssertions) {
+      if (method.library.isNonNullableByDefault) {
+        FunctionType type =
+            _closedWorld.elementEnvironment.getFunctionType(method);
+        if (_closedWorld.dartTypes.isNonNullableIfSound(type.returnType)) {
+          node.block.addBefore(node, replacement);
+          replacement = HNullCheck(replacement,
+              _abstractValueDomain.excludeNull(replacement.instructionType),
+              sticky: true);
+        }
+      }
+    }
+    return replacement;
   }
 
   // Try to 'inline' an instance setter call to a known native or js-interop
@@ -1025,14 +1043,15 @@
         AbstractValueFactory.fromNativeBehavior(nativeBehavior, _closedWorld);
     HInstruction receiver = inputs[1];
     receiver = maybeGuardWithNullCheck(receiver, node, null);
-    HInvokeExternal result = HInvokeExternal(
+    HInstruction result = HInvokeExternal(
         method,
         [receiver, ...inputs.skip(2)], // '2': Drop interceptor and receiver.
         returnType,
         nativeBehavior,
         sourceInformation: node.sourceInformation);
     _registry.registerStaticUse(StaticUse.methodInlining(method, null));
-    return result;
+
+    return maybeAddNativeReturnNullCheck(node, result, method);
   }
 
   @override
diff --git a/pkg/dart_internal/lib/extract_type_arguments.dart b/pkg/dart_internal/lib/extract_type_arguments.dart
index 218d075..4275e70 100644
--- a/pkg/dart_internal/lib/extract_type_arguments.dart
+++ b/pkg/dart_internal/lib/extract_type_arguments.dart
@@ -22,8 +22,8 @@
 /// print(extractIterableTypeArgument(iterable, <T>() => new Set<T>());
 /// // Prints "Instance of 'Set<int>'".
 /// ```
-Object extractIterableTypeArgument(
-        Iterable iterable, Object Function<T>() extract) =>
+Object? extractIterableTypeArgument(
+        Iterable iterable, Object? Function<T>() extract) =>
     internal.extractTypeArguments<Iterable>(iterable, extract);
 
 /// Given a [Map], invokes [extract], passing the [map]'s key and value type
@@ -40,5 +40,5 @@
 ///   // Prints "Instance of 'Two<String, int>'".
 /// }
 /// ```
-Object extractMapTypeArguments(Map map, Object Function<K, V>() extract) =>
+Object? extractMapTypeArguments(Map map, Object? Function<K, V>() extract) =>
     internal.extractTypeArguments<Map>(map, extract);
diff --git a/pkg/dart_internal/pubspec.yaml b/pkg/dart_internal/pubspec.yaml
index d499299..757bdf3 100644
--- a/pkg/dart_internal/pubspec.yaml
+++ b/pkg/dart_internal/pubspec.yaml
@@ -1,5 +1,7 @@
 name: dart_internal
-version: 0.1.10
+version: 0.1.11-nullsafety
+author: "Dart Team <misc@dartlang.org>"
+homepage: http://www.dartlang.org
 repository: https://github.com/dart-lang/sdk/tree/master/pkg/dart_internal
 description: >
   This package is not intended for wide use. It provides a temporary API to
@@ -16,4 +18,4 @@
 environment:
   # Restrict the upper bound so that we can remove support for this in a later
   # version of the SDK without it being a breaking change.
-  sdk: ">=2.0.0 <2.10.0"
+  sdk: ">=2.10.0-0.0 <2.10.0"
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index 52f6983..ff2d412 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -752,6 +752,7 @@
         combinerType,
         rhsType,
         combiner.returnType,
+        combiner,
       );
       if (!fixBuilder._typeSystem.isSubtypeOf(combinerReturnType, writeType)) {
         (fixBuilder._getChange(node) as NodeChangeForAssignmentLike)
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index f2d33c5..187cf92 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -603,11 +603,26 @@
                                      const char* path) {
   TextBuffer line(128);
   if (id != 1) {
-    line.Printf(",");
+    line.AddString(",\n");
   }
   line.Printf("{ \"id\": %" Pd ", \"path\": \"", id);
   line.AddEscapedString(path);
-  line.Printf("\" }");
+  line.AddString("\", \"libraries\": [\n");
+  Dart_Handle uris = Dart_LoadingUnitLibraryUris(id);
+  CHECK_RESULT(uris);
+  intptr_t length;
+  CHECK_RESULT(Dart_ListLength(uris, &length));
+  for (intptr_t i = 0; i < length; i++) {
+    const char* uri;
+    CHECK_RESULT(Dart_StringToCString(Dart_ListGetAt(uris, i), &uri));
+    if (i != 0) {
+      line.AddString(",\n");
+    }
+    line.AddString("\"");
+    line.AddEscapedString(uri);
+    line.AddString("\"");
+  }
+  line.AddString("]}");
   if (!manifest_file->Print("%s\n", line.buffer())) {
     PrintErrAndExit("Error: Unable to write file: %s\n\n",
                     loading_unit_manifest_filename);
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 8eebaed..d12d6c7 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -3685,6 +3685,8 @@
                                             intptr_t size);
 typedef void (*Dart_StreamingCloseCallback)(void* callback_data);
 
+DART_EXPORT Dart_Handle Dart_LoadingUnitLibraryUris(intptr_t loading_unit_id);
+
 // On Darwin systems, 'dlsym' adds an '_' to the beginning of the symbol name.
 // Use the '...CSymbol' definitions for resolving through 'dlsym'. The actual
 // symbol names in the objects are given by the '...AsmSymbol' definitions.
diff --git a/runtime/tests/vm/dart/incompatible_loading_unit_test.dart b/runtime/tests/vm/dart/incompatible_loading_unit_test.dart
index 1663e3a..5facc47 100644
--- a/runtime/tests/vm/dart/incompatible_loading_unit_test.dart
+++ b/runtime/tests/vm/dart/incompatible_loading_unit_test.dart
@@ -27,6 +27,25 @@
     throw "Cannot run test as $genSnapshot not available";
   }
 
+  sanitizedPartitioning(manifest) {
+    // Filter core libraries, relativize URIs, and sort to make the results less
+    // sensitive to compiler or test harness changes.
+    print(manifest);
+    var units = <List<String>>[];
+    for (var unit in manifest['loadingUnits']) {
+      var uris = <String>[];
+      for (var uri in unit['libraries']) {
+        if (uri.startsWith("dart:")) continue;
+        uris.add(Uri.file(uri).pathSegments.last);
+      }
+      uris.sort((a, b) => a.compareTo(b));
+      units.add(uris);
+    }
+    units.sort((a, b) => a.first.compareTo(b.first));
+    print(units);
+    return units;
+  }
+
   await withTempDir("incompatible-loading-unit-test", (String tempDir) async {
     final source1 = path.join(
         sdkDir, "runtime/tests/vm/dart_2/incompatible_loading_unit_1.dart");
@@ -67,6 +86,11 @@
     ]);
     var manifest = jsonDecode(await new File(manifest1).readAsString());
     Expect.equals(2, manifest["loadingUnits"].length);
+    // Note package:expect doesn't do deep equals on collections.
+    Expect.equals(
+        "[[incompatible_loading_unit_1.dart],"
+        " [incompatible_loading_unit_1_deferred.dart]]",
+        sanitizedPartitioning(manifest).toString());
     Expect.isTrue(await new File(deferredSnapshot1).exists());
 
     await run(genSnapshot, <String>[
@@ -76,8 +100,12 @@
       "--loading-unit-manifest=$manifest2",
       dill2,
     ]);
-    manifest = jsonDecode(await new File(manifest1).readAsString());
+    manifest = jsonDecode(await new File(manifest2).readAsString());
     Expect.equals(2, manifest["loadingUnits"].length);
+    Expect.equals(
+        "[[incompatible_loading_unit_2.dart],"
+        " [incompatible_loading_unit_2_deferred.dart]]",
+        sanitizedPartitioning(manifest).toString());
     Expect.isTrue(await new File(deferredSnapshot2).exists());
 
     // Works when used normally.
diff --git a/runtime/tests/vm/dart_2/incompatible_loading_unit_test.dart b/runtime/tests/vm/dart_2/incompatible_loading_unit_test.dart
index 1663e3a..5facc47 100644
--- a/runtime/tests/vm/dart_2/incompatible_loading_unit_test.dart
+++ b/runtime/tests/vm/dart_2/incompatible_loading_unit_test.dart
@@ -27,6 +27,25 @@
     throw "Cannot run test as $genSnapshot not available";
   }
 
+  sanitizedPartitioning(manifest) {
+    // Filter core libraries, relativize URIs, and sort to make the results less
+    // sensitive to compiler or test harness changes.
+    print(manifest);
+    var units = <List<String>>[];
+    for (var unit in manifest['loadingUnits']) {
+      var uris = <String>[];
+      for (var uri in unit['libraries']) {
+        if (uri.startsWith("dart:")) continue;
+        uris.add(Uri.file(uri).pathSegments.last);
+      }
+      uris.sort((a, b) => a.compareTo(b));
+      units.add(uris);
+    }
+    units.sort((a, b) => a.first.compareTo(b.first));
+    print(units);
+    return units;
+  }
+
   await withTempDir("incompatible-loading-unit-test", (String tempDir) async {
     final source1 = path.join(
         sdkDir, "runtime/tests/vm/dart_2/incompatible_loading_unit_1.dart");
@@ -67,6 +86,11 @@
     ]);
     var manifest = jsonDecode(await new File(manifest1).readAsString());
     Expect.equals(2, manifest["loadingUnits"].length);
+    // Note package:expect doesn't do deep equals on collections.
+    Expect.equals(
+        "[[incompatible_loading_unit_1.dart],"
+        " [incompatible_loading_unit_1_deferred.dart]]",
+        sanitizedPartitioning(manifest).toString());
     Expect.isTrue(await new File(deferredSnapshot1).exists());
 
     await run(genSnapshot, <String>[
@@ -76,8 +100,12 @@
       "--loading-unit-manifest=$manifest2",
       dill2,
     ]);
-    manifest = jsonDecode(await new File(manifest1).readAsString());
+    manifest = jsonDecode(await new File(manifest2).readAsString());
     Expect.equals(2, manifest["loadingUnits"].length);
+    Expect.equals(
+        "[[incompatible_loading_unit_2.dart],"
+        " [incompatible_loading_unit_2_deferred.dart]]",
+        sanitizedPartitioning(manifest).toString());
     Expect.isTrue(await new File(deferredSnapshot2).exists());
 
     // Works when used normally.
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index a9dfc83..a7882d7 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -6745,14 +6745,20 @@
   for (intptr_t id = 1; id < loading_units.Length(); id++) {
     void* write_callback_data = nullptr;
     void* write_debug_callback_data = nullptr;
-    next_callback(next_callback_data, id, &write_callback_data,
-                  &write_debug_callback_data);
+    {
+      TransitionVMToNative transition(T);
+      next_callback(next_callback_data, id, &write_callback_data,
+                    &write_debug_callback_data);
+    }
     CreateAppAOTSnapshot(write_callback, write_callback_data, strip, as_elf,
                          write_debug_callback_data, &data, data[id],
                          program_hash);
-    close_callback(write_callback_data);
-    if (write_debug_callback_data != nullptr) {
-      close_callback(write_debug_callback_data);
+    {
+      TransitionVMToNative transition(T);
+      close_callback(write_callback_data);
+      if (write_debug_callback_data != nullptr) {
+        close_callback(write_debug_callback_data);
+      }
     }
   }
 }
@@ -6899,6 +6905,37 @@
 #endif
 }
 
+DART_EXPORT Dart_Handle Dart_LoadingUnitLibraryUris(intptr_t loading_unit_id) {
+#if defined(TARGET_ARCH_IA32)
+  return Api::NewError("AOT compilation is not supported on IA32.");
+#elif !defined(DART_PRECOMPILER)
+  return Api::NewError(
+      "This VM was built without support for AOT compilation.");
+#else
+  DARTSCOPE(Thread::Current());
+  API_TIMELINE_DURATION(T);
+
+  const GrowableObjectArray& result =
+      GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
+  const GrowableObjectArray& libs =
+      GrowableObjectArray::Handle(Z, T->isolate()->object_store()->libraries());
+  Library& lib = Library::Handle(Z);
+  LoadingUnit& unit = LoadingUnit::Handle(Z);
+  String& uri = String::Handle(Z);
+  for (intptr_t i = 0; i < libs.Length(); i++) {
+    lib ^= libs.At(i);
+    unit = lib.loading_unit();
+    if (unit.IsNull() || (unit.id() != loading_unit_id)) {
+      continue;
+    }
+    uri = lib.url();
+    result.Add(uri);
+  }
+
+  return Api::NewHandle(T, Array::MakeFixedLength(result));
+#endif
+}
+
 #if (!defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME))
 
 // Any flag that affects how we compile code might cause a problem when the
diff --git a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart b/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
index e2922ca..2dc838d 100644
--- a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
@@ -57,7 +57,7 @@
 
 @patch
 @pragma('dart2js:noInline')
-Object extractTypeArguments<T>(T instance, Function extract) {
+Object? extractTypeArguments<T>(T instance, Function extract) {
   // This function is recognized and replaced with calls to js_runtime.
 
   // This call to [extract] is required to model that the function is called and
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index b904f9e..fa16bc6 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.dart
@@ -32,7 +32,7 @@
     native "Internal_makeFixedListUnmodifiable";
 
 @patch
-Object extractTypeArguments<T>(T instance, Function extract)
+Object? extractTypeArguments<T>(T instance, Function extract)
     native "Internal_extractTypeArguments";
 
 /// The returned string is a [_OneByteString] with uninitialized content.
diff --git a/tests/dart2js/native/null_assertions_opt_in_lib.dart b/tests/dart2js/native/null_assertions_opt_in_lib.dart
new file mode 100644
index 0000000..e08c788
--- /dev/null
+++ b/tests/dart2js/native/null_assertions_opt_in_lib.dart
@@ -0,0 +1,58 @@
+// 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 'native_testing.dart';
+
+abstract class Interface {
+  int get size;
+  String get name;
+  String? get optName;
+  int method1();
+  String method2();
+}
+
+@Native("AAA")
+class AAA implements Interface {
+  int get size native;
+  String get name native;
+  String? get optName native;
+  int method1() native;
+  String method2() native;
+}
+
+/// Returns an 'AAA' object that satisfies the interface.
+AAA makeA() native;
+
+/// Returns an 'AAA' object where each method breaks the interface's contract.
+AAA makeAX() native;
+
+void setup() {
+  JS('', r"""
+(function(){
+  function AAA(s,n,m1,m2) {
+    this.size = s;
+    this.name = n;
+    this.optName = n;
+    this._m1 = m1;
+    this._m2 = m2;
+  }
+  AAA.prototype.method1 = function(){return this._m1};
+  AAA.prototype.method2 = function(){return this._m2};
+
+  makeA = function() {return new AAA(100, 'Albert', 200, 'amazing!')};
+  makeAX = function() {return new AAA(void 0, void 0, void 0, void 0)};
+
+  self.nativeConstructor(AAA);
+})()""");
+}
+
+class BBB implements Interface {
+  int get size => 300;
+  String get name => 'Brenda';
+  String? get optName => name;
+  int method1() => 400;
+  String method2() => 'brilliant!';
+}
+
+List<Interface> items = [makeA(), BBB()];
diff --git a/tests/dart2js/native/null_assertions_test.dart b/tests/dart2js/native/null_assertions_test.dart
new file mode 100644
index 0000000..0a07785
--- /dev/null
+++ b/tests/dart2js/native/null_assertions_test.dart
@@ -0,0 +1,74 @@
+// 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.
+
+// Requirements=nnbd-weak
+// dart2jsOptions=--null-assertions
+
+// @dart=2.8
+
+// Test that `--null-assertions` injects null-checks on the returned value of
+// native methods with a non-nullable return type in an opt-in library.
+
+import 'native_testing.dart';
+import 'null_assertions_opt_in_lib.dart' as lib;
+
+// The 'Interface' version of the code is passed both native and Dart objects,
+// so there will be an interceptor dispatch to the method. This tests that the
+// null-check exists in the forwarding method.
+//
+// The 'AAA' version of the code is passed only objects of a single native
+// class, so the native method can be inlined (which happens in the optimizer).
+// This tests that the null-check exists in the 'inlined' code.
+
+@pragma('dart2js:noInline')
+String describeInterface(lib.Interface o) {
+  return '${o.name} ${o.method2()} ${o.size} ${o.method1()}';
+}
+
+@pragma('dart2js:noInline')
+String describeAAA(lib.AAA o) {
+  return '${o.name} ${o.method2()} ${o.size} ${o.method1()}';
+}
+
+@pragma('dart2js:noInline')
+void checkOptNameInterface(lib.Interface o, dynamic expected) {
+  Expect.equals(expected, o.optName);
+}
+
+@pragma('dart2js:noInline')
+void checkOptNameAAA(lib.AAA o, dynamic expected) {
+  Expect.equals(expected, o.optName);
+}
+
+const expectedA = 'Albert amazing! 100 200';
+const expectedB = 'Brenda brilliant! 300 400';
+
+void main() {
+  nativeTesting();
+  lib.setup();
+  lib.AAA a = lib.makeA();
+  lib.BBB b = lib.BBB();
+
+  Expect.equals(expectedA, describeInterface(a));
+  Expect.equals(expectedB, describeInterface(b));
+
+  Expect.equals(expectedA, describeAAA(a));
+
+  lib.AAA x = lib.makeAX(); // This object returns `null`!
+  Expect.throws(() => describeInterface(x));
+  Expect.throws(() => describeAAA(x));
+
+  Expect.throws(() => x.name);
+  Expect.throws(() => x.size);
+  Expect.throws(() => x.method1());
+  Expect.throws(() => x.method2());
+
+  // Now test that a nullable return type does not have a check.
+  checkOptNameInterface(a, 'Albert');
+  checkOptNameInterface(b, 'Brenda');
+  checkOptNameInterface(x, null);
+
+  checkOptNameAAA(a, 'Albert');
+  checkOptNameAAA(x, null);
+}
diff --git a/tests/language/unsorted/extract_type_arguments_test.dart b/tests/language/unsorted/extract_type_arguments_test.dart
index 52939c7..233dac4 100644
--- a/tests/language/unsorted/extract_type_arguments_test.dart
+++ b/tests/language/unsorted/extract_type_arguments_test.dart
@@ -39,7 +39,7 @@
   Expect.isTrue(called);
 
   // Returns result of function.
-  Object result = extractIterableTypeArgument(object, <T>() => new Set<T>());
+  Object? result = extractIterableTypeArgument(object, <T>() => new Set<T>());
   Expect.isTrue(result is Set<int>);
   Expect.isFalse(result is Set<bool>);
 
@@ -63,7 +63,7 @@
   Expect.isTrue(called);
 
   // Returns result of function.
-  Object result = extractMapTypeArguments(object, <K, V>() => new Two<K, V>());
+  Object? result = extractMapTypeArguments(object, <K, V>() => new Two<K, V>());
   Expect.isTrue(result is Two<String, int>);
   Expect.isFalse(result is Two<int, String>);
 
diff --git a/tools/VERSION b/tools/VERSION
index d5b4582..7306b60 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 10
 PATCH 0
-PRERELEASE 39
+PRERELEASE 40
 PRERELEASE_PATCH 0
\ No newline at end of file