mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 10:18:13 +00:00
f5b8cc2c76
Treating createSentinel as returning a value of type Never caused issues whenever its result flowed into a union, since the union would just simplify to its other component. This meant that if a late field started out uninitialized and was later initialized to a constant, we would see it as only ever having the constant value. This caused isSentinel to always return false even if the field hadn't been initialized yet. Instead, we support a late sentinel value in the abstract value domain and use this value as the return type of createSentinel during inference. Additionally, inference treats _lateReadCheck as a simple narrowing to exclude the late sentinel value. Change-Id: I086bfd77576930e3ca2a4cfc9bd63476b6636685 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/210646 Reviewed-by: Stephen Adams <sra@google.com>
24 lines
787 B
Dart
24 lines
787 B
Dart
// 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 'package:expect/expect.dart';
|
|
|
|
// Tests to ensure that narrowing type information does not discard late
|
|
// sentinel values unintentionally.
|
|
|
|
class Foo<T> {
|
|
// Since `List<T>` contains a free type variable, any access of [x] will be
|
|
// immediately followed by a narrowing to the appropriate instantiation of
|
|
// `List<T>`. This narrowing should not exclude the late sentinel value from
|
|
// the abstract value.
|
|
late final List<T> x;
|
|
}
|
|
|
|
void main() {
|
|
Foo<int> foo = Foo();
|
|
Expect.throws(() => foo.x);
|
|
foo.x = const [];
|
|
Expect.isTrue(foo.x.isEmpty);
|
|
}
|