Add alternatives for functions that should be deprecated.

`List.unmodifiable` and `Map.unmodifiable` is as badly typed
as `List.from` and `Map.from`, but does not have a better-typed
`.of` constructor. This adds such, to give a migration target
when deprecating the badly typed constructors.

The `Future.delayed` with no second argument is also unsafely
typed, it fails if the type argument is not nullable.
The `Future.pause` creates `Future<void>` instead.

CoreLibraryReviewExempt: No new or platform specific behavior.
Change-Id: Iba101b3dc62f412003abd501fa042aca0ce63116
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/499280
Commit-Queue: Lasse Nielsen <lrn@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Nate Bosch <nbosch@google.com>
This commit is contained in:
Lasse R.H. Nielsen
2026-05-04 08:08:35 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 70b0c87d5f
commit f35a3fcce4
20 changed files with 416 additions and 185 deletions
+28 -7
View File
@@ -399,16 +399,19 @@ abstract interface class Future<T> {
///
/// If [computation] returns a future,
/// the future returned by this constructor will complete with the value or
/// error of that future.
/// error of that future, which may not be available until even later.
///
/// If the duration is 0 or less,
/// it completes no sooner than in the next event-loop iteration,
/// after all microtasks have run.
/// (The waiting for the delay uses a [Timer] created in the current zone.)
///
/// If [computation] is omitted,
/// it will be treated as if [computation] was `() => null`,
/// The computation must not be omitted, and must not be null.
/// Use [Future.pause] instead if you just want to wait for duration.
/// Until that is reflected in the signature, if [computation] is omitted,
/// then [T] must be nullable.
/// Then the computation will be treated as if it was `() => null`,
/// and the future will eventually complete with the `null` value.
/// In that case, [T] must be nullable.
///
/// If calling [computation] throws, the created future will complete with the
/// error.
@@ -418,11 +421,16 @@ abstract interface class Future<T> {
///
/// Example:
/// ```dart
/// Future.delayed(const Duration(seconds: 1), () {
/// print('One second has passed.'); // Prints after 1 second.
/// var now = DateTime.now();
/// var later = await Future.delayed(const Duration(seconds: 1), () {
/// return DateTime.timestamp();
/// });
/// print(now.difference(later)); // At least a second.
/// ```
factory Future.delayed(Duration duration, [FutureOr<T> computation()?]) {
factory Future.delayed(
Duration duration, [
FutureOr<T> Function()? computation,
]) {
if (computation == null && !typeAcceptsNull<T>()) {
throw ArgumentError.value(
null,
@@ -448,6 +456,19 @@ abstract interface class Future<T> {
return result;
}
/// Creates a [Future] that completes with no result after [duration].
///
/// Like [Future.delayed], but does not perform any action,
/// and cannot complete with an error.
@Since("3.13")
static Future<void> pause([Duration duration = Duration.zero]) {
var result = _Future<void>();
Zone._current.createTimer(duration, () {
result._completeWithValue(null);
});
return result;
}
/// Waits for multiple futures to complete and collects their results.
///
/// Returns a future which will complete once all the provided futures
+20 -1
View File
@@ -191,7 +191,10 @@ abstract interface class List<E> implements Iterable<E>, _ListIterable<E> {
///
/// This constructor creates a growable list when [growable] is true;
/// otherwise, it returns a fixed-length list.
external factory List.from(Iterable elements, {bool growable = true});
external factory List.from(
Iterable<Object?> elements, {
bool growable = true,
});
/// Creates a list from [elements].
///
@@ -241,8 +244,24 @@ abstract interface class List<E> implements Iterable<E>, _ListIterable<E> {
/// final unmodifiableList = List.unmodifiable(numbers); // [1, 2, 3]
/// unmodifiableList[1] = 87; // Throws.
/// ```
// @Deprecated("Use List.unmodifiableOf instead")
external factory List.unmodifiable(Iterable elements);
/// Creates an unmodifiable list containing all [elements].
///
/// The [Iterator] of [elements] provides the order of the elements.
///
/// An unmodifiable list cannot have its length or elements changed.
/// If the elements are themselves immutable, then the resulting list
/// is also immutable.
/// ```dart
/// final numbers = <int>[1, 2, 3];
/// final unmodifiableList = List.unmodifiable(numbers); // [1, 2, 3]
/// unmodifiableList[1] = 87; // Throws.
/// ```
@Since("3.13")
factory List.unmodifiableOf(Iterable<E> elements) = List<E>.unmodifiable;
/// Adapts [source] to be a `List<T>`.
///
/// Any time the list would produce an element that is not a [T],
+18
View File
@@ -92,8 +92,26 @@ abstract interface class Map<K, V> {
/// final unmodifiableMap = Map.unmodifiable(planets);
/// unmodifiableMap[4] = 'Mars'; // Throws
/// ```
// @Deprecated("Use Map.unmodifiableOf instead")
external factory Map.unmodifiable(Map<dynamic, dynamic> other);
/// Creates an unmodifiable hash-based map containing the entries of [other].
///
/// The map requires the keys to implement compatible
/// `operator==` and `hashCode`.
/// The created map iterates keys in a fixed order,
/// preserving the order provided by [other].
///
/// The resulting map behaves like the result of [Map.of],
/// except that the map returned by this constructor is not modifiable.
/// ```dart
/// final planets = <int, String>{1: 'Mercury', 2: 'Venus', 3: 'Earth'};
/// final unmodifiableMap = Map.unmodifiableOf(planets);
/// unmodifiableMap[4] = 'Mars'; // Throws
/// ```
@Since("3.13")
factory Map.unmodifiableOf(Map<K, V> other) = Map<K, V>.unmodifiable;
/// Creates an identity map with the default implementation, [LinkedHashMap].
///
/// An identity map uses [identical] for equality and [identityHashCode]