[cfe] Adjust computation of nullability in flatten

Closes #47057.

Bug: https://github.com/dart-lang/sdk/issues/47057
Change-Id: Iad719192d0ecbe97461bfed868899072a6dd52e2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/212467
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
diff --git a/pkg/front_end/testcases/general/issue47057.dart b/pkg/front_end/testcases/general/issue47057.dart
new file mode 100644
index 0000000..8d5b88d
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47057.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2021, 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 'dart:async';
+
+Future<int> foo<X extends Object?>(X x) async {
+  if (x is Future<int>) {
+    return x;
+  } else {
+    throw 42;
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue47057.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue47057.dart.textual_outline.expect
new file mode 100644
index 0000000..af27955
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47057.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+import 'dart:async';
+
+Future<int> foo<X extends Object?>(X x) async {}
+main() {}
diff --git a/pkg/front_end/testcases/general/issue47057.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue47057.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..af27955
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47057.dart.textual_outline_modelled.expect
@@ -0,0 +1,4 @@
+import 'dart:async';
+
+Future<int> foo<X extends Object?>(X x) async {}
+main() {}
diff --git a/pkg/front_end/testcases/general/issue47057.dart.weak.expect b/pkg/front_end/testcases/general/issue47057.dart.weak.expect
new file mode 100644
index 0000000..abd22ad
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47057.dart.weak.expect
@@ -0,0 +1,16 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+static method foo<X extends core::Object?>(self::foo::X% x) → asy::Future<core::int> async {
+  if(x is{ForNonNullableByDefault} asy::Future<core::int>) {
+    return x{self::foo::X% & asy::Future<core::int> /* '%' & '!' = '!' */};
+  }
+  else {
+    throw 42;
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue47057.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue47057.dart.weak.outline.expect
new file mode 100644
index 0000000..e803dbe
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47057.dart.weak.outline.expect
@@ -0,0 +1,11 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+static method foo<X extends core::Object?>(self::foo::X% x) → asy::Future<core::int> async 
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/issue47057.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue47057.dart.weak.transformed.expect
new file mode 100644
index 0000000..e2413bc
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue47057.dart.weak.transformed.expect
@@ -0,0 +1,40 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+static method foo<X extends core::Object?>(self::foo::X% x) → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        if(x is{ForNonNullableByDefault} asy::Future<core::int>) {
+          :return_value = x{self::foo::X% & asy::Future<core::int> /* '%' & '!' = '!' */};
+          break #L1;
+        }
+        else {
+          throw 42;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method main() → dynamic {}
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index 6b22016..5320daf 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -102,8 +102,7 @@
       List<DartType>? futureArguments =
           getTypeArgumentsAsInstanceOf(resolved, coreTypes.futureClass);
       if (futureArguments != null) {
-        return _withDeclaredNullability(
-            futureArguments.single, t.declaredNullability);
+        return _withDeclaredNullability(futureArguments.single, t.nullability);
       }
     }