Fix top-level inference with ForElement and NNBD.

Change-Id: I7b656ad4af600a82ec13f007dbad3465cd502a3a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/137020
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Konstantin Shcheglov 2020-02-25 04:29:00 +00:00 committed by commit-bot@chromium.org
parent baa0bc0d8e
commit 07144ef876
6 changed files with 72 additions and 49 deletions

View file

@ -339,7 +339,7 @@ class TypeSystemTypeOperations
/// The visitor that gathers local variables that are potentially assigned
/// in corresponding statements, such as loops, `switch` and `try`.
class _AssignedVariablesVisitor extends RecursiveAstVisitor<void> {
final AssignedVariables assignedVariables;
final AssignedVariables<AstNode, PromotableElement> assignedVariables;
_AssignedVariablesVisitor(this.assignedVariables);

View file

@ -16,21 +16,13 @@ class AstResolver {
final CompilationUnitElement _unitElement;
final Scope _nameScope;
/// This field is set if the library is non-nullable by default.
FlowAnalysisHelper flowAnalysis;
AstResolver(this._linker, this._unitElement, this._nameScope) {
if (_unitElement.library.isNonNullableByDefault) {
flowAnalysis = FlowAnalysisHelper(
_unitElement.library.typeSystem,
false,
);
}
}
AstResolver(this._linker, this._unitElement, this._nameScope);
void resolve(
AstNode node,
AstNode Function() getNode, {
bool buildElements = true,
bool isTopLevelVariableInitializer = false,
ClassElement enclosingClassElement,
ExecutableElement enclosingExecutableElement,
FunctionBody enclosingFunctionBody,
@ -38,24 +30,37 @@ class AstResolver {
var featureSet = node.thisOrAncestorOfType<CompilationUnit>().featureSet;
var errorListener = AnalysisErrorListener.NULL_LISTENER;
node.accept(
ResolutionVisitor(
unitElement: _unitElement,
featureSet: featureSet,
nameScope: _nameScope,
errorListener: errorListener,
),
);
node = getNode();
if (buildElements) {
node.accept(
ResolutionVisitor(
unitElement: _unitElement,
featureSet: featureSet,
nameScope: _nameScope,
errorListener: errorListener,
),
);
node = getNode();
var variableResolverVisitor = VariableResolverVisitor(
_unitElement.library,
_unitElement.source,
_unitElement.library.typeProvider,
errorListener,
nameScope: _nameScope,
);
node.accept(variableResolverVisitor);
var variableResolverVisitor = VariableResolverVisitor(
_unitElement.library,
_unitElement.source,
_unitElement.library.typeProvider,
errorListener,
nameScope: _nameScope,
);
node.accept(variableResolverVisitor);
}
FlowAnalysisHelper flowAnalysis;
if (isTopLevelVariableInitializer) {
if (_unitElement.library.isNonNullableByDefault) {
flowAnalysis = FlowAnalysisHelper(
_unitElement.library.typeSystem,
false,
);
flowAnalysis.topLevelDeclaration_enter(node.parent, null, null);
}
}
var resolverVisitor = ResolverVisitor(
_linker.inheritance,
@ -78,5 +83,9 @@ class AstResolver {
}
node.accept(resolverVisitor);
if (isTopLevelVariableInitializer) {
flowAnalysis?.topLevelDeclaration_exit();
}
}
}

View file

@ -20,6 +20,7 @@ import 'package:analyzer/src/summary2/lazy_ast.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/linking_node_scope.dart';
import 'package:analyzer/src/task/strong_mode.dart';
import 'package:meta/meta.dart';
DartType _dynamicIfNull(DartType type) {
if (type == null || type.isBottom || type.isDartCoreNull) {
@ -399,7 +400,7 @@ class _VariableInferenceNode extends _InferenceNode {
@override
List<_InferenceNode> computeDependencies() {
_resolveInitializer();
_resolveInitializer(forDependencies: true);
var collector = _InferenceDependenciesCollector();
_node.initializer.accept(collector);
@ -427,7 +428,7 @@ class _VariableInferenceNode extends _InferenceNode {
@override
void evaluate() {
_resolveInitializer();
_resolveInitializer(forDependencies: false);
if (LazyAst.getType(_node) == null) {
var initializerType = _node.initializer.staticType;
@ -458,9 +459,13 @@ class _VariableInferenceNode extends _InferenceNode {
isEvaluated = true;
}
void _resolveInitializer() {
void _resolveInitializer({@required bool forDependencies}) {
var astResolver = AstResolver(_walker._linker, _unitElement, _scope);
astResolver.flowAnalysis?.topLevelDeclaration_enter(_node, null, null);
astResolver.resolve(_node.initializer, () => _node.initializer);
astResolver.resolve(
_node.initializer,
() => _node.initializer,
buildElements: forDependencies,
isTopLevelVariableInitializer: true,
);
}
}

View file

@ -258,7 +258,13 @@ f() async {
var a = [1, ...?await futureNull, 2];
}
''');
assertType(findNode.listLiteral('['), 'List<int>');
assertType(
findNode.listLiteral('['),
typeStringByNullability(
nullable: 'List<int?>',
legacy: 'List<int>',
),
);
}
test_noContext_noTypeArgs_spread_nullAware_onlyNull() async {
@ -302,7 +308,7 @@ var a = <num>[];
}
@reflectiveTest
class ListLiteralWithNnbdTest extends DriverResolutionTest {
class ListLiteralWithNnbdTest extends ListLiteralTest {
@override
AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
..contextFeatures = FeatureSet.forTesting(

View file

@ -271,7 +271,13 @@ f() async {
a;
}
''');
assertType(setOrMapLiteral('{1'), 'Map<int, String>');
assertType(
setOrMapLiteral('{1'),
typeStringByNullability(
nullable: 'Map<int?, String?>',
legacy: 'Map<int, String>',
),
);
}
test_noContext_noTypeArgs_spread_nullAware_nullAndNotNull_set() async {
@ -282,7 +288,13 @@ f() async {
a;
}
''');
assertType(setOrMapLiteral('{1'), 'Set<int>');
assertType(
setOrMapLiteral('{1'),
typeStringByNullability(
nullable: 'Set<int?>',
legacy: 'Set<int>',
),
);
}
test_noContext_noTypeArgs_spread_nullAware_onlyNull() async {
@ -343,7 +355,7 @@ var a = <num, String>{};
}
@reflectiveTest
class MapLiteralWithNnbdTest extends DriverResolutionTest {
class MapLiteralWithNnbdTest extends MapLiteralTest {
@override
AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
..contextFeatures = FeatureSet.fromEnableFlags(
@ -353,15 +365,6 @@ class MapLiteralWithNnbdTest extends DriverResolutionTest {
@override
bool get typeToStringWithNullability => true;
AstNode setOrMapLiteral(String search) => findNode.setOrMapLiteral(search);
test_context_noTypeArgs_noEntries() async {
await resolveTestCode('''
Map<String, String> a = {};
''');
assertType(setOrMapLiteral('{'), 'Map<String, String>');
}
test_context_noTypeArgs_noEntries_typeParameterNullable() async {
await resolveTestCode('''
class C<T extends Object?> {

View file

@ -267,7 +267,7 @@ var a = <num>{};
}
@reflectiveTest
class SetLiteralWithNnbdTest extends DriverResolutionTest {
class SetLiteralWithNnbdTest extends SetLiteralTest {
@override
AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
..contextFeatures = FeatureSet.fromEnableFlags(