Version 2.17.0-205.0.dev

Merge commit 'd0a1404d11875151f41ed2acda37a0881bc1e0da' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index acdf27e..545417e 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -57,63 +57,51 @@
   @override
   Future<SomeErrorsResult> getErrors(String path) async {
     _checkConsistency();
-    try {
-      return await _driver.getErrors(path);
-    } finally {
-      _checkConsistency();
-    }
+    var result = await _driver.getErrors(path);
+    _checkConsistency();
+    return result;
   }
 
   @Deprecated('Use getFile2() instead')
   @override
   SomeFileResult getFile(String path) {
     _checkConsistency();
-    try {
-      return _driver.getFileSync(path);
-    } finally {
-      _checkConsistency();
-    }
+    var result = _driver.getFileSync(path);
+    _checkConsistency();
+    return result;
   }
 
   @override
   Future<SomeFileResult> getFile2(String path) async {
     _checkConsistency();
-    try {
-      return await _driver.getFile(path);
-    } finally {
-      _checkConsistency();
-    }
+    var result = await _driver.getFile(path);
+    _checkConsistency();
+    return result;
   }
 
   @override
   Future<SomeLibraryElementResult> getLibraryByUri(String uri) async {
     _checkConsistency();
-    try {
-      return await _driver.getLibraryByUri(uri);
-    } finally {
-      _checkConsistency();
-    }
+    var result = await _driver.getLibraryByUri(uri);
+    _checkConsistency();
+    return result;
   }
 
   @Deprecated('Use getParsedLibrary2() instead')
   @override
   SomeParsedLibraryResult getParsedLibrary(String path) {
     _checkConsistency();
-    try {
-      return _driver.getParsedLibrary(path);
-    } finally {
-      _checkConsistency();
-    }
+    var result = _driver.getParsedLibrary(path);
+    _checkConsistency();
+    return result;
   }
 
   @override
   Future<SomeParsedLibraryResult> getParsedLibrary2(String path) async {
     _checkConsistency();
-    try {
-      return await _driver.getParsedLibrary2(path);
-    } finally {
-      _checkConsistency();
-    }
+    var result = await _driver.getParsedLibrary2(path);
+    _checkConsistency();
+    return result;
   }
 
   @Deprecated('Use getParsedLibraryByElement2() instead')
@@ -125,11 +113,9 @@
       return NotElementOfThisSessionResult();
     }
 
-    try {
-      return _driver.getParsedLibraryByUri(element.source.uri);
-    } finally {
-      _checkConsistency();
-    }
+    var result = _driver.getParsedLibraryByUri(element.source.uri);
+    _checkConsistency();
+    return result;
   }
 
   @override
@@ -142,42 +128,34 @@
       return NotElementOfThisSessionResult();
     }
 
-    try {
-      return await _driver.getParsedLibraryByUri2(element.source.uri);
-    } finally {
-      _checkConsistency();
-    }
+    var result = await _driver.getParsedLibraryByUri2(element.source.uri);
+    _checkConsistency();
+    return result;
   }
 
   @Deprecated('Use getParsedUnit2() instead')
   @override
   SomeParsedUnitResult getParsedUnit(String path) {
     _checkConsistency();
-    try {
-      return _driver.parseFileSync(path);
-    } finally {
-      _checkConsistency();
-    }
+    var result = _driver.parseFileSync(path);
+    _checkConsistency();
+    return result;
   }
 
   @override
   Future<SomeParsedUnitResult> getParsedUnit2(String path) async {
     _checkConsistency();
-    try {
-      return await _driver.parseFile(path);
-    } finally {
-      _checkConsistency();
-    }
+    var result = await _driver.parseFile(path);
+    _checkConsistency();
+    return result;
   }
 
   @override
   Future<SomeResolvedLibraryResult> getResolvedLibrary(String path) async {
     _checkConsistency();
-    try {
-      return await _driver.getResolvedLibrary(path);
-    } finally {
-      _checkConsistency();
-    }
+    var result = await _driver.getResolvedLibrary(path);
+    _checkConsistency();
+    return result;
   }
 
   @override
@@ -190,31 +168,25 @@
       return NotElementOfThisSessionResult();
     }
 
-    try {
-      return await _driver.getResolvedLibraryByUri(element.source.uri);
-    } finally {
-      _checkConsistency();
-    }
+    var result = await _driver.getResolvedLibraryByUri(element.source.uri);
+    _checkConsistency();
+    return result;
   }
 
   @override
   Future<SomeResolvedUnitResult> getResolvedUnit(String path) async {
     _checkConsistency();
-    try {
-      return await _driver.getResult(path);
-    } finally {
-      _checkConsistency();
-    }
+    var result = await _driver.getResult(path);
+    _checkConsistency();
+    return result;
   }
 
   @override
   Future<SomeUnitElementResult> getUnitElement(String path) {
     _checkConsistency();
-    try {
-      return _driver.getUnitElement(path);
-    } finally {
-      _checkConsistency();
-    }
+    var result = _driver.getUnitElement(path);
+    _checkConsistency();
+    return result;
   }
 
   /// Check to see that results from this session will be consistent, and throw
diff --git a/runtime/tests/vm/dart/regress_48522_test.dart b/runtime/tests/vm/dart/regress_48522_test.dart
new file mode 100644
index 0000000..d01562b
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_48522_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2022, 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.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/48522.
+// Test that FutureOr<T?> = FutureOr<T?>? <: Future<T?>?.
+
+import 'dart:async';
+
+import 'package:expect/expect.dart';
+
+Future<String?>? foo() {
+  return null;
+}
+
+FutureOr<String?>? bar() {
+  return null;
+}
+
+FutureOr<String?> baz() {
+  return null;
+}
+
+typedef F = FutureOr<String?> Function();
+typedef G = FutureOr<String?>? Function();
+
+void main() {
+  // Check Future<T?>? <: FutureOr<T?>?.
+  print(foo.runtimeType);
+  Expect.isTrue(foo is G);
+  (foo as dynamic) as G; // Should not throw.
+
+  final G v1 = foo;
+  print(v1.runtimeType);
+  Expect.isTrue(v1 is G);
+  (v1 as dynamic) as G; // Should not throw.
+
+  // Check Future<T?>? <: FutureOr<T?>.
+  print(foo.runtimeType);
+  Expect.isTrue(foo is F);
+  (foo as dynamic) as F; // Should not throw.
+
+  final F v2 = foo;
+  print(v2.runtimeType);
+  Expect.isTrue(v2 is F);
+  (v2 as dynamic) as F; // Should not throw.
+
+  // Check FutureOr<T?> = FutureOr<T?>?.
+  print(bar.runtimeType);
+  Expect.isTrue(bar is F);
+  (bar as dynamic) as F; // Should not throw.
+  print(baz.runtimeType);
+  Expect.isTrue(baz is G);
+  (baz as dynamic) as G; // Should not throw.
+}
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 241097c..4b789f8 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -19847,8 +19847,14 @@
       ASSERT(object_store->nullable_future_null_type() != Type::null());
       return object_store->nullable_future_null_type();
     }
-    if (IsNullable() && unwrapped_type.IsNullable()) {
-      return Type::Cast(*this).ToNullability(Nullability::kNonNullable, space);
+    // To avoid having to special case FutureOr in nullability checks, we lift
+    // the nullability of the type argument to FutureOr as appropriate.
+    if (IsNullable() || unwrapped_type.IsNullable()) {
+      // FutureOr<T?> = FutureOr<T?>* = FutureOr<T?>?, so mark as nullable.
+      return Type::Cast(*this).ToNullability(Nullability::kNullable, space);
+    } else if (unwrapped_type.IsLegacy()) {
+      // FutureOr<T*> = FutureOr<T*>*, so mark as legacy.
+      return Type::Cast(*this).ToNullability(Nullability::kLegacy, space);
     }
   }
   return ptr();
diff --git a/tools/VERSION b/tools/VERSION
index 8c45d2b..14c3783 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 204
+PRERELEASE 205
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/bot_utils.py b/tools/bots/bot_utils.py
index 58f136d..a010a6f 100755
--- a/tools/bots/bot_utils.py
+++ b/tools/bots/bot_utils.py
@@ -39,6 +39,19 @@
     'arm64': 'arm64',
 }
 
+SYSTEM_TO_CIPD = {
+    'windows': 'windows',
+    'linux': 'linux',
+    'macos': 'mac',
+}
+
+ARCH_TO_CIPD = {
+    'ia32': '386',
+    'x64': 'amd64',
+    'arm': 'arm6l',
+    'arm64': 'arm64',
+}
+
 
 class Channel(object):
     BETA = 'beta'
diff --git a/tools/bots/dart_sdk.py b/tools/bots/dart_sdk.py
index 934906f..7f6bfb4 100755
--- a/tools/bots/dart_sdk.py
+++ b/tools/bots/dart_sdk.py
@@ -19,6 +19,21 @@
                         utils.GetBuildRoot(BUILD_OS, build_mode, arch), path)
 
 
+def UploadFlutterCipd(arch, sdk_path, channel):
+    cipd_os = bot_utils.SYSTEM_TO_CIPD[BUILD_OS]
+    cipd_arch = bot_utils.ARCH_TO_CIPD[arch]
+    cipd_platform = cipd_os + '-' + cipd_arch
+    version = utils.GetVersion()
+    name = 'flutter/dart-sdk/%s' % cipd_platform
+    version_tag = 'version:%s' % version
+    git_tag = 'git_revision:%s' % utils.GetGitRevision()
+    bot_utils.run([
+        'cipd', 'create', '-name', name, '-in', sdk_path, '-install-mode',
+        'copy', '-tag', version_tag, '-tag', git_tag, '-ref', channel,
+        '-preserve-writable'
+    ])
+
+
 def BuildDartdocAPIDocs(dirname):
     dart_sdk = BuildRootPath('dart-sdk')
     dart_exe = os.path.join(dart_sdk, 'bin', 'dart')
@@ -234,6 +249,8 @@
             sdk_path = BuildRootPath('dart-sdk', arch=arch)
             CreateAndUploadSDKZip(arch, sdk_path)
             DartArchiveUnstrippedBinaries(arch)
+            if CHANNEL != bot_utils.Channel.BLEEDING_EDGE:
+                UploadFlutterCipd(arch, sdk_path, CHANNEL)
         if BUILD_OS == 'linux':
             CreateUploadVersionFile()
     else: