8000 [flow analysis] In tests, stop rewriting ordinary variable declarations. · dart-lang/sdk@b0e488f · GitHub
[go: up one dir, main page]

Skip to content

Commit b0e488f

Browse files
stereotype441Commit Queue
authored andcommitted
[flow analysis] In tests, stop rewriting ordinary variable declarations.
During the implementation of flow analysis for patterns, I added a hack to the flow analysis tests so that all variable declarations were desugared into the equivalent pattern variable declaration. This had the advantage of getting some extra testing "for free" during early development of the patterns feature, but it had a few disadvantages: - It the caused the shared flow analysis and type inference tests to stop exercising flow analysis code paths for ordinary variable declarations. - It forced the testing logic to "support" pattern variable declarations that are late or lack an initializer; these are things that regular Dart doesn't support, and they made the implementation of `PatternVariableDeclaration.visit` much more complicated than it needed to be. The language team is currently contemplating some changes to how promotions work in ordinary variable declarations and pattern variable declarations (see, for example, dart-lang/language#4347 (comment)). So in order to be able to experiment with these possibilities, I want to get rid of this hack. This CL adds a `VariableDeclaration` class, to represent ordinary variable declarations, and modifies the `declare` function (which is used by tests for creating an ordinary variable declaration) so that it creates a `VariableDeclaration`, rather than rewriting it into a `PatternVariableDeclaration` containing a `VariablePattern`. It removes "support" for testing pattern variable declarations that are late or lack an initializer, simplifying `PatternVariableDeclaration.visit`. A few test cases in `type_inference_test.dart` were checking the generated IR for ordinary variable declarations, verifying that it was properly desugared into a pattern variable declaration; these expectations have accordingly changed to no longer expect desugaring. There is no functional change to the compiler or analyzer toolchain. These changes only affect tests in `pkg/_fe_analyzer_shared/test`. Change-Id: I90f074cd6e7a6ed5ed11afadeadb6131ce1d282f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/432122 Commit-Queue: Paul Berry <paulberry@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
1 parent cfccc2a commit b0e488f

File tree

2 files changed

+141
-137
lines changed

2 files changed

+141
-137
lines changed

pkg/_fe_analyzer_shared/test/mini_ast.dart

Lines changed: 135 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -150,16 +150,13 @@ Statement declare(
150150
String? expectInferredType,
151151
}) {
152152
var location = computeLocation();
153-
return new PatternVariableDeclaration._(
154-
new VariablePattern._(
155-
type == null ? null : Type(type),
156-
variable,
157-
expectInferredType,
158-
location: location,
159-
),
160-
initializer?.asExpression(location: location),
153+
return new VariableDeclaration._(
154+
variable: variable,
161155
isLate: isLate,
162156
isFinal: isFinal,
157+
declaredType: type == null ? null : Type(type),
158+
initializer: initializer?.asExpression(location: location),
159+
expectInferredType: expectInferredType,
163160
location: location,
164161
);
165162
}
@@ -506,14 +503,12 @@ CollectionElement patternForInElement(
506503
Statement patternVariableDeclaration(
507504
Pattern pattern,
508505
ProtoExpression initializer, {
509-
bool isLate = false,
510506
bool isFinal = false,
511507
}) {
512508
var location = computeLocation();
513509
return new PatternVariableDeclaration._(
514510
pattern,
515511
initializer.asExpression(location: location),
516-
isLate: isLate,
517512
isFinal: isFinal,
518513
location: location,
519514
);
@@ -4082,15 +4077,13 @@ class PatternForInElement extends CollectionElement {
40824077
}
40834078

40844079
class PatternVariableDeclaration extends Statement {
4085-
final bool isLate;
40864080
final bool isFinal;
40874081
final Pattern pattern;
4088-
final Expression? initializer;
4082+
final Expression initializer;
40894083

40904084
PatternVariableDeclaration._(
40914085
this.pattern,
40924086
this.initializer, {
4093-
required this.isLate,
40944087
required this.isFinal,
40954088
required super.location,
40964089
});
@@ -4102,124 +4095,32 @@ class PatternVariableDeclaration extends Statement {
41024095
pattern.preVisit(visitor, variableBinder, isInAssignment: false);
41034096
variableBinder.casePatternFinish();
41044097
variableBinder.finish();
4105-
if (isLate) {
4106-
visitor._assignedVariables.beginNode();
4107-
}
4108-
initializer?.preVisit(visitor);
4109-
if (isLate) {
4110-
visitor._assignedVariables.endNode(this);
4111-
}
4098+
initializer.preVisit(visitor);
41124099
}
41134100

41144101
@override
41154102
String toString() {
41164103
var parts = <String>[
4117-
if (isLate) 'late',
41184104
if (isFinal) 'final',
41194105
pattern._debugString(needsKeywordOrType: !isFinal),
4120-
if (initializer != null) '= $initializer',
4106+
'= $initializer',
41214107
];
41224108
return '${parts.join(' ')};';
41234109
}
41244110

41254111
@override
41264112
void visit(Harness h) {
4127-
String irName;
4128-
List<Kind> argKinds;
4129-
List<String> names = const [];
4130-
var initializer = this.initializer;
4131-
if (isLate) {
4132-
// Late declarations are not allowed using patterns, so interpret the
4133-
// declaration as an old-fashioned variable declaration.
4134-
var pattern = this.pattern as VariablePattern;
4135-
var variable = pattern.variable;
4136-
h.irBuilder.atom(variable.name, Kind.variable, location: location);
4137-
var declaredType = pattern.declaredType;
4138-
Type staticType;
4139-
if (initializer == null) {
4140-
// Use the shared logic for analyzing uninitialized variable
4141-
// declarations.
4142-
staticType =
4143-
h.typeAnalyzer
4144-
.analyzeUninitializedVariableDeclaration(
4145-
this,
4146-
pattern.variable,
4147-
declaredType?.wrapSharedTypeView(),
4148-
isFinal: isFinal,
4149-
)
4150-
.unwrapTypeView();
4151-
irName = 'declare';
4152-
argKinds = [Kind.variable];
4153-
} else {
4154-
// There's no shared logic for analyzing initialized late variable
4155-
// declarations, so analyze the declaration directly.
4156-
h.flow.lateInitializer_begin(this);
4157-
var initializerType =
4158-
h.typeAnalyzer
4159-
.analyzeExpression(
4160-
initializer,
4161-
declaredType?.wrapSharedTypeSchemaView() ??
4162-
h.operations.unknownType,
4163-
)
4164-
.unwrapTypeView<Type>();
4165-
h.flow.lateInitializer_end();
4166-
staticType = variable.type = declaredType ?? initializerType;
4167-
h.flow.declare(variable, SharedTypeView(staticType), initialized: true);
4168-
h.flow.initialize(
4169-
variable,
4170-
SharedTypeView(initializerType),
4171-
initializer,
4172-
isFinal: isFinal,
4173-
isLate: true,
4174-
isImplicitlyTyped: declaredType == null,
4175-
);
4176-
h.irBuilder.atom(initializerType.type, Kind.type, location: location);
4177-
h.irBuilder.atom(staticType.type, Kind.type, location: location);
4178-
irName = 'declare';
4179-
argKinds = [Kind.variable, Kind.expression, Kind.type, Kind.type];
4180-
names = (['initializerType', 'staticType']);
4181-
}
4182-
// Finally, double check the inferred variable type, if necessary for the
4183-
// test.
4184-
var expectInferredType = pattern.expectInferredType;
4185-
if (expectInferredType != null) {
4186-
expect(staticType, expectInferredType);
4187-
}
4188-
} else if (initializer == null) {
4189-
var pattern = this.pattern as VariablePattern;
4190-
var declaredType = pattern.declaredType;
4191-
var staticType =
4192-
h.typeAnalyzer
4193-
.analyzeUninitializedVariableDeclaration(
4194-
this,
4195-
pattern.variable,
4196-
declaredType?.wrapSharedTypeView(),
4197-
isFinal: isFinal,
4198-
)
4199-
.unwrapTypeView<Type>();
4200-
h.typeAnalyzer.handleDeclaredVariablePattern(
4201-
pattern,
4202-
matchedType: staticType,
4203-
staticType: staticType,
4204-
);
4205-
irName = 'declare';
4206-
argKinds = [Kind.pattern];
4207-
} else {
4208-
h.typeAnalyzer.analyzePatternVariableDeclaration(
4209-
this,
4210-
pattern,
4211-
initializer,
4212-
isFinal: isFinal,
4213-
);
4214-
irName = 'match';
4215-
argKinds = [Kind.expression, Kind.pattern];
4216-
}
4113+
h.typeAnalyzer.analyzePatternVariableDeclaration(
4114+
this,
4115+
pattern,
4116+
initializer,
4117+
isFinal: isFinal,
4118+
);
42174119
h.irBuilder.apply(
4218-
[irName, if (isLate) 'late', if (isFinal) 'final'].join('_'),
4219-
argKinds,
4120+
['match', if (isFinal) 'final'].join('_'),
4121+
[Kind.expression, Kind.pattern],
42204122
Kind.statement,
42214123
location: location,
4222-
names: names,
42234124
);
42244125
}
42254126
}
@@ -5594,6 +5495,125 @@ class Var extends Node
55945495
}
55955496
}
55965497

5498+
class VariableDeclaration extends Statement {
5499+
final Var variable;
5500+
final bool isLate;
5501+
final bool isFinal;
5502+
final Type? declaredType;
5503+
final Expression? initializer;
5504+
final String? expectInferredType;
5505+
5506+
VariableDeclaration._({
5507+
required super.location,
5508+
required this.variable,
5509+
required this.isLate,
5510+
required this.isFinal,
5511+
required this.declaredType,
5512+
required this.initializer,
5513+
required this.expectInferredType,
5514+
});
5515+
5516+
@override
5517+
void preVisit(PreVisitor visitor) {
5518+
visitor._assignedVariables.declare(variable);
5519+
if (isLate) {
5520+
visitor._assignedVariables.beginNode();
5521+
}
5522+
initializer?.preVisit(visitor);
5523+
if (isLate) {
5524+
visitor._assignedVariables.endNode(this);
5525+
}
5526+
}
5527+
5528+
@override
5529+
String toString() {
5530+
var parts = <String>[
5531+
if (isLate) 'late',
5532+
if (isFinal) 'final',
5533+
if (declaredType != null) declaredType!.type else if (!isFinal) 'var',
5534+
variable.name,
5535+
if (expectInferredType != null) '(expected type $expectInferredType)',
5536+
if (initializer != null) '= $initializer',
5537+
];
5538+
return '${parts.join(' ')};';
5539+
}
5540+
5541+
@override
5542+
void visit(Harness h) {
5543+
String irName;
5544+
List<Kind> argKinds;
5545+
List<String> names = const [];
5546+
var initializer = this.initializer;
5547+
h.irBuilder.atom(variable.name, Kind.variable, location: location);
5548+
Type staticType;
5549+
if (initializer == null) {
5550+
// Use the shared logic for analyzing uninitialized variable
5551+
// declarations.
5552+
staticType =
5553+
h.typeAnalyzer
5554+
.analyzeUninitializedVariableDeclaration(
5555+
this,
5556+
variable,
5557+
declaredType?.wrapSharedTypeView(),
5558+
isFinal: isFinal,
5559+
)
5560+
.unwrapTypeView();
5561+
h.irBuilder.atom(staticType.type, Kind.type, location: location);
5562+
irName = 'declare';
5563+
argKinds = [Kind.variable, Kind.type];
5564+
names = ['staticType'];
5565+
} else {
5566+
// There's no shared logic for analyzing initialized variable
5567+
// declarations, so analyze the declaration directly.
5568+
if (isLate) h.flow.lateInitializer_begin(this);
5569+
var initializerType =
5570+
h.typeAnalyzer
5571+
.analyzeExpression(
5572+
initializer,
5573+
declaredType?.wrapSharedTypeSchemaView() ??
5574+
h.operations.unknownType,
5575+
)
5576+
.unwrapTypeView<Type>();
5577+
if (isLate) h.flow.lateInitializer_end();
5578+
staticType < B421 span class="pl-k">=
5579+
variable.type =
5580+
declaredType ??
5581+
h.typeAnalyzer
5582+
.variableTypeFromInitializerType(
5583+
initializerType.wrapSharedTypeView(),
5584+
)
5585+
.unwrapTypeView();
5586+
h.flow.declare(variable, SharedTypeView(staticType), initialized: true);
5587+
h.flow.initialize(
5588+
variable,
5589+
SharedTypeView(initializerType),
5590+
initializer,
5591+
isFinal: isFinal,
5592+
isLate: isLate,
5593+
isImplicitlyTyped: declaredType == null,
5594+
);
5595+
h.irBuilder.atom(initializerType.type, Kind.type, location: location);
5596+
h.irBuilder.atom(staticType.type, Kind.type, location: location);
5597+
irName = 'declare';
5598+
argKinds = [Kind.variable, Kind.expression, Kind.type, Kind.type];
5599+
names = ['initializerType', 'staticType'];
5600+
}
5601+
// Finally, double check the inferred variable type, if necessary for the
5602+
// test.
5603+
var expectInferredType = this.expectInferredType;
5604+
if (expectInferredType != null) {
5605+
expect(staticType.type, expectInferredType, reason: 'at $location');
5606+
}
5607+
h.irBuilder.apply(
5608+
[irName, if (isLate) 'late', if (isFinal) 'final'].join('_'),
5609+
argKinds,
5610+
Kind.statement,
5611+
location: location,
5612+
names: names,
5613+
);
5614+
}
5615+
}
5616+
55975617
class VariablePattern extends Pattern {
55985618
final Type? declaredType;
55995619

pkg/_fe_analyzer_shared/test/type_inference/type_inference_test.dart

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1590,8 +1590,7 @@ main() {
15901590
type: 'num',
15911591
initializer: expr('int').checkSchema('num'),
15921592
).checkIR(
1593-
'match(expr(int), '
1594-
'varPattern(x, matchedType: int, staticType: num))',
1593+
'declare(x, expr(int), initializerType: int, staticType: num)',
15951594
),
15961595
]);
15971596
});
@@ -1600,50 +1599,35 @@ main() {
16001599
var x = Var('x');
16011600
h.run([
16021601
declare(x, initializer: expr('int').checkSchema('_')).checkIR(
1603-
'match(expr(int), '
1604-
'varPattern(x, matchedType: int, staticType: int))',
1602+
'declare(x, expr(int), initializerType: int, staticType: int)',
16051603
),
16061604
]);
16071605
});
16081606

16091607
test('uninitialized, typed', () {
16101608
var x = Var('x');
1611-
h.run([
1612-
declare(x, type: 'int').checkIR(
1613-
'declare(varPattern(x, matchedType: int, staticType: int))',
1614-
),
1615-
]);
1609+
h.run([declare(x, type: 'int').checkIR('declare(x, staticType: int)')]);
16161610
});
16171611

16181612
test('uninitialized, untyped', () {
16191613
var x = Var('x');
1620-
h.run([
1621-
declare(x).checkIR(
1622-
'declare(varPattern(x, matchedType: dynamic, '
1623-
'staticType: dynamic))',
1624-
),
1625-
]);
1614+
h.run([declare(x).checkIR('declare(x, staticType: dynamic)')]);
16261615
});
16271616

16281617
test('promoted initializer', () {
16291618
TypeRegistry.addTypeParameter('T');
16301619
var x = Var('x');
16311620
h.run([
16321621
declare(x, initializer: expr('T&int')).checkIR(
1633-
'match(expr(T&int), '
1634-
'varPattern(x, matchedType: T&int, staticType: T))',
1622+
'declare(x, expr(T&int), initializerType: T&int, staticType: T)',
16351623
),
16361624
]);
16371625
});
16381626

16391627
test('legal late pattern', () {
16401628
var x = Var('x');
16411629
h.run([
1642-
patternVariableDeclaration(
1643-
x.pattern(),
1644-
intLiteral(0),
1645-
isLate: true,
1646-
).checkIR(
1630+
declare(x, initializer: intLiteral(0), isLate: true).checkIR(
16471631
'declare_late(x, 0, initializerType: int, staticType: int)',
16481632
),
16491633
]);

0 commit comments

Comments
 (0)
0