Skip to content

#3057. Add promotion via type test tests. Check top and bottom types and Null #3165

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

sgrekhov
Copy link
Contributor

@sgrekhov sgrekhov commented May 1, 2025

No description provided.

Copy link
Member

@eernstg eernstg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! I'm suggesting that a couple of tests should be deleted, because they unfold some cases where the test is basically not possible to perform ("check how this promotion works, except that this promotion never occurs").

Also, a couple of typos.

test4() {
Object? s = 1 > 2 ? null : "a";
if (s is FutureOr<void>) { // ignore: unnecessary_type_check
s.expectStaticType<Exactly<Object?>>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one won't actually fail in the case where the type of s is changed to FutureOr<void>.

Let's assume that s does have type FutureOr<void> here. We should then be able to test for Future<void>, and in the false continuation of that test s should have type void, so we should be able to see that by getting an error at s.hashCode.

So if it works correctly then s won't have type void at that point and s.hashCode is not an error.

test1() {
Object? o = 1 > 2 ? null : "a";
if (o is Void) { // ignore: unnecessary_type_check
print(o); // `void` <: `Object?`, `o` promoted to `void` and cannot be used
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, o should not be promoted because void is not a proper subtype of Object? (so S <: T, that is, "not S <: T" doesn't hold, so the promotion step cannot be taken).

(Note that the rules already imply this, so we don't actually need to wait for clarification of anything in order to be able to say that promotion only promotes to proper subtypes, that's already what the spec says).

test2() {
dynamic d = 42;
if (d is Void) { // ignore: unnecessary_type_check
print(d);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing: The test is fine if we just change the expectation to "no error" because d still has the type dynamic.

main() {
dynamic d = "a";
if (d is Object?) { // ignore: unnecessary_type_check
d.expectStaticType<Exactly<Object?>>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't promote from dynamic to Object?, but this test won't tell us that d still has the type dynamic before run time (it will throw because there is no such method).

Perhaps use if (1 > 2) d.testDynamic; instead?

Object? o = 1 > 2 ? null : "a";
if (o is dynamic) { // ignore: unnecessary_type_check
try {
o.whatever;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just expect an error here: There are no other tests in this library, so it's not a problem if we change it from being a "compiles and runs" test into an "encounters compile-time errors" test.

(Or would that imply that the test should have a different name because error tests and non-error tests can somehow be recognized by their names? In that case I guess it could just be renamed).

/// - and `T <: S` or (`S` is `X extends R` and `T <: R`) or (`S` is `X & R` and
/// `T <: R`)
///
/// @description Checks that a variable is promoted after the type test in one
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo:

Suggested change
/// @description Checks that a variable is promoted after the type test in one
/// @description Checks that if a variable is promoted after the type test in one

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the same phrase occurs in all the tests following this one.

///
/// @description Checks that a variable is promoted after the type test in one
/// of the branches, then is is not promoted in another branch and after it.
/// Test type `void`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid I'd recommend that this particular test is deleted.

The point is that a variable can never be promoted to have type void (because it would then have to have at least a declared type which is a proper supertype of void, and there is no such type). So we can't even get started investigating how a promotion to void would work, because they don't exist.

///
/// @description Checks that a variable is promoted after the type test in one
/// of the branches, then is is not promoted in another branch and after it.
/// Test type `dynamic`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

///
/// @description Checks that a variable is promoted after the type test in one
/// of the branches, then is is not promoted in another branch and after it.
/// Test type `Object?`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And again same here.

test1() {
String? s = 1 > 2 ? null : "a";
if (s is Never) {
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do have another test (or several) about the outcome of testing for Never, but it might still be good for the overall consistency and readability of this test to add this to the "then" part:

s.expectStaticType<Exactly<String?>>(); // Dead code and no promotion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants