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

Type Promotion on Record Attributes #4165

Open
caseycrogers opened this issue Nov 19, 2024 · 2 comments
Open

Type Promotion on Record Attributes #4165

caseycrogers opened this issue Nov 19, 2024 · 2 comments
Labels
feature Proposed language feature that solves one or more problems field-promotion Issues related to addressing the lack of field promotion type-inference Type inference, issues or improvements

Comments

@caseycrogers
Copy link

caseycrogers commented Nov 19, 2024

When accessing a field in a record, the static analyzer is not able to do type promotion. If you destructure the fields into local variables, type promotion works.

See:

void main() {
  // These do not work:
  final (int?, Object) foo = (1, 'asdf');
  if (foo.$1 == null) return;
  // Null reference static analysis error.
  print(foo.$1 + 1);
  if (foo.$2 is! String) return;
  // Method `length` not found on `Object`...
  print(foo.$2.length);

  // These do:
  final (int? a, Object b) = (1, 'asdf');
  if (a == null) return;
  print(a + 1);
  if (b is! String) return;
  print(b.length);
}

For fields on classes, type promotion is not possible, or at the very least would require some complex caveats and changes in the language spec: #1415

But records can't have getters and aren't sub-classable, so as far as I can tell, there should be no barriers to type promotion in theory. This would be very helpful to our team as currently we return records from functions regularly and ALWAYS destructure at call site to ensure type promotion, which in turn means adding more fields to a record bloats the call site namespace.
Partial destructuring would also solve our problem: #3964

@caseycrogers caseycrogers added the feature Proposed language feature that solves one or more problems label Nov 19, 2024
@lrhn
Copy link
Member

lrhn commented Nov 20, 2024

It doesn't sound impossible.

It requires some amount of "alias understanding" to know that ({num x, num y}) point = ...; if (point.x is int) implies that point is ({int x, num y}), and that doing point = otherPoint; can demote it again.
Still seems reasonably doable.

@lrhn lrhn added field-promotion Issues related to addressing the lack of field promotion type-inference Type inference, issues or improvements labels Nov 20, 2024
@rrousselGit
Copy link

The funny thing is that we can use record is ..., so in your example we can do:

void main() {
  final (int?, Object) foo = (1, 'asdf');
  if (foo is! (int, String)) return;
  print(foo.$1 + 1); // Valid
  print(foo.$2.length); // Valid too
}

But it's a bit though to write.

So it feels logical for foo.$1 != null to do type promotion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems field-promotion Issues related to addressing the lack of field promotion type-inference Type inference, issues or improvements
Projects
None yet
Development

No branches or pull requests

3 participants