Files
sdk/tests/language/nnbd/inference/variable_initialization_promotion_test.dart
T
Lasse R.H. Nielsen f8086c81ae Collect all test-related files in package:expect.
Collects files from `package:async_helper` and `tests/language`
that are generally useful, so that all test-related helpers are
in `package:expect`.

Moves the two libraries from `package:async_helper` into `package:expect`,
and the `tests/language/static_type_helper.dart` file too.

Deprecates `async_minitest.dart`, to follow `minitest.dart`,
expecting the Flutter use of it to have been fixed to not break
on deprecation (I believe Flutter no longer breaks builds on deprecations at all).

Patch 1 is the actual change.
Patch 2+4+8 is changing all existing references to the files.
Patch 6 ignores deprecation in files still using `async_minitest.dart`.

3+5+7+9 are updating this text to make the numbers match.
Then it's just test-expectations and small tweaks from there.

Change-Id: I1b665135b5fef9b9a0c3b340ffe9daf874d0174c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/373120
Reviewed-by: Nate Bosch <nbosch@google.com>
Reviewed-by: Devon Carew <devoncarew@google.com>
Commit-Queue: Lasse Nielsen <lrn@google.com>
2024-10-11 16:53:52 +00:00

341 lines
11 KiB
Dart

// 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.
import 'package:expect/static_type_helper.dart';
/// Test that the type of a local variable is treated as a "type of interest"
/// for the variable, and that for non-final variables, the initialization (if
/// any) is treated as an assignment for the purposes of promotion.
/// Verify that the declared type of a local variable is a type of interest.
void declaredTypeIsATypeOfInterest() {
// Check that a variable declared with a non-nullable type can be assignment
// demoted back to its declared type after being promoted.
{
num x = 3;
x.expectStaticType<Exactly<num>>();
// Promote x to int
if (x is int) {
x.expectStaticType<Exactly<int>>();
// Verify that demotion back to num works
x = 3.5;
x.expectStaticType<Exactly<num>>();
}
x.expectStaticType<Exactly<num>>();
}
// Check that a variable declared with a nullable type can be assignment
// promoted to the non-nullable variant of its type, and demoted back to both
// the non-nullable variant and the declared type after being promoted.
{
num? x = (3 as num?);
x.expectStaticType<Exactly<num?>>();
// This should promote to num, since num and num? should both be types of
// interest.
x = 3;
x.expectStaticType<Exactly<num>>();
// Promote x to int
if (x is int) {
x.expectStaticType<Exactly<int>>();
// Verify that demotion back to num works
x = 3.5;
x.expectStaticType<Exactly<num>>();
}
x.expectStaticType<Exactly<num>>();
// Verify that demotion back to num? works
x = null;
x.expectStaticType<Exactly<num?>>();
}
// Check that a late variable declared with a non-nullable type can be
// assignment demoted back to its declared type after being promoted.
{
late num x = 3;
x.expectStaticType<Exactly<num>>();
// Promote x to int
if (x is int) {
x.expectStaticType<Exactly<int>>();
// Verify that demotion back to num works
x = 3.5;
x.expectStaticType<Exactly<num>>();
}
x.expectStaticType<Exactly<num>>();
}
// Check that a late variable declared with a nullable type can be assignment
// promoted to the non-nullable variant of its type, and demoted back to both
// the non-nullable variant and the declared type after being promoted.
{
late num? x = (3 as num?);
x.expectStaticType<Exactly<num?>>();
// This should promote to num, since num and num? should both be types of
// interest.
x = 3;
x.expectStaticType<Exactly<num>>();
// Promote x to int
if (x is int) {
x.expectStaticType<Exactly<int>>();
// Verify that demotion back to num works
x = 3.5;
x.expectStaticType<Exactly<num>>();
}
x.expectStaticType<Exactly<num>>();
// Verify that demotion back to num? works
x = null;
x.expectStaticType<Exactly<num?>>();
}
// Final variables are not re-assignable, but can still be subject to
// to assignment based promotion and demotion in a few situations.
// Check that a late final variable declared with a non-nullable type can be
// assignment demoted back to its declared type after being promoted.
{
late final num x;
// Make x potentially assigned, and initialize it
if (num == num) {
x = 3.5;
}
// Branch will not be taken to avoid a double initialization error
if (x is int) {
x.expectStaticType<Exactly<int>>();
x = 3.5; // Demote to num.
x.expectStaticType<Exactly<num>>();
}
}
// Check that a final variable declared with a non-nullable type can be
// assignment promoted to the non-nullable variant of its type.
{
final num? x;
// Promote to num, since num is a type of interest
x = 3;
// Verify that we have promoted to num
x.expectStaticType<Exactly<num>>();
}
// Check that a late final variable declared with a non-nullable type can be
// assignment promoted to the non-nullable variant of its type.
{
late final num? x;
// Promote to num, since num is a type of interest
x = 3;
// Verify that we have promoted to num
x.expectStaticType<Exactly<num>>();
}
}
/// Verify that the inferred type of a local variable is a type of interest.
void inferredTypeIsATypeOfInterest() {
// Check that a variable inferred with a non-nullable type can be
// assignment demoted back to its declared type after being promoted.
{
var x = (3 as num);
x.expectStaticType<Exactly<num>>();
// Promote x to int
if (x is int) {
x.expectStaticType<Exactly<int>>();
// Verify that demotion back to num works
x = 3.5;
x.expectStaticType<Exactly<num>>();
}
x.expectStaticType<Exactly<num>>();
}
// Check that a variable inferred to have a nullable type can be assignment
// promoted to the non-nullable variant of its type, and demoted back to both
// the non-nullable variant and the declared type after being promoted.
{
var x = (3 as num?);
x.expectStaticType<Exactly<num?>>();
// This should promote to num, since num and num? should both be types of
// interest.
x = 3;
x.expectStaticType<Exactly<num>>();
// Promote x to int
if (x is int) {
x.expectStaticType<Exactly<int>>();
// Verify that demotion back to num works
x = 3.5;
x.expectStaticType<Exactly<num>>();
}
x.expectStaticType<Exactly<num>>();
// Verify that demotion back to num? works
x = null;
x.expectStaticType<Exactly<num?>>();
}
// Check that a variable inferred with a non-nullable type can be
// assignment demoted back to its declared type after being promoted.
{
late var x = (3 as num);
x.expectStaticType<Exactly<num>>();
// Promote x to int
if (x is int) {
x.expectStaticType<Exactly<int>>();
// Verify that demotion back to num works
x = 3.5;
x.expectStaticType<Exactly<num>>();
}
x.expectStaticType<Exactly<num>>();
}
// Check that a late variable inferred to have a nullable type can be
// assignment promoted to the non-nullable variant of its type, and demoted
// back to both the non-nullable variant and the declared type after being
// promoted.
{
late var x = (3 as num?);
x.expectStaticType<Exactly<num?>>();
// This should promote to num, since num and num? should both be types of
// interest.
x = 3;
x.expectStaticType<Exactly<num>>();
// Promote x to int
if (x is int) {
x.expectStaticType<Exactly<int>>();
// Verify that demotion back to num works
x = 3.5;
x.expectStaticType<Exactly<num>>();
}
x.expectStaticType<Exactly<num>>();
// Verify that demotion back to num? works
x = null;
x.expectStaticType<Exactly<num?>>();
}
}
/// Verify that the initializer on a mutable variable is treated as if it were
/// an assignment for the purposes of promotion, and therefore assigning a
/// non-nullable value can promote to a non-nullable variant of the declared
/// type.
void initializersOnVarPromote() {
// Check that a variable declared to have a nullable type can be promoted on
// initialization to the non-nullable variant of its type, demoted back to the
// declared type, and assignment promoted to the non-nullable variant of the
// declared type.
{
num? x = 3;
// Verify that we have promoted to num
x.expectStaticType<Exactly<num>>();
// Verify that num? is a type of interest by demoting to it
x = null;
x.expectStaticType<Exactly<num?>>();
// Verify that num is a type of interest by promoting to it.
x = 3;
x.expectStaticType<Exactly<num>>();
}
// Check that a late variable declared to have a nullable type can be promoted
// on initialization to the non-nullable variant of its type, demoted back to
// the declared type, and assignment promoted to the non-nullable variant of
// the declared type.
{
late num? x = 3;
// Verify that we have promoted to num
x.expectStaticType<Exactly<num>>();
// Verify that num? is a type of interest by demoting to it
x = null;
x.expectStaticType<Exactly<num?>>();
// Verify that num is a type of interest by promoting to it.
x = 3;
x.expectStaticType<Exactly<num>>();
}
}
/// Verify that the initializer on a final variable is not treated as if it were
/// an assignment for the purposes of promotion, and therefore assigning a
/// non-nullable value does not promote to a non-nullable variant of the
/// declared type.
void initializersOnFinalDoNotPromote() {
// Check that a final nullable variable initialized with a non-nullable value
// does not get promoted by the initializer to the non-nullable variant of the
// type.
{
final num? x = 3;
// Verify that we have not promoted to num
x.expectStaticType<Exactly<num?>>();
}
// Check that a late final nullable variable initialized with a non-nullable
// value does not get promoted by the initializer to the non-nullable variant
// of the type.
{
late final num? x = 3;
// Verify that we have not promoted to num
x.expectStaticType<Exactly<num?>>();
}
}
/// Check that when an initializer is a promoted type variable `X & T`, the
/// inferred type of the variable is `X`, but that the variable is immediately
/// promoted to `X & T`.
void typeVariableTypedVariableInferencePromotes<T>(T x0, T x1, bool b) {
if (x0 is num) {
// Promote `x0` to T & num
{
// Declare y, which should have inferred type T, and be promoted to T &
// num
var y = x0;
// Check that y is assignable to z, and hence that y is still promoted to
// T & num
num z = y;
// Check that y can be demoted to T, but do it conditionally so that T &
// num remains a type of interest.
if (b) y = x1;
// T & num is still a type of interest, and hence this assignment should
// promote to T & num.
y = x0;
// Check that y is assignable to z, and hence that y has been promoted T &
// num
z = y;
}
{
// Declare y, which should have inferred type T, and be promoted to T &
// num
late var y = x0;
// Check that y is assignable to z, and hence that y is still promoted to
// T & num
num z = y;
// Check that y can be demoted to T, but do it conditionally so that T &
// num remains a type of interest.
if (b) y = x1;
// T & num is still a type of interest, and hence this assignment should
// promote to T & num.
y = x0;
// Check that y is assignable to z, and hence that y has been promoted T &
// num
z = y;
}
{
// Declare y, which should have inferred type T, and be promoted to T &
// num
final y = x0;
// Check that y is assignable to z, and hence that y is still promoted to
// T & num
num z = y;
}
{
// Declare y, which should have inferred type T, and be promoted to T &
// num
late final y = x0;
// Check that y is assignable to z, and hence that y is still promoted to
// T & num
num z = y;
}
}
}
void main() {
declaredTypeIsATypeOfInterest();
inferredTypeIsATypeOfInterest();
initializersOnVarPromote();
initializersOnFinalDoNotPromote();
typeVariableTypedVariableInferencePromotes<num>(3, 3.5, true);
}