-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Current state
The following methods all return Uint8List, yet they are only declared to return List<int>:
Utf8Codec.encode()BytesBuilder.takeBytes()BytesBuilder.toBytes()File.readAsBytes()File.readAsBytesSync()RandomAccessFile.read()RandomAccessFile.readSync()Uint8List.sublist()
Relatedly, the following sublist() methods return sublists of the same type as
the source list, yet they only declare that they return the more generic type (e.g. List<int>, List<float>, or List<double>):
Int8ListUint8ClampedListInt16ListUint16ListInt32ListUint32ListInt64ListUint64ListFloat32ListFloat64ListFloat32x4ListInt32x4ListFloat64x2List
Intended change
This issues proposes to update the API of the aforementioned methods to declare the return value of the more specific return type (e.g. Uint8List rather than List<int>).
Rationale
-
Better type safety
Callers would like to statically prove that you can obtain a
ByteBufferfrom the result of these API calls. -
The current API/implementation combo encourages bad practices.
There are two dangers with an API saying it returns
List<int>and always returningUint8List:- People do roundabout things to guarantee that the result is a
Uint8List(such as defensively wrapping the result in aUint8List), which causes unnecessary overhead. - People start to depend on the result being a
Uint8Listand automatically performing a contravariant cast (which is already happening in Flutter and elsewhere) -- and if anyone new implements the interface and returns something other than aUint8List, code breaks.
- People do roundabout things to guarantee that the result is a
-
To match the documentation
Utf8EncoderandBase64Decoder.convert, for instance, already document that they returnUint8List.
See also:
- Bug BytesBuilder.takeBytes should explicitly provide a Uint8List #27818
- Bug File.readAsBytes should return Uint8List #31547
- Bug Should Base64 decoder have a return type of Uint8List? #31784
- Bug utf8.encode should return Uint8List #35521
Expected impact
On callers
Callers of these APIs will not be impacted at all since the new return types are subtypes of the existing return types (and moreover, the return values will be the exact same values).
On implementations of the interfaces
Libraries that are implementing the following interfaces will be broken because they will no longer be implementing the interface:
Utf8EncoderBytesBuilderFileRandomAccessFileInt8ListUint8ListUint8ClampedListInt16ListUint16ListInt32ListUint32ListInt64ListUint64ListFloat32ListFloat64ListFloat32x4ListInt32x4ListFloat64x2List
This includes (but is not limited to) some well-known packages, such as package:typed_data and package:file.
Steps for mitigation
For known affected packages, the plan will be to issue patch releases to those packages that tighten the SDK constraints to declare that the current version of the package is not compatible with an SDK version greater than the current dev version. Then, once the change lands, we'll update the affected packages to implement the new API and loosen their SDK constraints once again.