Skip to content

Make flow control treat final vars immutable #4131

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

Closed
dmitry-fbm opened this issue Oct 19, 2024 · 7 comments
Closed

Make flow control treat final vars immutable #4131

dmitry-fbm opened this issue Oct 19, 2024 · 7 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@dmitry-fbm
Copy link

Here is sample code:

@immutable
class C {
  final int? i;
  const C({required this.i});
}

void f(C c) {
  late int i;
  if (c.i != null) {
    i = c.i;
  }
}

Despite the var i is final, the container class is declared @immutable and there is explicit if (c.i != null) check, the IDE considers this code invalid:
image
Wouldn't it be possible to promote nullable vars to non-nullable implicitly inside the if block in such cases?

@dmitry-fbm dmitry-fbm added the feature Proposed language feature that solves one or more problems label Oct 19, 2024
@hydro63
Copy link

hydro63 commented Oct 19, 2024

pretty sure that's an edgecase that hasn't been considered. AFAIK, the reason why members are not promoted is because of possible sideeffects that can occur. Still, i don't see a reason not to promote it, since the immutability means that there are no sideeffects, even when working in async.

@ghost
Copy link

ghost commented Oct 19, 2024

If you try to subclass C and make i non-final there, the compiler will produce a warning, but not an error.

@hydro63
Copy link

hydro63 commented Oct 19, 2024

If you try to subclass C and make i non-final there, the compiler will produce a warning, but not an error.

I didn't consider this. Perhaps we should allow promoting in sealed classes, where non of the subclasses change the mutability of the variable. I know that currently this code doesn't work (tested in dartpad):

sealed class SuperClass {
  final int? i;
  const SuperClass(this.i);
}

class ChildClass extends SuperClass {
  int? b;
  // variable i is still final
  ChildClass(super.i, this.b);
}

void f(SuperClass c) {
  late int i;
  if (c.i != null) {
    i = c.i;
  }
}

AFAIK, sealed class prevents this problem by having information about every class, compiler would know when sideeffects can occur and when not. Still, i think it is feasable to do it for sealed classes.

@ghost
Copy link

ghost commented Oct 19, 2024

Still, i think it is feasable to do it for sealed classes.

Normally, similar requests (to implement something based on "holistic" knowledge) were rejected because such logic would be brittle (if subclasses don't exist today, it doesn't mean they won't emerge tomorrow).

For this promotion to become feasible, immutable should become a language feature (as opposed to an annotation)

@lrhn
Copy link
Member

lrhn commented Oct 20, 2024

What @tatumizer says.
If the language allows a final variable to be promoted, but doesn't allow a getter to be promoted (which it clearly shouldn't), then whether a declaration is one or the other becomes part of the API contract.
That breaks variable/getter symmetry, and prevents an author from switching between the two, even though they never intended to make a promise.

That's why anything that would treat the two differently must be opt-in.

Being a final class only affects the current program. We can know that nobody overrides the variable with something non-stable, but we still don't know if the author intended to promise that the property will always be stable.

@lrhn lrhn closed this as not planned Won't fix, can't repro, duplicate, stale Oct 20, 2024
@dmitry-fbm
Copy link
Author

dmitry-fbm commented Oct 20, 2024

For this promotion to become feasible, immutable should become a language feature (as opposed to an annotation)

@tatumizer hope this will come true one day.

@dmitry-fbm
Copy link
Author

where non of the subclasses change the mutability of the variable.

@hydro63 I'd say, this has to be default behavior even for non-sealed. At least, subclasses can be allowed to introduce immutability, but not ignore it.

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
Projects
None yet
Development

No branches or pull requests

3 participants