| // Copyright (c) 2018, 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. |
| |
| // Test checking that canonicalization rules for AssertAssignable IL |
| // instructions take into account that these instructions can be |
| // on unreachable code paths. |
| |
| // Class with two type parameters. |
| class A<U, T> { |
| T? field1; |
| List<T>? field2; |
| T Function(T)? field3; |
| } |
| |
| // Class with a single type parameter |
| class B<T> { |
| T? field1; |
| List<T>? field2; |
| T Function(T)? field3; |
| } |
| |
| var TRUE = true; |
| |
| void foo(bool f) { |
| dynamic x = f ? new B<int>() : new A<String, int>(); |
| if (f == TRUE) { |
| // Prevent constant folding by accessing a global |
| x.field1 = 10; |
| x.field2 = <int>[]; |
| x.field3 = (int i) => ++i; |
| } else { |
| x.field1 = 10; |
| x.field2 = <int>[]; |
| x.field3 = (int i) => ++i; |
| } |
| } |
| |
| void bar() { |
| // When foo() is inlined into bar() a graph where |
| // allocation of B will flow into code-path that |
| // expects A will arise. On that code-path (which |
| // is dynamically unreachable because it is guarded |
| // by CheckClass) there will be an assert assignable |
| // against A.T. |
| // Canonicalization rule should not crash when it tries |
| // to instantiate this type. |
| foo(true); |
| } |
| |
| void main() { |
| // Execute both paths to populate ICData. |
| foo(true); |
| foo(false); |
| |
| // Force optimization of bar(). |
| for (var i = 0; i < 100000; i++) bar(); |
| } |