Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library simple_types_inferrer; | 5 library simple_types_inferrer; |
| 6 | 6 |
| 7 import '../closure.dart' show ClosureRepresentationInfo; | 7 import '../closure.dart' show ClosureRepresentationInfo; |
| 8 import '../common.dart'; | 8 import '../common.dart'; |
| 9 import '../common/names.dart' show Identifiers, Selectors; | 9 import '../common/names.dart' show Identifiers, Selectors; |
| 10 import '../compiler.dart' show Compiler; | 10 import '../compiler.dart' show Compiler; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 49 SemanticSendResolvedMixin<TypeInformation, dynamic>, | 49 SemanticSendResolvedMixin<TypeInformation, dynamic>, |
| 50 CompoundBulkMixin<TypeInformation, dynamic>, | 50 CompoundBulkMixin<TypeInformation, dynamic>, |
| 51 SetIfNullBulkMixin<TypeInformation, dynamic>, | 51 SetIfNullBulkMixin<TypeInformation, dynamic>, |
| 52 PrefixBulkMixin<TypeInformation, dynamic>, | 52 PrefixBulkMixin<TypeInformation, dynamic>, |
| 53 PostfixBulkMixin<TypeInformation, dynamic>, | 53 PostfixBulkMixin<TypeInformation, dynamic>, |
| 54 ErrorBulkMixin<TypeInformation, dynamic>, | 54 ErrorBulkMixin<TypeInformation, dynamic>, |
| 55 NewBulkMixin<TypeInformation, dynamic>, | 55 NewBulkMixin<TypeInformation, dynamic>, |
| 56 SetBulkMixin<TypeInformation, dynamic> | 56 SetBulkMixin<TypeInformation, dynamic> |
| 57 implements SemanticSendVisitor<TypeInformation, dynamic> { | 57 implements SemanticSendVisitor<TypeInformation, dynamic> { |
| 58 final Compiler compiler; | 58 final Compiler compiler; |
| 59 final ExecutableElement analyzedElement; | 59 final MemberElement analyzedElement; |
| 60 final ResolvedAst resolvedAst; | 60 final ResolvedAst resolvedAst; |
| 61 final TypeSystem types; | 61 final TypeSystem types; |
| 62 final Map<JumpTarget, List<LocalsHandler>> breaksFor = | 62 final Map<JumpTarget, List<LocalsHandler>> breaksFor = |
| 63 new Map<JumpTarget, List<LocalsHandler>>(); | 63 new Map<JumpTarget, List<LocalsHandler>>(); |
| 64 final Map<JumpTarget, List<LocalsHandler>> continuesFor = | 64 final Map<JumpTarget, List<LocalsHandler>> continuesFor = |
| 65 new Map<JumpTarget, List<LocalsHandler>>(); | 65 new Map<JumpTarget, List<LocalsHandler>>(); |
| 66 LocalsHandler locals; | 66 LocalsHandler locals; |
| 67 final List<TypeInformation> cascadeReceiverStack = | 67 final List<TypeInformation> cascadeReceiverStack = |
| 68 new List<TypeInformation>(); | 68 new List<TypeInformation>(); |
| 69 | 69 |
| 70 TypeInformation returnType; | 70 TypeInformation returnType; |
| 71 bool visitingInitializers = false; | 71 bool visitingInitializers = false; |
| 72 bool isConstructorRedirect = false; | 72 bool isConstructorRedirect = false; |
| 73 bool seenSuperConstructorCall = false; | 73 bool seenSuperConstructorCall = false; |
| 74 SideEffects sideEffects = new SideEffects.empty(); | 74 SideEffects sideEffects = new SideEffects.empty(); |
| 75 final MemberElement outermostElement; | 75 final MemberElement outermostElement; |
| 76 final InferrerEngine inferrer; | 76 final InferrerEngine inferrer; |
| 77 final Setlet<Entity> capturedVariables = new Setlet<Entity>(); | 77 final Setlet<Entity> capturedVariables = new Setlet<Entity>(); |
| 78 final GlobalTypeInferenceElementData memberData; | 78 final GlobalTypeInferenceElementData memberData; |
| 79 | 79 |
| 80 ElementGraphBuilder.internal( | 80 ElementGraphBuilder.internal( |
| 81 ExecutableElement analyzedElement, | 81 MemberElement analyzedElement, |
| 82 this.resolvedAst, | 82 this.resolvedAst, |
| 83 this.outermostElement, | 83 this.outermostElement, |
| 84 InferrerEngine inferrer, | 84 InferrerEngine inferrer, |
| 85 this.compiler, | 85 this.compiler, |
| 86 this.locals) | 86 this.locals) |
| 87 : this.analyzedElement = analyzedElement, | 87 : this.analyzedElement = analyzedElement, |
| 88 this.inferrer = inferrer, | 88 this.inferrer = inferrer, |
| 89 this.types = inferrer.types, | 89 this.types = inferrer.types, |
| 90 this.memberData = inferrer.dataOfMember(analyzedElement.memberContext) { | 90 this.memberData = inferrer.dataOfMember(analyzedElement.memberContext) { |
| 91 assert(outermostElement != null); | 91 assert(outermostElement != null); |
| 92 if (locals != null) return; | 92 if (locals != null) return; |
| 93 ast.Node node; | 93 ast.Node node; |
| 94 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 94 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
| 95 node = resolvedAst.node; | 95 node = resolvedAst.node; |
| 96 } | 96 } |
| 97 FieldInitializationScope fieldScope = | 97 FieldInitializationScope fieldScope = |
| 98 analyzedElement.isGenerativeConstructor | 98 analyzedElement.isGenerativeConstructor |
| 99 ? new FieldInitializationScope(types) | 99 ? new FieldInitializationScope(types) |
| 100 : null; | 100 : null; |
| 101 locals = | 101 locals = |
| 102 new LocalsHandler(inferrer, types, compiler.options, node, fieldScope); | 102 new LocalsHandler(inferrer, types, compiler.options, node, fieldScope); |
| 103 } | 103 } |
| 104 | 104 |
| 105 ElementGraphBuilder(ExecutableElement element, ResolvedAst resolvedAst, | 105 ElementGraphBuilder(MemberElement element, ResolvedAst resolvedAst, |
| 106 Compiler compiler, InferrerEngine inferrer, [LocalsHandler handler]) | 106 Compiler compiler, InferrerEngine inferrer, [LocalsHandler handler]) |
| 107 : this.internal(element, resolvedAst, element.memberContext, inferrer, | 107 : this.internal(element, resolvedAst, element.memberContext, inferrer, |
| 108 compiler, handler); | 108 compiler, handler); |
| 109 | 109 |
| 110 TreeElements get elements => resolvedAst.elements; | 110 TreeElements get elements => resolvedAst.elements; |
| 111 | 111 |
| 112 bool accumulateIsChecks = false; | 112 bool accumulateIsChecks = false; |
| 113 bool conditionIsSimple = false; | 113 bool conditionIsSimple = false; |
| 114 List<ast.Send> isChecks; | 114 List<ast.Send> isChecks; |
| 115 int loopLevel = 0; | 115 int loopLevel = 0; |
| (...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 916 closureData.forEachCapturedVariable((variable, field) { | 916 closureData.forEachCapturedVariable((variable, field) { |
| 917 locals.setCaptured(variable, field); | 917 locals.setCaptured(variable, field); |
| 918 }); | 918 }); |
| 919 closureData.forEachBoxedVariable((variable, field) { | 919 closureData.forEachBoxedVariable((variable, field) { |
| 920 locals.setCapturedAndBoxed(variable, field); | 920 locals.setCapturedAndBoxed(variable, field); |
| 921 }); | 921 }); |
| 922 if (analyzedElement.isField) { | 922 if (analyzedElement.isField) { |
| 923 return visit(initializer); | 923 return visit(initializer); |
| 924 } | 924 } |
| 925 | 925 |
| 926 FunctionElement function = analyzedElement; | 926 MethodElement function = analyzedElement; |
| 927 FunctionSignature signature = function.functionSignature; | 927 FunctionSignature signature = function.functionSignature; |
| 928 signature.forEachOptionalParameter((FormalElement _element) { | 928 signature.forEachOptionalParameter((FormalElement _element) { |
| 929 ParameterElement element = _element; | 929 ParameterElement element = _element; |
| 930 ast.Expression defaultValue = element.initializer; | 930 ast.Expression defaultValue = element.initializer; |
| 931 // TODO(25566): The default value of a parameter of a redirecting factory | 931 // TODO(25566): The default value of a parameter of a redirecting factory |
| 932 // constructor comes from the corresponding parameter of the target. | 932 // constructor comes from the corresponding parameter of the target. |
| 933 | 933 |
| 934 // If this is a default value from a different context (because | 934 // If this is a default value from a different context (because |
| 935 // the current function is synthetic, e.g., a constructor from | 935 // the current function is synthetic, e.g., a constructor from |
| 936 // a mixin application), we have to start a new inferrer visitor | 936 // a mixin application), we have to start a new inferrer visitor |
| 937 // with the correct context. | 937 // with the correct context. |
| 938 // TODO(johnniwinther): Remove once function signatures are fixed. | 938 // TODO(johnniwinther): Remove once function signatures are fixed. |
| 939 ElementGraphBuilder visitor = this; | 939 ElementGraphBuilder visitor = this; |
| 940 if (inferrer.hasAlreadyComputedTypeOfParameterDefault(element)) return; | 940 if (inferrer.hasAlreadyComputedTypeOfParameterDefault(element)) return; |
| 941 if (element.functionDeclaration != analyzedElement) { | 941 if (element.functionDeclaration.isLocal) { |
|
Siggi Cherem (dart-lang)
2017/06/30 18:13:54
I was a bit confused by this extra check, but I th
Johnni Winther
2017/06/30 19:02:02
Copied in :)
| |
| 942 LocalFunctionElement localFunction = element.functionDeclaration; | |
| 943 assert( | |
| 944 localFunction.callMethod == analyzedElement, | |
| 945 failedAt( | |
| 946 element, | |
| 947 "Unexpected function declaration " | |
| 948 "${localFunction.callMethod}, expected ${analyzedElement}.")); | |
| 949 } else if (element.functionDeclaration != analyzedElement) { | |
| 942 ConstructorElement constructor = element.functionDeclaration; | 950 ConstructorElement constructor = element.functionDeclaration; |
| 943 visitor = new ElementGraphBuilder(constructor, | 951 visitor = new ElementGraphBuilder(constructor, |
| 944 element.functionDeclaration.resolvedAst, compiler, inferrer); | 952 element.functionDeclaration.resolvedAst, compiler, inferrer); |
| 945 } | 953 } |
| 946 TypeInformation type = | 954 TypeInformation type = |
| 947 (defaultValue == null) ? types.nullType : visitor.visit(defaultValue); | 955 (defaultValue == null) ? types.nullType : visitor.visit(defaultValue); |
| 948 inferrer.setDefaultTypeOfParameter(element, type); | 956 inferrer.setDefaultTypeOfParameter(element, type); |
| 949 }); | 957 }); |
| 950 | 958 |
| 951 if (inferrer.isNativeMember(analyzedElement)) { | 959 if (closedWorld.nativeData.isNativeMember(analyzedElement)) { |
| 952 // Native methods do not have a body, and we currently just say | 960 // Native methods do not have a body, and we currently just say |
| 953 // they return dynamic. | 961 // they return dynamic. |
| 954 return types.dynamicType; | 962 return types.dynamicType; |
| 955 } | 963 } |
| 956 | 964 |
| 957 if (analyzedElement.isGenerativeConstructor) { | 965 if (analyzedElement.isGenerativeConstructor) { |
| 958 isThisExposed = false; | 966 isThisExposed = false; |
| 959 signature.forEachParameter((FormalElement _element) { | 967 signature.forEachParameter((FormalElement _element) { |
| 960 ParameterElement element = _element; | 968 ParameterElement element = _element; |
| 961 TypeInformation parameterType = inferrer.typeOfParameter(element); | 969 TypeInformation parameterType = inferrer.typeOfParameter(element); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1060 case AsyncMarker.ASYNC: | 1068 case AsyncMarker.ASYNC: |
| 1061 recordReturnType(types.asyncFutureType); | 1069 recordReturnType(types.asyncFutureType); |
| 1062 break; | 1070 break; |
| 1063 | 1071 |
| 1064 case AsyncMarker.ASYNC_STAR: | 1072 case AsyncMarker.ASYNC_STAR: |
| 1065 recordReturnType(types.asyncStarStreamType); | 1073 recordReturnType(types.asyncStarStreamType); |
| 1066 break; | 1074 break; |
| 1067 } | 1075 } |
| 1068 } | 1076 } |
| 1069 | 1077 |
| 1070 inferrer.closedWorldRefiner | 1078 MethodElement declaration = analyzedElement.declaration; |
| 1071 .registerSideEffects(analyzedElement.declaration, sideEffects); | 1079 inferrer.closedWorldRefiner.registerSideEffects(declaration, sideEffects); |
| 1072 assert(breaksFor.isEmpty); | 1080 assert(breaksFor.isEmpty); |
| 1073 assert(continuesFor.isEmpty); | 1081 assert(continuesFor.isEmpty); |
| 1074 return returnType; | 1082 return returnType; |
| 1075 } | 1083 } |
| 1076 | 1084 |
| 1077 TypeInformation visitFunctionExpression(ast.FunctionExpression node) { | 1085 TypeInformation visitFunctionExpression(ast.FunctionExpression node) { |
| 1078 // We loose track of [this] in closures (see issue 20840). To be on | 1086 // We loose track of [this] in closures (see issue 20840). To be on |
| 1079 // the safe side, we mark [this] as exposed here. We could do better by | 1087 // the safe side, we mark [this] as exposed here. We could do better by |
| 1080 // analyzing the closure. | 1088 // analyzing the closure. |
| 1081 // TODO(herhut): Analyze whether closure exposes this. | 1089 // TODO(herhut): Analyze whether closure exposes this. |
| 1082 isThisExposed = true; | 1090 isThisExposed = true; |
| 1083 LocalFunctionElement element = elements.getFunctionDefinition(node); | 1091 LocalFunctionElement element = elements.getFunctionDefinition(node); |
| 1084 // We don'TypeInformation put the closure in the work queue of the | 1092 // We don'TypeInformation put the closure in the work queue of the |
| 1085 // inferrer, because it will share information with its enclosing | 1093 // inferrer, because it will share information with its enclosing |
| 1086 // method, like for example the types of local variables. | 1094 // method, like for example the types of local variables. |
| 1087 LocalsHandler closureLocals = | 1095 LocalsHandler closureLocals = |
| 1088 new LocalsHandler.from(locals, node, useOtherTryBlock: false); | 1096 new LocalsHandler.from(locals, node, useOtherTryBlock: false); |
| 1089 ElementGraphBuilder visitor = new ElementGraphBuilder( | 1097 ElementGraphBuilder visitor = new ElementGraphBuilder(element.callMethod, |
| 1090 element, element.resolvedAst, compiler, inferrer, closureLocals); | 1098 element.resolvedAst, compiler, inferrer, closureLocals); |
| 1091 visitor.run(); | 1099 visitor.run(); |
| 1092 inferrer.recordReturnTypeOfLocalFunction(element, visitor.returnType); | 1100 inferrer.recordReturnType(element.callMethod, visitor.returnType); |
| 1093 | 1101 |
| 1094 // Record the types of captured non-boxed variables. Types of | 1102 // Record the types of captured non-boxed variables. Types of |
| 1095 // these variables may already be there, because of an analysis of | 1103 // these variables may already be there, because of an analysis of |
| 1096 // a previous closure. | 1104 // a previous closure. |
| 1097 ClosureRepresentationInfo nestedClosureData = compiler | 1105 ClosureRepresentationInfo nestedClosureData = compiler |
| 1098 .backendStrategy.closureDataLookup | 1106 .backendStrategy.closureDataLookup |
| 1099 .getClosureRepresentationInfo(element); | 1107 .getClosureRepresentationInfo(element); |
| 1100 nestedClosureData.forEachCapturedVariable((variable, field) { | 1108 nestedClosureData.forEachCapturedVariable((variable, field) { |
| 1101 if (!nestedClosureData.isVariableBoxed(variable)) { | 1109 if (!nestedClosureData.isVariableBoxed(variable)) { |
| 1102 if (variable == nestedClosureData.thisLocal) { | 1110 if (variable == nestedClosureData.thisLocal) { |
| 1103 inferrer.recordTypeOfField(field, thisType); | 1111 inferrer.recordTypeOfField(field, thisType); |
| 1104 } | 1112 } |
| 1105 // The type is null for type parameters. | 1113 // The type is null for type parameters. |
| 1106 if (locals.locals[variable] == null) return; | 1114 if (locals.locals[variable] == null) return; |
| 1107 inferrer.recordTypeOfField(field, locals.locals[variable]); | 1115 inferrer.recordTypeOfField(field, locals.locals[variable]); |
| 1108 } | 1116 } |
| 1109 capturedVariables.add(variable); | 1117 capturedVariables.add(variable); |
| 1110 }); | 1118 }); |
| 1111 | 1119 |
| 1112 return inferrer.concreteTypes.putIfAbsent(node, () { | 1120 return inferrer.concreteTypes.putIfAbsent(node, () { |
| 1113 return types.allocateClosureForLocalFunction(node, element); | 1121 return types.allocateClosureForMethod(node, element.callMethod); |
| 1114 }); | 1122 }); |
| 1115 } | 1123 } |
| 1116 | 1124 |
| 1117 TypeInformation visitFunctionDeclaration(ast.FunctionDeclaration node) { | 1125 TypeInformation visitFunctionDeclaration(ast.FunctionDeclaration node) { |
| 1118 LocalFunctionElement element = | 1126 LocalFunctionElement element = |
| 1119 elements.getFunctionDefinition(node.function); | 1127 elements.getFunctionDefinition(node.function); |
| 1120 TypeInformation type = | 1128 TypeInformation type = |
| 1121 inferrer.concreteTypes.putIfAbsent(node.function, () { | 1129 inferrer.concreteTypes.putIfAbsent(node.function, () { |
| 1122 return types.allocateClosureForLocalFunction(node.function, element); | 1130 return types.allocateClosureForMethod(node.function, element.callMethod); |
| 1123 }); | 1131 }); |
| 1124 locals.update(element, type, node); | 1132 locals.update(element, type, node); |
| 1125 visit(node.function); | 1133 visit(node.function); |
| 1126 return type; | 1134 return type; |
| 1127 } | 1135 } |
| 1128 | 1136 |
| 1129 TypeInformation visitStringInterpolation(ast.StringInterpolation node) { | 1137 TypeInformation visitStringInterpolation(ast.StringInterpolation node) { |
| 1130 // Interpolation could have any effects since it could call any toString() | 1138 // Interpolation could have any effects since it could call any toString() |
| 1131 // method. | 1139 // method. |
| 1132 // TODO(sra): This could be modelled by a call to toString() but with a | 1140 // TODO(sra): This could be modelled by a call to toString() but with a |
| (...skipping 1555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2688 LocalFunctionElement function, | 2696 LocalFunctionElement function, |
| 2689 ast.NodeList arguments, | 2697 ast.NodeList arguments, |
| 2690 CallStructure callStructure, | 2698 CallStructure callStructure, |
| 2691 _) { | 2699 _) { |
| 2692 ArgumentsTypes argumentTypes = analyzeArguments(node.arguments); | 2700 ArgumentsTypes argumentTypes = analyzeArguments(node.arguments); |
| 2693 Selector selector = elements.getSelector(node); | 2701 Selector selector = elements.getSelector(node); |
| 2694 TypeMask mask = memberData.typeOfSend(node); | 2702 TypeMask mask = memberData.typeOfSend(node); |
| 2695 // This only works for function statements. We need a | 2703 // This only works for function statements. We need a |
| 2696 // more sophisticated type system with function types to support | 2704 // more sophisticated type system with function types to support |
| 2697 // more. | 2705 // more. |
| 2698 return inferrer.registerCalledLocalFunction(node, selector, mask, | 2706 return inferrer.registerCalledMember(node, selector, mask, outermostElement, |
| 2699 outermostElement, function, argumentTypes, sideEffects, inLoop); | 2707 function.callMethod, argumentTypes, sideEffects, inLoop); |
| 2700 } | 2708 } |
| 2701 | 2709 |
| 2702 @override | 2710 @override |
| 2703 TypeInformation visitLocalFunctionIncompatibleInvoke( | 2711 TypeInformation visitLocalFunctionIncompatibleInvoke( |
| 2704 ast.Send node, | 2712 ast.Send node, |
| 2705 LocalFunctionElement function, | 2713 LocalFunctionElement function, |
| 2706 ast.NodeList arguments, | 2714 ast.NodeList arguments, |
| 2707 CallStructure callStructure, | 2715 CallStructure callStructure, |
| 2708 _) { | 2716 _) { |
| 2709 analyzeArguments(node.arguments); | 2717 analyzeArguments(node.arguments); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2790 return types.boolType; | 2798 return types.boolType; |
| 2791 } else if (types.isNull(arguments.positional[0])) { | 2799 } else if (types.isNull(arguments.positional[0])) { |
| 2792 potentiallyAddNullCheck(node, node.receiver); | 2800 potentiallyAddNullCheck(node, node.receiver); |
| 2793 return types.boolType; | 2801 return types.boolType; |
| 2794 } | 2802 } |
| 2795 } | 2803 } |
| 2796 return handleDynamicSend(node, selector, mask, receiverType, arguments); | 2804 return handleDynamicSend(node, selector, mask, receiverType, arguments); |
| 2797 } | 2805 } |
| 2798 | 2806 |
| 2799 void recordReturnType(TypeInformation type) { | 2807 void recordReturnType(TypeInformation type) { |
| 2800 if (analyzedElement.isLocal) { | 2808 returnType = |
| 2801 returnType = inferrer.addReturnTypeForLocalFunction( | 2809 inferrer.addReturnTypeForMethod(analyzedElement, returnType, type); |
| 2802 analyzedElement, returnType, type); | |
| 2803 } else { | |
| 2804 returnType = | |
| 2805 inferrer.addReturnTypeForMethod(analyzedElement, returnType, type); | |
| 2806 } | |
| 2807 } | 2810 } |
| 2808 | 2811 |
| 2809 TypeInformation synthesizeForwardingCall( | 2812 TypeInformation synthesizeForwardingCall( |
| 2810 Spannable node, ConstructorElement element) { | 2813 Spannable node, ConstructorElement element) { |
| 2811 element = element.implementation; | 2814 element = element.implementation; |
| 2812 FunctionElement function = analyzedElement; | 2815 MethodElement function = analyzedElement; |
| 2813 FunctionSignature signature = function.functionSignature; | 2816 FunctionSignature signature = function.functionSignature; |
| 2814 FunctionSignature calleeSignature = element.functionSignature; | 2817 FunctionSignature calleeSignature = element.functionSignature; |
| 2815 if (!calleeSignature.isCompatibleWith(signature)) { | 2818 if (!calleeSignature.isCompatibleWith(signature)) { |
| 2816 return types.nonNullEmpty(); | 2819 return types.nonNullEmpty(); |
| 2817 } | 2820 } |
| 2818 | 2821 |
| 2819 List<TypeInformation> unnamed = <TypeInformation>[]; | 2822 List<TypeInformation> unnamed = <TypeInformation>[]; |
| 2820 signature.forEachRequiredParameter((FormalElement _element) { | 2823 signature.forEachRequiredParameter((FormalElement _element) { |
| 2821 ParameterElement element = _element; | 2824 ParameterElement element = _element; |
| 2822 assert(locals.use(element) != null); | 2825 assert(locals.use(element) != null); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2933 Selector moveNextSelector = Selectors.moveNext; | 2936 Selector moveNextSelector = Selectors.moveNext; |
| 2934 TypeMask moveNextMask = memberData.typeOfIteratorMoveNext(node); | 2937 TypeMask moveNextMask = memberData.typeOfIteratorMoveNext(node); |
| 2935 | 2938 |
| 2936 TypeInformation iteratorType = handleDynamicSend(node, iteratorSelector, | 2939 TypeInformation iteratorType = handleDynamicSend(node, iteratorSelector, |
| 2937 iteratorMask, expressionType, new ArgumentsTypes.empty()); | 2940 iteratorMask, expressionType, new ArgumentsTypes.empty()); |
| 2938 | 2941 |
| 2939 return handleForInLoop(node, iteratorType, currentSelector, currentMask, | 2942 return handleForInLoop(node, iteratorType, currentSelector, currentMask, |
| 2940 moveNextSelector, moveNextMask); | 2943 moveNextSelector, moveNextMask); |
| 2941 } | 2944 } |
| 2942 } | 2945 } |
| OLD | NEW |