Skip to content

Commit

Permalink
[front_end] Fix type of synthetic variables used in lowering of null-…
Browse files Browse the repository at this point in the history
…aware accesses.

Consider the following null-aware expression (taken from
`pkg/front_end/testcases/nnbd/null_shorting.dart`):

    n1?.nonNullable1Method()?.nonNullable1Method();

Where `n1` has type `Class1?` and `Class1.nonNullable1Method` has
return type `Class1`. Note that the second `?.` is not necessary, and
should, in principle, be possible to optimize to `.` during
compilation.

Prior to this fix, this expression was lowered to the following kernel
(line breaks inserted for clarity):

    let final self::Class1? #t80 = n1
    in #t80 == null
         ?{self::Class1?} null
         : let final self::Class1? #t81 =
             #t80{self::Class1}.{self::Class1::nonNullable1Method}
               (){() → self::Class1}
           in #t81 == null
                ?{self::Class1?} null
                : #t81{self::Class1}.{self::Class1::nonNullable1Method}
                    (){() → self::Class1};

Note that the type of #t81 is `self::Class1?`, which is nullable. But
it doesn't need to be, since the initializer is the value returned by
`nonNullable1Method()`, which returns a non-nullable type.

The reason this was happening was because
`InferenceVisitorImpl.inferSyntheticVariableNullAware` was incorrectly
using `result.inferredType` as the type for the synthetic variable;
when the target of the null-aware invocation is itself a null-aware
invocation, this is the type that the target would have in the
_absence_ of null shorting. But since null shorting is in effect, the
correct type is `result.nullAwareActionType` (which in this example is
non-nullable).

With the fix, the expression is lowered to:

    let final self::Class1? #t80 = n1
    in #t80 == null
         ?{self::Class1?} null
         : let final self::Class1 #t81 =
             #t80{self::Class1}.{self::Class1::nonNullable1Method}
               (){() → self::Class1}
           in #t81 == null
             ?{self::Class1?} null
             : #t81.{self::Class1::nonNullable1Method}(){() → self::Class1};

The runtime behavior of both lowerings is the same, but with the fix,
it should be easier for back-end optimizations to determine that the
null check `#t81 == null` is unnecessary.

Fixes #59636.

Bug: #59636
Change-Id: I3b426603c867bb586d57a0e323caba072bf05045
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/398121
Reviewed-by: Chloe Stefantsova <[email protected]>
Auto-Submit: Paul Berry <[email protected]>
Commit-Queue: Johnni Winther <[email protected]>
Reviewed-by: Johnni Winther <[email protected]>
  • Loading branch information
stereotype441 authored and Commit Queue committed Dec 2, 2024
1 parent bb1de17 commit a6cd285
Show file tree
Hide file tree
Showing 10 changed files with 20 additions and 20 deletions.
4 changes: 2 additions & 2 deletions pkg/front_end/lib/src/type_inference/inference_visitor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase
Link<NullAwareGuard> nullAwareGuards = result.nullAwareGuards;
variable.initializer = result.nullAwareAction..parent = variable;

DartType inferredType =
inferDeclarationType(result.inferredType, forSyntheticVariable: true);
DartType inferredType = inferDeclarationType(result.nullAwareActionType,
forSyntheticVariable: true);
instrumentation?.record(uriForInstrumentation, variable.fileOffset, 'type',
new InstrumentationValueForType(inferredType));
variable.type = inferredType;
Expand Down
4 changes: 2 additions & 2 deletions pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ Try accessing using ?. instead.
let final self::Class1? #t77 = n1 in #t77 == null ?{self::Class1?} null : #t77{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nullable1}{self::Class1?};
let final self::Class1? #t78 = n1 in #t78 == null ?{self::Class1?} null : #t78{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nullable1} = new self::Class1::•();
let final self::Class1? #t79 = n1 in #t79 == null ?{self::Class1?} null : #t79{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1};
let final self::Class1? #t80 = n1 in #t80 == null ?{self::Class1?} null : let final self::Class1? #t81 = #t80{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1} in #t81 == null ?{self::Class1?} null : #t81{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1};
let final self::Class1? #t80 = n1 in #t80 == null ?{self::Class1?} null : let final self::Class1 #t81 = #t80{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1} in #t81 == null ?{self::Class1?} null : #t81.{self::Class1::nonNullable1Method}(){() → self::Class1};
}
static method indexAccess(self::Class1? n1, self::Class2? n2, self::Class3? n3) → void {
self::Class1? nullable1 = n1;
Expand Down Expand Up @@ -209,7 +209,7 @@ static method indexAccess(self::Class1? n1, self::Class2? n2, self::Class3? n3)
let final self::Class1? #t154 = n1 in #t154 == null ?{self::Class2?} null : #t154{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2};
let final self::Class1? #t155 = n1 in #t155 == null ?{self::Class2?} null : #t155{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2}.{self::Class2::[]=}(nullable2, new self::Class2::•()){(self::Class2?, self::Class2?) → void};
nullable2 = let final self::Class1? #t156 = n1 in #t156 == null ?{self::Class2?} null : let final self::Class2 #t157 = #t156{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in let final self::Class2? #t158 = nullable2 in let final self::Class2 #t159 = new self::Class2::•() in let final void #t160 = #t157.{self::Class2::[]=}(#t158, #t159){(self::Class2?, self::Class2?) → void} in #t159;
let final self::Class1? #t161 = n1 in #t161 == null ?{self::Class2?} null : let final self::Class2? #t162 = #t161{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in #t162 == null ?{self::Class2?} null : #t162{self::Class2}.{self::Class2::nonNullable2Method}(){() → self::Class2};
let final self::Class1? #t161 = n1 in #t161 == null ?{self::Class2?} null : let final self::Class2 #t162 = #t161{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in #t162 == null ?{self::Class2?} null : #t162.{self::Class2::nonNullable2Method}(){() → self::Class2};
let final self::Class1? #t163 = n1 in #t163 == null ?{self::Class2?} null : let final self::Class2 #t164 = #t163{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in let final self::Class2? #t165 = nullable2 in #t164.{self::Class2::[]=}(#t165, #t164.{self::Class2::[]}(#t165){(self::Class2?) → self::Class2}.{self::Class2::+}(0){(core::int) → self::Class2}){(self::Class2?, self::Class2?) → void};
nullable2 = let final self::Class1? #t166 = n1 in #t166 == null ?{self::Class2?} null : let final self::Class2 #t167 = #t166{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in let final self::Class2? #t168 = nullable2 in let final self::Class2 #t169 = #t167.{self::Class2::[]}(#t168){(self::Class2?) → self::Class2}.{self::Class2::+}(0){(core::int) → self::Class2} in let final void #t170 = #t167.{self::Class2::[]=}(#t168, #t169){(self::Class2?, self::Class2?) → void} in #t169;
let final self::Class1? #t171 = n1 in #t171 == null ?{self::Class2?} null : let final self::Class2 #t172 = #t171{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in let final self::Class2? #t173 = nullable2 in #t172.{self::Class2::[]=}(#t173, #t172.{self::Class2::[]}(#t173){(self::Class2?) → self::Class2}.{self::Class2::+}(1){(core::int) → self::Class2}){(self::Class2?, self::Class2?) → void};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ Try accessing using ?. instead.
let final self::Class1? #t77 = n1 in #t77 == null ?{self::Class1?} null : #t77{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nullable1}{self::Class1?};
let final self::Class1? #t78 = n1 in #t78 == null ?{self::Class1?} null : #t78{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nullable1} = new self::Class1::•();
let final self::Class1? #t79 = n1 in #t79 == null ?{self::Class1?} null : #t79{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1};
let final self::Class1? #t80 = n1 in #t80 == null ?{self::Class1?} null : let final self::Class1? #t81 = #t80{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1} in #t81 == null ?{self::Class1?} null : #t81{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1};
let final self::Class1? #t80 = n1 in #t80 == null ?{self::Class1?} null : let final self::Class1 #t81 = #t80{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1} in #t81 == null ?{self::Class1?} null : #t81.{self::Class1::nonNullable1Method}(){() → self::Class1};
}
static method indexAccess(self::Class1? n1, self::Class2? n2, self::Class3? n3) → void {
self::Class1? nullable1 = n1;
Expand Down Expand Up @@ -209,7 +209,7 @@ static method indexAccess(self::Class1? n1, self::Class2? n2, self::Class3? n3)
let final self::Class1? #t154 = n1 in #t154 == null ?{self::Class2?} null : #t154{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2};
let final self::Class1? #t155 = n1 in #t155 == null ?{self::Class2?} null : #t155{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2}.{self::Class2::[]=}(nullable2, new self::Class2::•()){(self::Class2?, self::Class2?) → void};
nullable2 = let final self::Class1? #t156 = n1 in #t156 == null ?{self::Class2?} null : let final self::Class2 #t157 = #t156{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in let final self::Class2? #t158 = nullable2 in let final self::Class2 #t159 = new self::Class2::•() in let final void #t160 = #t157.{self::Class2::[]=}(#t158, #t159){(self::Class2?, self::Class2?) → void} in #t159;
let final self::Class1? #t161 = n1 in #t161 == null ?{self::Class2?} null : let final self::Class2? #t162 = #t161{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in #t162 == null ?{self::Class2?} null : #t162{self::Class2}.{self::Class2::nonNullable2Method}(){() → self::Class2};
let final self::Class1? #t161 = n1 in #t161 == null ?{self::Class2?} null : let final self::Class2 #t162 = #t161{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in #t162 == null ?{self::Class2?} null : #t162.{self::Class2::nonNullable2Method}(){() → self::Class2};
let final self::Class1? #t163 = n1 in #t163 == null ?{self::Class2?} null : let final self::Class2 #t164 = #t163{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in let final self::Class2? #t165 = nullable2 in #t164.{self::Class2::[]=}(#t165, #t164.{self::Class2::[]}(#t165){(self::Class2?) → self::Class2}.{self::Class2::+}(0){(core::int) → self::Class2}){(self::Class2?, self::Class2?) → void};
nullable2 = let final self::Class1? #t166 = n1 in #t166 == null ?{self::Class2?} null : let final self::Class2 #t167 = #t166{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in let final self::Class2? #t168 = nullable2 in let final self::Class2 #t169 = #t167.{self::Class2::[]}(#t168){(self::Class2?) → self::Class2}.{self::Class2::+}(0){(core::int) → self::Class2} in let final void #t170 = #t167.{self::Class2::[]=}(#t168, #t169){(self::Class2?, self::Class2?) → void} in #t169;
let final self::Class1? #t171 = n1 in #t171 == null ?{self::Class2?} null : let final self::Class2 #t172 = #t171{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in let final self::Class2? #t173 = nullable2 in #t172.{self::Class2::[]=}(#t173, #t172.{self::Class2::[]}(#t173){(self::Class2?) → self::Class2}.{self::Class2::+}(1){(core::int) → self::Class2}){(self::Class2?, self::Class2?) → void};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ Try accessing using ?. instead.
let final self::Class1? #t77 = n1 in #t77 == null ?{self::Class1?} null : #t77{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nullable1}{self::Class1?};
let final self::Class1? #t78 = n1 in #t78 == null ?{self::Class1?} null : #t78{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nullable1} = new self::Class1::•();
let final self::Class1? #t79 = n1 in #t79 == null ?{self::Class1?} null : #t79{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1};
let final self::Class1? #t80 = n1 in #t80 == null ?{self::Class1?} null : let final self::Class1? #t81 = #t80{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1} in #t81 == null ?{self::Class1?} null : #t81{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1};
let final self::Class1? #t80 = n1 in #t80 == null ?{self::Class1?} null : let final self::Class1 #t81 = #t80{self::Class1}.{self::Class1::nonNullable1Method}(){() → self::Class1} in #t81 == null ?{self::Class1?} null : #t81.{self::Class1::nonNullable1Method}(){() → self::Class1};
}
static method indexAccess(self::Class1? n1, self::Class2? n2, self::Class3? n3) → void {
self::Class1? nullable1 = n1;
Expand Down Expand Up @@ -209,7 +209,7 @@ static method indexAccess(self::Class1? n1, self::Class2? n2, self::Class3? n3)
let final self::Class1? #t154 = n1 in #t154 == null ?{self::Class2?} null : #t154{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2};
let final self::Class1? #t155 = n1 in #t155 == null ?{self::Class2?} null : #t155{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2}.{self::Class2::[]=}(nullable2, new self::Class2::•()){(self::Class2?, self::Class2?) → void};
nullable2 = let final self::Class1? #t156 = n1 in #t156 == null ?{self::Class2?} null : let final self::Class2 #t157 = #t156{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in let final self::Class2? #t158 = nullable2 in let final self::Class2 #t159 = new self::Class2::•() in let final void #t160 = #t157.{self::Class2::[]=}(#t158, #t159){(self::Class2?, self::Class2?) → void} in #t159;
let final self::Class1? #t161 = n1 in #t161 == null ?{self::Class2?} null : let final self::Class2? #t162 = #t161{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in #t162 == null ?{self::Class2?} null : #t162{self::Class2}.{self::Class2::nonNullable2Method}(){() → self::Class2};
let final self::Class1? #t161 = n1 in #t161 == null ?{self::Class2?} null : let final self::Class2 #t162 = #t161{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in #t162 == null ?{self::Class2?} null : #t162.{self::Class2::nonNullable2Method}(){() → self::Class2};
let final self::Class1? #t163 = n1 in #t163 == null ?{self::Class2?} null : let final self::Class2 #t164 = #t163{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in let final self::Class2? #t165 = nullable2 in #t164.{self::Class2::[]=}(#t165, #t164.{self::Class2::[]}(#t165){(self::Class2?) → self::Class2}.{self::Class2::+}(0){(core::int) → self::Class2}){(self::Class2?, self::Class2?) → void};
nullable2 = let final self::Class1? #t166 = n1 in #t166 == null ?{self::Class2?} null : let final self::Class2 #t167 = #t166{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in let final self::Class2? #t168 = nullable2 in let final self::Class2 #t169 = #t167.{self::Class2::[]}(#t168){(self::Class2?) → self::Class2}.{self::Class2::+}(0){(core::int) → self::Class2} in let final void #t170 = #t167.{self::Class2::[]=}(#t168, #t169){(self::Class2?, self::Class2?) → void} in #t169;
let final self::Class1? #t171 = n1 in #t171 == null ?{self::Class2?} null : let final self::Class2 #t172 = #t171{self::Class1}.{self::Class1::nonNullable2}{self::Class2}.{self::Class2::[]}(nullable2){(self::Class2?) → self::Class2} in let final self::Class2? #t173 = nullable2 in #t172.{self::Class2::[]=}(#t173, #t172.{self::Class2::[]}(#t173){(self::Class2?) → self::Class2}.{self::Class2::+}(1){(core::int) → self::Class2}){(self::Class2?, self::Class2?) → void};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ Try accessing using ?. instead.
let final self::Class1? #t163 = n1 in #t163 == null ?{self::Class1?} null : self::Extension1|get#nullable1(self::Extension1|nonNullable1Method(self::Extension1|nonNullable1Method(#t163{self::Class1})));
let final self::Class1? #t164 = n1 in #t164 == null ?{void} null : self::Extension1|set#nullable1(self::Extension1|nonNullable1Method(self::Extension1|nonNullable1Method(#t164{self::Class1})), new self::Class1::•());
let final self::Class1? #t165 = n1 in #t165 == null ?{self::Class1?} null : self::Extension1|nonNullable1Method(self::Extension1|nonNullable1Method(self::Extension1|nonNullable1Method(#t165{self::Class1})));
let final self::Class1? #t166 = n1 in #t166 == null ?{self::Class1?} null : let final self::Class1? #t167 = self::Extension1|nonNullable1Method(#t166{self::Class1}) in #t167 == null ?{self::Class1?} null : self::Extension1|nonNullable1Method(#t167{self::Class1});
let final self::Class1? #t166 = n1 in #t166 == null ?{self::Class1?} null : let final self::Class1 #t167 = self::Extension1|nonNullable1Method(#t166{self::Class1}) in #t167 == null ?{self::Class1?} null : self::Extension1|nonNullable1Method(#t167);
}
static method indexAccess(self::Class1? n1, self::Class2? n2, self::Class3? n3) → void {
self::Class1? nullable1 = n1;
Expand Down Expand Up @@ -238,7 +238,7 @@ static method indexAccess(self::Class1? n1, self::Class2? n2, self::Class3? n3)
let final self::Class1? #t240 = n1 in #t240 == null ?{self::Class2?} null : self::Extension2|[](self::Extension2|[](self::Extension1|get#nonNullable2(#t240{self::Class1}), nullable2), nullable2);
let final self::Class1? #t241 = n1 in #t241 == null ?{self::Class2?} null : self::Extension2|[]=(self::Extension2|[](self::Extension1|get#nonNullable2(#t241{self::Class1}), nullable2), nullable2, new self::Class2::•());
nullable2 = let final self::Class1? #t242 = n1 in #t242 == null ?{self::Class2?} null : let final self::Class2 #t243 = self::Extension2|[](self::Extension1|get#nonNullable2(#t242{self::Class1}), nullable2) in let final self::Class2? #t244 = nullable2 in let final self::Class2 #t245 = new self::Class2::•() in let final void #t246 = self::Extension2|[]=(#t243, #t244, #t245) in #t245;
let final self::Class1? #t247 = n1 in #t247 == null ?{self::Class2?} null : let final self::Class2? #t248 = self::Extension2|[](self::Extension2|[](self::Extension1|get#nonNullable2(#t247{self::Class1}), nullable2), nullable2) in #t248 == null ?{self::Class2?} null : self::Extension2|nonNullable2Method(#t248{self::Class2});
let final self::Class1? #t247 = n1 in #t247 == null ?{self::Class2?} null : let final self::Class2 #t248 = self::Extension2|[](self::Extension2|[](self::Extension1|get#nonNullable2(#t247{self::Class1}), nullable2), nullable2) in #t248 == null ?{self::Class2?} null : self::Extension2|nonNullable2Method(#t248);
let final self::Class1? #t249 = n1 in #t249 == null ?{self::Class2?} null : let final self::Class2 #t250 = self::Extension2|[](self::Extension1|get#nonNullable2(#t249{self::Class1}), nullable2) in let final self::Class2? #t251 = nullable2 in self::Extension2|[]=(#t250, #t251, self::Extension2|+(self::Extension2|[](#t250, #t251), 0));
nullable2 = let final self::Class1? #t252 = n1 in #t252 == null ?{self::Class2?} null : let final self::Class2 #t253 = self::Extension2|[](self::Extension1|get#nonNullable2(#t252{self::Class1}), nullable2) in let final self::Class2? #t254 = nullable2 in let final self::Class2 #t255 = self::Extension2|+(self::Extension2|[](#t253, #t254), 0) in let final void #t256 = self::Extension2|[]=(#t253, #t254, #t255) in #t255;
let final self::Class1? #t257 = n1 in #t257 == null ?{self::Class2?} null : let final self::Class2 #t258 = self::Extension2|[](self::Extension1|get#nonNullable2(#t257{self::Class1}), nullable2) in let final self::Class2? #t259 = nullable2 in self::Extension2|[]=(#t258, #t259, self::Extension2|+(self::Extension2|[](#t258, #t259), 1));
Expand Down
Loading

0 comments on commit a6cd285

Please sign in to comment.