[vm/tts] Fix TTS handling of Never

Similar to C<Never> as C<T> was not  handled on the fast path which
was caught by newly added assertion.

Fixes https://github.com/dart-lang/sdk/issues/44789

TEST=added cases to vm/cc/TTS* suite
R=alexmarkov@google.com

Fixed: 44789
Change-Id: If2d4ad66cbde036b0d81f7f63512396ed1164883
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/181406
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 5fe1f7c..34e5f63 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -499,6 +499,9 @@
       __ CompareImmediate(TTSInternalRegs::kScratchReg, kNullCid);
       __ BranchIf(EQUAL, &is_subtype);
     }
+    // Never is a bottom type.
+    __ CompareImmediate(TTSInternalRegs::kScratchReg, kNeverCid);
+    __ BranchIf(EQUAL, &is_subtype);
     FlowGraphCompiler::GenerateCidRangesCheck(
         assembler, TTSInternalRegs::kScratchReg, ranges, &is_subtype,
         check_failed, true);
diff --git a/runtime/vm/type_testing_stubs_test.cc b/runtime/vm/type_testing_stubs_test.cc
index 04e4012..e00f107 100644
--- a/runtime/vm/type_testing_stubs_test.cc
+++ b/runtime/vm/type_testing_stubs_test.cc
@@ -407,6 +407,7 @@
       createI2() => I2();
       createBaseInt() => Base<int>();
       createBaseNull() => Base<Null>();
+      createBaseNever() => Base<Never>();
       createA() => A();
       createA1() => A1();
       createA2() => A2<int>();
@@ -433,6 +434,8 @@
       Object::Handle(Invoke(root_library, "createBaseInt"));
   const auto& obj_base_null =
       Object::Handle(Invoke(root_library, "createBaseNull"));
+  const auto& obj_base_never =
+      Object::Handle(Invoke(root_library, "createBaseNever"));
   const auto& obj_a = Object::Handle(Invoke(root_library, "createA"));
   const auto& obj_a1 = Object::Handle(Invoke(root_library, "createA1"));
   const auto& obj_a2 = Object::Handle(Invoke(root_library, "createA2"));
@@ -516,20 +519,42 @@
   RunTTSTest(obj_b2, type_base, tav_null, tav_null, ExpectLazilyHandledViaTTS,
              ExpectHandledViaTTS);
 
-  // Base<Null> as Base<int?>
-  // This is a regression test verifying that Null is included in
-  // class-id ranges for int?.
-  auto& type_int = Type::Handle(Type::IntType());
-  type_int = type_int.ToNullability(
+  // Base<Null|Never> as Base<int?>
+  // This is a regression test verifying that we don't fall through into
+  // runtime for Null and Never.
+  auto& type_nullable_int = Type::Handle(Type::IntType());
+  type_nullable_int = type_nullable_int.ToNullability(
       TestCase::IsNNBD() ? Nullability::kNullable : Nullability::kLegacy,
       Heap::kNew);
-  auto& tav_int = TypeArguments::Handle(TypeArguments::New(1));
-  tav_int.SetTypeAt(0, type_int);
-  CanonicalizeTAV(&tav_int);
-  auto& type_base_int = AbstractType::Handle(Type::New(class_base, tav_int));
-  FinalizeAndCanonicalize(&type_base_int);
-  RunTTSTest(obj_base_null, type_base_int, tav_null, tav_null,
+  auto& tav_nullable_int = TypeArguments::Handle(TypeArguments::New(1));
+  tav_nullable_int.SetTypeAt(0, type_nullable_int);
+  CanonicalizeTAV(&tav_nullable_int);
+  auto& type_base_nullable_int =
+      AbstractType::Handle(Type::New(class_base, tav_nullable_int));
+  FinalizeAndCanonicalize(&type_base_nullable_int);
+  RunTTSTest(obj_base_null, type_base_nullable_int, tav_null, tav_null,
              ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+  RunTTSTest(obj_base_never, type_base_nullable_int, tav_null, tav_null,
+             ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+
+  if (TestCase::IsNNBD()) {
+    // Base<Null|Never> as Base<int>
+    auto& type_int = Type::Handle(Type::IntType());
+    type_int = type_int.ToNullability(Nullability::kNonNullable, Heap::kNew);
+    auto& tav_int = TypeArguments::Handle(TypeArguments::New(1));
+    tav_int.SetTypeAt(0, type_int);
+    CanonicalizeTAV(&tav_int);
+    auto& type_base_int = Type::Handle(Type::New(class_base, tav_int));
+    type_base_int =
+        type_base_int.ToNullability(Nullability::kNonNullable, Heap::kNew);
+    FinalizeAndCanonicalize(&type_base_int);
+    if (IsolateGroup::Current()->null_safety()) {
+      RunTTSTest(obj_base_null, type_base_int, tav_null, tav_null,
+                 ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+    }
+    RunTTSTest(obj_base_never, type_base_int, tav_null, tav_null,
+               ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+  }
 
   // <...> as I2
   const auto& type_i2 = AbstractType::Handle(class_i2.RareType());