[samples] Migrate ffi samples to NNBD

Closes: https://github.com/dart-lang/sdk/issues/43600.

TEST=samples/ffi

Change-Id: I620e6a73c8e37dd72f8f3921fa37dd4f8966e45c
Cq-Include-Trybots: luci.dart.try:vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,dart-sdk-linux-try,analyzer-nnbd-linux-release-try,analyzer-linux-release-try,front-end-nnbd-linux-release-x64-try,front-end-linux-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/173542
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
diff --git a/samples/ffi/async/async_test.dart b/samples/ffi/async/async_test.dart
index 297a76e..f438582 100644
--- a/samples/ffi/async/async_test.dart
+++ b/samples/ffi/async/async_test.dart
@@ -6,8 +6,6 @@
 //
 // SharedObjects=ffi_test_dynamic_library ffi_test_functions
 
-// @dart = 2.9
-
 import 'sample_async_callback.dart' as sample0;
 import 'sample_native_port_call.dart' as sample1;
 
diff --git a/samples/ffi/async/sample_async_callback.dart b/samples/ffi/async/sample_async_callback.dart
index 5e6d79a..59ae31b 100644
--- a/samples/ffi/async/sample_async_callback.dart
+++ b/samples/ffi/async/sample_async_callback.dart
@@ -8,8 +8,6 @@
 //
 // TODO(dartbug.com/37022): Update this when we get real async callbacks.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 import 'dart:isolate';
 
diff --git a/samples/ffi/async/sample_native_port_call.dart b/samples/ffi/async/sample_native_port_call.dart
index a2c3ee4..302a50f 100644
--- a/samples/ffi/async/sample_native_port_call.dart
+++ b/samples/ffi/async/sample_native_port_call.dart
@@ -16,8 +16,6 @@
 // The advantage is that finalizers can be used when passing ownership of data
 // (buffers) from C to Dart.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 import 'dart:isolate';
 import 'dart:typed_data';
@@ -79,8 +77,8 @@
 }
 
 class CppRequest {
-  final SendPort replyPort;
-  final int pendingCall;
+  final SendPort? replyPort;
+  final int? pendingCall;
   final String method;
   final Uint8List data;
 
@@ -114,9 +112,9 @@
     final int argument = cppRequest.data[0];
     final int result = myCallback1(argument);
     final cppResponse =
-        CppResponse(cppRequest.pendingCall, Uint8List.fromList([result]));
+        CppResponse(cppRequest.pendingCall!, Uint8List.fromList([result]));
     print('Dart:   Responding: $cppResponse');
-    cppRequest.replyPort.send(cppResponse.toCppMessage());
+    cppRequest.replyPort!.send(cppResponse.toCppMessage());
   } else if (cppRequest.method == 'myCallback2') {
     final int argument = cppRequest.data[0];
     myCallback2(argument);
diff --git a/samples/ffi/coordinate.dart b/samples/ffi/coordinate.dart
index 4ff34f5..8a54ba9 100644
--- a/samples/ffi/coordinate.dart
+++ b/samples/ffi/coordinate.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 
 import "package:ffi/ffi.dart";
@@ -11,12 +9,12 @@
 /// Sample struct for dart:ffi library.
 class Coordinate extends Struct {
   @Double()
-  double x;
+  external double x;
 
   @Double()
-  double y;
+  external double y;
 
-  Pointer<Coordinate> next;
+  external Pointer<Coordinate> next;
 
   factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
     return allocate<Coordinate>().ref
diff --git a/samples/ffi/dylib_utils.dart b/samples/ffi/dylib_utils.dart
index 39653fa..220c0fc 100644
--- a/samples/ffi/dylib_utils.dart
+++ b/samples/ffi/dylib_utils.dart
@@ -2,13 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 import 'dart:io' show Platform;
 
-String _platformPath(String name, {String path}) {
-  if (path == null) path = "";
+String _platformPath(String name, String path) {
   if (Platform.isLinux || Platform.isAndroid)
     return path + "lib" + name + ".so";
   if (Platform.isMacOS) return path + "lib" + name + ".dylib";
@@ -16,7 +13,7 @@
   throw Exception("Platform not implemented");
 }
 
-DynamicLibrary dlopenPlatformSpecific(String name, {String path}) {
-  String fullPath = _platformPath(name, path: path);
+DynamicLibrary dlopenPlatformSpecific(String name, {String path = ""}) {
+  String fullPath = _platformPath(name, path);
   return DynamicLibrary.open(fullPath);
 }
diff --git a/samples/ffi/resource_management/pool.dart b/samples/ffi/resource_management/pool.dart
index 776c331..7064f9f 100644
--- a/samples/ffi/resource_management/pool.dart
+++ b/samples/ffi/resource_management/pool.dart
@@ -4,8 +4,6 @@
 //
 // Explicit pool used for managing resources.
 
-// @dart = 2.9
-
 import "dart:async";
 import 'dart:convert';
 import 'dart:ffi';
diff --git a/samples/ffi/resource_management/pool_isolate_shutdown_sample.dart b/samples/ffi/resource_management/pool_isolate_shutdown_sample.dart
index 8d3401b..cab2cb0 100644
--- a/samples/ffi/resource_management/pool_isolate_shutdown_sample.dart
+++ b/samples/ffi/resource_management/pool_isolate_shutdown_sample.dart
@@ -4,8 +4,6 @@
 //
 // Sample illustrating resources are not cleaned up when isolate is shutdown.
 
-// @dart = 2.9
-
 import 'dart:io';
 import "dart:isolate";
 import 'dart:ffi';
@@ -24,7 +22,7 @@
       receiveFromHelper.sendPort,
     );
     print("Main: Helper started.");
-    Pointer<SomeResource> resource;
+    Pointer<SomeResource> resource = nullptr;
     receiveFromHelper.listen((message) {
       if (message is int) {
         resource = Pointer<SomeResource>.fromAddress(message);
diff --git a/samples/ffi/resource_management/pool_sample.dart b/samples/ffi/resource_management/pool_sample.dart
index 87c5e39..00ee1ae 100644
--- a/samples/ffi/resource_management/pool_sample.dart
+++ b/samples/ffi/resource_management/pool_sample.dart
@@ -4,8 +4,6 @@
 //
 // Sample illustrating resource management with an explicit pool.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 
 import 'package:expect/expect.dart';
diff --git a/samples/ffi/resource_management/pool_zoned_sample.dart b/samples/ffi/resource_management/pool_zoned_sample.dart
index 0b4e8ff..05f1794 100644
--- a/samples/ffi/resource_management/pool_zoned_sample.dart
+++ b/samples/ffi/resource_management/pool_zoned_sample.dart
@@ -4,8 +4,6 @@
 //
 // Sample illustrating resource management with an implicit pool in the zone.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 
 import 'package:expect/expect.dart';
diff --git a/samples/ffi/resource_management/resource_management_test.dart b/samples/ffi/resource_management/resource_management_test.dart
index 4b2bbb0..1cc14f7 100644
--- a/samples/ffi/resource_management/resource_management_test.dart
+++ b/samples/ffi/resource_management/resource_management_test.dart
@@ -6,8 +6,6 @@
 //
 // SharedObjects=ffi_test_dynamic_library ffi_test_functions
 
-// @dart = 2.9
-
 import 'pool_isolate_shutdown_sample.dart' as pool_isolate;
 import 'pool_sample.dart' as pool;
 import 'pool_zoned_sample.dart' as pool_zoned;
diff --git a/samples/ffi/resource_management/unmanaged_sample.dart b/samples/ffi/resource_management/unmanaged_sample.dart
index b8c9971..9c3e0f0 100644
--- a/samples/ffi/resource_management/unmanaged_sample.dart
+++ b/samples/ffi/resource_management/unmanaged_sample.dart
@@ -4,8 +4,6 @@
 //
 // Sample illustrating manual resource management, not advised.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 
 import 'package:expect/expect.dart';
diff --git a/samples/ffi/sample_ffi_bitfield.dart b/samples/ffi/sample_ffi_bitfield.dart
index 91bb65d..cc10a2d 100644
--- a/samples/ffi/sample_ffi_bitfield.dart
+++ b/samples/ffi/sample_ffi_bitfield.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 
 import 'package:ffi/ffi.dart';
@@ -20,7 +18,7 @@
 /// } ScreenCellAttrs;
 class ScreenCellAttrs extends Struct {
   @Int16()
-  int bits;
+  external int bits;
 
   int get bold => getBits(kBoldFieldOffset, kBoldFieldLength);
   void set bold(int value) =>
diff --git a/samples/ffi/sample_ffi_data.dart b/samples/ffi/sample_ffi_data.dart
index 09dba76..8e713d0 100644
--- a/samples/ffi/sample_ffi_data.dart
+++ b/samples/ffi/sample_ffi_data.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 import 'package:ffi/ffi.dart';
 
diff --git a/samples/ffi/sample_ffi_dynamic_library.dart b/samples/ffi/sample_ffi_dynamic_library.dart
index 94863d0..28772ff 100644
--- a/samples/ffi/sample_ffi_dynamic_library.dart
+++ b/samples/ffi/sample_ffi_dynamic_library.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 
 import 'dylib_utils.dart';
diff --git a/samples/ffi/sample_ffi_functions.dart b/samples/ffi/sample_ffi_functions.dart
index 4cd30b0..bff74eb 100644
--- a/samples/ffi/sample_ffi_functions.dart
+++ b/samples/ffi/sample_ffi_functions.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 
 import 'package:ffi/ffi.dart';
@@ -202,46 +200,6 @@
   }
 
   {
-    // Passing in null for an int argument throws a null pointer exception.
-    BinaryOp sumPlus42 =
-        ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
-
-    int x = null;
-    try {
-      sumPlus42(43, x);
-    } on Error {
-      print('Expected exception on passing null for int');
-    }
-  }
-
-  {
-    // Passing in null for a double argument throws a null pointer exception.
-    DoubleUnaryOp times1_337Double = ffiTestFunctions
-        .lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
-
-    double x = null;
-    try {
-      times1_337Double(x);
-    } on Error {
-      print('Expected exception on passing null for double');
-    }
-  }
-
-  {
-    // Passing in null for an int argument throws a null pointer exception.
-    VigesimalOp sumManyNumbers = ffiTestFunctions
-        .lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
-
-    int x = null;
-    try {
-      sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13,
-          14.0, 15, 16.0, 17, 18.0, x, 20.0);
-    } on Error {
-      print('Expected exception on passing null for int');
-    }
-  }
-
-  {
     // Passing in nullptr for a pointer argument results in a nullptr in c.
     Int64PointerUnOp nullableInt64ElemAt1 =
         ffiTestFunctions.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>(
diff --git a/samples/ffi/sample_ffi_functions_callbacks.dart b/samples/ffi/sample_ffi_functions_callbacks.dart
index 79f9a41..affdcef 100644
--- a/samples/ffi/sample_ffi_functions_callbacks.dart
+++ b/samples/ffi/sample_ffi_functions_callbacks.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 
 import 'coordinate.dart';
diff --git a/samples/ffi/sample_ffi_functions_callbacks_closures.dart b/samples/ffi/sample_ffi_functions_callbacks_closures.dart
index a6ce9a6..1d08340 100644
--- a/samples/ffi/sample_ffi_functions_callbacks_closures.dart
+++ b/samples/ffi/sample_ffi_functions_callbacks_closures.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 
 import 'package:expect/expect.dart';
diff --git a/samples/ffi/sample_ffi_functions_structs.dart b/samples/ffi/sample_ffi_functions_structs.dart
index 7129658..9aefb57 100644
--- a/samples/ffi/sample_ffi_functions_structs.dart
+++ b/samples/ffi/sample_ffi_functions_structs.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 
 import 'coordinate.dart';
diff --git a/samples/ffi/sample_ffi_structs.dart b/samples/ffi/sample_ffi_structs.dart
index d5af59e..bd6d7c7 100644
--- a/samples/ffi/sample_ffi_structs.dart
+++ b/samples/ffi/sample_ffi_structs.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 
 import 'package:ffi/ffi.dart';
diff --git a/samples/ffi/samples_test.dart b/samples/ffi/samples_test.dart
index a3674a4..954aa9c 100644
--- a/samples/ffi/samples_test.dart
+++ b/samples/ffi/samples_test.dart
@@ -6,8 +6,6 @@
 //
 // SharedObjects=ffi_test_dynamic_library ffi_test_functions
 
-// @dart = 2.9
-
 import 'sample_ffi_bitfield.dart' as bitfield;
 import 'sample_ffi_data.dart' as data;
 import 'sample_ffi_dynamic_library.dart' as dynamic_library;
diff --git a/samples/ffi/sqlite/example/main.dart b/samples/ffi/sqlite/example/main.dart
index 6af01d4..480ef42 100644
--- a/samples/ffi/sqlite/example/main.dart
+++ b/samples/ffi/sqlite/example/main.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import "../lib/sqlite.dart";
 
 void main() {
diff --git a/samples/ffi/sqlite/lib/sqlite.dart b/samples/ffi/sqlite/lib/sqlite.dart
index 825e434..d6bac5b 100644
--- a/samples/ffi/sqlite/lib/sqlite.dart
+++ b/samples/ffi/sqlite/lib/sqlite.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 /// A synchronous SQLite wrapper.
 ///
 /// Written using dart:ffi.
diff --git a/samples/ffi/sqlite/lib/src/bindings/bindings.dart b/samples/ffi/sqlite/lib/src/bindings/bindings.dart
index a1cdba7..a3d73bd 100644
--- a/samples/ffi/sqlite/lib/src/bindings/bindings.dart
+++ b/samples/ffi/sqlite/lib/src/bindings/bindings.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import "dart:ffi";
 import "package:ffi/ffi.dart";
 
@@ -13,7 +11,7 @@
 import "types.dart";
 
 class _SQLiteBindings {
-  DynamicLibrary sqlite;
+  late DynamicLibrary sqlite;
 
   /// Opening A New Database Connection
   ///
@@ -29,10 +27,13 @@
   /// [sqlite3_errmsg] or sqlite3_errmsg16() routines can be used to obtain
   /// an English language description of the error following a failure of any
   /// of the sqlite3_open() routines.
-  int Function(Pointer<Utf8> filename, Pointer<Pointer<Database>> databaseOut,
-      int flags, Pointer<Utf8> vfs) sqlite3_open_v2;
+  late int Function(
+      Pointer<Utf8> filename,
+      Pointer<Pointer<Database>> databaseOut,
+      int flags,
+      Pointer<Utf8> vfs) sqlite3_open_v2;
 
-  int Function(Pointer<Database> database) sqlite3_close_v2;
+  late int Function(Pointer<Database> database) sqlite3_close_v2;
 
   /// Compiling An SQL Statement
   ///
@@ -81,7 +82,7 @@
   /// that is returned (the sqlite3_stmt object) contains a copy of the
   /// original SQL text. This causes the [sqlite3_step] interface to
   /// behave differently in three ways:
-  int Function(
+  late int Function(
       Pointer<Database> database,
       Pointer<Utf8> query,
       int nbytes,
@@ -164,7 +165,7 @@
   /// of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces,
   /// then the more specific [error codes] are returned directly
   /// by sqlite3_step().  The use of the "v2" interface is recommended.
-  int Function(Pointer<Statement> statement) sqlite3_step;
+  late int Function(Pointer<Statement> statement) sqlite3_step;
 
   /// CAPI3REF: Reset A Prepared Statement Object
   ///
@@ -187,7 +188,7 @@
   /// [sqlite3_reset] returns an appropriate [Errors].
   ///
   /// ^The [sqlite3_reset] interface does not change the values
-  int Function(Pointer<Statement> statement) sqlite3_reset;
+  late int Function(Pointer<Statement> statement) sqlite3_reset;
 
   /// Destroy A Prepared Statement Object
   ///
@@ -212,14 +213,14 @@
   /// a prepared statement after it has been finalized.  Any use of a prepared
   /// statement after it has been finalized can result in undefined and
   /// undesirable behavior such as segfaults and heap corruption.
-  int Function(Pointer<Statement> statement) sqlite3_finalize;
+  late int Function(Pointer<Statement> statement) sqlite3_finalize;
 
   /// Number Of Columns In A Result Set
   ///
   /// ^Return the number of columns in the result set returned by the
   /// prepared statement. ^This routine returns 0 if pStmt is an SQL
   /// statement that does not return data (for example an [UPDATE]).
-  int Function(Pointer<Statement> statement) sqlite3_column_count;
+  late int Function(Pointer<Statement> statement) sqlite3_column_count;
 
   /// Column Names In A Result Set
   ///
@@ -244,7 +245,7 @@
   /// ^The name of a result column is the value of the "AS" clause for
   /// that column, if there is an AS clause.  If there is no AS clause
   /// then the name of the column is unspecified and may change from
-  Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
+  late Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
       sqlite3_column_name;
 
   /// CAPI3REF: Declared Datatype Of A Query Result
@@ -274,28 +275,28 @@
   /// strongly typed, but the typing is dynamic not static.  ^Type
   /// is associated with individual values, not with the containers
   /// used to hold those values.
-  Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
+  late Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
       sqlite3_column_decltype;
 
-  int Function(Pointer<Statement> statement, int columnIndex)
+  late int Function(Pointer<Statement> statement, int columnIndex)
       sqlite3_column_type;
 
-  Pointer<Value> Function(Pointer<Statement> statement, int columnIndex)
+  late Pointer<Value> Function(Pointer<Statement> statement, int columnIndex)
       sqlite3_column_value;
 
-  double Function(Pointer<Statement> statement, int columnIndex)
+  late double Function(Pointer<Statement> statement, int columnIndex)
       sqlite3_column_double;
 
-  int Function(Pointer<Statement> statement, int columnIndex)
+  late int Function(Pointer<Statement> statement, int columnIndex)
       sqlite3_column_int;
 
-  Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
+  late Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex)
       sqlite3_column_text;
 
   /// The sqlite3_errstr() interface returns the English-language text that
   /// describes the result code, as UTF-8. Memory to hold the error message
   /// string is managed internally and must not be freed by the application.
-  Pointer<Utf8> Function(int code) sqlite3_errstr;
+  late Pointer<Utf8> Function(int code) sqlite3_errstr;
 
   /// Error Codes And Messages
   ///
@@ -328,7 +329,7 @@
   /// If an interface fails with SQLITE_MISUSE, that means the interface
   /// was invoked incorrectly by the application.  In that case, the
   /// error code and message may or may not be set.
-  Pointer<Utf8> Function(Pointer<Database> database) sqlite3_errmsg;
+  late Pointer<Utf8> Function(Pointer<Database> database) sqlite3_errmsg;
 
   _SQLiteBindings() {
     sqlite = dlopenPlatformSpecific("sqlite3");
@@ -392,5 +393,5 @@
   }
 }
 
-_SQLiteBindings _cachedBindings;
+_SQLiteBindings? _cachedBindings;
 _SQLiteBindings get bindings => _cachedBindings ??= _SQLiteBindings();
diff --git a/samples/ffi/sqlite/lib/src/bindings/constants.dart b/samples/ffi/sqlite/lib/src/bindings/constants.dart
index 120d567..71aa82e 100644
--- a/samples/ffi/sqlite/lib/src/bindings/constants.dart
+++ b/samples/ffi/sqlite/lib/src/bindings/constants.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 /// Result Codes
 ///
 /// Many SQLite functions return an integer result code from the set shown
diff --git a/samples/ffi/sqlite/lib/src/bindings/signatures.dart b/samples/ffi/sqlite/lib/src/bindings/signatures.dart
index 8e5d6e6..2f38dad 100644
--- a/samples/ffi/sqlite/lib/src/bindings/signatures.dart
+++ b/samples/ffi/sqlite/lib/src/bindings/signatures.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import "dart:ffi";
 
 import "package:ffi/ffi.dart";
diff --git a/samples/ffi/sqlite/lib/src/bindings/types.dart b/samples/ffi/sqlite/lib/src/bindings/types.dart
index f6a1736..494cdef 100644
--- a/samples/ffi/sqlite/lib/src/bindings/types.dart
+++ b/samples/ffi/sqlite/lib/src/bindings/types.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import "dart:ffi";
 
 /// Database Connection Handle
diff --git a/samples/ffi/sqlite/lib/src/collections/closable_iterator.dart b/samples/ffi/sqlite/lib/src/collections/closable_iterator.dart
index 83ca2ba..a86a58b 100644
--- a/samples/ffi/sqlite/lib/src/collections/closable_iterator.dart
+++ b/samples/ffi/sqlite/lib/src/collections/closable_iterator.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 /// This iterator should be [close]d after use.
 ///
 /// [ClosableIterator]s often use resources which should be freed after use.
diff --git a/samples/ffi/sqlite/lib/src/database.dart b/samples/ffi/sqlite/lib/src/database.dart
index 38121a9..7725609 100644
--- a/samples/ffi/sqlite/lib/src/database.dart
+++ b/samples/ffi/sqlite/lib/src/database.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import "dart:collection";
 import "dart:ffi";
 
@@ -23,7 +21,7 @@
 ///
 /// This database interacts with SQLite synchonously.
 class Database {
-  Pointer<types.Database> _database;
+  late Pointer<types.Database> _database;
   bool _open = false;
 
   /// Open a database located at the file [path].
@@ -108,11 +106,8 @@
     return Result._(this, statement, columnIndices);
   }
 
-  SQLiteException _loadError([int errorCode]) {
+  SQLiteException _loadError(int errorCode) {
     String errorMessage = bindings.sqlite3_errmsg(_database).ref.toString();
-    if (errorCode == null) {
-      return SQLiteException(errorMessage);
-    }
     String errorCodeExplanation =
         bindings.sqlite3_errstr(errorCode).ref.toString();
     return SQLiteException(
@@ -126,18 +121,13 @@
 /// Please note that this iterator should be [close]d manually if not all [Row]s
 /// are consumed.
 class Result extends IterableBase<Row> implements ClosableIterable<Row> {
-  final Database _database;
   final ClosableIterator<Row> _iterator;
-  final Pointer<Statement> _statement;
-  final Map<String, int> _columnIndices;
-
-  Row _currentRow = null;
 
   Result._(
-    this._database,
-    this._statement,
-    this._columnIndices,
-  ) : _iterator = _ResultIterator(_statement, _columnIndices) {}
+    Database database,
+    Pointer<Statement> statement,
+    Map<String, int> columnIndices,
+  ) : _iterator = _ResultIterator(statement, columnIndices) {}
 
   void close() => _iterator.close();
 
@@ -148,7 +138,7 @@
   final Pointer<Statement> _statement;
   final Map<String, int> _columnIndices;
 
-  Row _currentRow = null;
+  Row? _currentRow;
   bool _closed = false;
 
   _ResultIterator(this._statement, this._columnIndices) {}
@@ -172,7 +162,7 @@
     if (_closed) {
       throw SQLiteException("The result has already been closed.");
     }
-    return _currentRow;
+    return _currentRow!;
   }
 
   void close() {
@@ -197,7 +187,7 @@
   /// for the column by the query compiler.
   dynamic readColumn(String columnName,
       {Convert convert = Convert.DynamicType}) {
-    return readColumnByIndex(_columnIndices[columnName], convert: convert);
+    return readColumnByIndex(_columnIndices[columnName]!, convert: convert);
   }
 
   /// Reads column [columnName].
@@ -227,7 +217,6 @@
         return readColumnByIndexAsText(columnIndex);
       case Type.Null:
         return null;
-        break;
       default:
     }
   }
@@ -235,7 +224,7 @@
   /// Reads column [columnName] and converts to [Type.Integer] if not an
   /// integer.
   int readColumnAsInt(String columnName) {
-    return readColumnByIndexAsInt(_columnIndices[columnName]);
+    return readColumnByIndexAsInt(_columnIndices[columnName]!);
   }
 
   /// Reads column [columnIndex] and converts to [Type.Integer] if not an
@@ -247,7 +236,7 @@
 
   /// Reads column [columnName] and converts to [Type.Text] if not text.
   String readColumnAsText(String columnName) {
-    return readColumnByIndexAsText(_columnIndices[columnName]);
+    return readColumnByIndexAsText(_columnIndices[columnName]!);
   }
 
   /// Reads column [columnIndex] and converts to [Type.Text] if not text.
@@ -298,7 +287,6 @@
     case "null":
       return Type.Null;
   }
-  if (textRepresentation == null) return Type.Null;
   throw Exception("Unknown type [$textRepresentation]");
 }
 
diff --git a/samples/ffi/sqlite/lib/src/ffi/arena.dart b/samples/ffi/sqlite/lib/src/ffi/arena.dart
index a26e807..d01b64f 100644
--- a/samples/ffi/sqlite/lib/src/ffi/arena.dart
+++ b/samples/ffi/sqlite/lib/src/ffi/arena.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import "dart:async";
 import "dart:ffi";
 
diff --git a/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart b/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart
index 39653fa..220c0fc 100644
--- a/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart
+++ b/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart
@@ -2,13 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:ffi';
 import 'dart:io' show Platform;
 
-String _platformPath(String name, {String path}) {
-  if (path == null) path = "";
+String _platformPath(String name, String path) {
   if (Platform.isLinux || Platform.isAndroid)
     return path + "lib" + name + ".so";
   if (Platform.isMacOS) return path + "lib" + name + ".dylib";
@@ -16,7 +13,7 @@
   throw Exception("Platform not implemented");
 }
 
-DynamicLibrary dlopenPlatformSpecific(String name, {String path}) {
-  String fullPath = _platformPath(name, path: path);
+DynamicLibrary dlopenPlatformSpecific(String name, {String path = ""}) {
+  String fullPath = _platformPath(name, path);
   return DynamicLibrary.open(fullPath);
 }
diff --git a/samples/ffi/sqlite/pubspec.yaml b/samples/ffi/sqlite/pubspec.yaml
index dcc5d40..71d9d59 100644
--- a/samples/ffi/sqlite/pubspec.yaml
+++ b/samples/ffi/sqlite/pubspec.yaml
@@ -4,8 +4,8 @@
   Sqlite3 wrapper. Demo for dart:ffi.
 author: Daco Harkes <dacoharkes@google.com>, Samir Jindel <sjindel@google.com>
 environment:
-  sdk: '>=2.1.0 <3.0.0'
+  sdk: '>=2.12.0-0 <3.0.0'
 dependencies:
-  ffi: ^0.1.3
+  ffi: ^0.2.0-nullsafety.1
 dev_dependencies:
-  test: ^1.5.3
+  test: ^1.16.0-nullsafety.12
diff --git a/samples/ffi/sqlite/test/sqlite_test.dart b/samples/ffi/sqlite/test/sqlite_test.dart
index f7d3744..130c95f 100644
--- a/samples/ffi/sqlite/test/sqlite_test.dart
+++ b/samples/ffi/sqlite/test/sqlite_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 // VMOptions=--optimization-counter-threshold=5
 
 import "dart:ffi";
@@ -49,8 +47,7 @@
       expect(true, 1 <= id && id <= 3);
       String name = r.readColumnByIndex(1);
       expect(true, name is String);
-      String alternativeName = r.readColumn("alternative_name");
-      expect(true, alternativeName is String || alternativeName == null);
+      final alternativeName = r.readColumn("alternative_name") as String?;
       dynamic multiTypedValue = r.readColumn("multi_typed_column");
       expect(
           true,
@@ -76,8 +73,7 @@
       expect(true, 1 <= id && id <= 3);
       String name = r.readColumnByIndex(1);
       expect(true, name is String);
-      String alternativeName = r.readColumn("alternative_name");
-      expect(true, alternativeName is String || alternativeName == null);
+      final alternativeName = r.readColumn("alternative_name") as String?;
       dynamic multiTypedValue = r.readColumn("multi_typed_column");
       expect(
           true,