From d77e4eb4d67ca1ff4e40a8da512eb6d0ba86b6fc Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Mon, 17 Aug 2020 17:07:09 +0000 Subject: [PATCH] [vm/aot/nnbd] Fix class range 'is' tests for nullable types Issue: https://github.com/flutter/flutter/issues/63819 Change-Id: I7d3fe2a3f6c40b4a5bae9b1ba3ab1dd36fab8f5c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/158800 Reviewed-by: Vyacheslav Egorov Commit-Queue: Alexander Markov --- .../vm/dart/regress_flutter63819_test.dart | 31 +++++++++++++++++++ runtime/vm/compiler/backend/il.cc | 6 ++++ 2 files changed, 37 insertions(+) create mode 100644 runtime/tests/vm/dart/regress_flutter63819_test.dart diff --git a/runtime/tests/vm/dart/regress_flutter63819_test.dart b/runtime/tests/vm/dart/regress_flutter63819_test.dart new file mode 100644 index 00000000000..56d24122d67 --- /dev/null +++ b/runtime/tests/vm/dart/regress_flutter63819_test.dart @@ -0,0 +1,31 @@ +// Copyright (c) 2020, 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. + +// Verify that 'is' test of a nullable type accepts null. +// Regression test for https://github.com/flutter/flutter/issues/63819. + +import 'package:expect/expect.dart'; + +abstract class A {} + +class B extends A {} + +class C extends A {} + +@pragma('vm:never-inline') +bool foo(A? x) { + if (x is C?) { + print('$x is C?'); + return true; + } + print('$x is not C?'); + return false; +} + +void main() { + B(); + C(); + Expect.isFalse(foo(B())); + Expect.isTrue(foo(null)); +} diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index d066f1193e7..5f51a5b384c 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -453,6 +453,12 @@ bool HierarchyInfo::InstanceOfHasClassRange(const AbstractType& type, intptr_t* lower_limit, intptr_t* upper_limit) { ASSERT(CompilerState::Current().is_aot()); + if (type.IsNullable()) { + // 'is' test for nullable types should accept null cid in addition to the + // class range. In most cases it is not possible to extend class range to + // include kNullCid. + return false; + } if (CanUseSubtypeRangeCheckFor(type)) { const Class& type_class = Class::Handle(thread()->zone(), type.type_class());