| Index: pkg/kernel/lib/analyzer/ast_from_analyzer.dart
|
| diff --git a/pkg/kernel/lib/analyzer/ast_from_analyzer.dart b/pkg/kernel/lib/analyzer/ast_from_analyzer.dart
|
| index 49ccc670342782e78b65e34650708d1355e07a5a..1ce83a479b7954271804a98f8bcc6f6299b60af7 100644
|
| --- a/pkg/kernel/lib/analyzer/ast_from_analyzer.dart
|
| +++ b/pkg/kernel/lib/analyzer/ast_from_analyzer.dart
|
| @@ -307,6 +307,11 @@ class TypeScope extends ReferenceScope {
|
|
|
| ast.DartType get defaultTypeParameterBound => getRootClassReference().rawType;
|
|
|
| + ast.TypeParameter tryGetTypeParameterReference(TypeParameterElement element) {
|
| + return localTypeParameters[element] ??
|
| + loader.tryGetClassTypeParameter(element);
|
| + }
|
| +
|
| ast.TypeParameter getTypeParameterReference(TypeParameterElement element) {
|
| return localTypeParameters[element] ??
|
| loader.tryGetClassTypeParameter(element) ??
|
| @@ -385,7 +390,8 @@ class TypeScope extends ReferenceScope {
|
| .toList();
|
| }
|
| return new List<ast.DartType>.filled(
|
| - genericFunctionType.typeParameters.length, const ast.DynamicType());
|
| + genericFunctionType.typeParameters.length, const ast.DynamicType(),
|
| + growable: true);
|
| } else {
|
| return <ast.DartType>[];
|
| }
|
| @@ -1184,6 +1190,28 @@ class StatementBuilder extends GeneralizingAstVisitor<ast.Statement> {
|
| return loop;
|
| }
|
|
|
| + DartType iterableElementType(DartType iterable) {
|
| + if (iterable is InterfaceType) {
|
| + var iterator = iterable.lookUpInheritedGetter('iterator')?.returnType;
|
| + if (iterator is InterfaceType) {
|
| + return iterator.lookUpInheritedGetter('current')?.returnType;
|
| + }
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + DartType streamElementType(DartType stream) {
|
| + if (stream is InterfaceType) {
|
| + var class_ = stream.element;
|
| + if (class_.library.isDartAsync &&
|
| + class_.name == 'Stream' &&
|
| + stream.typeArguments.length == 1) {
|
| + return stream.typeArguments[0];
|
| + }
|
| + }
|
| + return null;
|
| + }
|
| +
|
| ast.Statement visitForEachStatement(ForEachStatement node) {
|
| ast.VariableDeclaration variable;
|
| Accessor leftHand;
|
| @@ -1193,8 +1221,16 @@ class StatementBuilder extends GeneralizingAstVisitor<ast.Statement> {
|
| type: scope.buildOptionalTypeAnnotation(loopVariable.type));
|
| } else if (node.identifier != null) {
|
| leftHand = scope.buildLeftHandValue(node.identifier);
|
| - // TODO: In strong mode, set variable type based on iterable type.
|
| variable = new ast.VariableDeclaration(null, isFinal: true);
|
| + if (scope.strongMode) {
|
| + var containerType = node.iterable.staticType;
|
| + DartType elementType = node.awaitKeyword != null
|
| + ? streamElementType(containerType)
|
| + : iterableElementType(containerType);
|
| + if (elementType != null) {
|
| + variable.type = scope.buildType(elementType);
|
| + }
|
| + }
|
| }
|
| var breakNode = new LabelStack.unlabeled(breakStack);
|
| var continueNode = new LabelStack.unlabeled(continueStack);
|
| @@ -1221,7 +1257,7 @@ class StatementBuilder extends GeneralizingAstVisitor<ast.Statement> {
|
| variable,
|
| scope.buildExpression(node.iterable),
|
| makeBreakTarget(body, continueNode),
|
| - isAsync: node.awaitKeyword != null);
|
| + isAsync: node.awaitKeyword != null)..fileOffset = node.offset;
|
| return makeBreakTarget(loop, breakNode);
|
| }
|
|
|
| @@ -1292,9 +1328,9 @@ class StatementBuilder extends GeneralizingAstVisitor<ast.Statement> {
|
| var declaration = node.functionDeclaration;
|
| var expression = declaration.functionExpression;
|
| LocalElement element = declaration.element as dynamic; // Cross cast.
|
| - // TODO: Set a function type on the variable.
|
| return new ast.FunctionDeclaration(
|
| - scope.makeVariableDeclaration(element),
|
| + scope.makeVariableDeclaration(element,
|
| + type: scope.buildType(declaration.element.type)),
|
| scope.buildFunctionNode(expression.parameters, expression.body,
|
| typeParameters: scope.buildOptionalTypeParameterList(
|
| expression.typeParameters,
|
| @@ -2150,7 +2186,15 @@ class TypeAnnotationBuilder extends GeneralizingAstVisitor<ast.DartType> {
|
| return const ast.DynamicType();
|
| }
|
| if (boundVariables == null || boundVariables.contains(type)) {
|
| - var typeParameter = scope.getTypeParameterReference(type.element);
|
| + var typeParameter = scope.tryGetTypeParameterReference(type.element);
|
| + if (typeParameter == null) {
|
| + // The analyzer sometimes gives us a type parameter that was not
|
| + // bound anywhere. Make sure we do not emit a dangling reference.
|
| + if (type.element.bound != null) {
|
| + return convertType(type.element.bound, []);
|
| + }
|
| + return const ast.DynamicType();
|
| + }
|
| if (!scope.allowClassTypeParameters &&
|
| typeParameter.parent is ast.Class) {
|
| return const ast.InvalidType();
|
|
|