mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
Flow analysis: Pin down initialization behaviors before fixing #1785.
https://github.com/dart-lang/language/issues/1785 has a wide enough impact that its fix will have to be bundled in with a language version (i.e. future versions of Dart will have to reproduce the old buggy behavior for code that's not opted in to the latest language version). Therefore, we'll have to maintain tests of the behavior both before and after the fix. This CL is the first step in that process, adding tests that validate the current (buggy) behavior. Bug: https://github.com/dart-lang/language/issues/1785 Change-Id: I78f17999ac1cbc096a312ef977db24654e06a263 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/210400 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
parent
cf46f2848f
commit
d2b313227d
3 changed files with 291 additions and 0 deletions
|
@ -11,6 +11,16 @@ finalLocalBool(int? x) {
|
|||
}
|
||||
}
|
||||
|
||||
finalLocalBool_untyped(int? x) {
|
||||
final b = x == null;
|
||||
if (!b) {
|
||||
// No promotion due to https://github.com/dart-lang/language/issues/1785
|
||||
x;
|
||||
} else {
|
||||
x;
|
||||
}
|
||||
}
|
||||
|
||||
localBool(int? x) {
|
||||
bool b = x == null;
|
||||
if (!b) {
|
||||
|
@ -20,6 +30,16 @@ localBool(int? x) {
|
|||
}
|
||||
}
|
||||
|
||||
localBool_untyped(int? x) {
|
||||
var b = x == null;
|
||||
if (!b) {
|
||||
// No promotion due to https://github.com/dart-lang/language/issues/1785
|
||||
x;
|
||||
} else {
|
||||
x;
|
||||
}
|
||||
}
|
||||
|
||||
localBool_assigned(int? x, bool b1) {
|
||||
bool b2 = b1;
|
||||
b2 = x == null;
|
||||
|
@ -30,6 +50,16 @@ localBool_assigned(int? x, bool b1) {
|
|||
}
|
||||
}
|
||||
|
||||
localBool_assigned_untyped(int? x, bool b1) {
|
||||
var b2 = b1;
|
||||
b2 = x == null;
|
||||
if (!b2) {
|
||||
/*nonNullable*/ x;
|
||||
} else {
|
||||
x;
|
||||
}
|
||||
}
|
||||
|
||||
localBool_assignedDynamic(int? x, bool b1) {
|
||||
dynamic b2 = b1;
|
||||
b2 = x == null;
|
||||
|
@ -49,6 +79,15 @@ parameter_assigned(int? x, bool b) {
|
|||
}
|
||||
}
|
||||
|
||||
parameter_assigned_untyped(int? x, b) {
|
||||
b = x == null;
|
||||
if (!b) {
|
||||
/*nonNullable*/ x;
|
||||
} else {
|
||||
x;
|
||||
}
|
||||
}
|
||||
|
||||
parameter_assignedDynamic(int? x, dynamic b) {
|
||||
b = x == null;
|
||||
if (!b) {
|
||||
|
@ -69,6 +108,17 @@ lateFinalLocalBool(int? x) {
|
|||
}
|
||||
}
|
||||
|
||||
lateFinalLocalBool_untyped(int? x) {
|
||||
late final b = x == null;
|
||||
if (!b) {
|
||||
// We don't promote based on the initializers of late locals because we
|
||||
// don't know when they execute.
|
||||
x;
|
||||
} else {
|
||||
x;
|
||||
}
|
||||
}
|
||||
|
||||
lateLocalBool(int? x) {
|
||||
late bool b = x == null;
|
||||
if (!b) {
|
||||
|
@ -80,6 +130,17 @@ lateLocalBool(int? x) {
|
|||
}
|
||||
}
|
||||
|
||||
lateLocalBool_untyped(int? x) {
|
||||
late var b = x == null;
|
||||
if (!b) {
|
||||
// We don't promote based on the initializers of late locals because we
|
||||
// don't know when they execute.
|
||||
x;
|
||||
} else {
|
||||
x;
|
||||
}
|
||||
}
|
||||
|
||||
lateLocalBool_assignedAndInitialized(int? x, bool b1) {
|
||||
late bool b2 = b1;
|
||||
b2 = x == null;
|
||||
|
@ -90,6 +151,16 @@ lateLocalBool_assignedAndInitialized(int? x, bool b1) {
|
|||
}
|
||||
}
|
||||
|
||||
lateLocalBool_assignedAndInitialized_untyped(int? x, bool b1) {
|
||||
late var b2 = b1;
|
||||
b2 = x == null;
|
||||
if (!b2) {
|
||||
/*nonNullable*/ x;
|
||||
} else {
|
||||
x;
|
||||
}
|
||||
}
|
||||
|
||||
lateLocalBool_assignedButNotInitialized(int? x) {
|
||||
late bool b;
|
||||
b = x == null;
|
||||
|
@ -100,6 +171,16 @@ lateLocalBool_assignedButNotInitialized(int? x) {
|
|||
}
|
||||
}
|
||||
|
||||
lateLocalBool_assignedButNotInitialized_untyped(int? x) {
|
||||
late var b;
|
||||
b = x == null;
|
||||
if (!b) {
|
||||
/*nonNullable*/ x;
|
||||
} else {
|
||||
x;
|
||||
}
|
||||
}
|
||||
|
||||
rebaseWithDemotion(int? x, int? y, int? z, int? a) {
|
||||
x;
|
||||
y;
|
||||
|
|
|
@ -13,6 +13,11 @@ localVariable() {
|
|||
x;
|
||||
}
|
||||
|
||||
localVariable_null() {
|
||||
var x = null;
|
||||
x;
|
||||
}
|
||||
|
||||
localVariable_hasInitializer(num a) {
|
||||
var x = a;
|
||||
x = 1;
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
// 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.
|
||||
|
||||
// @dart=2.13
|
||||
|
||||
import '../../static_type_helper.dart';
|
||||
|
||||
// This test checks whether a local boolean variable can be used to perform type
|
||||
// promotion, if that variable is implicitly typed.
|
||||
//
|
||||
// Due to https://github.com/dart-lang/language/issues/1785, initializer
|
||||
// expressions on implicitly typed variables are ignored for the purposes of
|
||||
// type promotion (however, later assignments to those variables still do
|
||||
// influence promotion). To avoid introducing breaking language changes, we
|
||||
// intend to preserve this behavior until a specific Dart language version.
|
||||
// This test verifies that for code that is not opted in to the newer behavior,
|
||||
// the old (buggy) behavior persists.
|
||||
|
||||
parameterUnmodified(int? x) {
|
||||
{
|
||||
late final b = x != null;
|
||||
// We wouldn't promote based on the initializers of late locals anyhow,
|
||||
// because we don't know when they execute.
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
late final b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
{
|
||||
late var b = x != null;
|
||||
// We wouldn't promote based on the initializers of late locals anyhow,
|
||||
// because we don't know when they execute.
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
late var b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
{
|
||||
final b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
final b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
{
|
||||
var b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
var b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
}
|
||||
|
||||
parameterModifiedLater(int? x, int? y) {
|
||||
x = y;
|
||||
{
|
||||
late final b = x != null;
|
||||
// We wouldn't promote based on the initializers of late locals anyhow,
|
||||
// because we don't know when they execute.
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
late final b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
{
|
||||
late var b = x != null;
|
||||
// We wouldn't promote based on the initializers of late locals anyhow,
|
||||
// because we don't know when they execute.
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
late var b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
{
|
||||
final b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
final b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
{
|
||||
var b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
var b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
}
|
||||
|
||||
localVariableInitialized(int? y) {
|
||||
int? x = y;
|
||||
{
|
||||
late final b = x != null;
|
||||
// We wouldn't promote based on the initializers of late locals anyhow,
|
||||
// because we don't know when they execute.
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
late final b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
{
|
||||
late var b = x != null;
|
||||
// We wouldn't promote based on the initializers of late locals anyhow,
|
||||
// because we don't know when they execute.
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
late var b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
{
|
||||
final b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
final b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
{
|
||||
var b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
var b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
}
|
||||
|
||||
localVariableModifiedLater(int? y) {
|
||||
int? x;
|
||||
x = y;
|
||||
{
|
||||
late final b = x != null;
|
||||
// We wouldn't promote based on the initializers of late locals anyhow,
|
||||
// because we don't know when they execute.
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
late final b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
{
|
||||
late var b = x != null;
|
||||
// We wouldn't promote based on the initializers of late locals anyhow,
|
||||
// because we don't know when they execute.
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
late var b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
{
|
||||
final b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
final b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
{
|
||||
var b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
{
|
||||
var b;
|
||||
b = x != null;
|
||||
if (b) x.expectStaticType<Exactly<int>>();
|
||||
}
|
||||
}
|
||||
|
||||
main() {
|
||||
parameterUnmodified(null);
|
||||
parameterUnmodified(0);
|
||||
parameterModifiedLater(null, null);
|
||||
parameterModifiedLater(null, 0);
|
||||
localVariableInitialized(null);
|
||||
localVariableInitialized(0);
|
||||
localVariableModifiedLater(null);
|
||||
localVariableModifiedLater(0);
|
||||
}
|
Loading…
Reference in a new issue