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 953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 inferrer.setDefaultTypeOfParameter(parameter, type); | 964 inferrer.setDefaultTypeOfParameter(parameter, type); |
965 }); | 965 }); |
966 | 966 |
967 if (closedWorld.nativeData.isNativeMember(analyzedElement)) { | 967 if (closedWorld.nativeData.isNativeMember(analyzedElement)) { |
968 // Native methods do not have a body, and we currently just say | 968 // Native methods do not have a body, and we currently just say |
969 // they return dynamic. | 969 // they return dynamic. |
970 return types.dynamicType; | 970 return types.dynamicType; |
971 } | 971 } |
972 | 972 |
973 if (analyzedElement.isGenerativeConstructor) { | 973 if (analyzedElement.isGenerativeConstructor) { |
| 974 ConstructorElement analyzedConstructor = analyzedElement; |
974 isThisExposed = false; | 975 isThisExposed = false; |
975 signature.forEachParameter((FormalElement _element) { | 976 signature.forEachParameter((FormalElement _element) { |
976 ParameterElement element = _element; | 977 ParameterElement element = _element; |
977 TypeInformation parameterType = inferrer.typeOfParameter(element); | 978 TypeInformation parameterType = inferrer.typeOfParameter(element); |
978 if (element.isInitializingFormal) { | 979 if (element.isInitializingFormal) { |
979 InitializingFormalElement initializingFormal = element; | 980 InitializingFormalElement initializingFormal = element; |
980 if (initializingFormal.fieldElement.isFinal) { | 981 if (initializingFormal.fieldElement.isFinal) { |
981 inferrer.recordTypeOfField( | 982 inferrer.recordTypeOfField( |
982 initializingFormal.fieldElement, parameterType); | 983 initializingFormal.fieldElement, parameterType); |
983 } else { | 984 } else { |
984 locals.updateField(initializingFormal.fieldElement, parameterType); | 985 locals.updateField(initializingFormal.fieldElement, parameterType); |
985 inferrer.recordTypeOfField( | 986 inferrer.recordTypeOfField( |
986 initializingFormal.fieldElement, parameterType); | 987 initializingFormal.fieldElement, parameterType); |
987 } | 988 } |
988 } | 989 } |
989 locals.update(element, parameterType, node); | 990 locals.update(element, parameterType, node); |
990 }); | 991 }); |
991 ClassElement cls = analyzedElement.enclosingClass; | 992 ClassElement cls = analyzedConstructor.enclosingClass; |
992 Spannable spannable = node; | 993 Spannable spannable = node; |
993 if (analyzedElement.isSynthesized) { | 994 if (analyzedConstructor.isSynthesized) { |
994 spannable = analyzedElement; | 995 spannable = analyzedConstructor; |
995 ConstructorElement constructor = analyzedElement; | 996 synthesizeForwardingCall( |
996 synthesizeForwardingCall(spannable, constructor.definingConstructor); | 997 spannable, analyzedConstructor.definingConstructor); |
997 } else { | 998 } else { |
998 visitingInitializers = true; | 999 visitingInitializers = true; |
999 if (node.initializers != null) { | 1000 if (node.initializers != null) { |
1000 for (ast.Node initializer in node.initializers) { | 1001 for (ast.Node initializer in node.initializers) { |
1001 ast.SendSet fieldInitializer = initializer.asSendSet(); | 1002 ast.SendSet fieldInitializer = initializer.asSendSet(); |
1002 if (fieldInitializer != null) { | 1003 if (fieldInitializer != null) { |
1003 handleSendSet(fieldInitializer); | 1004 handleSendSet(fieldInitializer); |
1004 } else { | 1005 } else { |
1005 Element element = elements[initializer]; | 1006 Element element = elements[initializer]; |
1006 handleConstructorSend(initializer, element); | 1007 handleConstructorSend(initializer, element); |
1007 } | 1008 } |
1008 } | 1009 } |
1009 } | 1010 } |
1010 visitingInitializers = false; | 1011 visitingInitializers = false; |
1011 // For a generative constructor like: `Foo();`, we synthesize | 1012 // For a generative constructor like: `Foo();`, we synthesize |
1012 // a call to the default super constructor (the one that takes | 1013 // a call to the default super constructor (the one that takes |
1013 // no argument). Resolution ensures that such a constructor | 1014 // no argument). Resolution ensures that such a constructor |
1014 // exists. | 1015 // exists. |
1015 if (!isConstructorRedirect && | 1016 if (!isConstructorRedirect && |
1016 !seenSuperConstructorCall && | 1017 !seenSuperConstructorCall && |
1017 !cls.isObject) { | 1018 !cls.isObject) { |
1018 ConstructorElement target = cls.superclass.lookupDefaultConstructor(); | 1019 ConstructorElement target = cls.superclass.lookupDefaultConstructor(); |
1019 ArgumentsTypes arguments = new ArgumentsTypes([], {}); | 1020 ArgumentsTypes arguments = new ArgumentsTypes([], {}); |
1020 analyzeSuperConstructorCall(target, arguments); | 1021 analyzeSuperConstructorCall(target, arguments); |
1021 inferrer.registerCalledMember(node, null, null, outermostElement, | 1022 inferrer.registerCalledMember(node, null, null, outermostElement, |
1022 target.implementation, arguments, sideEffects, inLoop); | 1023 target, arguments, sideEffects, inLoop); |
1023 } | 1024 } |
1024 visit(node.body); | 1025 visit(node.body); |
1025 inferrer.recordExposesThis(analyzedElement, isThisExposed); | 1026 inferrer.recordExposesThis(analyzedConstructor, isThisExposed); |
1026 } | 1027 } |
1027 if (!isConstructorRedirect) { | 1028 if (!isConstructorRedirect) { |
1028 // Iterate over all instance fields, and give a null type to | 1029 // Iterate over all instance fields, and give a null type to |
1029 // fields that we haven'TypeInformation initialized for sure. | 1030 // fields that we haven'TypeInformation initialized for sure. |
1030 cls.forEachInstanceField((_, FieldElement field) { | 1031 cls.forEachInstanceField((_, FieldElement field) { |
1031 if (field.isFinal) return; | 1032 if (field.isFinal) return; |
1032 TypeInformation type = locals.fieldScope.readField(field); | 1033 TypeInformation type = locals.fieldScope.readField(field); |
1033 ResolvedAst resolvedAst = field.resolvedAst; | 1034 ResolvedAst resolvedAst = field.resolvedAst; |
1034 if (type == null && resolvedAst.body == null) { | 1035 if (type == null && resolvedAst.body == null) { |
1035 inferrer.recordTypeOfField(field, types.nullType); | 1036 inferrer.recordTypeOfField(field, types.nullType); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1199 bool isThisOrSuper(ast.Node node) => node.isThis() || node.isSuper(); | 1200 bool isThisOrSuper(ast.Node node) => node.isThis() || node.isSuper(); |
1200 | 1201 |
1201 bool isInClassOrSubclass(Element element) { | 1202 bool isInClassOrSubclass(Element element) { |
1202 ClassElement cls = outermostElement.enclosingClass; | 1203 ClassElement cls = outermostElement.enclosingClass; |
1203 ClassElement enclosing = element.enclosingClass; | 1204 ClassElement enclosing = element.enclosingClass; |
1204 return closedWorld.isSubclassOf(enclosing, cls); | 1205 return closedWorld.isSubclassOf(enclosing, cls); |
1205 } | 1206 } |
1206 | 1207 |
1207 void checkIfExposesThis(Selector selector, TypeMask mask) { | 1208 void checkIfExposesThis(Selector selector, TypeMask mask) { |
1208 if (isThisExposed) return; | 1209 if (isThisExposed) return; |
1209 inferrer.forEachElementMatching(selector, mask, (dynamic element) { | 1210 inferrer.forEachElementMatching(selector, mask, (MemberEntity element) { |
1210 if (element.isField) { | 1211 if (element.isField) { |
1211 ResolvedAst elementResolvedAst = element.resolvedAst; | 1212 FieldElement field = element; |
| 1213 ResolvedAst elementResolvedAst = field.resolvedAst; |
1212 if (!selector.isSetter && | 1214 if (!selector.isSetter && |
1213 isInClassOrSubclass(element) && | 1215 isInClassOrSubclass(field) && |
1214 !element.isFinal && | 1216 !field.isFinal && |
1215 locals.fieldScope.readField(element) == null && | 1217 locals.fieldScope.readField(field) == null && |
1216 elementResolvedAst.body == null) { | 1218 elementResolvedAst.body == null) { |
1217 // If the field is being used before this constructor | 1219 // If the field is being used before this constructor |
1218 // actually had a chance to initialize it, say it can be | 1220 // actually had a chance to initialize it, say it can be |
1219 // null. | 1221 // null. |
1220 inferrer.recordTypeOfField(element, types.nullType); | 1222 inferrer.recordTypeOfField(field, types.nullType); |
1221 } | 1223 } |
1222 // Accessing a field does not expose [:this:]. | 1224 // Accessing a field does not expose [:this:]. |
1223 return true; | 1225 return true; |
1224 } | 1226 } |
1225 // TODO(ngeoffray): We could do better here if we knew what we | 1227 // TODO(ngeoffray): We could do better here if we knew what we |
1226 // are calling does not expose this. | 1228 // are calling does not expose this. |
1227 isThisExposed = true; | 1229 isThisExposed = true; |
1228 return false; | 1230 return false; |
1229 }); | 1231 }); |
1230 } | 1232 } |
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1994 if (targets.length == 1) { | 1996 if (targets.length == 1) { |
1995 MemberElement single = targets.first; | 1997 MemberElement single = targets.first; |
1996 if (single.isField) { | 1998 if (single.isField) { |
1997 locals.updateField(single, rhsType); | 1999 locals.updateField(single, rhsType); |
1998 } | 2000 } |
1999 } | 2001 } |
2000 } | 2002 } |
2001 handleDynamicSend( | 2003 handleDynamicSend( |
2002 node, setterSelector, setterMask, receiverType, arguments); | 2004 node, setterSelector, setterMask, receiverType, arguments); |
2003 } else if (element.isField) { | 2005 } else if (element.isField) { |
2004 if (element.isFinal) { | 2006 FieldElement field = element; |
2005 inferrer.recordTypeOfField(element, rhsType); | 2007 if (field.isFinal) { |
| 2008 inferrer.recordTypeOfField(field, rhsType); |
2006 } else { | 2009 } else { |
2007 if (analyzedElement.isGenerativeConstructor) { | 2010 if (analyzedElement.isGenerativeConstructor) { |
2008 locals.updateField(element, rhsType); | 2011 locals.updateField(field, rhsType); |
2009 } | 2012 } |
2010 if (visitingInitializers) { | 2013 if (visitingInitializers) { |
2011 inferrer.recordTypeOfField(element, rhsType); | 2014 inferrer.recordTypeOfField(field, rhsType); |
2012 } else { | 2015 } else { |
2013 handleDynamicSend( | 2016 handleDynamicSend( |
2014 node, setterSelector, setterMask, receiverType, arguments); | 2017 node, setterSelector, setterMask, receiverType, arguments); |
2015 } | 2018 } |
2016 } | 2019 } |
2017 } else if (element.isLocal) { | 2020 } else if (element.isLocal) { |
2018 locals.update(element, rhsType, node); | 2021 locals.update(element, rhsType, node); |
2019 } | 2022 } |
2020 return rhsType; | 2023 return rhsType; |
2021 } | 2024 } |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2352 ? types.nullType | 2355 ? types.nullType |
2353 : arguments.positional[1]; | 2356 : arguments.positional[1]; |
2354 | 2357 |
2355 return inferrer.concreteTypes.putIfAbsent( | 2358 return inferrer.concreteTypes.putIfAbsent( |
2356 node, | 2359 node, |
2357 () => types.allocateList(types.fixedListType, node, outermostElement, | 2360 () => types.allocateList(types.fixedListType, node, outermostElement, |
2358 elementType, length)); | 2361 elementType, length)); |
2359 } else if (Elements.isConstructorOfTypedArraySubclass( | 2362 } else if (Elements.isConstructorOfTypedArraySubclass( |
2360 constructor, closedWorld)) { | 2363 constructor, closedWorld)) { |
2361 int length = findLength(node); | 2364 int length = findLength(node); |
2362 TypeInformation elementType = | 2365 MemberElement member = target.enclosingClass.lookupMember('[]'); |
2363 inferrer.returnTypeOfMember(target.enclosingClass.lookupMember('[]')); | 2366 TypeInformation elementType = inferrer.returnTypeOfMember(member); |
2364 return inferrer.concreteTypes.putIfAbsent( | 2367 return inferrer.concreteTypes.putIfAbsent( |
2365 node, | 2368 node, |
2366 () => types.allocateList(types.nonNullExact(target.enclosingClass), | 2369 () => types.allocateList(types.nonNullExact(target.enclosingClass), |
2367 node, outermostElement, elementType, length)); | 2370 node, outermostElement, elementType, length)); |
2368 } else { | 2371 } else { |
2369 return returnType; | 2372 return returnType; |
2370 } | 2373 } |
2371 } | 2374 } |
2372 | 2375 |
2373 @override | 2376 @override |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2809 return types.boolType; | 2812 return types.boolType; |
2810 } else if (types.isNull(arguments.positional[0])) { | 2813 } else if (types.isNull(arguments.positional[0])) { |
2811 potentiallyAddNullCheck(node, node.receiver); | 2814 potentiallyAddNullCheck(node, node.receiver); |
2812 return types.boolType; | 2815 return types.boolType; |
2813 } | 2816 } |
2814 } | 2817 } |
2815 return handleDynamicSend(node, selector, mask, receiverType, arguments); | 2818 return handleDynamicSend(node, selector, mask, receiverType, arguments); |
2816 } | 2819 } |
2817 | 2820 |
2818 void recordReturnType(TypeInformation type) { | 2821 void recordReturnType(TypeInformation type) { |
| 2822 MethodElement analyzedMethod = analyzedElement; |
2819 returnType = | 2823 returnType = |
2820 inferrer.addReturnTypeForMethod(analyzedElement, returnType, type); | 2824 inferrer.addReturnTypeForMethod(analyzedMethod, returnType, type); |
2821 } | 2825 } |
2822 | 2826 |
2823 TypeInformation synthesizeForwardingCall( | 2827 TypeInformation synthesizeForwardingCall( |
2824 Spannable node, ConstructorElement element) { | 2828 Spannable node, ConstructorElement element) { |
2825 assert(element.isDeclaration); | 2829 assert(element.isDeclaration); |
2826 MethodElement function = analyzedElement.implementation; | 2830 MethodElement function = analyzedElement.implementation; |
2827 FunctionSignature signature = function.functionSignature; | 2831 FunctionSignature signature = function.functionSignature; |
2828 FunctionSignature calleeSignature = element.functionSignature; | 2832 FunctionSignature calleeSignature = element.functionSignature; |
2829 if (!calleeSignature.isCompatibleWith(signature)) { | 2833 if (!calleeSignature.isCompatibleWith(signature)) { |
2830 return types.nonNullEmpty(); | 2834 return types.nonNullEmpty(); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2947 Selector moveNextSelector = Selectors.moveNext; | 2951 Selector moveNextSelector = Selectors.moveNext; |
2948 TypeMask moveNextMask = memberData.typeOfIteratorMoveNext(node); | 2952 TypeMask moveNextMask = memberData.typeOfIteratorMoveNext(node); |
2949 | 2953 |
2950 TypeInformation iteratorType = handleDynamicSend(node, iteratorSelector, | 2954 TypeInformation iteratorType = handleDynamicSend(node, iteratorSelector, |
2951 iteratorMask, expressionType, new ArgumentsTypes.empty()); | 2955 iteratorMask, expressionType, new ArgumentsTypes.empty()); |
2952 | 2956 |
2953 return handleForInLoop(node, iteratorType, currentSelector, currentMask, | 2957 return handleForInLoop(node, iteratorType, currentSelector, currentMask, |
2954 moveNextSelector, moveNextMask); | 2958 moveNextSelector, moveNextMask); |
2955 } | 2959 } |
2956 } | 2960 } |
OLD | NEW |