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

Infer non-nullability from local boolean variables #1274

Closed
yjbanov opened this issue Jun 24, 2020 · 11 comments
Closed

Infer non-nullability from local boolean variables #1274

yjbanov opened this issue Jun 24, 2020 · 11 comments
Assignees
Labels
nnbd NNBD related issues

Comments

@yjbanov
Copy link

yjbanov commented Jun 24, 2020

It is frequently more readable to give a boolean expression a name for self-documentation. For example:

final bool isSingleElement = fields == null;
if (!isSingleElement) {
  fields.forEach(...);
}

However, this does not promote fields to non-null inside the if block. A workaround is to remove the variable:

if (fields != null) {
  fields.forEach(...);
}

However, this makes the code less readable, because non-nullness of fields does not immediately imply that we're dealing with a "single line" mode of something.

Can the nullability inference be enhanced to infer using local booleans?

/cc @nturgut @leafpetersen

@srawlins
Copy link
Member

What is fields? A local variable? A field? Fields cannot be promoted.

@srawlins
Copy link
Member

Also, is this a bug with the migration tool (it should do something different)? Or with the null safety feature as implemented in the VM or something?

@leafpetersen
Copy link
Member

This isn't impossible, per se, but it's a pretty substantial lift. We'd need to track correlations between boolean valued variables and other pieces of our nullability state. I'm sympathetic to the request, but I don't think it's feasible in the time frame we have, and am not sure it would warrant the implementation complexity.

@mit-mit
Copy link
Member

mit-mit commented Oct 29, 2020

@leafpetersen did we decide to not do this? Then perhaps it should be turned into a potential, future language issue?

@leafpetersen
Copy link
Member

This is definitely not going to be in the feature as shipped. We could keep it as an option for future releases, but I'm pretty skeptical that this has the bang for the buck. This would require some pretty heavy machinery in the static analysis. I'll move it to the language repo for a round of discussion, but I think we may just want to close this out as unlikely to happen.

@leafpetersen leafpetersen transferred this issue from dart-lang/sdk Oct 29, 2020
@leafpetersen leafpetersen added the nnbd NNBD related issues label Oct 29, 2020
@leafpetersen
Copy link
Member

@lrhn @eernstg @stereotype441 @munificent @natebosch @jakemac53

Is this something we see potentially doing? Is there are a generalization that would increase the bang/buck, given that I expect the denominator there to be large?

@lrhn
Copy link
Member

lrhn commented Oct 30, 2020

The idea here is to abstract a test. That does make some sense. It's still a matter of "if this value is true, it implies something for some variables", we just don't branch on the boolean immediately.

I do worry about making the promotion inference rules too opaque.
A story of "If you do x != null or x == null in a branch, it will promote the local variable x on one of the branches" is simple and understandable.

We might be able to expand that to the implications being bound to boolean values stored in local variables, whether branched on immediately or not, we can still try to decide which code is dominated by the value being true vs false, even if some initial code is neither. It would even allow for something like:

var hasFoo = foo != null;
if (hasFoo) {
  foo.start();
}
// more code
if (hasFoo) {
  foo.end();
}

without needing to test twice. We can lose the information if anything assigns to either foo or hasFoo, so it's like hasFoo was "promoted" to boolean+variable information, and we can invalidate either.

As long as we can explain to users which tests promote which variables in a short and clear way, I'm for it.
I don't want to leave users guessing at whether one particular pattern is understood or not. It's too fragile if small changes to code structure makes promotion stop working, even though they are obviously innocuous.
A fractal boundary is impossible to internalize, a straight line is not, even though it might cut off some correct implications.

@stereotype441
Copy link
Member

To drill down a little further on the bang/buck question, I think the key implementation difficulty is that flow analysis models are snapshots of the state of the function at points in time; if we record a state at one time and then try to use it later, we need to somehow "rebase" that state to account for other promotions and demotions that have happened since we took the snapshot. Consider:

int? getPossiblyNullValue() => ...;
void f(int? x, int? y, int? z) {
  if (y == null) return;
  bool b = x == null; // (1)
  if (z == null) return;
  y = getPossiblyNullValue(); // (2)
  if (b) return; // (3)
}

At the time of (1), y has been promoted to non-nullable, but z remains nullable. So the false state we would store for b would be {x is int, y is int, z is int?, b is bool}. After (2), y has been demoted and z has been promoted so the state is {x is int?, y is int?, z is int, b is bool}. Then, at (3), we need to take the former state and somehow rebase it to account for the state changes that have happened to y and z. There's not currently enough information in our data structures to do that.

I think we could fix the problem by doing some SSA-like bookkeeping: associate each variable with a unique integer representing its "SSA node id". Whenever SSA analysis would need to allocate a fresh node (either because of an assignment or because of a phi node at a join point), we allocate a fresh id. That way the rebase algorithm can distinguish demotions from promotions by seeing that the ids are different. The algorithm would be: if the ids match, we take the most promoted type; if they differ, we take the more recent information. So considering the example above again, we would be rebasing {x₀ is int, y₁ is int, z₂ is int?, b₃ is bool} on top of {x₀ is int?, y₄ is int?, z₂ is int, b₃ is bool}, and that would produce {x₀ is int, y₄ is int?, z₂ is int, b₃ is bool}, which is what we want.

Another implementation difficulty is: at (3), when we recall the state we stored at (1), how do we make sure it hasn't been invalidated by intervening assignments to b or x? The rebase algorithm takes care of detecting intervening assignments to x; how about intervening assignments to b? We could address this by organizing our storage as a map from SSA node ids to true/false states. That way if b gets assigned, it will have a new SSA node id so we will ignore any true/false states we'd previously associated with it.

So that's the cost ("buck") part of the equation. What are the potential benefits ("bangs")? I can think of several:

  • This new "rebase" algorithm has the same functionality as the existing "restrict" algorithm, but with more intuitive bookkeeping. Replacing "restrict" with "rebase" wouldn't have any user visible effect but it would increase my confidence in flow analysis's soundness.
  • A lot of the complexity in flow analysis has to do with deciding when demotion should occur. I believe SSA node ids would simplify a lot of this logic too; again, no user visible effect but it would increase confidence in the algorithm.
  • The rebase algorithm should neatly address the main source of implementation difficulty for Using if (foo?.bar == somethingNotNull) should promote foo #1224. The key problem in that bug is very similar to this one: we have to take a flow analysis state from the LHS of an == comparison and update it to account for any promotions/demotions that happened during the RHS of the == comparison so that we can compare the two states and figure out if a promotion is in order. The rebase algorithm handles that nicely.
  • If we combined this with some simple common subexpression detection, we could potentially use these techniques to "restore" an old flow analysis state when a test is repeated. That could address a lot of scenarios where people currently have to insert nuisance !s, for example:
foo(int? x);
  int y;
  if (x != null) {
    y = x + 1;
    // Flow analysis state is implicitly saved here, associated with `x != null`
  }
  ...other logic...
  if (x != null) { // SSA ids let us see that this is the same condition as above
    // `x != null` state is restored here (and rebased over any promotions/demotions
    // that have occurred in the meantime)
    print(y + 1); // Ok; we know that `y` is definitely assigned.
  }
}

I'm not entirely sure whether the benefits justify the costs, but it sounds like a lot of fun to work on. I will try to set aside a few days after the Beta release ships to see if I can make these ideas pan out.

@stereotype441
Copy link
Member

One further thought. Extending my idea from yesterday, if we changed flow analysis so that it tracked promoted types via their SSA node id, then we could make promotion understand about reassigned variables, e.g.:

void foo(int? x) {
  var y = x;
  if (x != null) {
    print(y + 1); // Ok because y and x refer to the same value; and x != null
  }
}

Not a super compelling use case, but it would be a little extra "bang" that could potentially be unlocked if we wanted to go this direction.

dart-bot pushed a commit to dart-lang/sdk that referenced this issue Dec 3, 2020
The FlowModel._freshVariableInfo field was an optimization with
dubious benefit (it avoided a single allocation when seeing a variable
for the first time).  And it is getting in the way of changes I have
planned for dart-lang/language#1274 (which
will require each fresh variable to be allocated different
information).

Removing FlowModel._freshVariableInfo means that now we have a call to
VariableModel.fresh() whenever we see a variable for the first time,
so we can take advantage of this to elimiate the
VariableModel.initialize() method, and simply allocate the
VariableModel in the initialized state when it's appropriate to do so.

Change-Id: I4b6f7d004fff72eaa4025fdf79e9ca29a81d7f96
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/174566
Reviewed-by: Konstantin Shcheglov <[email protected]>
Reviewed-by: Johnni Winther <[email protected]>
Commit-Queue: Paul Berry <[email protected]>
@stereotype441 stereotype441 self-assigned this Dec 3, 2020
dart-bot pushed a commit to dart-lang/sdk that referenced this issue Dec 7, 2020
…nfo.

Previously, we used a single class hierarchy, ExpressionInfo, to store
all the information that flow analysis needs to know about a variable,
including:

1. What is known about the program state if the expression evaluates
   to true/false

2. Whether the expression is a `null` literal

3. Whether the expression is a reference to a variable.

However, in order to address
dart-lang/language#1274 (Infer
non-nullability from local boolean variables), we'll need #3 to be
tracked orthogonally from #1, so that when a local boolean is referred
to later, we can track information of type #1 and #3 simultaneously.

However, it makes sense to keep #1 and #2 in the same data structure,
because future work is planned to represent them in a more uniform
way, as part of addressing
dart-lang/language#1224 (Using `if (foo?.bar
== somethingNotNull)` should promote `foo`).

Change-Id: I432f6e2e80543bb1d565b49403180c520eef66a5
Bug: dart-lang/language#1274
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/175008
Reviewed-by: Johnni Winther <[email protected]>
Commit-Queue: Paul Berry <[email protected]>
dart-bot pushed a commit to dart-lang/sdk that referenced this issue Dec 7, 2020
…motion info."

This reverts commit fd2a6c6.

Reason for revert: Broke pkg/dds/test/sse_smoke_test

Original change's description:
> Flow analysis: Track expression variables separately from promotion info.
>
> Previously, we used a single class hierarchy, ExpressionInfo, to store
> all the information that flow analysis needs to know about a variable,
> including:
>
> 1. What is known about the program state if the expression evaluates
>    to true/false
>
> 2. Whether the expression is a `null` literal
>
> 3. Whether the expression is a reference to a variable.
>
> However, in order to address
> dart-lang/language#1274 (Infer
> non-nullability from local boolean variables), we'll need #3 to be
> tracked orthogonally from #1, so that when a local boolean is referred
> to later, we can track information of type #1 and #3 simultaneously.
>
> However, it makes sense to keep #1 and #2 in the same data structure,
> because future work is planned to represent them in a more uniform
> way, as part of addressing
> dart-lang/language#1224 (Using `if (foo?.bar
> == somethingNotNull)` should promote `foo`).
>
> Change-Id: I432f6e2e80543bb1d565b49403180c520eef66a5
> Bug: dart-lang/language#1274
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/175008
> Reviewed-by: Johnni Winther <[email protected]>
> Commit-Queue: Paul Berry <[email protected]>

[email protected],[email protected],[email protected]

Change-Id: I70b4adaf13f412a42a8128b9c7b9583b4171158e
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: dart-lang/language#1274
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/175321
Reviewed-by: Paul Berry <[email protected]>
Commit-Queue: Paul Berry <[email protected]>
dart-bot pushed a commit to dart-lang/sdk that referenced this issue Dec 9, 2020
…motion info."

This is a reland of fd2a6c6

Original change's description:
> Flow analysis: Track expression variables separately from promotion info.
>
> Previously, we used a single class hierarchy, ExpressionInfo, to store
> all the information that flow analysis needs to know about a variable,
> including:
>
> 1. What is known about the program state if the expression evaluates
>    to true/false
>
> 2. Whether the expression is a `null` literal
>
> 3. Whether the expression is a reference to a variable.
>
> However, in order to address
> dart-lang/language#1274 (Infer
> non-nullability from local boolean variables), we'll need #3 to be
> tracked orthogonally from #1, so that when a local boolean is referred
> to later, we can track information of type #1 and #3 simultaneously.
>
> However, it makes sense to keep #1 and #2 in the same data structure,
> because future work is planned to represent them in a more uniform
> way, as part of addressing
> dart-lang/language#1224 (Using `if (foo?.bar
> == somethingNotNull)` should promote `foo`).
>
> Change-Id: I432f6e2e80543bb1d565b49403180c520eef66a5
> Bug: dart-lang/language#1274
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/175008
> Reviewed-by: Johnni Winther <[email protected]>
> Commit-Queue: Paul Berry <[email protected]>

Bug: dart-lang/language#1274
Change-Id: I002adbde782887def50dc80ab6673411b321c341
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/175362
Reviewed-by: Konstantin Shcheglov <[email protected]>
Reviewed-by: Johnni Winther <[email protected]>
Commit-Queue: Paul Berry <[email protected]>
dart-bot pushed a commit to dart-lang/sdk that referenced this issue Dec 15, 2020
This is the first step in a sequence of CLs to support type promotion
based on local boolean variables
(dart-lang/language#1274).  To do this, we
will need a way to reliably tell whether a variable's value has
changed from one point in program execution to another, and to
associate additional information with a particular value of a
variable.  We'll accomplish both of these tasks by associating each
variable with a pointer to an "SSA node".  This pointer is updated to
point to a fresh node whenever the variable is written to, or two
different possible values come together at a control flow join.

Note that when a variable is write captured, it becomes impossible to
track when/if its value might change Previously we tracked this using
a `writeCaptured` boolean; now we track it by setting the SSA node
pointer to `null`.

This CL just lays the groundwork infrastructure and unit tests it;
there is no user-visible change.

Bug: dart-lang/language#1274
Change-Id: Id729390655c9371cba264816b418f6c0463e1758
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/176180
Reviewed-by: Konstantin Shcheglov <[email protected]>
Commit-Queue: Paul Berry <[email protected]>
stereotype441 added a commit to stereotype441/flutter_svg that referenced this issue Dec 17, 2020
When dart-lang/language#1274 (Infer
non-nullability from local boolean variables) is implemented, flow
analysis will detect that code like this is unreachable:

    bool hasArguments = false;
    ...
    if (hasArguments) {
      // Not reachable
    }

To prepare for this improvement, we need to add an "ignore" comment to
ignore the dead_code warning that will be generated.
stereotype441 added a commit to stereotype441/flutter that referenced this issue Dec 17, 2020
When dart-lang/language#1274 (Infer
non-nullability from local boolean variables) is implemented, flow
analysis will detect that code like this no longer needs to perform a
null check:

    final bool contextIsValid = focus != null && focus.context != null;
    ...
    if (contextIsValid) {
      ... focus! ... // Null check unnecessary
    }

To avoid a build failure due to the unnecessary null check, we need to
temporarily write it in a way that we can ignore it.  Once the feature
is complete and rolled into flutter, I'll remove the null check
entirely.
dart-bot pushed a commit to dart-lang/sdk that referenced this issue Dec 17, 2020
When dart-lang/language#1274 (Infer
non-nullability from local boolean variables) is fixed, this algorithm
will replace the `restrict` algorithm is currently used at the bottom
of a try/finally statement to combine the flow models from the `try`
and `finally` blocks.  The new algorithm has very similar behavior to
the old one, however since it is based on SSA nodes it (a) is able to
make slightly more promotions than the old one, and (b) will be able
to properly update SSA nodes so that local boolean variables assigned
inside a `try` block will be able to used for promotion after the
`finally` block.

The new functionality is hidden behind a flag for now, so there's no
customer-visible change yet.

Bug: dart-lang/language#1274
Change-Id: I1d37f981688f58da1e5c6c7eee48f2319c997cef
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/174960
Reviewed-by: Johnni Winther <[email protected]>
dart-bot pushed a commit to dart-lang/sdk that referenced this issue Dec 17, 2020
This CL modifies flow analysis API so that when a variable is written
or initialized, if the written expression has non-trivial flow
analysis information, it is captured in the SsaNode associated with
the variable.

The stored information is not yet used; in a follow-up CL, I will add
the ability to retrieve it on a read and use it for promotions.

Bug: dart-lang/language#1274
Change-Id: I1e2590205d4a0c59f4400a119f3d6b380a11414c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/176460
Reviewed-by: Konstantin Shcheglov <[email protected]>
Reviewed-by: Johnni Winther <[email protected]>
dart-bot pushed a commit to dart-lang/sdk that referenced this issue Dec 17, 2020
This CL adds functionality to FlowAnalysis.variableRead so that if the
truth value of the variable is known to be correlated with other flow
analysis state, that state can be restored.  This allows promotion
based on boolean variables in addition to boolean expressions, e.g.:

    int? x = ...;
    var xIsNotNull = x != null;
    if (xIsNotNull) {
      print(x + 1); // Ok; x is known to be non-null.
    }

This functionality is not enabled yet; it is hidden behind the flag
`allowLocalBooleanVarsToPromoteByDefault`.

Bug: dart-lang/language#1274
Change-Id: I2a0183b69d285193db7acb36cc6af5c34e165c2c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/176500
Commit-Queue: Paul Berry <[email protected]>
Reviewed-by: Johnni Winther <[email protected]>
Reviewed-by: Konstantin Shcheglov <[email protected]>
dart-bot pushed a commit to dart-lang/sdk that referenced this issue Dec 17, 2020
In preparation for supporting inference of non-nullability from local
boolean variables, we need to change a small amount of code to avoid
test breakages.

Bug: dart-lang/language#1274
Change-Id: Ia49e37f9ba2cd94967c7e1d411a3269593c0eeb9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/176501
Commit-Queue: Paul Berry <[email protected]>
Reviewed-by: Johnni Winther <[email protected]>
dart-bot pushed a commit to dart-lang/sdk that referenced this issue Dec 17, 2020
When analyzing code like this with the
`allowLocalBooleanVarsToPromote` flag enabled, don't treat a variable
containing `null` as equivalent to a literal `null`.  For example:

    f(int? x) {
      var y = null;
      if (x != y) {
        print(x + 1); // ERROR: x must be null checked.
      }
    }

The rationale is that flow analysis doesn't promote variables that are
known to be `null` to the `Null` type, so it seems like it would be
inconsistent if we used the fact that they're `null` to promote other
variables.

Bug: dart-lang/language#1274
Change-Id: Icfa14104936a26732353921e3a29a840c53d4d52
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/176560
Reviewed-by: Konstantin Shcheglov <[email protected]>
Commit-Queue: Paul Berry <[email protected]>
stereotype441 added a commit to flutter/flutter that referenced this issue Dec 17, 2020
…lity from local boolean variables" (#72494)

When dart-lang/language#1274 (Infer
non-nullability from local boolean variables) is implemented, flow
analysis will detect that code like this no longer needs to perform a
null check:

    final bool contextIsValid = focus != null && focus.context != null;
    ...
    if (contextIsValid) {
      ... focus! ... // Null check unnecessary
    }

To avoid a build failure due to the unnecessary null check, we need to
temporarily write it in a way that we can ignore it.  Once the feature
is complete and rolled into flutter, I'll remove the null check
entirely.
stereotype441 added a commit to flutter/engine that referenced this issue Dec 17, 2020
…23131)

When dart-lang/language#1274 (Infer
non-nullability from local boolean variables) is implemented, flow
analysis will detect that code like this no longer needs to perform a
null check:

    final bool hasIdentityTransform =
        transform == null || isIdentityFloat32ListTransform(transform);
    ...
    if (!hasIdentityTransform) {
      ... transform! ... // Null check unnecessary
    }

To avoid a build failure due to the unnecessary null check, we need to
temporarily write it in a way that we can ignore it.  Once the feature
is complete and rolled into flutter, I'll remove the null check
entirely.
zanderso pushed a commit to flutter/flutter that referenced this issue Dec 18, 2020
* c608b07 bump fuchsia toolchain to clang-12 (flutter/engine#23067)

* 8a3e9a2 fix crash in FontCollection::init() when FontFamily is empty (flutter/engine#23019)

* 95ba5ca Roll Skia from 6f31e27f1e29 to 85fa75616dfe (7 revisions) (flutter/engine#23118)

* 50e7d89 [web] Switch web-render option default to auto (flutter/engine#23090)

* 8854520 Roll Skia from 85fa75616dfe to d6f2338ab194 (3 revisions) (flutter/engine#23119)

* acad21c [web] Tests for rich paragraph DOM (flutter/engine#23097)

* 27ebbc4 Rename PointerState.isDown as per style guide (flutter/engine#23120)

* 19950f5 [web] Rich paragraph getBoxesForRange (flutter/engine#23098)

* 581acbe Roll Skia from d6f2338ab194 to 1d89532d5988 (1 revision) (flutter/engine#23122)

* 540b191 Roll Fuchsia Mac SDK from acylwa3i4... to chLTYsKMR... (flutter/engine#23125)

* 3b52edf Roll Skia from 1d89532d5988 to 7839f66540b6 (1 revision) (flutter/engine#23126)

* 6b25350 Roll Fuchsia Linux SDK from TIKHoiQyP... to wu6yV-_BL... (flutter/engine#23127)

* 9c72085 Roll Skia from 7839f66540b6 to 20f1b3462878 (1 revision) (flutter/engine#23129)

* ee323d0 Roll Skia from 20f1b3462878 to 995f0366bd21 (2 revisions) (flutter/engine#23132)

* 625aa69 Roll Skia from 995f0366bd21 to b64da3907f76 (1 revision) (flutter/engine#23135)

* affc421 Roll Skia from b64da3907f76 to 81da68af2ecf (7 revisions) (flutter/engine#23142)

* 9a6a31e Roll Fuchsia Mac SDK from chLTYsKMR... to RDUxjnng0... (flutter/engine#23143)

* 78657ed Added golden test to make sure that spawn engines work. (flutter/engine#23066)

* bb9cac2 Roll Fuchsia Linux SDK from wu6yV-_BL... to _l04etgVd... (flutter/engine#23145)

* 51c9ae9 Add --strict_null_safety_checks to the Dart flag allowlist (flutter/engine#23144)

* 76310c4 Add missing sdk constriant in pubspec.yaml files. (flutter/engine#23124)

* 6e54f0d [fuchsia] Add wrapper for zx_clock_get_monotonic. (flutter/engine#23128)

* ade75e0 [web] Rich paragraph getPositionForOffset (flutter/engine#23133)

* 2ef2c86 Fix engine in preparation for implementing dart-lang/language#1274 (flutter/engine#23131)

* 9384324 Update android_lint deps (flutter/engine#23151)

* ea4bb2a Roll Skia from 81da68af2ecf to 7b920446a8fc (14 revisions) (flutter/engine#23152)

* 4b5e4e6 Make it easier to turn on Xcode symlinks (flutter/engine#23150)

* 325f069 Roll fuchsia toolchain (flutter/engine#23155)

* 05704d3 Use include for C/C++ headers in darwin/macos (flutter/engine#23035)

* 8d3d69b Turned no malloc scribble and randomized the tests. (flutter/engine#23014)

* 418cc48 Fix macOS crash when modifier keys pressed. (flutter/engine#23154)

* a8c360d Update FlutterPlatformViewsTests (flutter/engine#23158)

* d941aef [web] Rich text painting on bitmap canvas (flutter/engine#23136)

* 67cb0f3 Revert "[web] Switch web-render option default to auto (#23090)" (flutter/engine#23161)

* c4b48c5 Roll Skia from 7b920446a8fc to dfc880bd9ba0 (14 revisions) (flutter/engine#23164)

* de1de9d Disable FlutterPluginAppLifeCycleDelegateTest testWillResignActive (flutter/engine#23166)
gspencergoog pushed a commit to gspencergoog/engine that referenced this issue Jan 5, 2021
…lutter#23131)

When dart-lang/language#1274 (Infer
non-nullability from local boolean variables) is implemented, flow
analysis will detect that code like this no longer needs to perform a
null check:

    final bool hasIdentityTransform =
        transform == null || isIdentityFloat32ListTransform(transform);
    ...
    if (!hasIdentityTransform) {
      ... transform! ... // Null check unnecessary
    }

To avoid a build failure due to the unnecessary null check, we need to
temporarily write it in a way that we can ignore it.  Once the feature
is complete and rolled into flutter, I'll remove the null check
entirely.
@stereotype441
Copy link
Member

We discussed this at the language team meeting this morning and we're moving forward with the change. I'll send out https://dart-review.googlesource.com/c/sdk/+/175500 for code review shortly.

dart-bot pushed a commit to dart-lang/sdk that referenced this issue Jan 8, 2021
The feature is not turned on yet; these tests will verify that it's
working properly once it is enabled.

Bug: dart-lang/language#1274
Change-Id: Ia48996d4525b84b523627a7b254cba18bdef48c7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/177641
Reviewed-by: Leaf Petersen <[email protected]>
dart-bot pushed a commit to dart-lang/sdk that referenced this issue Jan 8, 2021
The implementation was completed in previous CLs, but hidden behind a
flag.  This CL switches on the feature and adds integration tests.

Bug: dart-lang/language#1274
Change-Id: I0e2d7ac96d3a6d68d33d49f1eab5c341c9167f6f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/175500
Commit-Queue: Paul Berry <[email protected]>
Reviewed-by: Konstantin Shcheglov <[email protected]>
Reviewed-by: Johnni Winther <[email protected]>
@stereotype441
Copy link
Member

Fully implemented in dart-lang/sdk@88cd473.

stereotype441 added a commit to stereotype441/flutter that referenced this issue Jan 21, 2021
…variables.

This change removes a workaround that was introduced prior to landing
Dart language feature
dart-lang/language#1274, which allows type
promotion in null safe code to account for local boolean variables.
The workaround ensured that the code would analyze the same regardless
of whether the feature was enabled, allowing for a smoother
transition.  Now that the feature has fully landed, the workaround
isn't needed anymore.
stereotype441 added a commit to flutter/engine that referenced this issue Jan 22, 2021
… variables. (#23862)

This change removes workarounds that were introduced prior to landing
Dart language feature
dart-lang/language#1274, which allows type
promotion in null safe code to account for local boolean variables.
The workarounds ensured that the code would analyze the same
regardless of whether the feature was enabled, allowing for a smoother
transition.  Now that the feature has fully landed, the workarounds
aren't needed anymore.
dart-bot pushed a commit to dart-lang/sdk that referenced this issue Feb 26, 2021
This flag was being kept around in case the corresponding feature
(dart-lang/language#1274) wound up having
bugs and needed to be switched off.  It's now had sufficient bake time
that we no longer need the flag.

Removing the flag allows us to remove a bunch of flow analysis code
that's no longer needed.

Bug: dart-lang/language#1274
Change-Id: Ib91fa09a560bb0ebc6bff280ffc37d6037816ef9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/187981
Reviewed-by: Konstantin Shcheglov <[email protected]>
Commit-Queue: Paul Berry <[email protected]>
hjfreyer pushed a commit to hjfreyer/engine that referenced this issue Mar 22, 2021
… variables. (flutter#23862)

This change removes workarounds that were introduced prior to landing
Dart language feature
dart-lang/language#1274, which allows type
promotion in null safe code to account for local boolean variables.
The workarounds ensured that the code would analyze the same
regardless of whether the feature was enabled, allowing for a smoother
transition.  Now that the feature has fully landed, the workarounds
aren't needed anymore.
naturallymitchell pushed a commit to naturallymitchell/fuchsia that referenced this issue May 23, 2022
…age#1274

When dart-lang/language#1274 (Infer
non-nullability from local boolean variables) is implemented, flow
analysis will detect that code like this no longer needs to perform a
null check:

    final bool present = value != null && value.isValid;
    ...
    if (present) {
      ... value! ... // Null check unnecessary
    }

To avoid a build failure due to the unnecessary null check, we need to
temporarily write it in a way that we can ignore it.  Once the feature
is complete and rolled in, I'll remove the null check entirely.

Bug: dart-lang/language#1274
Change-Id: I212db32b71f381de3ec4f10cc2631ab9523b6f70
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/463601
Reviewed-by: Chase Latta <[email protected]>
Reviewed-by: Jerry Belton <[email protected]>
Commit-Queue: Auto-Submit <[email protected]>
Fuchsia-Auto-Submit: Paul Berry <[email protected]>
naturallymitchell pushed a commit to naturallymitchell/fuchsia that referenced this issue May 23, 2022
…oolean variables.

This change removes a workaround that was introduced prior to landing
Dart language feature
dart-lang/language#1274, which allows type
promotion in null safe code to account for local boolean variables.
The workaround ensured that the code would analyze the same regardless
of whether the feature was enabled, allowing for a smoother
transition.  Now that the feature has fully landed, the workaround
isn't needed anymore.

Change-Id: I5338bd5e25c977452881239e5d5b843c80a59b31
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/474237
Commit-Queue: Paul Berry <[email protected]>
Reviewed-by: Chase Latta <[email protected]>
RobertSun123 pushed a commit to RobertSun123/engine that referenced this issue May 8, 2024
When dart-lang/language#1274 (Infer
non-nullability from local boolean variables) is implemented, flow
analysis will detect that code like this no longer needs to perform a
null check:

    final bool hasIdentityTransform =
        transform == null || isIdentityFloat32ListTransform(transform);
    ...
    if (!hasIdentityTransform) {
      ... transform! ... // Null check unnecessary
    }

To avoid a build failure due to the unnecessary null check, we need to
temporarily write it in a way that we can ignore it.  Once the feature
is complete and rolled into flutter, I'll remove the null check
entirely.
RobertSun123 pushed a commit to RobertSun123/engine that referenced this issue May 8, 2024
… variables.

This change removes workarounds that were introduced prior to landing
Dart language feature
dart-lang/language#1274, which allows type
promotion in null safe code to account for local boolean variables.
The workarounds ensured that the code would analyze the same
regardless of whether the feature was enabled, allowing for a smoother
transition.  Now that the feature has fully landed, the workarounds
aren't needed anymore.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
nnbd NNBD related issues
Projects
None yet
Development

No branches or pull requests

6 participants