[tests] Add tests for generic function type bounds with null safety

Testing that type arguments bounded by legacy types are equivalent
with nullable and non-nullable versions of the same types.

Re-landing this change with preapprovals for the VM configurations that
failed the last time.

Change-Id: Ic1709033dc3f3d9d7fc08357c0ad29bf976ed06b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134867
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Nicholas Shahan <nshahan@google.com>
This commit is contained in:
Nicholas Shahan 2020-02-11 22:31:55 +00:00 committed by commit-bot@chromium.org
parent e441b9fa9b
commit 69d481065b
5 changed files with 129 additions and 0 deletions

View file

@ -0,0 +1,20 @@
// 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.
// Opt out of NNBD:
// @dart = 2.6
/// A legacy library of helper methods to construct types and values containing
/// legacy (star *) types.
typedef fnTypeWithLegacyObjectBound = void Function<T extends Object>();
typedef fnTypeWithLegacyIntBound = void Function<T extends int>();
typedef fnTypeWithLegacyStringLegacyObjectBounds = void
Function<T extends String, S extends Object>();
void fnWithLegacyObjectBound<T extends Object>() => null;
void fnWithLegacyIntBound<T extends int>() => null;
void fnWithLegacyStringLegacyObjectBounds<T extends String,
S extends Object>() =>
null;

View file

@ -0,0 +1,23 @@
// 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.
/// A null safe library of helper methods to construct types and values
/// containing non-nullable and nullable (question ?) types.
typedef fnTypeWithNonNullObjectBound = void Function<T extends Object>();
typedef fnTypeWithNullableObjectBound = void Function<T extends Object?>();
typedef fnTypeWithNonNullIntBound = void Function<T extends int>();
typedef fnTypeWithNullableIntBound = void Function<T extends int?>();
typedef fnTypeWithNonNullableStringNullableObjectBounds = void
Function<T extends String, S extends Object?>();
typedef fnTypeWithNeverBound = void Function<T extends Never>();
void fnWithNonNullObjectBound<T extends Object>() => null;
void fnWithNullableObjectBound<T extends Object?>() => null;
void fnWithNonNullIntBound<T extends int>() => null;
void fnWithNullableIntBound<T extends int?>() => null;
void fnWithNonNullableStringNullableObjectBounds<T extends String,
S extends Object?>() =>
null;
void fnWithNullBound<T extends Null>() => null;

View file

@ -0,0 +1,21 @@
// 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.
// Requirements=nnbd-strong
import 'package:expect/expect.dart';
import 'function_type_bounds_null_safe_lib.dart';
main() {
// void fn<T extends Object>() is void Function<T extends Object?>()
// Should fail with strong checking because Object and Object? should be
// treated as type bounds that are not equivalent.
Expect.isFalse(fnWithNonNullObjectBound is fnTypeWithNullableObjectBound);
// void fn<T extends Null>() is void Function<T extends Never>()
// Should fail with strong checking because because Null and Never are treated
// as distinct.
Expect.isFalse(fnWithNullBound is fnTypeWithNeverBound);
}

View file

@ -0,0 +1,44 @@
// 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.
// Requirements=nnbd
import 'package:expect/expect.dart';
import 'function_type_bounds_legacy_lib.dart';
import 'function_type_bounds_null_safe_lib.dart';
main() {
// void fn<T extends Object>() is void Function<T extends Object>()
Expect.isTrue(fnWithNonNullObjectBound is fnTypeWithNonNullObjectBound);
// void fn<T extends Object>() is void Function<T extends Object*>()
Expect.isTrue(fnWithNonNullObjectBound is fnTypeWithLegacyObjectBound);
// void fn<T extends Object?>() is void Function<T extends Object*>()
Expect.isTrue(fnWithNullableObjectBound is fnTypeWithLegacyObjectBound);
// void fn<T extends Object*>() is void Function<T extends Object>()
Expect.isTrue(fnWithLegacyObjectBound is fnTypeWithNonNullObjectBound);
// void fn<T extends Object*>() is void Function<T extends Object?>()
Expect.isTrue(fnWithLegacyObjectBound is fnTypeWithNullableObjectBound);
// void fn<T extends int>() is void Function<T extends int>()
Expect.isTrue(fnWithNonNullIntBound is fnTypeWithNonNullIntBound);
// void fn<T extends int>() is void Function<T extends int*>()
Expect.isTrue(fnWithNonNullIntBound is fnTypeWithLegacyIntBound);
// void fn<T extends int?>() is void Function<T extends int*>()
Expect.isTrue(fnWithNullableIntBound is fnTypeWithLegacyIntBound);
// void fn<T extends int*>() is void Function<T extends int>()
Expect.isTrue(fnWithLegacyIntBound is fnTypeWithNonNullIntBound);
// void fn<T extends int*>() is void Function<T extends int?>()
Expect.isTrue(fnWithLegacyIntBound is fnTypeWithNullableIntBound);
// void fn<T extends String*, S extends Object*>() is
// void Function<T extends String, S extends Object?>()
Expect.isTrue(fnWithLegacyStringLegacyObjectBounds
is fnTypeWithNonNullableStringNullableObjectBounds);
// void fn<T extends String, S extends Object?>() is
// void Function<T extends String*, S extends Object*>()
Expect.isTrue(fnWithNonNullableStringNullableObjectBounds
is fnTypeWithLegacyStringLegacyObjectBounds);
}

View file

@ -0,0 +1,21 @@
// 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.
// Requirements=nnbd-weak
import 'package:expect/expect.dart';
import 'function_type_bounds_null_safe_lib.dart';
main() {
// void fn<T extends Object>() is void Function<T extends Object?>()
// Should pass with weak checking because when the nullability information on
// Object and Object? are erased the type bounds are equivalent.
Expect.isTrue(fnWithNonNullObjectBound is fnTypeWithNullableObjectBound);
// void fn<T extends Null>() is void Function<T extends Never>()
// Should pass with weak checking because because Null becomes equivalent to
// the bottom type.
Expect.isTrue(fnWithNullBound is fnTypeWithNeverBound);
}