Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[breaking change] Change the context for the operand of throw to Object. #56065

Closed
stereotype441 opened this issue Jun 21, 2024 · 10 comments
Closed
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). breaking-change-approved breaking-change-request This tracks requests for feedback on breaking changes triage-automation See https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot. type-enhancement A request for a change that isn't a bug

Comments

@stereotype441
Copy link
Member

Intended Change

The type schema for type inference of the operand of a throw expression will be changed from _ (the unknown type) to non-nullable Object.

Rationale

The type schema for an expression is intended to capture information from the surrounding context about what static type the expression is expected or intended to have. Since the operand of a throw expression is required by the compiler to be assignable to Object, it makes sense for this type to also be the context. Making this change furthers a longstanding goal of removing inconsistencies and unexpected behaviors from the Dart type inference process.

Expected Impact

The impact of this change is expected to be very low, since the operands of most throw expressions do not require any type inference. A trial run of this change over Google's internal Dart code base caused zero breakages.

However, it's theoretically possible that some code could change behavior as a result of this change. Here is an example of a program whose behavior would change:

T f<T>() {
  return StateError('f<$T> was called') as T;
}

main() {
  try {
    throw f();
  } on StateError catch (e) {
    print(e);
  }
}

Today this program prints Bad state: f<dynamic> was called. With the change, it will print Bad state: f<Object> was called.

Mitigation

In the unlikely event that some code is affected by this change, the old behavior may be restored by supplying explicit types inside the operand of the throw expression, so that no type inference is needed. For example, in the code above, the old behavior may be restored by changing throw f() to throw f<dynamic>().

@stereotype441 stereotype441 added the breaking-change-request This tracks requests for feedback on breaking changes label Jun 21, 2024
@dart-github-bot
Copy link
Collaborator

Summary: This change updates the type inference context for throw operands from the unknown type (_) to Object. This aligns the context with the compiler's requirement that throw operands be assignable to Object, improving consistency in type inference.

@dart-github-bot dart-github-bot added area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). triage-automation See https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot. type-enhancement A request for a change that isn't a bug labels Jun 21, 2024
@itsjustkevin
Copy link
Contributor

@vsmenon @leonsenft @Hixie for breaking change review.

@leonsenft
Copy link

LGTM

@vsmenon
Copy link
Member

vsmenon commented Jun 26, 2024

Curious, does throw null become a static error?

@leonsenft
Copy link

Curious, does throw null become a static error?

It already is:

throw null;

produces:

The type 'Null' of the thrown expression must be assignable to 'Object'.

@vsmenon
Copy link
Member

vsmenon commented Jun 26, 2024

Interesting. :-)

Is that Object not already coming from the context?

Anyway, lgtm on the change.

@stereotype441
Copy link
Member Author

Yeah, when we implemented null safety we added the requirement that anything being thrown must be assignable to Object (i.e. non-nullable). It would have made sense to change the context to Object at the same time, but we didn't think to do so. (Usually the context matches what type the expression has to be in order to avoid a compile-time error, but there are exceptions, so the implementation has to keep contexts and static error checking separate. As a result, if we don't think to update the context when we add an error condition, it doesn't happen automatically.)

@stereotype441
Copy link
Member Author

@Hixie ping

@itsjustkevin
Copy link
Contributor

Marking this breaking change as approved. @Hixie if you object, please speak up.

@Hixie
Copy link
Contributor

Hixie commented Jul 19, 2024

Sorry for missing this. This seems like a good change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). breaking-change-approved breaking-change-request This tracks requests for feedback on breaking changes triage-automation See https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot. type-enhancement A request for a change that isn't a bug
Projects
Status: Complete
Development

No branches or pull requests

6 participants