Report an error when a potentially non-nullable local variable is not initialized.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: Ie1d148ff584c202edc334659eeb4f792bb8773d4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106620
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index ed09816..046a034 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -236,6 +236,7 @@
   CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR,
   CompileTimeErrorCode.NON_SYNC_FACTORY,
   CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS,
+  CompileTimeErrorCode.NOT_INITIALIZED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE,
   CompileTimeErrorCode.NOT_ITERABLE_SPREAD,
   CompileTimeErrorCode.NOT_MAP_SPREAD,
   CompileTimeErrorCode.NOT_NULL_AWARE_NULL_SPREAD,
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 278a7f7..faec666 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -2453,6 +2453,22 @@
           correction: "Try adding the missing arguments.");
 
   /**
+   * It is an error if a potentially non-nullable local variable which has no
+   * initializer expression and is not marked `late` is used before it is
+   * definitely assigned.
+   *
+   * TODO(scheglov) Update the code and the message when implement definite
+   * assignment analysis.
+   */
+  static const CompileTimeErrorCode
+      NOT_INITIALIZED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE =
+      const CompileTimeErrorCode(
+          'NOT_INITIALIZED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE',
+          "Non-nullable local variable '{0}' must be initialized.",
+          correction:
+              "Try giving it an initializer expression, or mark it 'late'.");
+
+  /**
    * No parameters.
    */
   // #### Description
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index db6b5ca..bcb76f5 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -1439,6 +1439,7 @@
   @override
   void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
     _checkForFinalNotInitialized(node.variables);
+    _checkForNotInitializedPotentiallyNonNullableLocalVariable(node.variables);
     super.visitVariableDeclarationStatement(node);
   }
 
@@ -3367,6 +3368,43 @@
     }
   }
 
+  void _checkForNotInitializedPotentiallyNonNullableLocalVariable(
+    VariableDeclarationList node,
+  ) {
+    // Const and final checked separately.
+    if (node.isConst || node.isFinal) {
+      return;
+    }
+
+    if (!_isNonNullable) {
+      return;
+    }
+
+    if (node.isLate) {
+      return;
+    }
+
+    if (node.type == null) {
+      return;
+    }
+    var type = node.type.type;
+
+    if (!_typeSystem.isPotentiallyNonNullable(type)) {
+      return;
+    }
+
+    for (var variable in node.variables) {
+      if (variable.initializer == null) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode
+              .NOT_INITIALIZED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE,
+          variable.name,
+          [variable.name.name],
+        );
+      }
+    }
+  }
+
   /**
    * If there are no constructors in the given [members], verify that all
    * final fields are initialized.  Cases in which there is at least one
diff --git a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
index c722521..35f6532 100644
--- a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
@@ -26,243 +26,6 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  test_local_getterNullAwareAccess_interfaceType() async {
-    addTestFile(r'''
-m() {
-  int? x;
-  return x?.isEven;
-}
-''');
-
-    await resolveTestFile();
-    assertNoTestErrors();
-    assertType(findNode.propertyAccess('x?.isEven'), 'bool?');
-  }
-
-  test_local_methodNullAwareCall_interfaceType() async {
-    await addTestFile(r'''
-class C {
-  bool x() => true;
-}
-m() {
-  C? c;
-  return c?.x();
-}
-''');
-
-    await resolveTestFile();
-    assertNoTestErrors();
-    assertType(findNode.methodInvocation('c?.x()'), 'bool?');
-  }
-
-  test_local_nullCoalesce_nullableInt_int() async {
-    await addTestFile(r'''
-m() {
-  int? x;
-  int y;
-  x ?? y;
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-    assertType(findNode.binary('x ?? y'), 'int');
-  }
-
-  test_local_nullCoalesce_nullableInt_nullableInt() async {
-    await addTestFile(r'''
-m() {
-  int? x;
-  x ?? x;
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-    assertType(findNode.binary('x ?? x'), 'int?');
-  }
-
-  test_local_nullCoalesceAssign_nullableInt_int() async {
-    await addTestFile(r'''
-m() {
-  int? x;
-  int y;
-  x ??= y;
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-    assertType(findNode.assignment('x ??= y'), 'int');
-  }
-
-  test_local_nullCoalesceAssign_nullableInt_nullableInt() async {
-    await addTestFile(r'''
-m() {
-  int? x;
-  x ??= x;
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-    assertType(findNode.assignment('x ??= x'), 'int?');
-  }
-
-  test_local_parameter_interfaceType() async {
-    addTestFile('''
-main() {
-  f(int? a, int b) {}
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-
-    assertType(findNode.typeName('int? a'), 'int?');
-    assertType(findNode.typeName('int b'), 'int');
-  }
-
-  test_local_returnType_interfaceType() async {
-    addTestFile('''
-main() {
-  int? f() => 0;
-  int g() => 0;
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-
-    assertType(findNode.typeName('int? f'), 'int?');
-    assertType(findNode.typeName('int g'), 'int');
-  }
-
-  @failingTest
-  test_local_variable_genericFunctionType() async {
-    addTestFile('''
-main() {
-  int? Function(bool, String?)? a;
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-
-    assertType(
-      findNode.genericFunctionType('Function('),
-      '(bool!, String?) → int??',
-    );
-  }
-
-  test_local_variable_interfaceType() async {
-    addTestFile('''
-main() {
-  int? a = 0;
-  int b = 0;
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-
-    assertType(findNode.typeName('int? a'), 'int?');
-    assertType(findNode.typeName('int b'), 'int');
-  }
-
-  test_local_variable_interfaceType_generic() async {
-    addTestFile('''
-main() {
-  List<int?>? a = [];
-  List<int>? b = [];
-  List<int?> c = [];
-  List<int> d = [];
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-
-    assertType(findNode.typeName('List<int?>? a'), 'List<int?>?');
-    assertType(findNode.typeName('List<int>? b'), 'List<int>?');
-    assertType(findNode.typeName('List<int?> c'), 'List<int?>');
-    assertType(findNode.typeName('List<int> d'), 'List<int>');
-  }
-
-  test_local_variable_typeParameter() async {
-    addTestFile('''
-class A<T> {
-  main(T a) {
-    T? b;
-  }
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-
-    assertType(findNode.typeName('T a'), 'T');
-    assertType(findNode.typeName('T? b'), 'T?');
-  }
-
-  test_member_potentiallyNullable_called() async {
-    addTestFile(r'''
-m<T extends Function>() {
-  List<T?> x;
-  x.first();
-}
-''');
-    await resolveTestFile();
-    // Do not assert no test errors. Deliberately invokes nullable type.
-    assertType(findNode.methodInvocation('first').methodName, 'Function?');
-  }
-
-  test_null_assertion_operator_changes_null_to_never() async {
-    addTestFile('''
-main() {
-  Null x = null;
-  x!;
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-    assertType(findNode.postfix('x!'), 'Never');
-  }
-
-  test_null_assertion_operator_removes_nullability() async {
-    addTestFile('''
-main() {
-  Object? x = null;
-  x!;
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-    assertType(findNode.postfix('x!'), 'Object');
-  }
-
-  test_typedef_classic() async {
-    addTestFile('''
-typedef int? F(bool a, String? b);
-
-main() {
-  F? a;
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-
-    assertType(findNode.typeName('F? a'), 'int? Function(bool, String?)?');
-  }
-
-  @failingTest
-  test_typedef_function() async {
-    addTestFile('''
-typedef F<T> = int? Function(bool, T, T?);
-
-main() {
-  F<String>? a;
-}
-''');
-    await resolveTestFile();
-    assertNoTestErrors();
-
-    assertType(
-      findNode.typeName('F<String>'),
-      'int? Function(bool!, String!, String?)?',
-    );
-  }
-
   test_class_hierarchy() async {
     addTestFile('''
 class A {}
@@ -295,6 +58,187 @@
     assertType(findNode.typeName('C;'), 'C');
   }
 
+  test_local_getterNullAwareAccess_interfaceType() async {
+    addTestFile(r'''
+main() {
+  int? x;
+  return x?.isEven;
+}
+''');
+
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.propertyAccess('x?.isEven'), 'bool?');
+  }
+
+  test_local_interfaceType() async {
+    addTestFile('''
+main() {
+  int? a = 0;
+  int b = 0;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(findNode.typeName('int? a'), 'int?');
+    assertType(findNode.typeName('int b'), 'int');
+  }
+
+  test_local_interfaceType_generic() async {
+    addTestFile('''
+main() {
+  List<int?>? a = [];
+  List<int>? b = [];
+  List<int?> c = [];
+  List<int> d = [];
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(findNode.typeName('List<int?>? a'), 'List<int?>?');
+    assertType(findNode.typeName('List<int>? b'), 'List<int>?');
+    assertType(findNode.typeName('List<int?> c'), 'List<int?>');
+    assertType(findNode.typeName('List<int> d'), 'List<int>');
+  }
+
+  test_local_methodNullAwareCall_interfaceType() async {
+    await addTestFile(r'''
+class C {
+  bool x() => true;
+}
+
+main() {
+  C? c;
+  return c?.x();
+}
+''');
+
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.methodInvocation('c?.x()'), 'bool?');
+  }
+
+  test_local_nullCoalesce_nullableInt_int() async {
+    await addTestFile(r'''
+main() {
+  int? x;
+  int y = 0;
+  x ?? y;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.binary('x ?? y'), 'int');
+  }
+
+  test_local_nullCoalesce_nullableInt_nullableInt() async {
+    await addTestFile(r'''
+main() {
+  int? x;
+  x ?? x;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.binary('x ?? x'), 'int?');
+  }
+
+  test_local_nullCoalesceAssign_nullableInt_int() async {
+    await addTestFile(r'''
+main() {
+  int? x;
+  int y = 0;
+  x ??= y;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.assignment('x ??= y'), 'int');
+  }
+
+  test_local_nullCoalesceAssign_nullableInt_nullableInt() async {
+    await addTestFile(r'''
+main() {
+  int? x;
+  x ??= x;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.assignment('x ??= x'), 'int?');
+  }
+
+  test_local_typeParameter() async {
+    addTestFile('''
+main<T>(T a) {
+  T x = a;
+  T? y;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(findNode.typeName('T x'), 'T');
+    assertType(findNode.typeName('T? y'), 'T?');
+  }
+
+  @failingTest
+  test_local_variable_genericFunctionType() async {
+    addTestFile('''
+main() {
+  int? Function(bool, String?)? a;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(
+      findNode.genericFunctionType('Function('),
+      '(bool!, String?) → int??',
+    );
+  }
+
+  test_localFunction_parameter_interfaceType() async {
+    addTestFile('''
+main() {
+  f(int? a, int b) {}
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(findNode.typeName('int? a'), 'int?');
+    assertType(findNode.typeName('int b'), 'int');
+  }
+
+  test_localFunction_returnType_interfaceType() async {
+    addTestFile('''
+main() {
+  int? f() => 0;
+  int g() => 0;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(findNode.typeName('int? f'), 'int?');
+    assertType(findNode.typeName('int g'), 'int');
+  }
+
+  test_member_potentiallyNullable_called() async {
+    addTestFile(r'''
+m<T extends Function>() {
+  List<T?> x;
+  x.first();
+}
+''');
+    await resolveTestFile();
+    // Do not assert no test errors. Deliberately invokes nullable type.
+    assertType(findNode.methodInvocation('first').methodName, 'Function?');
+  }
+
   test_mixin_hierarchy() async {
     addTestFile('''
 class A {}
@@ -308,6 +252,187 @@
     assertType(findNode.typeName('A {} // 1'), 'A');
     assertType(findNode.typeName('A {} // 2'), 'A');
   }
+
+  test_null_assertion_operator_changes_null_to_never() async {
+    addTestFile('''
+main() {
+  Null x = null;
+  x!;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.postfix('x!'), 'Never');
+  }
+
+  test_null_assertion_operator_removes_nullability() async {
+    addTestFile('''
+main() {
+  Object? x = null;
+  x!;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.postfix('x!'), 'Object');
+  }
+
+  @failingTest
+  test_parameter_genericFunctionType() async {
+    addTestFile('''
+main(int? Function(bool, String?)? a) {
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(
+      findNode.genericFunctionType('Function('),
+      '(bool!, String?) → int??',
+    );
+  }
+
+  test_parameter_getterNullAwareAccess_interfaceType() async {
+    addTestFile(r'''
+main(int? x) {
+  return x?.isEven;
+}
+''');
+
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.propertyAccess('x?.isEven'), 'bool?');
+  }
+
+  test_parameter_interfaceType() async {
+    addTestFile('''
+main(int? a, int b) {
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(findNode.typeName('int? a'), 'int?');
+    assertType(findNode.typeName('int b'), 'int');
+  }
+
+  test_parameter_interfaceType_generic() async {
+    addTestFile('''
+main(List<int?>? a, List<int>? b, List<int?> c, List<int> d) {
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(findNode.typeName('List<int?>? a'), 'List<int?>?');
+    assertType(findNode.typeName('List<int>? b'), 'List<int>?');
+    assertType(findNode.typeName('List<int?> c'), 'List<int?>');
+    assertType(findNode.typeName('List<int> d'), 'List<int>');
+  }
+
+  test_parameter_methodNullAwareCall_interfaceType() async {
+    await addTestFile(r'''
+class C {
+  bool x() => true;
+}
+
+main(C? c) {
+  return c?.x();
+}
+''');
+
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.methodInvocation('c?.x()'), 'bool?');
+  }
+
+  test_parameter_nullCoalesce_nullableInt_int() async {
+    await addTestFile(r'''
+main(int? x, int y) {
+  x ?? y;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.binary('x ?? y'), 'int');
+  }
+
+  test_parameter_nullCoalesce_nullableInt_nullableInt() async {
+    await addTestFile(r'''
+main(int? x) {
+  x ?? x;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.binary('x ?? x'), 'int?');
+  }
+
+  test_parameter_nullCoalesceAssign_nullableInt_int() async {
+    await addTestFile(r'''
+main(int? x, int y) {
+  x ??= y;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.assignment('x ??= y'), 'int');
+  }
+
+  test_parameter_nullCoalesceAssign_nullableInt_nullableInt() async {
+    await addTestFile(r'''
+main(int? x) {
+  x ??= x;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    assertType(findNode.assignment('x ??= x'), 'int?');
+  }
+
+  test_parameter_typeParameter() async {
+    addTestFile('''
+main<T>(T a, T? b) {
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(findNode.typeName('T a'), 'T');
+    assertType(findNode.typeName('T? b'), 'T?');
+  }
+
+  test_typedef_classic() async {
+    addTestFile('''
+typedef int? F(bool a, String? b);
+
+main() {
+  F? a;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(findNode.typeName('F? a'), 'int? Function(bool, String?)?');
+  }
+
+  @failingTest
+  test_typedef_function() async {
+    addTestFile('''
+typedef F<T> = int? Function(bool, T, T?);
+
+main() {
+  F<String>? a;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    assertType(
+      findNode.typeName('F<String>'),
+      'int? Function(bool!, String!, String?)?',
+    );
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
index c84553a..3a2c54b 100644
--- a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
@@ -724,12 +724,11 @@
 @pragma('analyzer:non-nullable')
 library foo;
 
-m() {
-  int x;
+m(int x) {
   x ?? 1;
 }
 ''', [
-      error(HintCode.DEAD_CODE, 69, 1),
+      error(HintCode.DEAD_CODE, 65, 1),
     ]);
   }
 
@@ -774,12 +773,11 @@
 @pragma('analyzer:non-nullable')
 library foo;
 
-m() {
-  int x;
+m(int x) {
   x ??= 1;
 }
 ''', [
-      error(HintCode.DEAD_CODE, 70, 1),
+      error(HintCode.DEAD_CODE, 66, 1),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/not_initialized_potentially_non_nullable_local_variable_test.dart b/pkg/analyzer/test/src/diagnostics/not_initialized_potentially_non_nullable_local_variable_test.dart
new file mode 100644
index 0000000..373e9b5
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/not_initialized_potentially_non_nullable_local_variable_test.dart
@@ -0,0 +1,104 @@
+// 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 file.
+
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(
+      NotInitializedPotentiallyNonNullableLocalVariableTest,
+    );
+  });
+}
+
+@reflectiveTest
+class NotInitializedPotentiallyNonNullableLocalVariableTest
+    extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions =>
+      AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
+
+  test_hasInitializer() async {
+    assertNoErrorsInCode('''
+f() {
+  int v = 0;
+}
+''');
+  }
+
+  test_late() async {
+    assertNoErrorsInCode('''
+f() {
+  late int v;
+}
+''');
+  }
+
+  test_noInitializer() async {
+    assertErrorsInCode('''
+f() {
+  int v;
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .NOT_INITIALIZED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE,
+          12,
+          1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 12, 1),
+    ]);
+  }
+
+  test_noInitializer_typeParameter() async {
+    assertErrorsInCode('''
+f<T>() {
+  T v;
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .NOT_INITIALIZED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE,
+          13,
+          1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
+    ]);
+  }
+
+  test_nullable() async {
+    assertNoErrorsInCode('''
+f() {
+  int? v;
+}
+''');
+  }
+
+  test_type_dynamic() async {
+    assertNoErrorsInCode('''
+f() {
+  dynamic v;
+}
+''');
+  }
+
+  test_type_dynamicImplicit() async {
+    assertNoErrorsInCode('''
+f() {
+  var v;
+}
+''');
+  }
+
+  test_type_void() async {
+    assertNoErrorsInCode('''
+f() {
+  void v;
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index bf27038..2f965be 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -96,6 +96,8 @@
 import 'non_constant_spread_expression_from_deferred_library_test.dart'
     as non_constant_spread_expression_from_deferred_library;
 import 'non_null_opt_out_test.dart' as non_null_opt_out;
+import 'not_initialized_potentially_non_nullable_local_variable_test.dart'
+    as not_initialized_potentially_non_nullable_local_variable;
 import 'not_iterable_spread_test.dart' as not_iterable_spread;
 import 'not_map_spread_test.dart' as not_map_spread;
 import 'not_null_aware_null_spread_test.dart' as not_null_aware_null_spread;
@@ -235,6 +237,7 @@
     non_constant_set_element_from_deferred_library.main();
     non_constant_spread_expression_from_deferred_library.main();
     non_null_opt_out.main();
+    not_initialized_potentially_non_nullable_local_variable.main();
     not_iterable_spread.main();
     not_map_spread.main();
     not_null_aware_null_spread.main();
diff --git a/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart b/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
index a78ae34..906d4da 100644
--- a/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
@@ -305,23 +305,21 @@
 
   test_member_potentiallyNullable() async {
     await assertErrorsInCode(r'''
-m<T extends int?>() {
-  T x;
+m<T extends int?>(T x) {
   x.isEven;
 }
 ''', [
-      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 31, 1),
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 27, 1),
     ]);
   }
 
   test_member_potentiallyNullable_called() async {
     await assertErrorsInCode(r'''
-m<T extends Function>() {
-  List<T?> x;
+m<T extends Function>(List<T?> x) {
   x.first();
 }
 ''', [
-      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 44, 5),
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 40, 5),
     ]);
   }
 
@@ -354,8 +352,7 @@
 
   test_method_noSuchMethod_nullable() async {
     await assertNoErrorsInCode(r'''
-m() {
-  int x;
+m(int x) {
   x.noSuchMethod(throw '');
 }
 ''');
@@ -383,8 +380,7 @@
 
   test_method_toString_nullable() async {
     await assertNoErrorsInCode(r'''
-m() {
-  int x;
+m(int x) {
   x.toString();
 }
 ''');
@@ -503,8 +499,7 @@
 
   test_operatorPostfixInc_nonNullable() async {
     await assertNoErrorsInCode(r'''
-m() {
-  int x;
+m(int x) {
   x++;
 }
 ''');
@@ -512,13 +507,11 @@
 
   test_operatorPostfixInc_nullable() async {
     await assertErrorsInCode(r'''
-m() {
-  int? x;
+m(int? x) {
   x++;
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
-      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 14, 1),
     ]);
   }
 
@@ -545,8 +538,7 @@
 
   test_operatorPrefixInc_nonNullable() async {
     await assertNoErrorsInCode(r'''
-m() {
-  int x;
+m(int x) {
   ++x;
 }
 ''');
@@ -554,13 +546,11 @@
 
   test_operatorPrefixInc_nullable() async {
     await assertErrorsInCode(r'''
-m() {
-  int? x;
+m(int? x) {
   ++x;
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
-      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 20, 1),
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 16, 1),
     ]);
   }
 
@@ -607,8 +597,7 @@
 
   test_plusEq_nonNullable() async {
     await assertNoErrorsInCode(r'''
-m() {
-  int x;
+m(int x) {
   x += 1;
 }
 ''');
@@ -616,13 +605,11 @@
 
   test_plusEq_nullable() async {
     await assertErrorsInCode(r'''
-m() {
-  int? x;
+m(int? x) {
   x += 1;
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
-      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 14, 1),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_null_aware_call_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_null_aware_call_test.dart
index 35d157a..110b35b 100644
--- a/pkg/analyzer/test/src/diagnostics/unnecessary_null_aware_call_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_null_aware_call_test.dart
@@ -23,19 +23,17 @@
 
   test_getter_parenthesized_nonNull() async {
     await assertErrorsInCode('''
-f() {
-  int x;
+f(int x) {
   (x)?.isEven;
 }
 ''', [
-      error(HintCode.UNNECESSARY_NULL_AWARE_CALL, 20, 2),
+      error(HintCode.UNNECESSARY_NULL_AWARE_CALL, 16, 2),
     ]);
   }
 
   test_getter_parenthesized_nullable() async {
     await assertNoErrorsInCode('''
-f() {
-  int? x;
+f(int? x) {
   (x)?.isEven;
 }
 ''');
@@ -43,19 +41,17 @@
 
   test_getter_simple_nonNull() async {
     await assertErrorsInCode('''
-f() {
-  int x;
+f(int x) {
   x?.isEven;
 }
 ''', [
-      error(HintCode.UNNECESSARY_NULL_AWARE_CALL, 18, 2),
+      error(HintCode.UNNECESSARY_NULL_AWARE_CALL, 14, 2),
     ]);
   }
 
   test_getter_simple_nullable() async {
     await assertNoErrorsInCode('''
-f() {
-  int? x;
+f(int? x) {
   x?.isEven;
 }
 ''');
@@ -63,19 +59,17 @@
 
   test_method_parenthesized_nonNull() async {
     await assertErrorsInCode('''
-f() {
-  int x;
+f(int x) {
   (x)?.round();
 }
 ''', [
-      error(HintCode.UNNECESSARY_NULL_AWARE_CALL, 20, 2),
+      error(HintCode.UNNECESSARY_NULL_AWARE_CALL, 16, 2),
     ]);
   }
 
   test_method_parenthesized_nullable() async {
     await assertNoErrorsInCode('''
-f() {
-  int? x;
+f(int? x) {
   (x)?.round();
 }
 ''');
@@ -83,19 +77,17 @@
 
   test_method_simple_nonNull() async {
     await assertErrorsInCode('''
-f() {
-  int x;
+f(int x) {
   x?.round();
 }
 ''', [
-      error(HintCode.UNNECESSARY_NULL_AWARE_CALL, 18, 2),
+      error(HintCode.UNNECESSARY_NULL_AWARE_CALL, 14, 2),
     ]);
   }
 
   test_method_simple_nullable() async {
     await assertNoErrorsInCode('''
-f() {
-  int? x;
+f(int? x) {
   x?.round();
 }
 ''');
diff --git a/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart b/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart
index 35e756e..9757f79 100644
--- a/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart
+++ b/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart
@@ -20,14 +20,14 @@
 // operator==, but it should not be an error to "assign null" to the parameter
 // of the comparison operator.
 main() {
-  Object o;
+  Object o = 0;
   // Valid comparison.
   o == null;
 
   // Caveat: it is NOT that the argument is promoted to non-null. Otherwise,
   // types which we can't cleanly promote, such as FutureOr<int?>, would not be
   // assignable in comparisons.
-  FutureOr<int?> foInt;
+  FutureOr<int?> foInt = Future.value(0);
 
   // Valid comparison.
   o == foInt;
diff --git a/tests/language_2/nnbd/static_errors/not_initialized_potentially_non_nullable_local_test.dart b/tests/language_2/nnbd/static_errors/not_initialized_potentially_non_nullable_local_test.dart
new file mode 100644
index 0000000..d4b2207
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/not_initialized_potentially_non_nullable_local_test.dart
@@ -0,0 +1,29 @@
+// 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 file.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// It is an error if a potentially non-nullable local variable which has no
+// initializer expression and is not marked `late` is used before it is
+// definitely assigned.
+// TODO(scheglov) Update once we implement definite assignment analysis.
+
+void main() {
+  int v; //# 01: compile-time error
+  int v = 0; //# 02: ok
+  late int v; //# 03: ok
+  late int v = 0; //# 04: ok
+  int? v; //# 05: ok
+  int? v = 0; //# 06: ok
+
+}
+
+f<T>(T a) {
+  T v; //# 07: compile-time error
+  T v = a; //# 08: ok
+  late T v; //# 09: ok
+  late T v = a; //# 10: ok
+  T? v; //# 11: ok
+  T? v = a; //# 12: ok
+}
diff --git a/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart b/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart
index 56679cf..9043d0e 100644
--- a/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart
+++ b/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart
@@ -10,7 +10,7 @@
   bool? cond;
   List? list;
   Function? func;
-  List<Function?> funcList;
+  List<Function?> funcList = [];
   Stream? stream;
   x.isEven; //# 00: compile-time error
   x.round(); //# 01: compile-time error
diff --git a/tests/language_2/nnbd/syntax/null_assertion_ambiguous_test.dart b/tests/language_2/nnbd/syntax/null_assertion_ambiguous_test.dart
index 29200e7..68c6037 100644
--- a/tests/language_2/nnbd/syntax/null_assertion_ambiguous_test.dart
+++ b/tests/language_2/nnbd/syntax/null_assertion_ambiguous_test.dart
@@ -38,7 +38,7 @@
   // behavior by trying to assign to a non-nullable variable.  We check the
   // runtime behavior by verifying that the exception is thrown before an
   // assignment occurs.
-  Object x3;
+  Object x3 = 0;
   Expect.throws(() {
       x3 = a!;
   });
diff --git a/tests/language_2/nnbd/syntax/null_assertion_test.dart b/tests/language_2/nnbd/syntax/null_assertion_test.dart
index 4b27e00..6acea53 100644
--- a/tests/language_2/nnbd/syntax/null_assertion_test.dart
+++ b/tests/language_2/nnbd/syntax/null_assertion_test.dart
@@ -23,7 +23,7 @@
 Object? f() => null;
 
 main() {
-  List<Object> listOfObject;
+  List<Object> listOfObject = [];
 
   var x1 = [0!];
   listOfObject = x1;