Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(862)

Side by Side Diff: pkg/compiler/lib/src/inferrer/inferrer_engine.dart

Issue 2968743002: Use .callMethod instead of LocalFunctionElement as key in inference (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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 import 'package:kernel/ast.dart' as ir; 5 import 'package:kernel/ast.dart' as ir;
6 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../common/names.dart'; 8 import '../common/names.dart';
9 import '../compiler.dart'; 9 import '../compiler.dart';
10 import '../constants/expressions.dart'; 10 import '../constants/expressions.dart';
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 element, () => new GlobalTypeInferenceElementData()); 116 element, () => new GlobalTypeInferenceElementData());
117 117
118 GlobalTypeInferenceElementData lookupDataOfMember(MemberElement element) => 118 GlobalTypeInferenceElementData lookupDataOfMember(MemberElement element) =>
119 _memberData[element]; 119 _memberData[element];
120 120
121 /** 121 /**
122 * Update [sideEffects] with the side effects of [callee] being 122 * Update [sideEffects] with the side effects of [callee] being
123 * called with [selector]. 123 * called with [selector].
124 */ 124 */
125 void updateSideEffects( 125 void updateSideEffects(
126 SideEffects sideEffects, Selector selector, Element callee) { 126 SideEffects sideEffects, Selector selector, MemberElement callee) {
127 if (callee.isField) { 127 if (callee.isField) {
128 if (callee.isInstanceMember) { 128 if (callee.isInstanceMember) {
129 if (selector.isSetter) { 129 if (selector.isSetter) {
130 sideEffects.setChangesInstanceProperty(); 130 sideEffects.setChangesInstanceProperty();
131 } else if (selector.isGetter) { 131 } else if (selector.isGetter) {
132 sideEffects.setDependsOnInstancePropertyStore(); 132 sideEffects.setDependsOnInstancePropertyStore();
133 } else { 133 } else {
134 sideEffects.setAllSideEffects(); 134 sideEffects.setAllSideEffects();
135 sideEffects.setDependsOnSomething(); 135 sideEffects.setDependsOnSomething();
136 } 136 }
137 } else { 137 } else {
138 if (selector.isSetter) { 138 if (selector.isSetter) {
139 sideEffects.setChangesStaticProperty(); 139 sideEffects.setChangesStaticProperty();
140 } else if (selector.isGetter) { 140 } else if (selector.isGetter) {
141 sideEffects.setDependsOnStaticPropertyStore(); 141 sideEffects.setDependsOnStaticPropertyStore();
142 } else { 142 } else {
143 sideEffects.setAllSideEffects(); 143 sideEffects.setAllSideEffects();
144 sideEffects.setDependsOnSomething(); 144 sideEffects.setDependsOnSomething();
145 } 145 }
146 } 146 }
147 } else if (callee.isGetter && !selector.isGetter) { 147 } else if (callee.isGetter && !selector.isGetter) {
148 sideEffects.setAllSideEffects(); 148 sideEffects.setAllSideEffects();
149 sideEffects.setDependsOnSomething(); 149 sideEffects.setDependsOnSomething();
150 } else { 150 } else {
151 sideEffects.add( 151 MethodElement method = callee.declaration;
152 closedWorldRefiner.getCurrentlyKnownSideEffects(callee.declaration)); 152 sideEffects.add(closedWorldRefiner.getCurrentlyKnownSideEffects(method));
153 } 153 }
154 } 154 }
155 155
156 /** 156 /**
157 * Returns the type for [nativeBehavior]. See documentation on 157 * Returns the type for [nativeBehavior]. See documentation on
158 * [native.NativeBehavior]. 158 * [native.NativeBehavior].
159 */ 159 */
160 TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior) { 160 TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior) {
161 if (nativeBehavior == null) return types.dynamicType; 161 if (nativeBehavior == null) return types.dynamicType;
162 List typesReturned = nativeBehavior.typesReturned; 162 List typesReturned = nativeBehavior.typesReturned;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 data.setIteratorTypeMask(node, mask); 216 data.setIteratorTypeMask(node, mask);
217 } else if (selector == Selectors.current) { 217 } else if (selector == Selectors.current) {
218 data.setCurrentTypeMask(node, mask); 218 data.setCurrentTypeMask(node, mask);
219 } else { 219 } else {
220 assert(selector == Selectors.moveNext); 220 assert(selector == Selectors.moveNext);
221 data.setMoveNextTypeMask(node, mask); 221 data.setMoveNextTypeMask(node, mask);
222 } 222 }
223 } 223 }
224 } 224 }
225 225
226 bool isNativeMember(Element element) {
227 return element is MemberElement &&
228 closedWorld.nativeData.isNativeMember(element);
229 }
230
231 bool checkIfExposesThis(ConstructorElement element) { 226 bool checkIfExposesThis(ConstructorElement element) {
232 element = element.implementation; 227 element = element.implementation;
233 return generativeConstructorsExposingThis.contains(element); 228 return generativeConstructorsExposingThis.contains(element);
234 } 229 }
235 230
236 void recordExposesThis(ConstructorElement element, bool exposesThis) { 231 void recordExposesThis(ConstructorElement element, bool exposesThis) {
237 element = element.implementation; 232 element = element.implementation;
238 if (exposesThis) { 233 if (exposesThis) {
239 generativeConstructorsExposingThis.add(element); 234 generativeConstructorsExposingThis.add(element);
240 } 235 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 types.allocatedLists.values.forEach((TypeInformation info) { 338 types.allocatedLists.values.forEach((TypeInformation info) {
344 analyzeListAndEnqueue(info); 339 analyzeListAndEnqueue(info);
345 }); 340 });
346 341
347 // Try to infer the key and value types for maps and compute the values' 342 // Try to infer the key and value types for maps and compute the values'
348 // escape information. 343 // escape information.
349 types.allocatedMaps.values.forEach((TypeInformation info) { 344 types.allocatedMaps.values.forEach((TypeInformation info) {
350 analyzeMapAndEnqueue(info); 345 analyzeMapAndEnqueue(info);
351 }); 346 });
352 347
353 Set<FunctionElement> bailedOutOn = new Set<FunctionElement>(); 348 Set<MethodElement> bailedOutOn = new Set<MethodElement>();
354 349
355 // Trace closures to potentially infer argument types. 350 // Trace closures to potentially infer argument types.
356 types.allocatedClosures.forEach((dynamic info) { 351 types.allocatedClosures.forEach((dynamic info) {
357 void trace( 352 void trace(
358 Iterable<FunctionElement> elements, ClosureTracerVisitor tracer) { 353 Iterable<MethodElement> elements, ClosureTracerVisitor tracer) {
359 tracer.run(); 354 tracer.run();
360 if (!tracer.continueAnalyzing) { 355 if (!tracer.continueAnalyzing) {
361 elements.forEach((FunctionElement e) { 356 elements.forEach((MethodElement e) {
362 closedWorldRefiner.registerMightBePassedToApply(e); 357 closedWorldRefiner.registerMightBePassedToApply(e);
363 if (debug.VERBOSE) print("traced closure $e as ${true} (bail)"); 358 if (debug.VERBOSE) print("traced closure $e as ${true} (bail)");
364 e.functionSignature.forEachParameter((parameter) { 359 e.functionSignature.forEachParameter((parameter) {
365 types 360 types
366 .getInferredTypeOfParameter(parameter) 361 .getInferredTypeOfParameter(parameter)
367 .giveUp(this, clearAssignments: false); 362 .giveUp(this, clearAssignments: false);
368 }); 363 });
369 }); 364 });
370 bailedOutOn.addAll(elements); 365 bailedOutOn.addAll(elements);
371 return; 366 return;
372 } 367 }
373 elements 368 elements
374 .where((e) => !bailedOutOn.contains(e)) 369 .where((e) => !bailedOutOn.contains(e))
375 .forEach((FunctionElement e) { 370 .forEach((MethodElement e) {
376 e.functionSignature.forEachParameter((parameter) { 371 e.functionSignature.forEachParameter((parameter) {
377 var info = types.getInferredTypeOfParameter(parameter); 372 var info = types.getInferredTypeOfParameter(parameter);
378 info.maybeResume(); 373 info.maybeResume();
379 workQueue.add(info); 374 workQueue.add(info);
380 }); 375 });
381 if (tracer.tracedType.mightBePassedToFunctionApply) { 376 if (tracer.tracedType.mightBePassedToFunctionApply) {
382 closedWorldRefiner.registerMightBePassedToApply(e); 377 closedWorldRefiner.registerMightBePassedToApply(e);
383 } 378 }
384 if (debug.VERBOSE) { 379 if (debug.VERBOSE) {
385 print("traced closure $e as " 380 print("traced closure $e as "
386 "${closedWorldRefiner 381 "${closedWorldRefiner
387 .getCurrentlyKnownMightBePassedToApply(e)}"); 382 .getCurrentlyKnownMightBePassedToApply(e)}");
388 } 383 }
389 }); 384 });
390 } 385 }
391 386
392 if (info is ClosureTypeInformation) { 387 if (info is ClosureTypeInformation) {
393 Iterable<FunctionElement> elements = [info.closure]; 388 Iterable<MethodElement> elements = [info.closure];
394 trace(elements, new ClosureTracerVisitor(elements, info, this)); 389 trace(elements, new ClosureTracerVisitor(elements, info, this));
395 } else if (info is CallSiteTypeInformation) { 390 } else if (info is CallSiteTypeInformation) {
396 if (info is StaticCallSiteTypeInformation && 391 if (info is StaticCallSiteTypeInformation &&
397 info.selector != null && 392 info.selector != null &&
398 info.selector.isCall) { 393 info.selector.isCall) {
399 // This is a constructor call to a class with a call method. So we 394 // This is a constructor call to a class with a call method. So we
400 // need to trace the call method here. 395 // need to trace the call method here.
401 assert(info.calledElement.isGenerativeConstructor); 396 assert(info.calledElement.isGenerativeConstructor);
402 ClassElement cls = info.calledElement.enclosingClass; 397 ClassElement cls = info.calledElement.enclosingClass;
403 FunctionElement callMethod = cls.lookupMember(Identifiers.call); 398 MethodElement callMethod = cls.lookupMember(Identifiers.call);
404 assert(callMethod != null, failedAt(cls)); 399 assert(callMethod != null, failedAt(cls));
405 Iterable<FunctionElement> elements = [callMethod]; 400 Iterable<MethodElement> elements = [callMethod];
406 trace(elements, new ClosureTracerVisitor(elements, info, this)); 401 trace(elements, new ClosureTracerVisitor(elements, info, this));
407 } else { 402 } else {
408 // We only are interested in functions here, as other targets 403 // We only are interested in functions here, as other targets
409 // of this closure call are not a root to trace but an intermediate 404 // of this closure call are not a root to trace but an intermediate
410 // for some other function. 405 // for some other function.
411 Iterable<FunctionElement> elements = new List<FunctionElement>.from( 406 Iterable<MethodElement> elements = new List<MethodElement>.from(
412 info.callees.where((e) => e.isFunction)); 407 info.callees.where((e) => e.isFunction));
413 trace(elements, new ClosureTracerVisitor(elements, info, this)); 408 trace(elements, new ClosureTracerVisitor(elements, info, this));
414 } 409 }
415 } else if (info is MemberTypeInformation) { 410 } else if (info is MemberTypeInformation) {
416 trace([info.member], 411 trace([info.member],
417 new StaticTearOffClosureTracerVisitor(info.member, info, this)); 412 new StaticTearOffClosureTracerVisitor(info.member, info, this));
418 } else if (info is ParameterTypeInformation) { 413 } else if (info is ParameterTypeInformation) {
419 throw new SpannableAssertionFailure( 414 throw new SpannableAssertionFailure(
420 NO_LOCATION_SPANNABLE, 'Unexpected closure allocation info $info'); 415 NO_LOCATION_SPANNABLE, 'Unexpected closure allocation info $info');
421 } 416 }
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 } 568 }
574 } else { 569 } else {
575 recordReturnType(element, type); 570 recordReturnType(element, type);
576 } 571 }
577 } 572 }
578 573
579 void processLoopInformation() { 574 void processLoopInformation() {
580 types.allocatedCalls.forEach((dynamic info) { 575 types.allocatedCalls.forEach((dynamic info) {
581 if (!info.inLoop) return; 576 if (!info.inLoop) return;
582 if (info is StaticCallSiteTypeInformation) { 577 if (info is StaticCallSiteTypeInformation) {
583 closedWorldRefiner 578 MemberElement member = info.calledElement.declaration;
584 .addFunctionCalledInLoop(info.calledElement.declaration); 579 closedWorldRefiner.addFunctionCalledInLoop(member);
585 } else if (info.mask != null && !info.mask.containsAll(closedWorld)) { 580 } else if (info.mask != null && !info.mask.containsAll(closedWorld)) {
586 // For instance methods, we only register a selector called in a 581 // For instance methods, we only register a selector called in a
587 // loop if it is a typed selector, to avoid marking too many 582 // loop if it is a typed selector, to avoid marking too many
588 // methods as being called from within a loop. This cuts down 583 // methods as being called from within a loop. This cuts down
589 // on the code bloat. 584 // on the code bloat.
590 info.targets.forEach((MemberElement element) { 585 info.targets.forEach((MemberElement element) {
591 closedWorldRefiner.addFunctionCalledInLoop(element); 586 closedWorldRefiner.addFunctionCalledInLoop(element);
592 }); 587 });
593 } 588 }
594 }); 589 });
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 * Returns the type of [element]. 774 * Returns the type of [element].
780 */ 775 */
781 TypeInformation typeOfMember(MemberElement element) { 776 TypeInformation typeOfMember(MemberElement element) {
782 if (element is MethodElement) return types.functionType; 777 if (element is MethodElement) return types.functionType;
783 return types.getInferredTypeOfMember(element); 778 return types.getInferredTypeOfMember(element);
784 } 779 }
785 780
786 /** 781 /**
787 * Returns the return type of [element]. 782 * Returns the return type of [element].
788 */ 783 */
789 @deprecated
790 TypeInformation returnTypeOfLocalFunction(LocalFunctionElement element) {
791 return types.getInferredTypeOfLocalFunction(element);
792 }
793
794 /**
795 * Returns the return type of [element].
796 */
797 TypeInformation returnTypeOfMember(MemberElement element) { 784 TypeInformation returnTypeOfMember(MemberElement element) {
798 if (element is! MethodElement) return types.dynamicType; 785 if (element is! MethodElement) return types.dynamicType;
799 return types.getInferredTypeOfMember(element); 786 return types.getInferredTypeOfMember(element);
800 } 787 }
801 788
802 /** 789 /**
803 * Records that [node] sets final field [element] to be of type [type]. 790 * Records that [node] sets final field [element] to be of type [type].
804 * 791 *
805 * [nodeHolder] is the element holder of [node]. 792 * [nodeHolder] is the element holder of [node].
806 */ 793 */
(...skipping 14 matching lines...) Expand all
821 */ 808 */
822 // TODO(johnniwinther): Merge [recordTypeOfFinalField] and 809 // TODO(johnniwinther): Merge [recordTypeOfFinalField] and
823 // [recordTypeOfNonFinalField] with this? 810 // [recordTypeOfNonFinalField] with this?
824 void recordTypeOfField(FieldElement element, TypeInformation type) { 811 void recordTypeOfField(FieldElement element, TypeInformation type) {
825 types.getInferredTypeOfMember(element).addAssignment(type); 812 types.getInferredTypeOfMember(element).addAssignment(type);
826 } 813 }
827 814
828 /** 815 /**
829 * Records that the return type [element] is of type [type]. 816 * Records that the return type [element] is of type [type].
830 */ 817 */
831 @deprecated
832 void recordReturnTypeOfLocalFunction(
833 LocalFunctionElement element, TypeInformation type) {
834 TypeInformation info = types.getInferredTypeOfLocalFunction(element);
835 if (element.name == '==') {
836 // Even if x.== doesn't return a bool, 'x == null' evaluates to 'false'.
837 info.addAssignment(types.boolType);
838 }
839 // TODO(ngeoffray): Clean up. We do these checks because
840 // [SimpleTypesInferrer] deals with two different inferrers.
841 if (type == null) return;
842 if (info.assignments.isEmpty) info.addAssignment(type);
843 }
844
845 /**
846 * Records that the return type [element] is of type [type].
847 */
848 void recordReturnType(MethodElement element, TypeInformation type) { 818 void recordReturnType(MethodElement element, TypeInformation type) {
849 TypeInformation info = types.getInferredTypeOfMember(element); 819 TypeInformation info = types.getInferredTypeOfMember(element);
850 if (element.name == '==') { 820 if (element.name == '==') {
851 // Even if x.== doesn't return a bool, 'x == null' evaluates to 'false'. 821 // Even if x.== doesn't return a bool, 'x == null' evaluates to 'false'.
852 info.addAssignment(types.boolType); 822 info.addAssignment(types.boolType);
853 } 823 }
854 // TODO(ngeoffray): Clean up. We do these checks because 824 // TODO(ngeoffray): Clean up. We do these checks because
855 // [SimpleTypesInferrer] deals with two different inferrers. 825 // [SimpleTypesInferrer] deals with two different inferrers.
856 if (type == null) return; 826 if (type == null) return;
857 if (info.assignments.isEmpty) info.addAssignment(type); 827 if (info.assignments.isEmpty) info.addAssignment(type);
858 } 828 }
859 829
860 /** 830 /**
861 * Notifies to the inferrer that [analyzedElement] can have return 831 * Notifies to the inferrer that [analyzedElement] can have return
862 * type [newType]. [currentType] is the type the [ElementGraphBuilder] 832 * type [newType]. [currentType] is the type the [ElementGraphBuilder]
863 * currently found. 833 * currently found.
864 * 834 *
865 * Returns the new type for [analyzedElement]. 835 * Returns the new type for [analyzedElement].
866 */ 836 */
867 @deprecated
868 TypeInformation addReturnTypeForLocalFunction(LocalFunctionElement element,
869 TypeInformation unused, TypeInformation newType) {
870 TypeInformation type = types.getInferredTypeOfLocalFunction(element);
871 // TODO(ngeoffray): Clean up. We do this check because
872 // [SimpleTypesInferrer] deals with two different inferrers.
873 if (element.isGenerativeConstructor) return type;
874 type.addAssignment(newType);
875 return type;
876 }
877
878 /**
879 * Notifies to the inferrer that [analyzedElement] can have return
880 * type [newType]. [currentType] is the type the [ElementGraphBuilder]
881 * currently found.
882 *
883 * Returns the new type for [analyzedElement].
884 */
885 TypeInformation addReturnTypeForMethod( 837 TypeInformation addReturnTypeForMethod(
886 MethodElement element, TypeInformation unused, TypeInformation newType) { 838 MethodElement element, TypeInformation unused, TypeInformation newType) {
887 TypeInformation type = types.getInferredTypeOfMember(element); 839 TypeInformation type = types.getInferredTypeOfMember(element);
888 // TODO(ngeoffray): Clean up. We do this check because 840 // TODO(ngeoffray): Clean up. We do this check because
889 // [SimpleTypesInferrer] deals with two different inferrers. 841 // [SimpleTypesInferrer] deals with two different inferrers.
890 if (element.isGenerativeConstructor) return type; 842 if (element.isGenerativeConstructor) return type;
891 type.addAssignment(newType); 843 type.addAssignment(newType);
892 return type; 844 return type;
893 } 845 }
894 846
895 /** 847 /**
896 * Registers that [caller] calls [callee] at location [node], with 848 * Registers that [caller] calls [callee] at location [node], with
897 * [selector], and [arguments]. Note that [selector] is null for 849 * [selector], and [arguments]. Note that [selector] is null for
898 * forwarding constructors. 850 * forwarding constructors.
899 * 851 *
900 * [sideEffects] will be updated to incorporate [callee]'s side 852 * [sideEffects] will be updated to incorporate [callee]'s side
901 * effects. 853 * effects.
902 * 854 *
903 * [inLoop] tells whether the call happens in a loop. 855 * [inLoop] tells whether the call happens in a loop.
904 */ 856 */
905 @deprecated
906 TypeInformation registerCalledLocalFunction(
907 Spannable node,
908 Selector selector,
909 TypeMask mask,
910 MemberElement caller,
911 LocalFunctionElement callee,
912 ArgumentsTypes arguments,
913 SideEffects sideEffects,
914 bool inLoop) {
915 CallSiteTypeInformation info = new LocalFunctionCallSiteTypeInformation(
916 types.currentMember,
917 node,
918 caller,
919 callee,
920 selector,
921 mask,
922 arguments,
923 inLoop);
924 return _registerCalledElement(info, selector, callee, sideEffects);
925 }
926
927 /**
928 * Registers that [caller] calls [callee] at location [node], with
929 * [selector], and [arguments]. Note that [selector] is null for
930 * forwarding constructors.
931 *
932 * [sideEffects] will be updated to incorporate [callee]'s side
933 * effects.
934 *
935 * [inLoop] tells whether the call happens in a loop.
936 */
937 TypeInformation registerCalledMember( 857 TypeInformation registerCalledMember(
938 Spannable node, 858 Spannable node,
939 Selector selector, 859 Selector selector,
940 TypeMask mask, 860 TypeMask mask,
941 MemberElement caller, 861 MemberElement caller,
942 MemberElement callee, 862 MemberElement callee,
943 ArgumentsTypes arguments, 863 ArgumentsTypes arguments,
944 SideEffects sideEffects, 864 SideEffects sideEffects,
945 bool inLoop) { 865 bool inLoop) {
946 CallSiteTypeInformation info = new StaticCallSiteTypeInformation( 866 CallSiteTypeInformation info = new StaticCallSiteTypeInformation(
947 types.currentMember, 867 types.currentMember,
948 node, 868 node,
949 caller, 869 caller,
950 callee, 870 callee,
951 selector, 871 selector,
952 mask, 872 mask,
953 arguments, 873 arguments,
954 inLoop); 874 inLoop);
955 return _registerCalledElement(info, selector, callee, sideEffects);
956 }
957
958 /**
959 * Registers that [caller] calls [callee] at location [node], with
960 * [selector], and [arguments]. Note that [selector] is null for
961 * forwarding constructors.
962 *
963 * [sideEffects] will be updated to incorporate [callee]'s side
964 * effects.
965 *
966 * [inLoop] tells whether the call happens in a loop.
967 */
968 TypeInformation _registerCalledElement(CallSiteTypeInformation info,
969 Selector selector, Element callee, SideEffects sideEffects) {
970 // If this class has a 'call' method then we have essentially created a 875 // If this class has a 'call' method then we have essentially created a
971 // closure here. Register it as such so that it is traced. 876 // closure here. Register it as such so that it is traced.
972 // Note: we exclude factory constructors because they don't always create an 877 // Note: we exclude factory constructors because they don't always create an
973 // instance of the type. They are static methods that delegate to some other 878 // instance of the type. They are static methods that delegate to some other
974 // generative constructor to do the actual creation of the object. 879 // generative constructor to do the actual creation of the object.
975 if (selector != null && selector.isCall && callee.isGenerativeConstructor) { 880 if (selector != null && selector.isCall && callee.isGenerativeConstructor) {
976 ClassElement cls = callee.enclosingClass; 881 ClassElement cls = callee.enclosingClass;
977 if (cls.callType != null) { 882 if (cls.callType != null) {
978 types.allocatedClosures.add(info); 883 types.allocatedClosures.add(info);
979 } 884 }
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
1154 throw new UnsupportedError( 1059 throw new UnsupportedError(
1155 "Cannot query the type inferrer when type inference is disabled."); 1060 "Cannot query the type inferrer when type inference is disabled.");
1156 } 1061 }
1157 MemberTypeInformation info = types.getInferredTypeOfMember(element); 1062 MemberTypeInformation info = types.getInferredTypeOfMember(element);
1158 return info.callers; 1063 return info.callers;
1159 } 1064 }
1160 1065
1161 /** 1066 /**
1162 * Returns the type of [element] when being called with [selector]. 1067 * Returns the type of [element] when being called with [selector].
1163 */ 1068 */
1164 TypeInformation typeOfLocalFunctionWithSelector(
1165 LocalFunctionElement element, Selector selector) {
1166 return _typeOfElementWithSelector(element, selector);
1167 }
1168
1169 /**
1170 * Returns the type of [element] when being called with [selector].
1171 */
1172 TypeInformation typeOfMemberWithSelector( 1069 TypeInformation typeOfMemberWithSelector(
1173 MemberElement element, Selector selector) { 1070 MemberElement element, Selector selector) {
1174 return _typeOfElementWithSelector(element, selector); 1071 return _typeOfElementWithSelector(element, selector);
1175 } 1072 }
1176 1073
1177 /** 1074 /**
1178 * Returns the type of [element] when being called with [selector]. 1075 * Returns the type of [element] when being called with [selector].
1179 */ 1076 */
1180 TypeInformation _typeOfElementWithSelector( 1077 TypeInformation _typeOfElementWithSelector(
1181 Element element, Selector selector) { 1078 MemberElement element, Selector selector) {
1182 if (element.name == Identifiers.noSuchMethod_ && 1079 if (element.name == Identifiers.noSuchMethod_ &&
1183 selector.name != element.name) { 1080 selector.name != element.name) {
1184 // An invocation can resolve to a [noSuchMethod], in which case 1081 // An invocation can resolve to a [noSuchMethod], in which case
1185 // we get the return type of [noSuchMethod]. 1082 // we get the return type of [noSuchMethod].
1186 if (element.isLocal) { 1083 return returnTypeOfMember(element);
1187 return returnTypeOfLocalFunction(element);
1188 } else {
1189 return returnTypeOfMember(element);
1190 }
1191 } else if (selector.isGetter) { 1084 } else if (selector.isGetter) {
1192 if (element.isFunction) { 1085 if (element.isFunction) {
1193 // [functionType] is null if the inferrer did not run. 1086 // [functionType] is null if the inferrer did not run.
1194 return types.functionType == null 1087 return types.functionType == null
1195 ? types.dynamicType 1088 ? types.dynamicType
1196 : types.functionType; 1089 : types.functionType;
1197 } else if (element.isField) { 1090 } else if (element.isField) {
1198 return typeOfMember(element); 1091 return typeOfMember(element);
1199 } else if (Elements.isUnresolved(element)) { 1092 } else if (Elements.isUnresolved(element)) {
1200 return types.dynamicType; 1093 return types.dynamicType;
1201 } else { 1094 } else {
1202 assert(element.isGetter); 1095 assert(element.isGetter);
1203 if (element.isLocal) { 1096 return returnTypeOfMember(element);
1204 return returnTypeOfLocalFunction(element);
1205 } else {
1206 return returnTypeOfMember(element);
1207 }
1208 } 1097 }
1209 } else if (element.isGetter || element.isField) { 1098 } else if (element.isGetter || element.isField) {
1210 assert(selector.isCall || selector.isSetter); 1099 assert(selector.isCall || selector.isSetter);
1211 return types.dynamicType; 1100 return types.dynamicType;
1212 } else { 1101 } else {
1213 if (element.isLocal) { 1102 return returnTypeOfMember(element);
1214 return returnTypeOfLocalFunction(element);
1215 } else {
1216 return returnTypeOfMember(element);
1217 }
1218 } 1103 }
1219 } 1104 }
1220 1105
1221 /** 1106 /**
1222 * Records that the captured variable [local] is read. 1107 * Records that the captured variable [local] is read.
1223 */ 1108 */
1224 void recordCapturedLocalRead(Local local) {} 1109 void recordCapturedLocalRead(Local local) {}
1225 1110
1226 /** 1111 /**
1227 * Records that the variable [local] is being updated. 1112 * Records that the variable [local] is being updated.
1228 */ 1113 */
1229 void recordLocalUpdate(Local local, TypeInformation type) {} 1114 void recordLocalUpdate(Local local, TypeInformation type) {}
1230 } 1115 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698