Version 2.10.0-116.0.dev

Merge commit '8d68480746dbb7878bdc6e3926d0324760af6c5f' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
index deea96b..a533fdc 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -168,11 +168,24 @@
       returnType: nameForType(id, returnType));
 }
 
-DefaultArgument getDefaultStringParameterValue(ParameterElement param) {
-  if (param != null) {
-    var type = param.type;
-    if (type is InterfaceType && type.isDartCoreList) {
-      return DefaultArgument('[]', cursorPosition: 1);
+/// Return a default argument value for the given [parameter].
+DefaultArgument getDefaultStringParameterValue(ParameterElement parameter) {
+  if (parameter != null) {
+    var type = parameter.type;
+    if (type is InterfaceType) {
+      if (type.isDartCoreBool) {
+        return DefaultArgument('false');
+      } else if (type.isDartCoreDouble) {
+        return DefaultArgument('0.0');
+      } else if (type.isDartCoreInt) {
+        return DefaultArgument('0');
+      } else if (type.isDartCoreList) {
+        return DefaultArgument('[]', cursorPosition: 1);
+      } else if (type.isDartCoreMap) {
+        return DefaultArgument('{}', cursorPosition: 1);
+      } else if (type.isDartCoreString) {
+        return DefaultArgument("''", cursorPosition: 1);
+      }
     } else if (type is FunctionType) {
       var params = type.parameters
           .map((p) => '${getTypeString(p.type)}${p.name}')
@@ -181,9 +194,6 @@
       var text = '($params) {  }';
       return DefaultArgument(text, cursorPosition: text.length - 2);
     }
-
-    // TODO(pq): support map literals
-
   }
 
   return null;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_missing_required_argument.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_missing_required_argument.dart
index 065deff..cbd9a2d 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_missing_required_argument.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_missing_required_argument.dart
@@ -8,6 +8,7 @@
 import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 
@@ -43,7 +44,7 @@
     }
 
     if (targetElement is ExecutableElement) {
-      // Format: "Missing required argument 'foo"
+      // Format: "Missing required argument 'foo'."
       var messageParts = diagnostic.problemMessage.message.split("'");
       if (messageParts.length < 2) {
         return;
@@ -78,6 +79,15 @@
           }
         }
       }
+      var defaultValue = getDefaultStringParameterValue(missingParameter);
+      if (defaultValue == null &&
+          libraryElement.isNonNullableByDefault &&
+          missingParameter.type.nullabilitySuffix == NullabilitySuffix.none) {
+        // In a library opted in to Null Safety we don't want to propose an
+        // argument value of `null` for a parameter whose type doesn't allow
+        // `null`.
+        return;
+      }
 
       await builder.addDartFileEdit(file, (builder) {
         builder.addInsertion(offset, (builder) {
@@ -87,7 +97,6 @@
 
           builder.write('$_missingParameterName: ');
 
-          var defaultValue = getDefaultStringParameterValue(missingParameter);
           // Use defaultValue.cursorPosition if it's not null.
           if (defaultValue?.cursorPosition != null) {
             builder.write(
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index a979965..7160cf4 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -720,6 +720,9 @@
     CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER: [
       AddRequiredKeyword.newInstance,
     ],
+    CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT: [
+      AddMissingRequiredArgument.newInstance,
+    ],
     CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE: [
       ExtendClassForMixin.newInstance,
     ],
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart
index 11b0ee0..9dc2245 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -11,6 +12,7 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AddMissingRequiredArgumentTest);
+    defineReflectiveTests(AddMissingRequiredArgumentWithNullSafetyTest);
   });
 }
 
@@ -72,7 +74,7 @@
 }
 
 build() {
-  return new MyWidget(a: 1, b: null,);
+  return new MyWidget(a: 1, b: 0,);
 }
 ''');
   }
@@ -99,7 +101,7 @@
 }
 
 void f() {
-  A a = new A.named(a: null);
+  A a = new A.named(a: 0);
   print(a);
 }
 ''');
@@ -126,7 +128,7 @@
 import 'package:test/a.dart';
 
 main() {
-  A a = new A(a: null);
+  A a = new A(a: 0);
   print(a);
 }
 ''');
@@ -290,7 +292,7 @@
 
 test({@required int a, @required int bcd}) {}
 main() {
-  test(a: 3, bcd: null);
+  test(a: 3, bcd: 0);
 }
 ''');
   }
@@ -310,7 +312,7 @@
 
 test({@required int a, @required int bcd}) {}
 main() {
-  test(a: null);
+  test(a: 0);
 }
 ''', errorFilter: (error) => error.message.contains("'a'"));
   }
@@ -330,7 +332,7 @@
 
 test({@required int a, @required int bcd}) {}
 main() {
-  test(bcd: null);
+  test(bcd: 0);
 }
 ''', errorFilter: (error) => error.message.contains("'bcd'"));
   }
@@ -362,7 +364,7 @@
 
 build() {
   return new MyWidget(
-    foo: null,
+    foo: '',
     child: null,
   );
 }
@@ -396,7 +398,7 @@
 
 build() {
   return new MyWidget(
-    foo: null,
+    foo: '',
     children: null,
   );
 }
@@ -418,10 +420,10 @@
 
 test({@required int abc}) {}
 main() {
-  test(abc: null);
+  test(abc: 0);
 }
 ''');
-    assertLinkedGroup(change.linkedEditGroups[0], ['null);']);
+    assertLinkedGroup(change.linkedEditGroups[0], ['0);']);
   }
 
   Future<void> test_single_normal() async {
@@ -439,7 +441,7 @@
 
 test(String x, {@required int abc}) {}
 main() {
-  test("foo", abc: null);
+  test("foo", abc: 0);
 }
 ''');
   }
@@ -459,7 +461,71 @@
 
 test({@Required("Really who doesn't need an abc?") int abc}) {}
 main() {
-  test(abc: null);
+  test(abc: 0);
+}
+''');
+  }
+}
+
+@reflectiveTest
+class AddMissingRequiredArgumentWithNullSafetyTest extends FixProcessorTest {
+  @override
+  List<String> get experiments => [EnableString.non_nullable];
+
+  @override
+  FixKind get kind => DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT;
+
+  Future<void> test_nonNullable_supported() async {
+    await resolveTestUnit('''
+void f({required int x}) {}
+void g() {
+  f();
+}
+''');
+    await assertHasFix('''
+void f({required int x}) {}
+void g() {
+  f(x: 0);
+}
+''');
+  }
+
+  Future<void> test_nonNullable_unsupported() async {
+    await resolveTestUnit('''
+void f({required DateTime d}) {}
+void g() {
+  f();
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_nullable_supported() async {
+    await resolveTestUnit('''
+void f({required int? x}) {}
+void g() {
+  f();
+}
+''');
+    await assertHasFix('''
+void f({required int? x}) {}
+void g() {
+  f(x: 0);
+}
+''');
+  }
+
+  Future<void> test_nullable_unsupported() async {
+    await resolveTestUnit('''
+void f({required DateTime? x}) {}
+void g() {
+  f();
+}
+''');
+    await assertHasFix('''
+void f({required DateTime? x}) {}
+void g() {
+  f(x: null);
 }
 ''');
   }
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 2827fd4..ceb5d63 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -983,10 +983,11 @@
     if (variable != null) {
       Local local = _localsMap.getLocalVariable(variable);
       if (!_capturedVariables.contains(local)) {
+        // Receiver strengthening to non-null.
         DartType type = _localsMap.getLocalType(_elementMap, local);
         _state.updateLocal(
             _inferrer, _capturedAndBoxed, local, receiverType, node, type,
-            isNullable: selector.appliesToNullWithoutThrow());
+            excludeNull: !selector.appliesToNullWithoutThrow());
       }
     }
 
@@ -1445,11 +1446,16 @@
     ir.Expression operand = node.operand;
     if (operand is ir.VariableGet) {
       Local local = _localsMap.getLocalVariable(operand.variable);
-      DartType type = _elementMap.getDartType(node.type);
+      DartType localType = _elementMap.getDartType(node.type);
       LocalState stateAfterCheckWhenTrue = new LocalState.childPath(_state);
       LocalState stateAfterCheckWhenFalse = new LocalState.childPath(_state);
-      stateAfterCheckWhenTrue.narrowLocal(
-          _inferrer, _capturedAndBoxed, local, type, node);
+
+      // Narrow variable to tested type on true branch.
+      TypeInformation currentTypeInformation = stateAfterCheckWhenTrue
+          .readLocal(_inferrer, _capturedAndBoxed, local);
+      stateAfterCheckWhenTrue.updateLocal(_inferrer, _capturedAndBoxed, local,
+          currentTypeInformation, node, localType,
+          isCast: false);
       _setStateAfter(_state, stateAfterCheckWhenTrue, stateAfterCheckWhenFalse);
     }
   }
@@ -1462,10 +1468,18 @@
       DartType localType = _localsMap.getLocalType(_elementMap, local);
       LocalState stateAfterCheckWhenTrue = new LocalState.childPath(_state);
       LocalState stateAfterCheckWhenFalse = new LocalState.childPath(_state);
+
+      // Narrow tested variable to 'Null' on true branch.
       stateAfterCheckWhenTrue.updateLocal(_inferrer, _capturedAndBoxed, local,
           _types.nullType, node, localType);
-      stateAfterCheckWhenFalse.narrowLocal(_inferrer, _capturedAndBoxed, local,
-          _closedWorld.commonElements.objectType, node);
+
+      // Narrow tested variable to 'not null' on false branch.
+      TypeInformation currentTypeInformation = stateAfterCheckWhenFalse
+          .readLocal(_inferrer, _capturedAndBoxed, local);
+      stateAfterCheckWhenFalse.updateLocal(_inferrer, _capturedAndBoxed, local,
+          currentTypeInformation, node, _closedWorld.commonElements.objectType,
+          excludeNull: true);
+
       _setStateAfter(_state, stateAfterCheckWhenTrue, stateAfterCheckWhenFalse);
     }
   }
@@ -1620,7 +1634,7 @@
       DartType type = _localsMap.getLocalType(_elementMap, local);
       _state.updateLocal(
           _inferrer, _capturedAndBoxed, local, localFunctionType, node, type,
-          isNullable: false);
+          excludeNull: true);
     }
 
     // We don't put the closure in the work queue of the
@@ -1737,7 +1751,7 @@
       Local local = _localsMap.getLocalVariable(exception);
       _state.updateLocal(_inferrer, _capturedAndBoxed, local, mask, node,
           _dartTypes.dynamicType(),
-          isNullable: false /* `throw null` produces a NullThrownError */);
+          excludeNull: true /* `throw null` produces a NullThrownError */);
     }
     ir.VariableDeclaration stackTrace = node.stackTrace;
     if (stackTrace != null) {
@@ -2088,9 +2102,11 @@
       TypeInformation type,
       ir.Node node,
       DartType staticType,
-      {isNullable: true}) {
+      {isCast: true,
+      excludeNull: false}) {
     assert(type != null);
-    type = inferrer.types.narrowType(type, staticType, isNullable: isNullable);
+    type = inferrer.types
+        .narrowType(type, staticType, isCast: isCast, excludeNull: excludeNull);
 
     FieldEntity field = capturedAndBoxed[local];
     if (field != null) {
@@ -2100,17 +2116,6 @@
     }
   }
 
-  void narrowLocal(
-      InferrerEngine inferrer,
-      Map<Local, FieldEntity> capturedAndBoxed,
-      Local local,
-      DartType type,
-      ir.Node node) {
-    TypeInformation currentType = readLocal(inferrer, capturedAndBoxed, local);
-    updateLocal(inferrer, capturedAndBoxed, local, currentType, node, type,
-        isNullable: false);
-  }
-
   LocalState mergeFlow(InferrerEngine inferrer, LocalState other) {
     seenReturnOrThrow = false;
     seenBreakOrContinue = false;
diff --git a/pkg/compiler/lib/src/inferrer/type_system.dart b/pkg/compiler/lib/src/inferrer/type_system.dart
index 865fbcc..3817dc9 100644
--- a/pkg/compiler/lib/src/inferrer/type_system.dart
+++ b/pkg/compiler/lib/src/inferrer/type_system.dart
@@ -7,6 +7,7 @@
 import '../constants/values.dart' show BoolConstantValue;
 import '../elements/entities.dart';
 import '../elements/types.dart';
+import '../ir/static_type.dart' show ClassRelation;
 import '../world.dart';
 import 'abstract_value_domain.dart';
 import 'type_graph_nodes.dart';
@@ -332,46 +333,42 @@
       _abstractValueDomain.isNull(type.typeAnnotation).isDefinitelyFalse;
 
   /// Returns the intersection between [type] and [annotation].
-  /// [isNullable] indicates whether the annotation implies a null
-  /// type.
+  ///
+  /// [isCast] indicates whether narrowing comes from a cast or parameter check
+  /// rather than an 'is' test. (In legacy semantics these differ on whether
+  /// `null` is accepted).
+  ///
+  /// If [excludeNull] is true, the intersection excludes `null` even if the
+  /// Dart type implies `null`.
   TypeInformation narrowType(TypeInformation type, DartType annotation,
-      {bool isNullable: true}) {
-    TypeInformation _narrowTo(AbstractValue otherType) {
-      if (_abstractValueDomain.isExact(type.type).isDefinitelyTrue) return type;
-      if (isNullable) {
-        otherType = _abstractValueDomain.includeNull(otherType);
-      }
-      TypeInformation newType =
-          new NarrowTypeInformation(_abstractValueDomain, type, otherType);
-      allocatedTypes.add(newType);
-      return newType;
+      {bool isCast: true, bool excludeNull: false}) {
+    // Avoid refining an input with an exact type. It we are almost always
+    // adding a narrowing to a subtype of the same class or a superclass.
+    if (_abstractValueDomain.isExact(type.type).isDefinitelyTrue) return type;
+
+    AbstractValueWithPrecision narrowing =
+        _abstractValueDomain.createFromStaticType(annotation,
+            classRelation: ClassRelation.subtype, nullable: isCast);
+
+    AbstractValue abstractValue = narrowing.abstractValue;
+    if (excludeNull) {
+      abstractValue = _abstractValueDomain.excludeNull(abstractValue);
     }
 
-    // TODO(fishythefish): Use nullability.
-    annotation = annotation.withoutNullability;
-    if (annotation is VoidType) return type;
-    if (_closedWorld.dartTypes.isTopType(annotation)) {
-      if (isNullable) return type;
+    if (_abstractValueDomain.containsAll(abstractValue).isPotentiallyTrue) {
+      // Top, or non-nullable Top.
+      if (_abstractValueDomain.isNull(abstractValue).isPotentiallyTrue) {
+        return type;
+      }
       // If the input is already narrowed to be not-null, there is no value
       // in adding another narrowing node.
       if (_isNonNullNarrow(type)) return type;
-      return _narrowTo(_abstractValueDomain.excludeNull(dynamicType.type));
-    } else if (annotation is NeverType) {
-      return _narrowTo(_abstractValueDomain.emptyType);
-    } else if (annotation is InterfaceType) {
-      return _narrowTo(
-          _abstractValueDomain.createNonNullSubtype(annotation.element));
-    } else if (annotation is FunctionType) {
-      return _narrowTo(functionType.type);
-    } else if (annotation is FutureOrType) {
-      // TODO(johnniwinther): Support narrowing of FutureOr.
-      return type;
-    } else if (annotation is TypeVariableType) {
-      // TODO(ngeoffray): Narrow to bound.
-      return type;
-    } else {
-      throw 'Unexpected annotation type $annotation';
     }
+
+    TypeInformation newType =
+        NarrowTypeInformation(_abstractValueDomain, type, abstractValue);
+    allocatedTypes.add(newType);
+    return newType;
   }
 
   ParameterTypeInformation getInferredTypeOfParameter(Local parameter) {
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 8ea2061..8a3c266 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -239,6 +239,11 @@
             }
             break;
           case VariableUseKind.localReturnType:
+            // SSA requires the element type of generators.
+            if (usage.localFunction.function.asyncMarker !=
+                ir.AsyncMarker.Sync) {
+              return true;
+            }
             if (rtiNeed.localFunctionNeedsSignature(usage.localFunction)) {
               return true;
             }
diff --git a/pkg/compiler/test/analyses/api_allowed.json b/pkg/compiler/test/analyses/api_allowed.json
index 737224b..e303a89 100644
--- a/pkg/compiler/test/analyses/api_allowed.json
+++ b/pkg/compiler/test/analyses/api_allowed.json
@@ -69,7 +69,6 @@
     "Dynamic access of 'dart.collection::_modifications'.": 5,
     "Dynamic access of 'dart.collection::_map'.": 4,
     "Dynamic access of 'dart.collection::_elements'.": 1,
-    "Dynamic access of 'dart.collection::_element'.": 1,
     "Dynamic access of 'dart.collection::_first'.": 1
   },
   "org-dartlang-sdk:///lib/html/dart2js/html_dart2js.dart": {
@@ -198,4 +197,4 @@
   "org-dartlang-sdk:///lib/_http/websocket_impl.dart": {
     "Dynamic invocation of 'dart._http::_toJSON'.": 1
   }
-}
+}
\ No newline at end of file
diff --git a/sdk/lib/_internal/js_runtime/lib/collection_patch.dart b/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
index a1d76bf..4d4076c 100644
--- a/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
@@ -357,7 +357,7 @@
     JS('void', 'delete #[#]', table, key);
   }
 
-  List _getBucket(var table, var key) {
+  List? _getBucket(var table, var key) {
     var hash = _computeHashCode(key);
     return JS('var', '#[#]', table, hash);
   }
@@ -905,7 +905,7 @@
     var bucket = _getBucket(rest, object);
     var index = _findBucketIndex(bucket, object);
     if (index < 0) return null;
-    return bucket[index];
+    return JS('', '#[#]', bucket, index);
   }
 
   // Collection.
@@ -1091,7 +1091,7 @@
     JS('void', 'delete #[#]', table, key);
   }
 
-  List _getBucket(var table, var element) {
+  List? _getBucket(var table, var element) {
     var hash = _computeHashCode(element);
     return JS('var', '#[#]', table, hash);
   }
@@ -1357,7 +1357,7 @@
     var bucket = _getBucket(rest, object);
     var index = _findBucketIndex(bucket, object);
     if (index < 0) return null;
-    return bucket[index]._element;
+    return JS<_LinkedHashSetCell>('', '#[#]', bucket, index)._element;
   }
 
   void forEach(void action(E element)) {
@@ -1564,7 +1564,7 @@
     JS('void', 'delete #[#]', table, key);
   }
 
-  List _getBucket(var table, var element) {
+  List? _getBucket(var table, var element) {
     var hash = _computeHashCode(element);
     return JS('var', '#[#]', table, hash);
   }
diff --git a/tests/language/regress/regress43366_test.dart b/tests/language/regress/regress43366_test.dart
new file mode 100644
index 0000000..a24d7d4
--- /dev/null
+++ b/tests/language/regress/regress43366_test.dart
@@ -0,0 +1,28 @@
+// 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.
+
+String upcase(String? s) {
+  if (s == null) return '';
+  return s.toUpperCase();
+}
+
+String format(dynamic thing) {
+  if (thing is String?) return upcase(thing);
+  if (thing is num) return '$thing';
+  return '?';
+}
+
+main() {
+  log(format(null));
+  log(format('hello'));
+  log(format([]));
+
+  if (trace != '[][HELLO][?]') throw 'Unexpected: "$trace"';
+}
+
+String trace = '';
+
+void log(String s) {
+  trace += '[$s]';
+}
diff --git a/tools/VERSION b/tools/VERSION
index 20be6fa..72808e9 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 10
 PATCH 0
-PRERELEASE 115
+PRERELEASE 116
 PRERELEASE_PATCH 0
\ No newline at end of file