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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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(Element element, ResolvedAst resolvedAst, | 105 ElementGraphBuilder(AstElement element, ResolvedAst resolvedAst, |
| 106 Compiler compiler, InferrerEngine inferrer, [LocalsHandler handler]) | 106 Compiler compiler, InferrerEngine inferrer, [LocalsHandler handler]) |
| 107 : this.internal( | 107 : this.internal( |
| 108 element, | 108 element, |
| 109 resolvedAst, | 109 resolvedAst, |
| 110 element.outermostEnclosingMemberOrTopLevel.implementation, | 110 element.outermostEnclosingMemberOrTopLevel.implementation, |
| 111 inferrer, | 111 inferrer, |
| 112 compiler, | 112 compiler, |
| 113 handler); | 113 handler); |
| 114 | 114 |
| 115 TreeElements get elements => resolvedAst.elements; | 115 TreeElements get elements => resolvedAst.elements; |
| (...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 884 } | 884 } |
| 885 | 885 |
| 886 TypeInformation visitCascade(ast.Cascade node) { | 886 TypeInformation visitCascade(ast.Cascade node) { |
| 887 // Ignore the result of the cascade send and return the type of the cascade | 887 // Ignore the result of the cascade send and return the type of the cascade |
| 888 // receiver. | 888 // receiver. |
| 889 visit(node.expression); | 889 visit(node.expression); |
| 890 return cascadeReceiverStack.removeLast(); | 890 return cascadeReceiverStack.removeLast(); |
| 891 } | 891 } |
| 892 | 892 |
| 893 void analyzeSuperConstructorCall( | 893 void analyzeSuperConstructorCall( |
| 894 AstElement target, ArgumentsTypes arguments) { | 894 ConstructorElement target, ArgumentsTypes arguments) { |
| 895 ResolvedAst resolvedAst = target.resolvedAst; | 895 ResolvedAst resolvedAst = target.resolvedAst; |
| 896 inferrer.analyze(resolvedAst, arguments); | 896 inferrer.analyze(resolvedAst, arguments); |
| 897 isThisExposed = isThisExposed || inferrer.checkIfExposesThis(target); | 897 isThisExposed = isThisExposed || inferrer.checkIfExposesThis(target); |
| 898 } | 898 } |
| 899 | 899 |
| 900 TypeInformation run() { | 900 TypeInformation run() { |
| 901 var node; | 901 var node; |
| 902 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 902 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
| 903 node = resolvedAst.node; | 903 node = resolvedAst.node; |
| 904 } | 904 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 937 // constructor comes from the corresponding parameter of the target. | 937 // constructor comes from the corresponding parameter of the target. |
| 938 | 938 |
| 939 // If this is a default value from a different context (because | 939 // If this is a default value from a different context (because |
| 940 // the current function is synthetic, e.g., a constructor from | 940 // the current function is synthetic, e.g., a constructor from |
| 941 // a mixin application), we have to start a new inferrer visitor | 941 // a mixin application), we have to start a new inferrer visitor |
| 942 // with the correct context. | 942 // with the correct context. |
| 943 // TODO(johnniwinther): Remove once function signatures are fixed. | 943 // TODO(johnniwinther): Remove once function signatures are fixed. |
| 944 ElementGraphBuilder visitor = this; | 944 ElementGraphBuilder visitor = this; |
| 945 if (inferrer.hasAlreadyComputedTypeOfParameterDefault(element)) return; | 945 if (inferrer.hasAlreadyComputedTypeOfParameterDefault(element)) return; |
| 946 if (element.functionDeclaration != analyzedElement) { | 946 if (element.functionDeclaration != analyzedElement) { |
| 947 visitor = new ElementGraphBuilder(element.functionDeclaration, | 947 ConstructorElement constructor = element.functionDeclaration; |
| 948 visitor = new ElementGraphBuilder(constructor, | |
| 948 element.functionDeclaration.resolvedAst, compiler, inferrer); | 949 element.functionDeclaration.resolvedAst, compiler, inferrer); |
| 949 } | 950 } |
| 950 TypeInformation type = | 951 TypeInformation type = |
| 951 (defaultValue == null) ? types.nullType : visitor.visit(defaultValue); | 952 (defaultValue == null) ? types.nullType : visitor.visit(defaultValue); |
| 952 inferrer.setDefaultTypeOfParameter(element, type); | 953 inferrer.setDefaultTypeOfParameter(element, type); |
| 953 }); | 954 }); |
| 954 | 955 |
| 955 if (inferrer.isNativeMember(analyzedElement)) { | 956 if (inferrer.isNativeMember(analyzedElement)) { |
| 956 // Native methods do not have a body, and we currently just say | 957 // Native methods do not have a body, and we currently just say |
| 957 // they return dynamic. | 958 // they return dynamic. |
| 958 return types.dynamicType; | 959 return types.dynamicType; |
| 959 } | 960 } |
| 960 | 961 |
| 961 if (analyzedElement.isGenerativeConstructor) { | 962 if (analyzedElement.isGenerativeConstructor) { |
| 962 isThisExposed = false; | 963 isThisExposed = false; |
| 963 signature.forEachParameter((FormalElement _element) { | 964 signature.forEachParameter((FormalElement _element) { |
| 964 ParameterElement element = _element; | 965 ParameterElement element = _element; |
| 965 TypeInformation parameterType = inferrer.typeOfElement(element); | 966 TypeInformation parameterType = inferrer.typeOfParameter(element); |
| 966 if (element.isInitializingFormal) { | 967 if (element.isInitializingFormal) { |
| 967 InitializingFormalElement initializingFormal = element; | 968 InitializingFormalElement initializingFormal = element; |
| 968 if (initializingFormal.fieldElement.isFinal) { | 969 if (initializingFormal.fieldElement.isFinal) { |
| 969 inferrer.recordTypeOfFinalField(node, analyzedElement, | 970 inferrer.recordTypeOfFinalField( |
| 970 initializingFormal.fieldElement, parameterType); | 971 initializingFormal.fieldElement, parameterType); |
| 971 } else { | 972 } else { |
| 972 locals.updateField(initializingFormal.fieldElement, parameterType); | 973 locals.updateField(initializingFormal.fieldElement, parameterType); |
| 973 inferrer.recordTypeOfNonFinalField(initializingFormal.node, | 974 inferrer.recordTypeOfNonFinalField( |
| 974 initializingFormal.fieldElement, parameterType); | 975 initializingFormal.fieldElement, parameterType); |
| 975 } | 976 } |
| 976 } | 977 } |
| 977 locals.update(element, parameterType, node); | 978 locals.update(element, parameterType, node); |
| 978 }); | 979 }); |
| 979 ClassElement cls = analyzedElement.enclosingClass; | 980 ClassElement cls = analyzedElement.enclosingClass; |
| 980 Spannable spannable = node; | 981 Spannable spannable = node; |
| 981 if (analyzedElement.isSynthesized) { | 982 if (analyzedElement.isSynthesized) { |
| 982 spannable = analyzedElement; | 983 spannable = analyzedElement; |
| 983 ConstructorElement constructor = analyzedElement; | 984 ConstructorElement constructor = analyzedElement; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 999 // For a generative constructor like: `Foo();`, we synthesize | 1000 // For a generative constructor like: `Foo();`, we synthesize |
| 1000 // a call to the default super constructor (the one that takes | 1001 // a call to the default super constructor (the one that takes |
| 1001 // no argument). Resolution ensures that such a constructor | 1002 // no argument). Resolution ensures that such a constructor |
| 1002 // exists. | 1003 // exists. |
| 1003 if (!isConstructorRedirect && | 1004 if (!isConstructorRedirect && |
| 1004 !seenSuperConstructorCall && | 1005 !seenSuperConstructorCall && |
| 1005 !cls.isObject) { | 1006 !cls.isObject) { |
| 1006 ConstructorElement target = cls.superclass.lookupDefaultConstructor(); | 1007 ConstructorElement target = cls.superclass.lookupDefaultConstructor(); |
| 1007 ArgumentsTypes arguments = new ArgumentsTypes([], {}); | 1008 ArgumentsTypes arguments = new ArgumentsTypes([], {}); |
| 1008 analyzeSuperConstructorCall(target, arguments); | 1009 analyzeSuperConstructorCall(target, arguments); |
| 1009 inferrer.registerCalledElement(node, null, null, outermostElement, | 1010 inferrer.registerCalledMember(node, null, null, outermostElement, |
| 1010 target.implementation, arguments, sideEffects, inLoop); | 1011 target.implementation, arguments, sideEffects, inLoop); |
| 1011 } | 1012 } |
| 1012 visit(node.body); | 1013 visit(node.body); |
| 1013 inferrer.recordExposesThis(analyzedElement, isThisExposed); | 1014 inferrer.recordExposesThis(analyzedElement, isThisExposed); |
| 1014 } | 1015 } |
| 1015 if (!isConstructorRedirect) { | 1016 if (!isConstructorRedirect) { |
| 1016 // Iterate over all instance fields, and give a null type to | 1017 // Iterate over all instance fields, and give a null type to |
| 1017 // fields that we haven'TypeInformation initialized for sure. | 1018 // fields that we haven'TypeInformation initialized for sure. |
| 1018 cls.forEachInstanceField((_, FieldElement field) { | 1019 cls.forEachInstanceField((_, FieldElement field) { |
| 1019 if (field.isFinal) return; | 1020 if (field.isFinal) return; |
| 1020 TypeInformation type = locals.fieldScope.readField(field); | 1021 TypeInformation type = locals.fieldScope.readField(field); |
| 1021 ResolvedAst resolvedAst = field.resolvedAst; | 1022 ResolvedAst resolvedAst = field.resolvedAst; |
| 1022 if (type == null && resolvedAst.body == null) { | 1023 if (type == null && resolvedAst.body == null) { |
| 1023 inferrer.recordTypeOfNonFinalField( | 1024 inferrer.recordTypeOfNonFinalField(field, types.nullType); |
| 1024 spannable, field, types.nullType); | |
| 1025 } | 1025 } |
| 1026 }); | 1026 }); |
| 1027 } | 1027 } |
| 1028 if (analyzedElement.isGenerativeConstructor && cls.isAbstract) { | 1028 if (analyzedElement.isGenerativeConstructor && cls.isAbstract) { |
| 1029 if (closedWorld.isInstantiated(cls)) { | 1029 if (closedWorld.isInstantiated(cls)) { |
| 1030 returnType = types.nonNullSubclass(cls); | 1030 returnType = types.nonNullSubclass(cls); |
| 1031 } else { | 1031 } else { |
| 1032 // TODO(johnniwinther): Avoid analyzing [analyzedElement] in this | 1032 // TODO(johnniwinther): Avoid analyzing [analyzedElement] in this |
| 1033 // case; it's never called. | 1033 // case; it's never called. |
| 1034 returnType = types.nonNullEmpty(); | 1034 returnType = types.nonNullEmpty(); |
| 1035 } | 1035 } |
| 1036 } else { | 1036 } else { |
| 1037 returnType = types.nonNullExact(cls); | 1037 returnType = types.nonNullExact(cls); |
| 1038 } | 1038 } |
| 1039 } else { | 1039 } else { |
| 1040 signature.forEachParameter((FormalElement _element) { | 1040 signature.forEachParameter((FormalElement _element) { |
| 1041 ParameterElement element = _element; | 1041 ParameterElement element = _element; |
| 1042 locals.update(element, inferrer.typeOfElement(element), node); | 1042 locals.update(element, inferrer.typeOfParameter(element), node); |
| 1043 }); | 1043 }); |
| 1044 visit(node.body); | 1044 visit(node.body); |
| 1045 switch (function.asyncMarker) { | 1045 switch (function.asyncMarker) { |
| 1046 case AsyncMarker.SYNC: | 1046 case AsyncMarker.SYNC: |
| 1047 if (returnType == null) { | 1047 if (returnType == null) { |
| 1048 // No return in the body. | 1048 // No return in the body. |
| 1049 returnType = locals.seenReturnOrThrow | 1049 returnType = locals.seenReturnOrThrow |
| 1050 ? types.nonNullEmpty() // Body always throws. | 1050 ? types.nonNullEmpty() // Body always throws. |
| 1051 : types.nullType; | 1051 : types.nullType; |
| 1052 } else if (!locals.seenReturnOrThrow) { | 1052 } else if (!locals.seenReturnOrThrow) { |
| 1053 // We haven'TypeInformation seen returns on all branches. So the met hod may | 1053 // We haven'TypeInformation seen returns on all branches. So the met hod may |
| 1054 // also return null. | 1054 // also return null. |
| 1055 returnType = inferrer.addReturnTypeFor( | 1055 if (analyzedElement.isLocal) { |
|
Siggi Cherem (dart-lang)
2017/06/28 16:30:24
to avoid duplicating this if-else in these four ca
Johnni Winther
2017/06/29 12:36:48
Done.
| |
| 1056 analyzedElement, returnType, types.nullType); | 1056 returnType = inferrer.addReturnTypeForLocalFunction( |
| 1057 analyzedElement, returnType, types.nullType); | |
| 1058 } else { | |
| 1059 returnType = inferrer.addReturnTypeForMethod( | |
| 1060 analyzedElement, returnType, types.nullType); | |
| 1061 } | |
| 1057 } | 1062 } |
| 1058 break; | 1063 break; |
| 1059 | 1064 |
| 1060 case AsyncMarker.SYNC_STAR: | 1065 case AsyncMarker.SYNC_STAR: |
| 1061 // TODO(asgerf): Maybe make a ContainerTypeMask for these? The type | 1066 // TODO(asgerf): Maybe make a ContainerTypeMask for these? The type |
| 1062 // contained is the method body's return type. | 1067 // contained is the method body's return type. |
| 1063 returnType = inferrer.addReturnTypeFor( | 1068 if (analyzedElement.isLocal) { |
| 1064 analyzedElement, returnType, types.syncStarIterableType); | 1069 returnType = inferrer.addReturnTypeForLocalFunction( |
| 1070 analyzedElement, returnType, types.syncStarIterableType); | |
| 1071 } else { | |
| 1072 returnType = inferrer.addReturnTypeForMethod( | |
| 1073 analyzedElement, returnType, types.syncStarIterableType); | |
| 1074 } | |
| 1065 break; | 1075 break; |
| 1066 | 1076 |
| 1067 case AsyncMarker.ASYNC: | 1077 case AsyncMarker.ASYNC: |
| 1068 returnType = inferrer.addReturnTypeFor( | 1078 if (analyzedElement.isLocal) { |
| 1069 analyzedElement, returnType, types.asyncFutureType); | 1079 returnType = inferrer.addReturnTypeForLocalFunction( |
| 1080 analyzedElement, returnType, types.asyncFutureType); | |
| 1081 } else { | |
| 1082 returnType = inferrer.addReturnTypeForMethod( | |
| 1083 analyzedElement, returnType, types.asyncFutureType); | |
| 1084 } | |
| 1070 break; | 1085 break; |
| 1071 | 1086 |
| 1072 case AsyncMarker.ASYNC_STAR: | 1087 case AsyncMarker.ASYNC_STAR: |
| 1073 returnType = inferrer.addReturnTypeFor( | 1088 if (analyzedElement.isLocal) { |
| 1074 analyzedElement, returnType, types.asyncStarStreamType); | 1089 returnType = inferrer.addReturnTypeForLocalFunction( |
| 1090 analyzedElement, returnType, types.asyncStarStreamType); | |
| 1091 } else { | |
| 1092 returnType = inferrer.addReturnTypeForMethod( | |
| 1093 analyzedElement, returnType, types.asyncStarStreamType); | |
| 1094 } | |
| 1075 break; | 1095 break; |
| 1076 } | 1096 } |
| 1077 } | 1097 } |
| 1078 | 1098 |
| 1079 inferrer.closedWorldRefiner | 1099 inferrer.closedWorldRefiner |
| 1080 .registerSideEffects(analyzedElement.declaration, sideEffects); | 1100 .registerSideEffects(analyzedElement.declaration, sideEffects); |
| 1081 assert(breaksFor.isEmpty); | 1101 assert(breaksFor.isEmpty); |
| 1082 assert(continuesFor.isEmpty); | 1102 assert(continuesFor.isEmpty); |
| 1083 return returnType; | 1103 return returnType; |
| 1084 } | 1104 } |
| 1085 | 1105 |
| 1086 TypeInformation visitFunctionExpression(ast.FunctionExpression node) { | 1106 TypeInformation visitFunctionExpression(ast.FunctionExpression node) { |
| 1087 // We loose track of [this] in closures (see issue 20840). To be on | 1107 // We loose track of [this] in closures (see issue 20840). To be on |
| 1088 // the safe side, we mark [this] as exposed here. We could do better by | 1108 // the safe side, we mark [this] as exposed here. We could do better by |
| 1089 // analyzing the closure. | 1109 // analyzing the closure. |
| 1090 // TODO(herhut): Analyze whether closure exposes this. | 1110 // TODO(herhut): Analyze whether closure exposes this. |
| 1091 isThisExposed = true; | 1111 isThisExposed = true; |
| 1092 LocalFunctionElement element = elements.getFunctionDefinition(node); | 1112 LocalFunctionElement element = elements.getFunctionDefinition(node); |
| 1093 // We don'TypeInformation put the closure in the work queue of the | 1113 // We don'TypeInformation put the closure in the work queue of the |
| 1094 // inferrer, because it will share information with its enclosing | 1114 // inferrer, because it will share information with its enclosing |
| 1095 // method, like for example the types of local variables. | 1115 // method, like for example the types of local variables. |
| 1096 LocalsHandler closureLocals = | 1116 LocalsHandler closureLocals = |
| 1097 new LocalsHandler.from(locals, node, useOtherTryBlock: false); | 1117 new LocalsHandler.from(locals, node, useOtherTryBlock: false); |
| 1098 ElementGraphBuilder visitor = new ElementGraphBuilder( | 1118 ElementGraphBuilder visitor = new ElementGraphBuilder( |
| 1099 element, element.resolvedAst, compiler, inferrer, closureLocals); | 1119 element, element.resolvedAst, compiler, inferrer, closureLocals); |
| 1100 visitor.run(); | 1120 visitor.run(); |
| 1101 inferrer.recordReturnType(element, visitor.returnType); | 1121 inferrer.recordReturnTypeOfLocalFunction(element, visitor.returnType); |
| 1102 | 1122 |
| 1103 // Record the types of captured non-boxed variables. Types of | 1123 // Record the types of captured non-boxed variables. Types of |
| 1104 // these variables may already be there, because of an analysis of | 1124 // these variables may already be there, because of an analysis of |
| 1105 // a previous closure. | 1125 // a previous closure. |
| 1106 ClosureRepresentationInfo nestedClosureData = compiler | 1126 ClosureRepresentationInfo nestedClosureData = compiler |
| 1107 .backendStrategy.closureDataLookup | 1127 .backendStrategy.closureDataLookup |
| 1108 .getClosureRepresentationInfo(element); | 1128 .getClosureRepresentationInfo(element); |
| 1109 nestedClosureData.forEachCapturedVariable((variable, field) { | 1129 nestedClosureData.forEachCapturedVariable((variable, field) { |
| 1110 if (!nestedClosureData.isVariableBoxed(variable)) { | 1130 if (!nestedClosureData.isVariableBoxed(variable)) { |
| 1111 if (variable == nestedClosureData.thisLocal) { | 1131 if (variable == nestedClosureData.thisLocal) { |
| 1112 inferrer.recordType(field, thisType); | 1132 inferrer.recordTypeOfField(field, thisType); |
| 1113 } | 1133 } |
| 1114 // The type is null for type parameters. | 1134 // The type is null for type parameters. |
| 1115 if (locals.locals[variable] == null) return; | 1135 if (locals.locals[variable] == null) return; |
| 1116 inferrer.recordType(field, locals.locals[variable]); | 1136 inferrer.recordTypeOfField(field, locals.locals[variable]); |
| 1117 } | 1137 } |
| 1118 capturedVariables.add(variable); | 1138 capturedVariables.add(variable); |
| 1119 }); | 1139 }); |
| 1120 | 1140 |
| 1121 return inferrer.concreteTypes.putIfAbsent(node, () { | 1141 return inferrer.concreteTypes.putIfAbsent(node, () { |
| 1122 return types.allocateClosure(node, element); | 1142 return types.allocateClosure(node, element); |
| 1123 }); | 1143 }); |
| 1124 } | 1144 } |
| 1125 | 1145 |
| 1126 TypeInformation visitFunctionDeclaration(ast.FunctionDeclaration node) { | 1146 TypeInformation visitFunctionDeclaration(ast.FunctionDeclaration node) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1203 if (element.isField) { | 1223 if (element.isField) { |
| 1204 ResolvedAst elementResolvedAst = element.resolvedAst; | 1224 ResolvedAst elementResolvedAst = element.resolvedAst; |
| 1205 if (!selector.isSetter && | 1225 if (!selector.isSetter && |
| 1206 isInClassOrSubclass(element) && | 1226 isInClassOrSubclass(element) && |
| 1207 !element.isFinal && | 1227 !element.isFinal && |
| 1208 locals.fieldScope.readField(element) == null && | 1228 locals.fieldScope.readField(element) == null && |
| 1209 elementResolvedAst.body == null) { | 1229 elementResolvedAst.body == null) { |
| 1210 // If the field is being used before this constructor | 1230 // If the field is being used before this constructor |
| 1211 // actually had a chance to initialize it, say it can be | 1231 // actually had a chance to initialize it, say it can be |
| 1212 // null. | 1232 // null. |
| 1213 inferrer.recordTypeOfNonFinalField( | 1233 inferrer.recordTypeOfNonFinalField(element, types.nullType); |
| 1214 resolvedAst.node, element, types.nullType); | |
| 1215 } | 1234 } |
| 1216 // Accessing a field does not expose [:this:]. | 1235 // Accessing a field does not expose [:this:]. |
| 1217 return true; | 1236 return true; |
| 1218 } | 1237 } |
| 1219 // TODO(ngeoffray): We could do better here if we knew what we | 1238 // TODO(ngeoffray): We could do better here if we knew what we |
| 1220 // are calling does not expose this. | 1239 // are calling does not expose this. |
| 1221 isThisExposed = true; | 1240 isThisExposed = true; |
| 1222 return false; | 1241 return false; |
| 1223 }); | 1242 }); |
| 1224 } | 1243 } |
| (...skipping 764 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1989 MemberElement single = targets.first; | 2008 MemberElement single = targets.first; |
| 1990 if (single.isField) { | 2009 if (single.isField) { |
| 1991 locals.updateField(single, rhsType); | 2010 locals.updateField(single, rhsType); |
| 1992 } | 2011 } |
| 1993 } | 2012 } |
| 1994 } | 2013 } |
| 1995 handleDynamicSend( | 2014 handleDynamicSend( |
| 1996 node, setterSelector, setterMask, receiverType, arguments); | 2015 node, setterSelector, setterMask, receiverType, arguments); |
| 1997 } else if (element.isField) { | 2016 } else if (element.isField) { |
| 1998 if (element.isFinal) { | 2017 if (element.isFinal) { |
| 1999 inferrer.recordTypeOfFinalField( | 2018 inferrer.recordTypeOfFinalField(element, rhsType); |
| 2000 node, outermostElement, element, rhsType); | |
| 2001 } else { | 2019 } else { |
| 2002 if (analyzedElement.isGenerativeConstructor) { | 2020 if (analyzedElement.isGenerativeConstructor) { |
| 2003 locals.updateField(element, rhsType); | 2021 locals.updateField(element, rhsType); |
| 2004 } | 2022 } |
| 2005 if (visitingInitializers) { | 2023 if (visitingInitializers) { |
| 2006 inferrer.recordTypeOfNonFinalField(node, element, rhsType); | 2024 inferrer.recordTypeOfNonFinalField(element, rhsType); |
| 2007 } else { | 2025 } else { |
| 2008 handleDynamicSend( | 2026 handleDynamicSend( |
| 2009 node, setterSelector, setterMask, receiverType, arguments); | 2027 node, setterSelector, setterMask, receiverType, arguments); |
| 2010 } | 2028 } |
| 2011 } | 2029 } |
| 2012 } else if (element.isLocal) { | 2030 } else if (element.isLocal) { |
| 2013 locals.update(element, rhsType, node); | 2031 locals.update(element, rhsType, node); |
| 2014 } | 2032 } |
| 2015 return rhsType; | 2033 return rhsType; |
| 2016 } | 2034 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 2037 if (!Selectors.noSuchMethod_.signatureApplies(element)) { | 2055 if (!Selectors.noSuchMethod_.signatureApplies(element)) { |
| 2038 ClassElement objectClass = closedWorld.commonElements.objectClass; | 2056 ClassElement objectClass = closedWorld.commonElements.objectClass; |
| 2039 element = objectClass.lookupMember(Identifiers.noSuchMethod_); | 2057 element = objectClass.lookupMember(Identifiers.noSuchMethod_); |
| 2040 } | 2058 } |
| 2041 return handleStaticSend(node, selector, mask, element, arguments); | 2059 return handleStaticSend(node, selector, mask, element, arguments); |
| 2042 } | 2060 } |
| 2043 | 2061 |
| 2044 /// Handle a .call invocation on the values retrieved from the super | 2062 /// Handle a .call invocation on the values retrieved from the super |
| 2045 /// [element]. For instance `super.foo(bar)` where `foo` is a field or getter. | 2063 /// [element]. For instance `super.foo(bar)` where `foo` is a field or getter. |
| 2046 TypeInformation handleSuperClosureCall( | 2064 TypeInformation handleSuperClosureCall( |
| 2047 ast.Send node, Element element, ast.NodeList arguments) { | 2065 ast.Send node, MemberElement element, ast.NodeList arguments) { |
| 2048 ArgumentsTypes argumentTypes = analyzeArguments(arguments.nodes); | 2066 ArgumentsTypes argumentTypes = analyzeArguments(arguments.nodes); |
| 2049 Selector selector = elements.getSelector(node); | 2067 Selector selector = elements.getSelector(node); |
| 2050 TypeMask mask = inTreeData.typeOfSend(node); | 2068 TypeMask mask = inTreeData.typeOfSend(node); |
| 2051 // TODO(herhut): We could do better here if we knew what we | 2069 // TODO(herhut): We could do better here if we knew what we |
| 2052 // are calling does not expose this. | 2070 // are calling does not expose this. |
| 2053 isThisExposed = true; | 2071 isThisExposed = true; |
| 2054 return inferrer.registerCalledClosure( | 2072 return inferrer.registerCalledClosure( |
| 2055 node, | 2073 node, |
| 2056 selector, | 2074 selector, |
| 2057 mask, | 2075 mask, |
| 2058 inferrer.typeOfElement(element), | 2076 inferrer.typeOfMember(element), |
| 2059 outermostElement, | 2077 outermostElement, |
| 2060 argumentTypes, | 2078 argumentTypes, |
| 2061 sideEffects, | 2079 sideEffects, |
| 2062 inLoop); | 2080 inLoop); |
| 2063 } | 2081 } |
| 2064 | 2082 |
| 2065 /// Handle an invocation of super [method]. | 2083 /// Handle an invocation of super [method]. |
| 2066 TypeInformation handleSuperMethodInvoke( | 2084 TypeInformation handleSuperMethodInvoke( |
| 2067 ast.Send node, MethodElement method, ArgumentsTypes arguments) { | 2085 ast.Send node, MethodElement method, ArgumentsTypes arguments) { |
| 2068 // TODO(herhut): We could do better here if we knew what we | 2086 // TODO(herhut): We could do better here if we knew what we |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2347 ? types.nullType | 2365 ? types.nullType |
| 2348 : arguments.positional[1]; | 2366 : arguments.positional[1]; |
| 2349 | 2367 |
| 2350 return inferrer.concreteTypes.putIfAbsent( | 2368 return inferrer.concreteTypes.putIfAbsent( |
| 2351 node, | 2369 node, |
| 2352 () => types.allocateList(types.fixedListType, node, outermostElement, | 2370 () => types.allocateList(types.fixedListType, node, outermostElement, |
| 2353 elementType, length)); | 2371 elementType, length)); |
| 2354 } else if (Elements.isConstructorOfTypedArraySubclass( | 2372 } else if (Elements.isConstructorOfTypedArraySubclass( |
| 2355 constructor, closedWorld)) { | 2373 constructor, closedWorld)) { |
| 2356 int length = findLength(node); | 2374 int length = findLength(node); |
| 2357 TypeInformation elementType = inferrer | 2375 TypeInformation elementType = |
| 2358 .returnTypeOfElement(target.enclosingClass.lookupMember('[]')); | 2376 inferrer.returnTypeOfMember(target.enclosingClass.lookupMember('[]')); |
| 2359 return inferrer.concreteTypes.putIfAbsent( | 2377 return inferrer.concreteTypes.putIfAbsent( |
| 2360 node, | 2378 node, |
| 2361 () => types.allocateList(types.nonNullExact(target.enclosingClass), | 2379 () => types.allocateList(types.nonNullExact(target.enclosingClass), |
| 2362 node, outermostElement, elementType, length)); | 2380 node, outermostElement, elementType, length)); |
| 2363 } else { | 2381 } else { |
| 2364 return returnType; | 2382 return returnType; |
| 2365 } | 2383 } |
| 2366 } | 2384 } |
| 2367 | 2385 |
| 2368 @override | 2386 @override |
| 2369 TypeInformation bulkHandleNew(ast.NewExpression node, _) { | 2387 TypeInformation bulkHandleNew(ast.NewExpression node, _) { |
| 2370 Element element = elements[node.send]; | 2388 Element element = elements[node.send]; |
| 2371 return handleConstructorSend(node.send, element); | 2389 return handleConstructorSend(node.send, element); |
| 2372 } | 2390 } |
| 2373 | 2391 |
| 2374 @override | 2392 @override |
| 2375 TypeInformation errorNonConstantConstructorInvoke( | 2393 TypeInformation errorNonConstantConstructorInvoke( |
| 2376 ast.NewExpression node, | 2394 ast.NewExpression node, |
| 2377 Element element, | 2395 Element element, |
| 2378 ResolutionDartType type, | 2396 ResolutionDartType type, |
| 2379 ast.NodeList arguments, | 2397 ast.NodeList arguments, |
| 2380 CallStructure callStructure, | 2398 CallStructure callStructure, |
| 2381 _) { | 2399 _) { |
| 2382 return bulkHandleNew(node, _); | 2400 return bulkHandleNew(node, _); |
| 2383 } | 2401 } |
| 2384 | 2402 |
| 2385 /// Handle invocation of a top level or static field or getter [element]. | 2403 /// Handle invocation of a top level or static field or getter [element]. |
| 2386 TypeInformation handleStaticFieldOrGetterInvoke( | 2404 TypeInformation handleStaticFieldOrGetterInvoke( |
| 2387 ast.Send node, Element element) { | 2405 ast.Send node, MemberElement element) { |
| 2388 ArgumentsTypes arguments = analyzeArguments(node.arguments); | 2406 ArgumentsTypes arguments = analyzeArguments(node.arguments); |
| 2389 Selector selector = elements.getSelector(node); | 2407 Selector selector = elements.getSelector(node); |
| 2390 TypeMask mask = inTreeData.typeOfSend(node); | 2408 TypeMask mask = inTreeData.typeOfSend(node); |
| 2391 handleStaticSend(node, selector, mask, element, arguments); | 2409 handleStaticSend(node, selector, mask, element, arguments); |
| 2392 return inferrer.registerCalledClosure( | 2410 return inferrer.registerCalledClosure( |
| 2393 node, | 2411 node, |
| 2394 selector, | 2412 selector, |
| 2395 mask, | 2413 mask, |
| 2396 inferrer.typeOfElement(element), | 2414 inferrer.typeOfMember(element), |
| 2397 outermostElement, | 2415 outermostElement, |
| 2398 arguments, | 2416 arguments, |
| 2399 sideEffects, | 2417 sideEffects, |
| 2400 inLoop); | 2418 inLoop); |
| 2401 } | 2419 } |
| 2402 | 2420 |
| 2403 /// Handle invocation of a top level or static [function]. | 2421 /// Handle invocation of a top level or static [function]. |
| 2404 TypeInformation handleStaticFunctionInvoke( | 2422 TypeInformation handleStaticFunctionInvoke( |
| 2405 ast.Send node, MethodElement function) { | 2423 ast.Send node, MethodElement function) { |
| 2406 if (compiler.backend.isForeign(closedWorld.commonElements, function)) { | 2424 if (compiler.backend.isForeign(closedWorld.commonElements, function)) { |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2699 LocalFunctionElement function, | 2717 LocalFunctionElement function, |
| 2700 ast.NodeList arguments, | 2718 ast.NodeList arguments, |
| 2701 CallStructure callStructure, | 2719 CallStructure callStructure, |
| 2702 _) { | 2720 _) { |
| 2703 ArgumentsTypes argumentTypes = analyzeArguments(node.arguments); | 2721 ArgumentsTypes argumentTypes = analyzeArguments(node.arguments); |
| 2704 Selector selector = elements.getSelector(node); | 2722 Selector selector = elements.getSelector(node); |
| 2705 TypeMask mask = inTreeData.typeOfSend(node); | 2723 TypeMask mask = inTreeData.typeOfSend(node); |
| 2706 // This only works for function statements. We need a | 2724 // This only works for function statements. We need a |
| 2707 // more sophisticated type system with function types to support | 2725 // more sophisticated type system with function types to support |
| 2708 // more. | 2726 // more. |
| 2709 return inferrer.registerCalledElement(node, selector, mask, | 2727 return inferrer.registerCalledLocalFunction(node, selector, mask, |
| 2710 outermostElement, function, argumentTypes, sideEffects, inLoop); | 2728 outermostElement, function, argumentTypes, sideEffects, inLoop); |
| 2711 } | 2729 } |
| 2712 | 2730 |
| 2713 @override | 2731 @override |
| 2714 TypeInformation visitLocalFunctionIncompatibleInvoke( | 2732 TypeInformation visitLocalFunctionIncompatibleInvoke( |
| 2715 ast.Send node, | 2733 ast.Send node, |
| 2716 LocalFunctionElement function, | 2734 LocalFunctionElement function, |
| 2717 ast.NodeList arguments, | 2735 ast.NodeList arguments, |
| 2718 CallStructure callStructure, | 2736 CallStructure callStructure, |
| 2719 _) { | 2737 _) { |
| 2720 analyzeArguments(node.arguments); | 2738 analyzeArguments(node.arguments); |
| 2721 return types.dynamicType; | 2739 return types.dynamicType; |
| 2722 } | 2740 } |
| 2723 | 2741 |
| 2724 TypeInformation handleStaticSend(ast.Node node, Selector selector, | 2742 TypeInformation handleStaticSend(ast.Node node, Selector selector, |
| 2725 TypeMask mask, Element element, ArgumentsTypes arguments) { | 2743 TypeMask mask, MemberElement element, ArgumentsTypes arguments) { |
| 2726 assert(!element.isFactoryConstructor || | 2744 assert(!element.isFactoryConstructor || |
| 2727 !(element as ConstructorElement).isRedirectingFactory); | 2745 !(element as ConstructorElement).isRedirectingFactory); |
| 2728 // Erroneous elements may be unresolved, for example missing getters. | 2746 // Erroneous elements may be unresolved, for example missing getters. |
| 2729 if (Elements.isUnresolved(element)) return types.dynamicType; | 2747 if (Elements.isUnresolved(element)) return types.dynamicType; |
| 2730 // TODO(herhut): should we follow redirecting constructors here? We would | 2748 // TODO(herhut): should we follow redirecting constructors here? We would |
| 2731 // need to pay attention if the constructor is pointing to an erroneous | 2749 // need to pay attention if the constructor is pointing to an erroneous |
| 2732 // element. | 2750 // element. |
| 2733 return inferrer.registerCalledElement(node, selector, mask, | 2751 return inferrer.registerCalledMember(node, selector, mask, outermostElement, |
| 2734 outermostElement, element, arguments, sideEffects, inLoop); | 2752 element, arguments, sideEffects, inLoop); |
| 2735 } | 2753 } |
| 2736 | 2754 |
| 2737 TypeInformation handleDynamicSend(ast.Node node, Selector selector, | 2755 TypeInformation handleDynamicSend(ast.Node node, Selector selector, |
| 2738 TypeMask mask, TypeInformation receiverType, ArgumentsTypes arguments) { | 2756 TypeMask mask, TypeInformation receiverType, ArgumentsTypes arguments) { |
| 2739 assert(receiverType != null); | 2757 assert(receiverType != null); |
| 2740 if (types.selectorNeedsUpdate(receiverType, mask)) { | 2758 if (types.selectorNeedsUpdate(receiverType, mask)) { |
| 2741 mask = receiverType == types.dynamicType | 2759 mask = receiverType == types.dynamicType |
| 2742 ? null | 2760 ? null |
| 2743 : types.newTypedSelector(receiverType, mask); | 2761 : types.newTypedSelector(receiverType, mask); |
| 2744 inferrer.updateSelectorInTree(analyzedElement, node, selector, mask); | 2762 inferrer.updateSelectorInTree(analyzedElement, node, selector, mask); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2801 return types.boolType; | 2819 return types.boolType; |
| 2802 } else if (types.isNull(arguments.positional[0])) { | 2820 } else if (types.isNull(arguments.positional[0])) { |
| 2803 potentiallyAddNullCheck(node, node.receiver); | 2821 potentiallyAddNullCheck(node, node.receiver); |
| 2804 return types.boolType; | 2822 return types.boolType; |
| 2805 } | 2823 } |
| 2806 } | 2824 } |
| 2807 return handleDynamicSend(node, selector, mask, receiverType, arguments); | 2825 return handleDynamicSend(node, selector, mask, receiverType, arguments); |
| 2808 } | 2826 } |
| 2809 | 2827 |
| 2810 void recordReturnType(TypeInformation type) { | 2828 void recordReturnType(TypeInformation type) { |
| 2811 returnType = inferrer.addReturnTypeFor(analyzedElement, returnType, type); | 2829 if (analyzedElement.isLocal) { |
| 2830 returnType = inferrer.addReturnTypeForLocalFunction( | |
| 2831 analyzedElement, returnType, type); | |
| 2832 } else { | |
| 2833 returnType = | |
| 2834 inferrer.addReturnTypeForMethod(analyzedElement, returnType, type); | |
| 2835 } | |
| 2812 } | 2836 } |
| 2813 | 2837 |
| 2814 TypeInformation synthesizeForwardingCall( | 2838 TypeInformation synthesizeForwardingCall( |
| 2815 Spannable node, ConstructorElement element) { | 2839 Spannable node, ConstructorElement element) { |
| 2816 element = element.implementation; | 2840 element = element.implementation; |
| 2817 FunctionElement function = analyzedElement; | 2841 FunctionElement function = analyzedElement; |
| 2818 FunctionSignature signature = function.functionSignature; | 2842 FunctionSignature signature = function.functionSignature; |
| 2819 FunctionSignature calleeSignature = element.functionSignature; | 2843 FunctionSignature calleeSignature = element.functionSignature; |
| 2820 if (!calleeSignature.isCompatibleWith(signature)) { | 2844 if (!calleeSignature.isCompatibleWith(signature)) { |
| 2821 return types.nonNullEmpty(); | 2845 return types.nonNullEmpty(); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2836 named[element.name] = locals.use(element); | 2860 named[element.name] = locals.use(element); |
| 2837 }); | 2861 }); |
| 2838 } else { | 2862 } else { |
| 2839 signature.forEachOptionalParameter((FormalElement _element) { | 2863 signature.forEachOptionalParameter((FormalElement _element) { |
| 2840 ParameterElement element = _element; | 2864 ParameterElement element = _element; |
| 2841 unnamed.add(locals.use(element)); | 2865 unnamed.add(locals.use(element)); |
| 2842 }); | 2866 }); |
| 2843 } | 2867 } |
| 2844 | 2868 |
| 2845 ArgumentsTypes arguments = new ArgumentsTypes(unnamed, named); | 2869 ArgumentsTypes arguments = new ArgumentsTypes(unnamed, named); |
| 2846 return inferrer.registerCalledElement(node, null, null, outermostElement, | 2870 return inferrer.registerCalledMember(node, null, null, outermostElement, |
| 2847 element, arguments, sideEffects, inLoop); | 2871 element, arguments, sideEffects, inLoop); |
| 2848 } | 2872 } |
| 2849 | 2873 |
| 2850 TypeInformation visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { | 2874 TypeInformation visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { |
| 2851 ConstructorElement element = elements.getRedirectingTargetConstructor(node); | 2875 ConstructorElement element = elements.getRedirectingTargetConstructor(node); |
| 2852 if (Elements.isMalformed(element)) { | 2876 if (Elements.isMalformed(element)) { |
| 2853 recordReturnType(types.dynamicType); | 2877 recordReturnType(types.dynamicType); |
| 2854 } else { | 2878 } else { |
| 2855 // We don'TypeInformation create a selector for redirecting factories, and | 2879 // We don'TypeInformation create a selector for redirecting factories, and |
| 2856 // the send is just a property access. Therefore we must | 2880 // the send is just a property access. Therefore we must |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2938 Selector moveNextSelector = Selectors.moveNext; | 2962 Selector moveNextSelector = Selectors.moveNext; |
| 2939 TypeMask moveNextMask = inTreeData.typeOfIteratorMoveNext(node); | 2963 TypeMask moveNextMask = inTreeData.typeOfIteratorMoveNext(node); |
| 2940 | 2964 |
| 2941 TypeInformation iteratorType = handleDynamicSend(node, iteratorSelector, | 2965 TypeInformation iteratorType = handleDynamicSend(node, iteratorSelector, |
| 2942 iteratorMask, expressionType, new ArgumentsTypes.empty()); | 2966 iteratorMask, expressionType, new ArgumentsTypes.empty()); |
| 2943 | 2967 |
| 2944 return handleForInLoop(node, iteratorType, currentSelector, currentMask, | 2968 return handleForInLoop(node, iteratorType, currentSelector, currentMask, |
| 2945 moveNextSelector, moveNextMask); | 2969 moveNextSelector, moveNextMask); |
| 2946 } | 2970 } |
| 2947 } | 2971 } |
| OLD | NEW |