dart-lang / dart-lang/language

Enforce strict method override behavior in Dart

Open
#4,018 4 comments 0 reactions 0 assignees View on GitHub
request
Dominant language
TeX
Stars
2.9k
Forks
239
Avg merge
2d 18h
Merged PRs (30d)
14

Description

Currently, Dart allows methods marked with `@override` to be declared with different return types, including asynchronous versions of methods that are expected to be synchronous. This can lead to runtime exceptions in frameworks like Flutter, where certain lifecycle methods must be strictly synchronous. Enforcing stricter method override behavior at compile-time would prevent these issues.

Imagine method declaration:
```
@protected
@mustCallSuper
void initState() {
assert(_debugLifecycleState == _StateLifecycle.created);
if (kFlutterMemoryAllocationsEnabled) {
FlutterMemoryAllocations.instance.dispatchObjectCreated(
library: _flutterWidgetsLibrary,
className: '$State',
object: this,
);
}
}
```

Now it is fine to override it like this: ( and correct )
```
@override
void initState() {
super.initState();
// Synchronous initState
}
```

but we can also write sth like this ( incorrect! could lead to flutter build method executed before initState finished ... )

```
@override
Future initState() async {
print('init state method called');
super.initState();
await Future.delayed(const Duration(seconds: 5));
print('init state method finished');
}
```

**Expected Behavior:**

The Dart compiler should enforce stricter method override rules, producing a compilation error if an overridden method's return type differs from the expected type. This ensures that methods expected to be synchronous (e.g., initState) cannot be overridden as asynchronous methods.

**Actual Behavior:**

Methods marked with `@override` can be declared with different return types, including asynchronous versions, leading to runtime exceptions in frameworks like Flutter.

**Additional Context:**

Enforcing stricter method override behavior in Dart would align with best practices and prevent runtime exceptions caused by incorrect method overrides. This change would improve the developer experience and ensure that methods expected to be synchronous remain synchronous when overridden.

**Steps to Reproduce:**

1. Create a new Flutter project. `flutter create test`.
2. Implement a stateful widget with an asynchronous initState method, which is supposed to be synchronous:
3. Run the app and observe the runtime exception:

![image](https://github.com/user-attachments/assets/a115af67-8c43-41b2-ab5b-080e3596d8a9)

Contributor guide

Open the contributing guide

Research direction

Start with the issue's Flutter reproduction using an asynchronous override of initState and compare it with Dart's current override rules. Done means the compiler rejects an overriding method whose return type changes a required synchronous method, while preserving valid synchronous overrides.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.