Sobes.tech
Senior

Why was the decision made to abandon implicit type conversion in Dart 2.10?

sobes.tech AI

Answer from AI

In Dart 2.10, the rejection of implicit downcasting was motivated by several key reasons:

  1. Improved code safety: Implicit downcasting could lead to runtime errors that were difficult to debug. For example, attempting to call a method that does not exist in the actual object type but was present in the predicted static type. Explicit casting makes such potential errors visible at compile time or runtime with clearer indication of the problem.

  2. Increased predictability: Code with explicit casting is more predictable, as the developer explicitly states what type of object they expect. This simplifies reading and understanding the code.

  3. Preparation for Sound Null Safety: Removing implicit downcasting was an important step towards implementing Sound Null Safety in Dart 2.12. Sound Null Safety guarantees that references cannot contain null without explicit indication. Implicit downcasting could violate these guarantees, as typing becomes less strict.

Consider the example:

// Before Dart 2.10
void processList(List<int> list) {
  // In older Dart versions:
  // If actualList is actually List<dynamic> with non-numeric elements,
  // implicit downcasting could occur without a compile error,
  // but could cause an error when accessing elements.
  dynamic actualList = [1, 'hello'];
  List<int> potentiallyUnsafeList = actualList; // Implicit downcast

  // Accessing an element could lead to a runtime error
  // print(potentiallyUnsafeList[1] + 1); // Runtime error!
}

// After Dart 2.10
void processListSafe(List<int> list) {
  dynamic actualList = [1, 'hello'];

  // Here, explicit casting is required
  // List<int> unsafeList = actualList; // Compile error in Dart 2.10+

  // Explicit casting with a check
  if (actualList is List<int>) {
    List<int> safeList = actualList; // Safe cast after check
    print(safeList[0] + 1);
  } else {
    print("The list is not List<int>");
  }

  // Or explicit cast with the 'as' operator.
  // Important: if actualList is not List<int>, this will throw a runtime error.
  try {
    List<int> anotherSafeList = actualList as List<int>;
    print(anotherSafeList[0] + 1);
  } on TypeError {
    print("Type error during explicit cast");
  }
}

Thus, the removal of implicit downcasting in Dart 2.10 made the language more type-safe and laid the groundwork for Sound Null Safety."}]}]}

Why was the decision made to abandon implicit type… - sobes.tech