Skip to content

Commit 47420c0

Browse files
chloestefantsovaCommit Queue
authored and
Commit Queue
committed
[cfe] Avoid repearing type inference on pattern for-in loops
Previously the type inference was repeated in order to obtain the static type of the iterable expression. That type is computed in the shared analysis, and this CL passes the computed type to the clients of the analysis routine in the result object. In addition to being redundant, the repeated inference pass caused crashes. Closes #53092 Change-Id: I63d3d82be046884fa16d904a43e3bb6e01cf6f7e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/321141 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Chloe Stefantsova <[email protected]>
1 parent 8c5f895 commit 47420c0

13 files changed

+36
-23
lines changed

pkg/_fe_analyzer_shared/lib/src/type_inference/type_analysis_result.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,11 +320,15 @@ class PatternForInResult<Type extends Object, Error> {
320320
/// The static type of the elements of the for in expression.
321321
final Type elementType;
322322

323+
/// The static type of the collection of elements of the for in expression.
324+
final Type expressionType;
325+
323326
/// Error for when the expression is not an iterable.
324327
final Error? patternForInExpressionIsNotIterableError;
325328

326329
PatternForInResult(
327330
{required this.elementType,
331+
required this.expressionType,
328332
required this.patternForInExpressionIsNotIterableError});
329333
}
330334

pkg/_fe_analyzer_shared/lib/src/type_inference/type_analyzer.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,7 @@ mixin TypeAnalyzer<
14251425

14261426
return new PatternForInResult(
14271427
elementType: elementType,
1428+
expressionType: expressionType,
14281429
patternForInExpressionIsNotIterableError:
14291430
patternForInExpressionIsNotIterableError);
14301431
}

pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,20 +1636,28 @@ class InferenceVisitorImpl extends InferenceVisitorBase
16361636
ForInVariable forInVariable =
16371637
new PatternVariableDeclarationForInVariable(patternVariableDeclaration);
16381638

1639-
DartType elementType = forInVariable.computeElementType(this);
1640-
ExpressionInferenceResult iterableResult =
1641-
inferForInIterable(iterable, elementType, isAsync: isAsync);
1642-
DartType inferredType = iterableResult.inferredType;
1643-
variable.type = inferredType;
1639+
variable.type = result.elementType;
1640+
iterable = ensureAssignable(
1641+
wrapType(
1642+
const DynamicType(),
1643+
isAsync ? coreTypes.streamClass : coreTypes.iterableClass,
1644+
libraryBuilder.nonNullable),
1645+
result.expressionType,
1646+
iterable,
1647+
errorTemplate: templateForInLoopTypeNotIterable,
1648+
nullabilityErrorTemplate: templateForInLoopTypeNotIterableNullability,
1649+
nullabilityPartErrorTemplate:
1650+
templateForInLoopTypeNotIterablePartNullability);
16441651
// This is matched by the call to [forEach_end] in
16451652
// [inferElement], [inferMapEntry] or [inferForInStatement].
16461653
flowAnalysis.forEach_bodyBegin(node);
1647-
syntheticAssignment = forInVariable.inferAssignment(this, inferredType);
1654+
syntheticAssignment =
1655+
forInVariable.inferAssignment(this, result.elementType);
16481656
if (syntheticAssignment is VariableSet) {
1649-
flowAnalysis.write(node, variable, inferredType, null);
1657+
flowAnalysis.write(node, variable, result.elementType, null);
16501658
}
16511659

1652-
return new ForInResult(variable, iterableResult.expression,
1660+
return new ForInResult(variable, /*iterableResult.expression*/ iterable,
16531661
syntheticAssignment, patternVariableDeclaration);
16541662
}
16551663

pkg/front_end/testcases/patterns/for_in_inference_error.dart.strong.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import self as self;
1111
import "dart:core" as core;
1212

1313
static method test() → dynamic {
14-
for (final dynamic #t1 in invalid-expression "pkg/front_end/testcases/patterns/for_in_inference_error.dart:6:23: Error: The type 'int' used in the 'for' loop must implement 'Iterable<dynamic>'.
14+
for (final invalid-type #t1 in invalid-expression "pkg/front_end/testcases/patterns/for_in_inference_error.dart:6:23: Error: The type 'int' used in the 'for' loop must implement 'Iterable<dynamic>'.
1515
- 'Iterable' is from 'dart:core'.
1616
for (var [int x] in 0) {} // Error.
1717
^" in 0 as{TypeError} core::Iterable<dynamic>) {

pkg/front_end/testcases/patterns/for_in_inference_error.dart.strong.transformed.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ static method test() → dynamic {
1717
for (var [int x] in 0) {} // Error.
1818
^" in 0 as{TypeError} core::Iterable<dynamic>.{core::Iterable::iterator}{core::Iterator<Never>};
1919
for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
20-
final dynamic #t1 = :sync-for-iterator.{core::Iterator::current}{Never};
20+
final invalid-type #t1 = :sync-for-iterator.{core::Iterator::current}{Never};
2121
{
2222
hoisted core::int x;
2323
{

pkg/front_end/testcases/patterns/for_in_inference_error.dart.weak.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import self as self;
1111
import "dart:core" as core;
1212

1313
static method test() → dynamic {
14-
for (final dynamic #t1 in invalid-expression "pkg/front_end/testcases/patterns/for_in_inference_error.dart:6:23: Error: The type 'int' used in the 'for' loop must implement 'Iterable<dynamic>'.
14+
for (final invalid-type #t1 in invalid-expression "pkg/front_end/testcases/patterns/for_in_inference_error.dart:6:23: Error: The type 'int' used in the 'for' loop must implement 'Iterable<dynamic>'.
1515
- 'Iterable' is from 'dart:core'.
1616
for (var [int x] in 0) {} // Error.
1717
^" in 0 as{TypeError} core::Iterable<dynamic>) {

pkg/front_end/testcases/patterns/for_in_inference_error.dart.weak.modular.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import self as self;
1111
import "dart:core" as core;
1212

1313
static method test() → dynamic {
14-
for (final dynamic #t1 in invalid-expression "pkg/front_end/testcases/patterns/for_in_inference_error.dart:6:23: Error: The type 'int' used in the 'for' loop must implement 'Iterable<dynamic>'.
14+
for (final invalid-type #t1 in invalid-expression "pkg/front_end/testcases/patterns/for_in_inference_error.dart:6:23: Error: The type 'int' used in the 'for' loop must implement 'Iterable<dynamic>'.
1515
- 'Iterable' is from 'dart:core'.
1616
for (var [int x] in 0) {} // Error.
1717
^" in 0 as{TypeError} core::Iterable<dynamic>) {

pkg/front_end/testcases/patterns/for_in_inference_error.dart.weak.transformed.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ static method test() → dynamic {
1717
for (var [int x] in 0) {} // Error.
1818
^" in 0 as{TypeError} core::Iterable<dynamic>.{core::Iterable::iterator}{core::Iterator<Never>};
1919
for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
20-
final dynamic #t1 = :sync-for-iterator.{core::Iterator::current}{Never};
20+
final invalid-type #t1 = :sync-for-iterator.{core::Iterator::current}{Never};
2121
{
2222
hoisted core::int x;
2323
{

pkg/front_end/testcases/patterns/issue52228.dart.strong.expect

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ library;
88
// ^^^^^
99
//
1010
import self as self;
11-
import "dart:async" as asy;
1211
import "dart:core" as core;
12+
import "dart:async" as asy;
1313

1414
static method test() → dynamic {
15-
await for (final dynamic #t1 in asy::Stream::fromIterable<dynamic>(<core::List<core::int>>[<core::int>[1], <core::int>[2], <core::int>[3]])) {
15+
await for (final core::List<core::int> #t1 in asy::Stream::fromIterable<core::List<core::int>>(<core::List<core::int>>[<core::int>[1], <core::int>[2], <core::int>[3]])) {
1616
hoisted core::int v1;
1717
{
1818
final synthesized core::List<core::int> #0#0 = #t1;

pkg/front_end/testcases/patterns/issue52228.dart.strong.transformed.expect

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ library;
88
// ^^^^^
99
//
1010
import self as self;
11-
import "dart:async" as asy;
1211
import "dart:core" as core;
12+
import "dart:async" as asy;
1313

1414
static method test() → dynamic {
15-
await for (final dynamic #t1 in asy::Stream::fromIterable<dynamic>(core::_GrowableList::_literal3<core::List<core::int>>(core::_GrowableList::_literal1<core::int>(1), core::_GrowableList::_literal1<core::int>(2), core::_GrowableList::_literal1<core::int>(3)))) {
15+
await for (final core::List<core::int> #t1 in asy::Stream::fromIterable<core::List<core::int>>(core::_GrowableList::_literal3<core::List<core::int>>(core::_GrowableList::_literal1<core::int>(1), core::_GrowableList::_literal1<core::int>(2), core::_GrowableList::_literal1<core::int>(3)))) {
1616
hoisted core::int v1;
1717
{
1818
final synthesized core::List<core::int> #0#0 = #t1;

pkg/front_end/testcases/patterns/issue52228.dart.weak.expect

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ library;
88
// ^^^^^
99
//
1010
import self as self;
11-
import "dart:async" as asy;
1211
import "dart:core" as core;
12+
import "dart:async" as asy;
1313

1414
static method test() → dynamic {
15-
await for (final dynamic #t1 in asy::Stream::fromIterable<dynamic>(<core::List<core::int>>[<core::int>[1], <core::int>[2], <core::int>[3]])) {
15+
await for (final core::List<core::int> #t1 in asy::Stream::fromIterable<core::List<core::int>>(<core::List<core::int>>[<core::int>[1], <core::int>[2], <core::int>[3]])) {
1616
hoisted core::int v1;
1717
{
1818
final synthesized core::List<core::int> #0#0 = #t1;

pkg/front_end/testcases/patterns/issue52228.dart.weak.modular.expect

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ library;
88
// ^^^^^
99
//
1010
import self as self;
11-
import "dart:async" as asy;
1211
import "dart:core" as core;
12+
import "dart:async" as asy;
1313

1414
static method test() → dynamic {
15-
await for (final dynamic #t1 in asy::Stream::fromIterable<dynamic>(<core::List<core::int>>[<core::int>[1], <core::int>[2], <core::int>[3]])) {
15+
await for (final core::List<core::int> #t1 in asy::Stream::fromIterable<core::List<core::int>>(<core::List<core::int>>[<core::int>[1], <core::int>[2], <core::int>[3]])) {
1616
hoisted core::int v1;
1717
{
1818
final synthesized core::List<core::int> #0#0 = #t1;

pkg/front_end/testcases/patterns/issue52228.dart.weak.transformed.expect

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ library;
88
// ^^^^^
99
//
1010
import self as self;
11-
import "dart:async" as asy;
1211
import "dart:core" as core;
12+
import "dart:async" as asy;
1313

1414
static method test() → dynamic {
15-
await for (final dynamic #t1 in asy::Stream::fromIterable<dynamic>(core::_GrowableList::_literal3<core::List<core::int>>(core::_GrowableList::_literal1<core::int>(1), core::_GrowableList::_literal1<core::int>(2), core::_GrowableList::_literal1<core::int>(3)))) {
15+
await for (final core::List<core::int> #t1 in asy::Stream::fromIterable<core::List<core::int>>(core::_GrowableList::_literal3<core::List<core::int>>(core::_GrowableList::_literal1<core::int>(1), core::_GrowableList::_literal1<core::int>(2), core::_GrowableList::_literal1<core::int>(3)))) {
1616
hoisted core::int v1;
1717
{
1818
final synthesized core::List<core::int> #0#0 = #t1;

0 commit comments

Comments
 (0)