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

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

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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) 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 compiler.src.inferrer.type_graph_nodes; 5 library compiler.src.inferrer.type_graph_nodes;
6 6
7 import 'dart:collection' show IterableBase; 7 import 'dart:collection' show IterableBase;
8 8
9 import '../common.dart'; 9 import '../common.dart';
10 import '../common/names.dart' show Identifiers; 10 import '../common/names.dart' show Identifiers;
11 import '../compiler.dart' show Compiler; 11 import '../compiler.dart' show Compiler;
12 import '../constants/values.dart'; 12 import '../constants/values.dart';
13 import '../cps_ir/cps_ir_nodes.dart' as cps_ir show Node; 13 import '../cps_ir/cps_ir_nodes.dart' as cps_ir show Node;
14 import '../dart_types.dart' show 14 import '../dart_types.dart'
15 DartType, 15 show DartType, FunctionType, InterfaceType, TypeKind;
16 FunctionType,
17 InterfaceType,
18 TypeKind;
19 import '../elements/elements.dart'; 16 import '../elements/elements.dart';
20 import '../native/native.dart' as native; 17 import '../native/native.dart' as native;
21 import '../tree/tree.dart' as ast show 18 import '../tree/tree.dart' as ast
22 DartString, 19 show DartString, Node, LiteralBool, Send, SendSet, TryStatement;
23 Node, 20 import '../types/types.dart'
24 LiteralBool, 21 show
25 Send, 22 ContainerTypeMask,
26 SendSet, 23 DictionaryTypeMask,
27 TryStatement; 24 MapTypeMask,
28 import '../types/types.dart' show 25 TypeMask,
29 ContainerTypeMask, 26 ValueTypeMask;
30 DictionaryTypeMask,
31 MapTypeMask,
32 TypeMask,
33 ValueTypeMask;
34 import '../universe/selector.dart' show Selector; 27 import '../universe/selector.dart' show Selector;
35 import '../util/util.dart' show ImmutableEmptySet, Setlet; 28 import '../util/util.dart' show ImmutableEmptySet, Setlet;
36 import '../world.dart' show ClassWorld; 29 import '../world.dart' show ClassWorld;
37 30
38 import 'inferrer_visitor.dart' show ArgumentsTypes; 31 import 'inferrer_visitor.dart' show ArgumentsTypes;
39 import 'type_graph_inferrer.dart' show 32 import 'type_graph_inferrer.dart'
40 TypeGraphInferrerEngine, 33 show TypeGraphInferrerEngine, TypeInformationSystem;
41 TypeInformationSystem;
42 import 'debug.dart' as debug; 34 import 'debug.dart' as debug;
43 35
44 /** 36 /**
45 * Common class for all nodes in the graph. The current nodes are: 37 * Common class for all nodes in the graph. The current nodes are:
46 * 38 *
47 * - Concrete types 39 * - Concrete types
48 * - Elements 40 * - Elements
49 * - Call sites 41 * - Call sites
50 * - Narrowing instructions 42 * - Narrowing instructions
51 * - Phi instructions 43 * - Phi instructions
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 /// Whether this [TypeInformation] has a stable [type] that will not 90 /// Whether this [TypeInformation] has a stable [type] that will not
99 /// change. 91 /// change.
100 bool isStable = false; 92 bool isStable = false;
101 93
102 // TypeInformations are unique. 94 // TypeInformations are unique.
103 static int staticHashCode = 0; 95 static int staticHashCode = 0;
104 final int hashCode = staticHashCode++; 96 final int hashCode = staticHashCode++;
105 97
106 bool get isConcrete => false; 98 bool get isConcrete => false;
107 99
108 TypeInformation(this.context) : _assignments = <TypeInformation>[], 100 TypeInformation(this.context)
109 users = new Setlet<TypeInformation>(); 101 : _assignments = <TypeInformation>[],
102 users = new Setlet<TypeInformation>();
110 103
111 TypeInformation.noAssignments(this.context) 104 TypeInformation.noAssignments(this.context)
112 : _assignments = const <TypeInformation>[], 105 : _assignments = const <TypeInformation>[],
113 users = new Setlet<TypeInformation>(); 106 users = new Setlet<TypeInformation>();
114 107
115 TypeInformation.untracked() 108 TypeInformation.untracked()
116 : _assignments = const <TypeInformation>[], 109 : _assignments = const <TypeInformation>[],
117 users = const ImmutableEmptySet(), 110 users = const ImmutableEmptySet(),
118 context = null; 111 context = null;
119 112
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 /// the information. 206 /// the information.
214 Element get owner => (context != null) ? context.element : null; 207 Element get owner => (context != null) ? context.element : null;
215 208
216 /// Returns whether the type cannot change after it has been 209 /// Returns whether the type cannot change after it has been
217 /// inferred. 210 /// inferred.
218 bool hasStableType(TypeGraphInferrerEngine inferrer) { 211 bool hasStableType(TypeGraphInferrerEngine inferrer) {
219 return !mightResume && assignments.every((e) => e.isStable); 212 return !mightResume && assignments.every((e) => e.isStable);
220 } 213 }
221 214
222 void removeAndClearReferences(TypeGraphInferrerEngine inferrer) { 215 void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
223 assignments.forEach((info) { info.removeUser(this); }); 216 assignments.forEach((info) {
217 info.removeUser(this);
218 });
224 } 219 }
225 220
226 void stabilize(TypeGraphInferrerEngine inferrer) { 221 void stabilize(TypeGraphInferrerEngine inferrer) {
227 removeAndClearReferences(inferrer); 222 removeAndClearReferences(inferrer);
228 // Do not remove users because the tracing analysis could be interested 223 // Do not remove users because the tracing analysis could be interested
229 // in tracing the users of this node. 224 // in tracing the users of this node.
230 _assignments = STOP_TRACKING_ASSIGNMENTS_MARKER; 225 _assignments = STOP_TRACKING_ASSIGNMENTS_MARKER;
231 abandonInferencing = true; 226 abandonInferencing = true;
232 isStable = true; 227 isStable = true;
233 } 228 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 } 267 }
273 268
274 /** 269 /**
275 * Parameters of instance functions behave differently than other 270 * Parameters of instance functions behave differently than other
276 * elements because the inferrer may remove assignments. This happens 271 * elements because the inferrer may remove assignments. This happens
277 * when the receiver of a dynamic call site can be refined 272 * when the receiver of a dynamic call site can be refined
278 * to a type where we know more about which instance method is being 273 * to a type where we know more about which instance method is being
279 * called. 274 * called.
280 */ 275 */
281 class ParameterAssignments extends IterableBase<TypeInformation> { 276 class ParameterAssignments extends IterableBase<TypeInformation> {
282 final Map<TypeInformation, int> assignments = 277 final Map<TypeInformation, int> assignments = new Map<TypeInformation, int>();
283 new Map<TypeInformation, int>();
284 278
285 void remove(TypeInformation info) { 279 void remove(TypeInformation info) {
286 int existing = assignments[info]; 280 int existing = assignments[info];
287 if (existing == null) return; 281 if (existing == null) return;
288 if (existing == 1) { 282 if (existing == 1) {
289 assignments.remove(info); 283 assignments.remove(info);
290 } else { 284 } else {
291 assignments[info] = existing - 1; 285 assignments[info] = existing - 1;
292 } 286 }
293 } 287 }
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 if (parameter.functionDeclaration.isInstanceMember) { 352 if (parameter.functionDeclaration.isInstanceMember) {
359 return new ParameterTypeInformation._instanceMember(element, types); 353 return new ParameterTypeInformation._instanceMember(element, types);
360 } 354 }
361 return new ParameterTypeInformation._internal(element, types); 355 return new ParameterTypeInformation._internal(element, types);
362 } 356 }
363 return new MemberTypeInformation._internal(element); 357 return new MemberTypeInformation._internal(element);
364 } 358 }
365 359
366 ElementTypeInformation._internal(MemberTypeInformation context, this.element) 360 ElementTypeInformation._internal(MemberTypeInformation context, this.element)
367 : super(context); 361 : super(context);
368 ElementTypeInformation._withAssignments(MemberTypeInformation context, 362 ElementTypeInformation._withAssignments(
369 this.element, assignments) 363 MemberTypeInformation context, this.element, assignments)
370 : super.withAssignments(context, assignments); 364 : super.withAssignments(context, assignments);
371 } 365 }
372 366
373 /** 367 /**
374 * A node representing members in the broadest sense: 368 * A node representing members in the broadest sense:
375 * 369 *
376 * - Functions 370 * - Functions
377 * - Constructors 371 * - Constructors
378 * - Fields (also synthetic ones due to closures) 372 * - Fields (also synthetic ones due to closures)
379 * - Local functions (closures) 373 * - Local functions (closures)
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 454
461 // Closurized methods never become stable to ensure that the information in 455 // Closurized methods never become stable to ensure that the information in
462 // [users] is accurate. The inference stops tracking users for stable types. 456 // [users] is accurate. The inference stops tracking users for stable types.
463 // Note that we only override the getter, the setter will still modify the 457 // Note that we only override the getter, the setter will still modify the
464 // state of the [isStable] field inhertied from [TypeInformation]. 458 // state of the [isStable] field inhertied from [TypeInformation].
465 bool get isStable => super.isStable && !isClosurized; 459 bool get isStable => super.isStable && !isClosurized;
466 460
467 TypeMask handleSpecialCases(TypeGraphInferrerEngine inferrer) { 461 TypeMask handleSpecialCases(TypeGraphInferrerEngine inferrer) {
468 if (element.isField && 462 if (element.isField &&
469 (!inferrer.backend.canBeUsedForGlobalOptimizations(element) || 463 (!inferrer.backend.canBeUsedForGlobalOptimizations(element) ||
470 inferrer.annotations.assumeDynamic(element))) { 464 inferrer.annotations.assumeDynamic(element))) {
471 // Do not infer types for fields that have a corresponding annotation or 465 // Do not infer types for fields that have a corresponding annotation or
472 // are assigned by synthesized calls 466 // are assigned by synthesized calls
473 467
474 giveUp(inferrer); 468 giveUp(inferrer);
475 return safeType(inferrer); 469 return safeType(inferrer);
476 } 470 }
477 if (inferrer.isNativeElement(element)) { 471 if (inferrer.isNativeElement(element)) {
478 // Use the type annotation as the type for native elements. We 472 // Use the type annotation as the type for native elements. We
479 // also give up on inferring to make sure this element never 473 // also give up on inferring to make sure this element never
480 // goes in the work queue. 474 // goes in the work queue.
481 giveUp(inferrer); 475 giveUp(inferrer);
482 if (element.isField) { 476 if (element.isField) {
483 return inferrer.typeOfNativeBehavior( 477 return inferrer
484 native.NativeBehavior.ofFieldLoad(element, inferrer.compiler)).type; 478 .typeOfNativeBehavior(
479 native.NativeBehavior.ofFieldLoad(element, inferrer.compiler))
480 .type;
485 } else { 481 } else {
486 assert(element.isFunction || 482 assert(element.isFunction ||
487 element.isGetter || 483 element.isGetter ||
488 element.isSetter || 484 element.isSetter ||
489 element.isConstructor); 485 element.isConstructor);
490 TypedElement typedElement = element; 486 TypedElement typedElement = element;
491 var elementType = typedElement.type; 487 var elementType = typedElement.type;
492 if (elementType.kind != TypeKind.FUNCTION) { 488 if (elementType.kind != TypeKind.FUNCTION) {
493 return safeType(inferrer); 489 return safeType(inferrer);
494 } else { 490 } else {
495 return inferrer.typeOfNativeBehavior( 491 return inferrer
496 native.NativeBehavior.ofMethod(element, inferrer.compiler)).type; 492 .typeOfNativeBehavior(
493 native.NativeBehavior.ofMethod(element, inferrer.compiler))
494 .type;
497 } 495 }
498 } 496 }
499 } 497 }
500 498
501 Compiler compiler = inferrer.compiler; 499 Compiler compiler = inferrer.compiler;
502 if (element.declaration == compiler.intEnvironment) { 500 if (element.declaration == compiler.intEnvironment) {
503 giveUp(inferrer); 501 giveUp(inferrer);
504 return compiler.typesTask.intType.nullable(); 502 return compiler.typesTask.intType.nullable();
505 } else if (element.declaration == compiler.boolEnvironment) { 503 } else if (element.declaration == compiler.boolEnvironment) {
506 giveUp(inferrer); 504 giveUp(inferrer);
507 return compiler.typesTask.boolType.nullable(); 505 return compiler.typesTask.boolType.nullable();
508 } else if (element.declaration == compiler.stringEnvironment) { 506 } else if (element.declaration == compiler.stringEnvironment) {
509 giveUp(inferrer); 507 giveUp(inferrer);
510 return compiler.typesTask.stringType.nullable(); 508 return compiler.typesTask.stringType.nullable();
511 } 509 }
512 return null; 510 return null;
513 } 511 }
514 512
515 TypeMask potentiallyNarrowType(TypeMask mask, 513 TypeMask potentiallyNarrowType(
516 TypeGraphInferrerEngine inferrer) { 514 TypeMask mask, TypeGraphInferrerEngine inferrer) {
517 Compiler compiler = inferrer.compiler; 515 Compiler compiler = inferrer.compiler;
518 if (!compiler.options.trustTypeAnnotations && 516 if (!compiler.options.trustTypeAnnotations &&
519 !compiler.options.enableTypeAssertions && 517 !compiler.options.enableTypeAssertions &&
520 !inferrer.annotations.trustTypeAnnotations(element)) { 518 !inferrer.annotations.trustTypeAnnotations(element)) {
521 return mask; 519 return mask;
522 } 520 }
523 if (element.isGenerativeConstructor || 521 if (element.isGenerativeConstructor || element.isSetter) {
524 element.isSetter) {
525 return mask; 522 return mask;
526 } 523 }
527 if (element.isField) { 524 if (element.isField) {
528 return _narrowType(compiler, mask, element.type); 525 return _narrowType(compiler, mask, element.type);
529 } 526 }
530 assert(element.isFunction || 527 assert(
531 element.isGetter || 528 element.isFunction || element.isGetter || element.isFactoryConstructor);
532 element.isFactoryConstructor);
533 529
534 FunctionType type = element.type; 530 FunctionType type = element.type;
535 return _narrowType(compiler, mask, type.returnType); 531 return _narrowType(compiler, mask, type.returnType);
536 } 532 }
537 533
538 TypeMask computeType(TypeGraphInferrerEngine inferrer) { 534 TypeMask computeType(TypeGraphInferrerEngine inferrer) {
539 TypeMask special = handleSpecialCases(inferrer); 535 TypeMask special = handleSpecialCases(inferrer);
540 if (special != null) return potentiallyNarrowType(special, inferrer); 536 if (special != null) return potentiallyNarrowType(special, inferrer);
541 return potentiallyNarrowType( 537 return potentiallyNarrowType(
542 inferrer.types.computeTypeMask(assignments), inferrer); 538 inferrer.types.computeTypeMask(assignments), inferrer);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 * - Parameters 575 * - Parameters
580 * - Initializing formals 576 * - Initializing formals
581 * 577 *
582 * These should never be created directly but instead are constructed by 578 * These should never be created directly but instead are constructed by
583 * the [ElementTypeInformation] factory. 579 * the [ElementTypeInformation] factory.
584 */ 580 */
585 class ParameterTypeInformation extends ElementTypeInformation { 581 class ParameterTypeInformation extends ElementTypeInformation {
586 ParameterElement get element => super.element; 582 ParameterElement get element => super.element;
587 FunctionElement get declaration => element.functionDeclaration; 583 FunctionElement get declaration => element.functionDeclaration;
588 584
589 ParameterTypeInformation._internal(ParameterElement element, 585 ParameterTypeInformation._internal(
590 TypeInformationSystem types) 586 ParameterElement element, TypeInformationSystem types)
591 : super._internal(types.getInferredTypeOf(element.functionDeclaration), 587 : super._internal(
592 element) { 588 types.getInferredTypeOf(element.functionDeclaration), element) {
593 assert(!element.functionDeclaration.isInstanceMember); 589 assert(!element.functionDeclaration.isInstanceMember);
594 } 590 }
595 591
596 ParameterTypeInformation._instanceMember(ParameterElement element, 592 ParameterTypeInformation._instanceMember(
597 TypeInformationSystem types) 593 ParameterElement element, TypeInformationSystem types)
598 : super._withAssignments( 594 : super._withAssignments(
599 types.getInferredTypeOf(element.functionDeclaration), 595 types.getInferredTypeOf(element.functionDeclaration),
600 element, 596 element,
601 new ParameterAssignments()) { 597 new ParameterAssignments()) {
602 assert(element.functionDeclaration.isInstanceMember); 598 assert(element.functionDeclaration.isInstanceMember);
603 } 599 }
604 600
605 bool isTearOffClosureParameter = false; 601 bool isTearOffClosureParameter = false;
606 602
607 void tagAsTearOffClosureParameter(TypeGraphInferrerEngine inferrer) { 603 void tagAsTearOffClosureParameter(TypeGraphInferrerEngine inferrer) {
608 assert(element.isParameter); 604 assert(element.isParameter);
609 isTearOffClosureParameter = true; 605 isTearOffClosureParameter = true;
610 // We have to add a flow-edge for the default value (if it exists), as we 606 // We have to add a flow-edge for the default value (if it exists), as we
611 // might not see all call-sites and thus miss the use of it. 607 // might not see all call-sites and thus miss the use of it.
(...skipping 18 matching lines...) Expand all
630 if ((isTearOffClosureParameter || declaration.isLocal) && 626 if ((isTearOffClosureParameter || declaration.isLocal) &&
631 disableInferenceForClosures) { 627 disableInferenceForClosures) {
632 // Do not infer types for parameters of closures. We do not 628 // Do not infer types for parameters of closures. We do not
633 // clear the assignments in case the closure is successfully 629 // clear the assignments in case the closure is successfully
634 // traced. 630 // traced.
635 giveUp(inferrer, clearAssignments: false); 631 giveUp(inferrer, clearAssignments: false);
636 return safeType(inferrer); 632 return safeType(inferrer);
637 } 633 }
638 if (declaration.isInstanceMember && 634 if (declaration.isInstanceMember &&
639 (declaration.name == Identifiers.noSuchMethod_ || 635 (declaration.name == Identifiers.noSuchMethod_ ||
640 (declaration.name == Identifiers.call && 636 (declaration.name == Identifiers.call &&
641 disableInferenceForClosures))) { 637 disableInferenceForClosures))) {
642 // Do not infer types for parameters of [noSuchMethod] and 638 // Do not infer types for parameters of [noSuchMethod] and
643 // [call] instance methods. 639 // [call] instance methods.
644 giveUp(inferrer); 640 giveUp(inferrer);
645 return safeType(inferrer); 641 return safeType(inferrer);
646 } 642 }
647 if (inferrer.compiler.world.getMightBePassedToApply(declaration)) { 643 if (inferrer.compiler.world.getMightBePassedToApply(declaration)) {
648 giveUp(inferrer); 644 giveUp(inferrer);
649 return safeType(inferrer); 645 return safeType(inferrer);
650 } 646 }
651 if (declaration == inferrer.mainElement) { 647 if (declaration == inferrer.mainElement) {
652 // The implicit call to main is not seen by the inferrer, 648 // The implicit call to main is not seen by the inferrer,
653 // therefore we explicitly set the type of its parameters as 649 // therefore we explicitly set the type of its parameters as
654 // dynamic. 650 // dynamic.
655 // TODO(14566): synthesize a call instead to get the exact 651 // TODO(14566): synthesize a call instead to get the exact
656 // types. 652 // types.
657 giveUp(inferrer); 653 giveUp(inferrer);
658 return safeType(inferrer); 654 return safeType(inferrer);
659 } 655 }
660 656
661 return null; 657 return null;
662 } 658 }
663 659
664 TypeMask potentiallyNarrowType(TypeMask mask, 660 TypeMask potentiallyNarrowType(
665 TypeGraphInferrerEngine inferrer) { 661 TypeMask mask, TypeGraphInferrerEngine inferrer) {
666 Compiler compiler = inferrer.compiler; 662 Compiler compiler = inferrer.compiler;
667 if (!compiler.options.trustTypeAnnotations && 663 if (!compiler.options.trustTypeAnnotations &&
668 !inferrer.annotations.trustTypeAnnotations(declaration)) { 664 !inferrer.annotations.trustTypeAnnotations(declaration)) {
669 return mask; 665 return mask;
670 } 666 }
671 // When type assertions are enabled (aka checked mode), we have to always 667 // When type assertions are enabled (aka checked mode), we have to always
672 // ignore type annotations to ensure that the checks are actually inserted 668 // ignore type annotations to ensure that the checks are actually inserted
673 // into the function body and retained until runtime. 669 // into the function body and retained until runtime.
674 assert(!compiler.options.enableTypeAssertions); 670 assert(!compiler.options.enableTypeAssertions);
675 return _narrowType(compiler, mask, element.type); 671 return _narrowType(compiler, mask, element.type);
676 } 672 }
677 673
678 TypeMask computeType(TypeGraphInferrerEngine inferrer) { 674 TypeMask computeType(TypeGraphInferrerEngine inferrer) {
679 TypeMask special = handleSpecialCases(inferrer); 675 TypeMask special = handleSpecialCases(inferrer);
680 if (special != null) return special; 676 if (special != null) return special;
681 return potentiallyNarrowType(inferrer.types.computeTypeMask(assignments), 677 return potentiallyNarrowType(
682 inferrer); 678 inferrer.types.computeTypeMask(assignments), inferrer);
683 } 679 }
684 680
685 TypeMask safeType(TypeGraphInferrerEngine inferrer) { 681 TypeMask safeType(TypeGraphInferrerEngine inferrer) {
686 return potentiallyNarrowType(super.safeType(inferrer), inferrer); 682 return potentiallyNarrowType(super.safeType(inferrer), inferrer);
687 } 683 }
688 684
689 bool hasStableType(TypeGraphInferrerEngine inferrer) { 685 bool hasStableType(TypeGraphInferrerEngine inferrer) {
690 // The number of assignments of parameters of instance methods is 686 // The number of assignments of parameters of instance methods is
691 // not stable. Therefore such a parameter cannot be stable. 687 // not stable. Therefore such a parameter cannot be stable.
692 if (element.functionDeclaration.isInstanceMember) { 688 if (element.functionDeclaration.isInstanceMember) {
(...skipping 21 matching lines...) Expand all
714 */ 710 */
715 abstract class CallSiteTypeInformation extends TypeInformation 711 abstract class CallSiteTypeInformation extends TypeInformation
716 with ApplyableTypeInformation { 712 with ApplyableTypeInformation {
717 final Spannable call; 713 final Spannable call;
718 final Element caller; 714 final Element caller;
719 final Selector selector; 715 final Selector selector;
720 final TypeMask mask; 716 final TypeMask mask;
721 final ArgumentsTypes arguments; 717 final ArgumentsTypes arguments;
722 final bool inLoop; 718 final bool inLoop;
723 719
724 CallSiteTypeInformation( 720 CallSiteTypeInformation(MemberTypeInformation context, this.call, this.caller,
725 MemberTypeInformation context, 721 this.selector, this.mask, this.arguments, this.inLoop)
726 this.call, 722 : super.noAssignments(context);
727 this.caller,
728 this.selector,
729 this.mask,
730 this.arguments,
731 this.inLoop) : super.noAssignments(context);
732 723
733 String toString() => 'Call site $call $type'; 724 String toString() => 'Call site $call $type';
734 725
735 /// Add [this] to the graph being computed by [engine]. 726 /// Add [this] to the graph being computed by [engine].
736 void addToGraph(TypeGraphInferrerEngine engine); 727 void addToGraph(TypeGraphInferrerEngine engine);
737 728
738 /// Return an iterable over the targets of this call. 729 /// Return an iterable over the targets of this call.
739 Iterable<Element> get callees; 730 Iterable<Element> get callees;
740 } 731 }
741 732
(...skipping 13 matching lines...) Expand all
755 746
756 void addToGraph(TypeGraphInferrerEngine inferrer) { 747 void addToGraph(TypeGraphInferrerEngine inferrer) {
757 MemberTypeInformation callee = 748 MemberTypeInformation callee =
758 inferrer.types.getInferredTypeOf(calledElement); 749 inferrer.types.getInferredTypeOf(calledElement);
759 callee.addCall(caller, call); 750 callee.addCall(caller, call);
760 callee.addUser(this); 751 callee.addUser(this);
761 if (arguments != null) { 752 if (arguments != null) {
762 arguments.forEach((info) => info.addUser(this)); 753 arguments.forEach((info) => info.addUser(this));
763 } 754 }
764 inferrer.updateParameterAssignments( 755 inferrer.updateParameterAssignments(
765 this, calledElement, arguments, selector, mask, remove: false, 756 this, calledElement, arguments, selector, mask,
766 addToQueue: false); 757 remove: false, addToQueue: false);
767 } 758 }
768 759
769 bool get isSynthesized { 760 bool get isSynthesized {
770 // Some calls do not have a corresponding selector, for example 761 // Some calls do not have a corresponding selector, for example
771 // fowarding factory constructors, or synthesized super 762 // fowarding factory constructors, or synthesized super
772 // constructor calls. We synthesize these calls but do 763 // constructor calls. We synthesize these calls but do
773 // not create a selector for them. 764 // not create a selector for them.
774 return selector == null; 765 return selector == null;
775 } 766 }
776 767
(...skipping 24 matching lines...) Expand all
801 callee.removeUser(this); 792 callee.removeUser(this);
802 if (arguments != null) { 793 if (arguments != null) {
803 arguments.forEach((info) => info.removeUser(this)); 794 arguments.forEach((info) => info.removeUser(this));
804 } 795 }
805 super.removeAndClearReferences(inferrer); 796 super.removeAndClearReferences(inferrer);
806 } 797 }
807 } 798 }
808 799
809 class DynamicCallSiteTypeInformation extends CallSiteTypeInformation { 800 class DynamicCallSiteTypeInformation extends CallSiteTypeInformation {
810 final TypeInformation receiver; 801 final TypeInformation receiver;
802
811 /// Cached targets of this call. 803 /// Cached targets of this call.
812 Iterable<Element> targets; 804 Iterable<Element> targets;
813 805
814 DynamicCallSiteTypeInformation( 806 DynamicCallSiteTypeInformation(
815 MemberTypeInformation context, 807 MemberTypeInformation context,
816 Spannable call, 808 Spannable call,
817 Element enclosing, 809 Element enclosing,
818 Selector selector, 810 Selector selector,
819 TypeMask mask, 811 TypeMask mask,
820 this.receiver, 812 this.receiver,
821 ArgumentsTypes arguments, 813 ArgumentsTypes arguments,
822 bool inLoop) 814 bool inLoop)
823 : super(context, call, enclosing, selector, mask, arguments, inLoop); 815 : super(context, call, enclosing, selector, mask, arguments, inLoop);
824 816
825 void addToGraph(TypeGraphInferrerEngine inferrer) { 817 void addToGraph(TypeGraphInferrerEngine inferrer) {
826 assert(receiver != null); 818 assert(receiver != null);
827 TypeMask typeMask = computeTypedSelector(inferrer); 819 TypeMask typeMask = computeTypedSelector(inferrer);
828 targets = inferrer.compiler.world.allFunctions.filter(selector, typeMask); 820 targets = inferrer.compiler.world.allFunctions.filter(selector, typeMask);
829 receiver.addUser(this); 821 receiver.addUser(this);
830 if (arguments != null) { 822 if (arguments != null) {
831 arguments.forEach((info) => info.addUser(this)); 823 arguments.forEach((info) => info.addUser(this));
832 } 824 }
833 for (Element element in targets) { 825 for (Element element in targets) {
834 MemberTypeInformation callee = inferrer.types.getInferredTypeOf(element); 826 MemberTypeInformation callee = inferrer.types.getInferredTypeOf(element);
835 callee.addCall(caller, call); 827 callee.addCall(caller, call);
836 callee.addUser(this); 828 callee.addUser(this);
837 inferrer.updateParameterAssignments( 829 inferrer.updateParameterAssignments(
838 this, element, arguments, selector, typeMask, remove: false, 830 this, element, arguments, selector, typeMask,
839 addToQueue: false); 831 remove: false, addToQueue: false);
840 } 832 }
841 } 833 }
842 834
843 Iterable<Element> get callees => targets.map((e) => e.implementation); 835 Iterable<Element> get callees => targets.map((e) => e.implementation);
844 836
845 TypeMask computeTypedSelector(TypeGraphInferrerEngine inferrer) { 837 TypeMask computeTypedSelector(TypeGraphInferrerEngine inferrer) {
846 TypeMask receiverType = receiver.type; 838 TypeMask receiverType = receiver.type;
847 839
848 if (mask != receiverType) { 840 if (mask != receiverType) {
849 return receiverType == inferrer.compiler.typesTask.dynamicType 841 return receiverType == inferrer.compiler.typesTask.dynamicType
850 ? null : receiverType; 842 ? null
843 : receiverType;
851 } else { 844 } else {
852 return mask; 845 return mask;
853 } 846 }
854 } 847 }
855 848
856 bool targetsIncludeComplexNoSuchMethod(TypeGraphInferrerEngine inferrer) { 849 bool targetsIncludeComplexNoSuchMethod(TypeGraphInferrerEngine inferrer) {
857 return targets.any((Element e) { 850 return targets.any((Element e) {
858 return e is FunctionElement && 851 return e is FunctionElement &&
859 e.isInstanceMember && 852 e.isInstanceMember &&
860 e.name == Identifiers.noSuchMethod_ && 853 e.name == Identifiers.noSuchMethod_ &&
861 inferrer.backend.isComplexNoSuchMethod(e); 854 inferrer.backend.isComplexNoSuchMethod(e);
862 }); 855 });
863 } 856 }
864 857
865 /** 858 /**
866 * We optimize certain operations on the [int] class because we know 859 * We optimize certain operations on the [int] class because we know
867 * more about their return type than the actual Dart code. For 860 * more about their return type than the actual Dart code. For
868 * example, we know int + int returns an int. The Dart code for 861 * example, we know int + int returns an int. The Dart code for
869 * [int.operator+] only says it returns a [num]. 862 * [int.operator+] only says it returns a [num].
870 */ 863 */
871 TypeInformation handleIntrisifiedSelector(Selector selector, 864 TypeInformation handleIntrisifiedSelector(
872 TypeMask mask, 865 Selector selector, TypeMask mask, TypeGraphInferrerEngine inferrer) {
873 TypeGraphInferrerEngine inferrer) {
874 ClassWorld classWorld = inferrer.classWorld; 866 ClassWorld classWorld = inferrer.classWorld;
875 if (!classWorld.backend.intImplementation.isResolved) return null; 867 if (!classWorld.backend.intImplementation.isResolved) return null;
876 if (mask == null) return null; 868 if (mask == null) return null;
877 if (!mask.containsOnlyInt(classWorld)) { 869 if (!mask.containsOnlyInt(classWorld)) {
878 return null; 870 return null;
879 } 871 }
880 if (!selector.isCall && !selector.isOperator) return null; 872 if (!selector.isCall && !selector.isOperator) return null;
881 if (!arguments.named.isEmpty) return null; 873 if (!arguments.named.isEmpty) return null;
882 if (arguments.positional.length > 1) return null; 874 if (arguments.positional.length > 1) return null;
883 875
884 ClassElement uint31Implementation = classWorld.backend.uint31Implementation; 876 ClassElement uint31Implementation = classWorld.backend.uint31Implementation;
885 bool isInt(info) => info.type.containsOnlyInt(classWorld); 877 bool isInt(info) => info.type.containsOnlyInt(classWorld);
886 bool isEmpty(info) => info.type.isEmpty; 878 bool isEmpty(info) => info.type.isEmpty;
887 bool isUInt31(info) { 879 bool isUInt31(info) {
888 return info.type.satisfies(uint31Implementation, classWorld); 880 return info.type.satisfies(uint31Implementation, classWorld);
889 } 881 }
890 bool isPositiveInt(info) { 882 bool isPositiveInt(info) {
891 return info.type.satisfies( 883 return info.type
892 classWorld.backend.positiveIntImplementation, classWorld); 884 .satisfies(classWorld.backend.positiveIntImplementation, classWorld);
893 } 885 }
894 886
895 String name = selector.name; 887 String name = selector.name;
896 // We are optimizing for the cases that are not expressed in the 888 // We are optimizing for the cases that are not expressed in the
897 // Dart code, for example: 889 // Dart code, for example:
898 // int + int -> int 890 // int + int -> int
899 // uint31 | uint31 -> uint31 891 // uint31 | uint31 -> uint31
900 if (name == '*' || name == '+' || name == '%' || name == 'remainder' || 892 if (name == '*' ||
893 name == '+' ||
894 name == '%' ||
895 name == 'remainder' ||
901 name == '~/') { 896 name == '~/') {
902 if (isPositiveInt(receiver) && 897 if (isPositiveInt(receiver) &&
903 arguments.hasOnePositionalArgumentThatMatches(isPositiveInt)) { 898 arguments.hasOnePositionalArgumentThatMatches(isPositiveInt)) {
904 // uint31 + uint31 -> uint32 899 // uint31 + uint31 -> uint32
905 if (name == '+' && isUInt31(receiver) && 900 if (name == '+' &&
901 isUInt31(receiver) &&
906 arguments.hasOnePositionalArgumentThatMatches(isUInt31)) { 902 arguments.hasOnePositionalArgumentThatMatches(isUInt31)) {
907 return inferrer.types.uint32Type; 903 return inferrer.types.uint32Type;
908 } else { 904 } else {
909 return inferrer.types.positiveIntType; 905 return inferrer.types.positiveIntType;
910 } 906 }
911 } else if (arguments.hasOnePositionalArgumentThatMatches(isInt)) { 907 } else if (arguments.hasOnePositionalArgumentThatMatches(isInt)) {
912 return inferrer.types.intType; 908 return inferrer.types.intType;
913 } else if (arguments.hasOnePositionalArgumentThatMatches(isEmpty)) { 909 } else if (arguments.hasOnePositionalArgumentThatMatches(isEmpty)) {
914 return inferrer.types.nonNullEmptyType; 910 return inferrer.types.nonNullEmptyType;
915 } else { 911 } else {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
947 } 943 }
948 944
949 TypeMask computeType(TypeGraphInferrerEngine inferrer) { 945 TypeMask computeType(TypeGraphInferrerEngine inferrer) {
950 Iterable<Element> oldTargets = targets; 946 Iterable<Element> oldTargets = targets;
951 TypeMask typeMask = computeTypedSelector(inferrer); 947 TypeMask typeMask = computeTypedSelector(inferrer);
952 inferrer.updateSelectorInTree(caller, call, selector, typeMask); 948 inferrer.updateSelectorInTree(caller, call, selector, typeMask);
953 949
954 Compiler compiler = inferrer.compiler; 950 Compiler compiler = inferrer.compiler;
955 TypeMask maskToUse = 951 TypeMask maskToUse =
956 compiler.world.extendMaskIfReachesAll(selector, typeMask); 952 compiler.world.extendMaskIfReachesAll(selector, typeMask);
957 bool canReachAll = compiler.enabledInvokeOn && 953 bool canReachAll = compiler.enabledInvokeOn && (maskToUse != typeMask);
958 (maskToUse != typeMask);
959 954
960 // If this call could potentially reach all methods that satisfy 955 // If this call could potentially reach all methods that satisfy
961 // the untyped selector (through noSuchMethod's `Invocation` 956 // the untyped selector (through noSuchMethod's `Invocation`
962 // and a call to `delegate`), we iterate over all these methods to 957 // and a call to `delegate`), we iterate over all these methods to
963 // update their parameter types. 958 // update their parameter types.
964 targets = compiler.world.allFunctions.filter(selector, maskToUse); 959 targets = compiler.world.allFunctions.filter(selector, maskToUse);
965 Iterable<Element> typedTargets = canReachAll 960 Iterable<Element> typedTargets = canReachAll
966 ? compiler.world.allFunctions.filter(selector, typeMask) 961 ? compiler.world.allFunctions.filter(selector, typeMask)
967 : targets; 962 : targets;
968 963
969 // Update the call graph if the targets could have changed. 964 // Update the call graph if the targets could have changed.
970 if (!identical(targets, oldTargets)) { 965 if (!identical(targets, oldTargets)) {
971 // Add calls to new targets to the graph. 966 // Add calls to new targets to the graph.
972 targets 967 targets
973 .where((target) => !oldTargets.contains(target)) 968 .where((target) => !oldTargets.contains(target))
974 .forEach((element) { 969 .forEach((element) {
975 MemberTypeInformation callee = 970 MemberTypeInformation callee =
976 inferrer.types.getInferredTypeOf(element); 971 inferrer.types.getInferredTypeOf(element);
977 callee.addCall(caller, call); 972 callee.addCall(caller, call);
978 callee.addUser(this); 973 callee.addUser(this);
979 inferrer.updateParameterAssignments( 974 inferrer.updateParameterAssignments(
980 this, element, arguments, selector, typeMask, remove: false, 975 this, element, arguments, selector, typeMask,
981 addToQueue: true); 976 remove: false, addToQueue: true);
982 }); 977 });
983 978
984 // Walk over the old targets, and remove calls that cannot happen anymore. 979 // Walk over the old targets, and remove calls that cannot happen anymore.
985 oldTargets 980 oldTargets
986 .where((target) => !targets.contains(target)) 981 .where((target) => !targets.contains(target))
987 .forEach((element) { 982 .forEach((element) {
988 MemberTypeInformation callee = 983 MemberTypeInformation callee =
989 inferrer.types.getInferredTypeOf(element); 984 inferrer.types.getInferredTypeOf(element);
990 callee.removeCall(caller, call); 985 callee.removeCall(caller, call);
991 callee.removeUser(this); 986 callee.removeUser(this);
992 inferrer.updateParameterAssignments( 987 inferrer.updateParameterAssignments(
993 this, element, arguments, selector, typeMask, remove: true, 988 this, element, arguments, selector, typeMask,
994 addToQueue: true); 989 remove: true, addToQueue: true);
995 }); 990 });
996 } 991 }
997 992
998 // Walk over the found targets, and compute the joined union type mask 993 // Walk over the found targets, and compute the joined union type mask
999 // for all these targets. 994 // for all these targets.
1000 TypeMask result = inferrer.types.joinTypeMasks(targets.map((element) { 995 TypeMask result = inferrer.types.joinTypeMasks(targets.map((element) {
1001 // If [canReachAll] is true, then we are iterating over all 996 // If [canReachAll] is true, then we are iterating over all
1002 // targets that satisfy the untyped selector. We skip the return 997 // targets that satisfy the untyped selector. We skip the return
1003 // type of the targets that can only be reached through 998 // type of the targets that can only be reached through
1004 // `Invocation.delegate`. Note that the `noSuchMethod` targets 999 // `Invocation.delegate`. Note that the `noSuchMethod` targets
1005 // are included in [typedTargets]. 1000 // are included in [typedTargets].
1006 if (canReachAll && !typedTargets.contains(element)) { 1001 if (canReachAll && !typedTargets.contains(element)) {
1007 return const TypeMask.nonNullEmpty(); 1002 return const TypeMask.nonNullEmpty();
1008 } 1003 }
1009 1004
1010 if (inferrer.returnsListElementType(selector, typeMask)) { 1005 if (inferrer.returnsListElementType(selector, typeMask)) {
1011 ContainerTypeMask containerTypeMask = receiver.type; 1006 ContainerTypeMask containerTypeMask = receiver.type;
1012 return containerTypeMask.elementType; 1007 return containerTypeMask.elementType;
1013 } else if (inferrer.returnsMapValueType(selector, typeMask)) { 1008 } else if (inferrer.returnsMapValueType(selector, typeMask)) {
1014 if (typeMask.isDictionary && 1009 if (typeMask.isDictionary &&
1015 arguments.positional[0].type.isValue && 1010 arguments.positional[0].type.isValue &&
1016 arguments.positional[0].type.value.isString) { 1011 arguments.positional[0].type.value.isString) {
1017 DictionaryTypeMask dictionaryTypeMask = typeMask; 1012 DictionaryTypeMask dictionaryTypeMask = typeMask;
1018 ValueTypeMask arg = arguments.positional[0].type; 1013 ValueTypeMask arg = arguments.positional[0].type;
1019 String key = arg.value.primitiveValue.slowToString(); 1014 String key = arg.value.primitiveValue.slowToString();
1020 if (dictionaryTypeMask.typeMap.containsKey(key)) { 1015 if (dictionaryTypeMask.typeMap.containsKey(key)) {
1021 if (debug.VERBOSE) { 1016 if (debug.VERBOSE) {
1022 print("Dictionary lookup for $key yields " 1017 print("Dictionary lookup for $key yields "
1023 "${dictionaryTypeMask.typeMap[key]}."); 1018 "${dictionaryTypeMask.typeMap[key]}.");
1024 } 1019 }
1025 return dictionaryTypeMask.typeMap[key]; 1020 return dictionaryTypeMask.typeMap[key];
1026 } else { 1021 } else {
1027 // The typeMap is precise, so if we do not find the key, the lookup 1022 // The typeMap is precise, so if we do not find the key, the lookup
1028 // will be [null] at runtime. 1023 // will be [null] at runtime.
1029 if (debug.VERBOSE) { 1024 if (debug.VERBOSE) {
1030 print("Dictionary lookup for $key yields [null]."); 1025 print("Dictionary lookup for $key yields [null].");
1031 } 1026 }
1032 return inferrer.types.nullType.type; 1027 return inferrer.types.nullType.type;
1033 } 1028 }
1034 } 1029 }
1035 MapTypeMask mapTypeMask = typeMask; 1030 MapTypeMask mapTypeMask = typeMask;
1036 if (debug.VERBOSE) { 1031 if (debug.VERBOSE) {
1037 print( 1032 print("Map lookup for $selector yields ${mapTypeMask.valueType}.");
1038 "Map lookup for $selector yields ${mapTypeMask.valueType}.");
1039 } 1033 }
1040 return mapTypeMask.valueType; 1034 return mapTypeMask.valueType;
1041 } else { 1035 } else {
1042 TypeInformation info = 1036 TypeInformation info =
1043 handleIntrisifiedSelector(selector, typeMask, inferrer); 1037 handleIntrisifiedSelector(selector, typeMask, inferrer);
1044 if (info != null) return info.type; 1038 if (info != null) return info.type;
1045 return inferrer.typeOfElementWithSelector(element, selector).type; 1039 return inferrer.typeOfElementWithSelector(element, selector).type;
1046 } 1040 }
1047 })); 1041 }));
1048 1042
(...skipping 11 matching lines...) Expand all
1060 if (!abandonInferencing) { 1054 if (!abandonInferencing) {
1061 inferrer.updateSelectorInTree(caller, call, selector, mask); 1055 inferrer.updateSelectorInTree(caller, call, selector, mask);
1062 Iterable<Element> oldTargets = targets; 1056 Iterable<Element> oldTargets = targets;
1063 targets = inferrer.compiler.world.allFunctions.filter(selector, mask); 1057 targets = inferrer.compiler.world.allFunctions.filter(selector, mask);
1064 for (Element element in targets) { 1058 for (Element element in targets) {
1065 if (!oldTargets.contains(element)) { 1059 if (!oldTargets.contains(element)) {
1066 MemberTypeInformation callee = 1060 MemberTypeInformation callee =
1067 inferrer.types.getInferredTypeOf(element); 1061 inferrer.types.getInferredTypeOf(element);
1068 callee.addCall(caller, call); 1062 callee.addCall(caller, call);
1069 inferrer.updateParameterAssignments( 1063 inferrer.updateParameterAssignments(
1070 this, element, arguments, selector, mask, remove: false, 1064 this, element, arguments, selector, mask,
1071 addToQueue: true); 1065 remove: false, addToQueue: true);
1072 } 1066 }
1073 } 1067 }
1074 } 1068 }
1075 super.giveUp(inferrer, clearAssignments: clearAssignments); 1069 super.giveUp(inferrer, clearAssignments: clearAssignments);
1076 } 1070 }
1077 1071
1078 void removeAndClearReferences(TypeGraphInferrerEngine inferrer) { 1072 void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
1079 for (Element element in targets) { 1073 for (Element element in targets) {
1080 ElementTypeInformation callee = inferrer.types.getInferredTypeOf(element); 1074 ElementTypeInformation callee = inferrer.types.getInferredTypeOf(element);
1081 callee.removeUser(this); 1075 callee.removeUser(this);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 void addUser(TypeInformation user) { 1158 void addUser(TypeInformation user) {
1165 // Nothing to do, a concrete type does not get updated so never 1159 // Nothing to do, a concrete type does not get updated so never
1166 // needs to notify its users. 1160 // needs to notify its users.
1167 } 1161 }
1168 1162
1169 void addUsersOf(TypeInformation other) { 1163 void addUsersOf(TypeInformation other) {
1170 // Nothing to do, a concrete type does not get updated so never 1164 // Nothing to do, a concrete type does not get updated so never
1171 // needs to notify its users. 1165 // needs to notify its users.
1172 } 1166 }
1173 1167
1174 void removeUser(TypeInformation user) { 1168 void removeUser(TypeInformation user) {}
1175 }
1176 1169
1177 void addAssignment(TypeInformation assignment) { 1170 void addAssignment(TypeInformation assignment) {
1178 throw "Not supported"; 1171 throw "Not supported";
1179 } 1172 }
1180 1173
1181 void removeAssignment(TypeInformation assignment) { 1174 void removeAssignment(TypeInformation assignment) {
1182 throw "Not supported"; 1175 throw "Not supported";
1183 } 1176 }
1184 1177
1185 TypeMask computeType(TypeGraphInferrerEngine inferrer) => type; 1178 TypeMask computeType(TypeGraphInferrerEngine inferrer) => type;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1254 addAssignment(narrowedType); 1247 addAssignment(narrowedType);
1255 } 1248 }
1256 1249
1257 addAssignment(TypeInformation info) { 1250 addAssignment(TypeInformation info) {
1258 super.addAssignment(info); 1251 super.addAssignment(info);
1259 assert(assignments.length == 1); 1252 assert(assignments.length == 1);
1260 } 1253 }
1261 1254
1262 TypeMask computeType(TypeGraphInferrerEngine inferrer) { 1255 TypeMask computeType(TypeGraphInferrerEngine inferrer) {
1263 TypeMask input = assignments.first.type; 1256 TypeMask input = assignments.first.type;
1264 TypeMask intersection = input.intersection(typeAnnotation, 1257 TypeMask intersection =
1265 inferrer.classWorld); 1258 input.intersection(typeAnnotation, inferrer.classWorld);
1266 if (debug.ANOMALY_WARN) { 1259 if (debug.ANOMALY_WARN) {
1267 if (!input.containsMask(intersection, inferrer.classWorld) || 1260 if (!input.containsMask(intersection, inferrer.classWorld) ||
1268 !typeAnnotation.containsMask(intersection, inferrer.classWorld)) { 1261 !typeAnnotation.containsMask(intersection, inferrer.classWorld)) {
1269 print("ANOMALY WARNING: narrowed $input to $intersection via " 1262 print("ANOMALY WARNING: narrowed $input to $intersection via "
1270 "$typeAnnotation"); 1263 "$typeAnnotation");
1271 } 1264 }
1272 } 1265 }
1273 return intersection; 1266 return intersection;
1274 } 1267 }
1275 1268
1276 String toString() { 1269 String toString() {
1277 return 'Narrow to $typeAnnotation $type'; 1270 return 'Narrow to $typeAnnotation $type';
1278 } 1271 }
1279 1272
1280 accept(TypeInformationVisitor visitor) { 1273 accept(TypeInformationVisitor visitor) {
1281 return visitor.visitNarrowTypeInformation(this); 1274 return visitor.visitNarrowTypeInformation(this);
1282 } 1275 }
1283 } 1276 }
1284 1277
1285 /** 1278 /**
1286 * An [InferredTypeInformation] is a [TypeInformation] that 1279 * An [InferredTypeInformation] is a [TypeInformation] that
1287 * defaults to the dynamic type until it is marked as beeing 1280 * defaults to the dynamic type until it is marked as beeing
1288 * inferred, at which point it computes its type based on 1281 * inferred, at which point it computes its type based on
1289 * its assignments. 1282 * its assignments.
1290 */ 1283 */
1291 abstract class InferredTypeInformation extends TypeInformation { 1284 abstract class InferredTypeInformation extends TypeInformation {
1292 /** Whether the element type in that container has been inferred. */ 1285 /** Whether the element type in that container has been inferred. */
1293 bool inferred = false; 1286 bool inferred = false;
1294 1287
1295 InferredTypeInformation(MemberTypeInformation context, 1288 InferredTypeInformation(
1296 TypeInformation parentType) 1289 MemberTypeInformation context, TypeInformation parentType)
1297 : super(context) { 1290 : super(context) {
1298 if (parentType != null) addAssignment(parentType); 1291 if (parentType != null) addAssignment(parentType);
1299 } 1292 }
1300 1293
1301 TypeMask computeType(TypeGraphInferrerEngine inferrer) { 1294 TypeMask computeType(TypeGraphInferrerEngine inferrer) {
1302 if (!inferred) return safeType(inferrer); 1295 if (!inferred) return safeType(inferrer);
1303 return inferrer.types.computeTypeMask(assignments); 1296 return inferrer.types.computeTypeMask(assignments);
1304 } 1297 }
1305 1298
1306 bool hasStableType(TypeGraphInferrerEngine inferrer) { 1299 bool hasStableType(TypeGraphInferrerEngine inferrer) {
1307 return inferred && super.hasStableType(inferrer); 1300 return inferred && super.hasStableType(inferrer);
1308 } 1301 }
1309 } 1302 }
1310 1303
1311 /** 1304 /**
1312 * A [ListTypeInformation] is a [TypeInformation] created 1305 * A [ListTypeInformation] is a [TypeInformation] created
1313 * for each `List` instantiations. 1306 * for each `List` instantiations.
1314 */ 1307 */
1315 class ListTypeInformation extends TypeInformation 1308 class ListTypeInformation extends TypeInformation with TracedTypeInformation {
1316 with TracedTypeInformation {
1317 final ElementInContainerTypeInformation elementType; 1309 final ElementInContainerTypeInformation elementType;
1318 1310
1319 /** The container type before it is inferred. */ 1311 /** The container type before it is inferred. */
1320 final ContainerTypeMask originalType; 1312 final ContainerTypeMask originalType;
1321 1313
1322 /** The length at the allocation site. */ 1314 /** The length at the allocation site. */
1323 final int originalLength; 1315 final int originalLength;
1324 1316
1325 /** The length after the container has been traced. */ 1317 /** The length after the container has been traced. */
1326 int inferredLength; 1318 int inferredLength;
1327 1319
1328 /** 1320 /**
1329 * Whether this list goes through a growable check. 1321 * Whether this list goes through a growable check.
1330 * We conservatively assume it does. 1322 * We conservatively assume it does.
1331 */ 1323 */
1332 bool checksGrowable = true; 1324 bool checksGrowable = true;
1333 1325
1334 ListTypeInformation(MemberTypeInformation context, 1326 ListTypeInformation(MemberTypeInformation context, this.originalType,
1335 this.originalType, 1327 this.elementType, this.originalLength)
1336 this.elementType,
1337 this.originalLength)
1338 : super(context) { 1328 : super(context) {
1339 type = originalType; 1329 type = originalType;
1340 inferredLength = originalType.length; 1330 inferredLength = originalType.length;
1341 elementType.addUser(this); 1331 elementType.addUser(this);
1342 } 1332 }
1343 1333
1344 String toString() => 'List type $type'; 1334 String toString() => 'List type $type';
1345 1335
1346 accept(TypeInformationVisitor visitor) { 1336 accept(TypeInformationVisitor visitor) {
1347 return visitor.visitListTypeInformation(this); 1337 return visitor.visitListTypeInformation(this);
1348 } 1338 }
1349 1339
1350 bool hasStableType(TypeGraphInferrerEngine inferrer) { 1340 bool hasStableType(TypeGraphInferrerEngine inferrer) {
1351 return elementType.isStable && super.hasStableType(inferrer); 1341 return elementType.isStable && super.hasStableType(inferrer);
1352 } 1342 }
1353 1343
1354 TypeMask computeType(TypeGraphInferrerEngine inferrer) { 1344 TypeMask computeType(TypeGraphInferrerEngine inferrer) {
1355 var mask = type; 1345 var mask = type;
1356 if (!mask.isContainer || 1346 if (!mask.isContainer ||
1357 mask.elementType != elementType.type || 1347 mask.elementType != elementType.type ||
1358 mask.length != inferredLength) { 1348 mask.length != inferredLength) {
1359 return new ContainerTypeMask(originalType.forwardTo, 1349 return new ContainerTypeMask(
1360 originalType.allocationNode, 1350 originalType.forwardTo,
1361 originalType.allocationElement, 1351 originalType.allocationNode,
1362 elementType.type, 1352 originalType.allocationElement,
1363 inferredLength); 1353 elementType.type,
1354 inferredLength);
1364 } 1355 }
1365 return mask; 1356 return mask;
1366 } 1357 }
1367 1358
1368 TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType; 1359 TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType;
1369 1360
1370 void cleanup() { 1361 void cleanup() {
1371 super.cleanup(); 1362 super.cleanup();
1372 elementType.cleanup(); 1363 elementType.cleanup();
1373 _flowsInto = null; 1364 _flowsInto = null;
1374 } 1365 }
1375 } 1366 }
1376 1367
1377 /** 1368 /**
1378 * An [ElementInContainerTypeInformation] holds the common type of the 1369 * An [ElementInContainerTypeInformation] holds the common type of the
1379 * elements in a [ListTypeInformation]. 1370 * elements in a [ListTypeInformation].
1380 */ 1371 */
1381 class ElementInContainerTypeInformation extends InferredTypeInformation { 1372 class ElementInContainerTypeInformation extends InferredTypeInformation {
1382 ElementInContainerTypeInformation(MemberTypeInformation context, 1373 ElementInContainerTypeInformation(MemberTypeInformation context, elementType)
1383 elementType)
1384 : super(context, elementType); 1374 : super(context, elementType);
1385 1375
1386 String toString() => 'Element in container $type'; 1376 String toString() => 'Element in container $type';
1387 1377
1388 accept(TypeInformationVisitor visitor) { 1378 accept(TypeInformationVisitor visitor) {
1389 return visitor.visitElementInContainerTypeInformation(this); 1379 return visitor.visitElementInContainerTypeInformation(this);
1390 } 1380 }
1391 } 1381 }
1392 1382
1393 /** 1383 /**
1394 * A [MapTypeInformation] is a [TypeInformation] created 1384 * A [MapTypeInformation] is a [TypeInformation] created
1395 * for maps. 1385 * for maps.
1396 */ 1386 */
1397 class MapTypeInformation extends TypeInformation 1387 class MapTypeInformation extends TypeInformation with TracedTypeInformation {
1398 with TracedTypeInformation {
1399 // When in Dictionary mode, this map tracks the type of the values that 1388 // When in Dictionary mode, this map tracks the type of the values that
1400 // have been assigned to a specific [String] key. 1389 // have been assigned to a specific [String] key.
1401 final Map<String, ValueInMapTypeInformation> typeInfoMap = {}; 1390 final Map<String, ValueInMapTypeInformation> typeInfoMap = {};
1402 // These fields track the overall type of the keys/values in the map. 1391 // These fields track the overall type of the keys/values in the map.
1403 final KeyInMapTypeInformation keyType; 1392 final KeyInMapTypeInformation keyType;
1404 final ValueInMapTypeInformation valueType; 1393 final ValueInMapTypeInformation valueType;
1405 final MapTypeMask originalType; 1394 final MapTypeMask originalType;
1406 1395
1407 // Set to false if a statically unknown key flows into this map. 1396 // Set to false if a statically unknown key flows into this map.
1408 bool _allKeysAreStrings = true; 1397 bool _allKeysAreStrings = true;
1409 1398
1410 bool get inDictionaryMode => !bailedOut && _allKeysAreStrings; 1399 bool get inDictionaryMode => !bailedOut && _allKeysAreStrings;
1411 1400
1412 MapTypeInformation(MemberTypeInformation context, 1401 MapTypeInformation(MemberTypeInformation context, this.originalType,
1413 this.originalType, 1402 this.keyType, this.valueType)
1414 this.keyType,
1415 this.valueType)
1416 : super(context) { 1403 : super(context) {
1417 keyType.addUser(this); 1404 keyType.addUser(this);
1418 valueType.addUser(this); 1405 valueType.addUser(this);
1419 type = originalType; 1406 type = originalType;
1420 } 1407 }
1421 1408
1422 TypeInformation addEntryAssignment(TypeInformation key, 1409 TypeInformation addEntryAssignment(TypeInformation key, TypeInformation value,
1423 TypeInformation value, 1410 [bool nonNull = false]) {
1424 [bool nonNull = false]) {
1425 TypeInformation newInfo = null; 1411 TypeInformation newInfo = null;
1426 if (_allKeysAreStrings && key is StringLiteralTypeInformation) { 1412 if (_allKeysAreStrings && key is StringLiteralTypeInformation) {
1427 String keyString = key.asString(); 1413 String keyString = key.asString();
1428 typeInfoMap.putIfAbsent(keyString, () { 1414 typeInfoMap.putIfAbsent(keyString, () {
1429 newInfo = new ValueInMapTypeInformation(context, null, nonNull); 1415 newInfo = new ValueInMapTypeInformation(context, null, nonNull);
1430 return newInfo; 1416 return newInfo;
1431 }); 1417 });
1432 typeInfoMap[keyString].addAssignment(value); 1418 typeInfoMap[keyString].addAssignment(value);
1433 } else { 1419 } else {
1434 _allKeysAreStrings = false; 1420 _allKeysAreStrings = false;
1435 typeInfoMap.clear(); 1421 typeInfoMap.clear();
1436 } 1422 }
1437 keyType.addAssignment(key); 1423 keyType.addAssignment(key);
1438 valueType.addAssignment(value); 1424 valueType.addAssignment(value);
1439 if (newInfo != null) newInfo.addUser(this); 1425 if (newInfo != null) newInfo.addUser(this);
1440 1426
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1475 accept(TypeInformationVisitor visitor) { 1461 accept(TypeInformationVisitor visitor) {
1476 return visitor.visitMapTypeInformation(this); 1462 return visitor.visitMapTypeInformation(this);
1477 } 1463 }
1478 1464
1479 TypeMask toTypeMask(TypeGraphInferrerEngine inferrer) { 1465 TypeMask toTypeMask(TypeGraphInferrerEngine inferrer) {
1480 if (inDictionaryMode) { 1466 if (inDictionaryMode) {
1481 Map<String, TypeMask> mappings = new Map<String, TypeMask>(); 1467 Map<String, TypeMask> mappings = new Map<String, TypeMask>();
1482 for (var key in typeInfoMap.keys) { 1468 for (var key in typeInfoMap.keys) {
1483 mappings[key] = typeInfoMap[key].type; 1469 mappings[key] = typeInfoMap[key].type;
1484 } 1470 }
1485 return new DictionaryTypeMask(originalType.forwardTo, 1471 return new DictionaryTypeMask(
1486 originalType.allocationNode, 1472 originalType.forwardTo,
1487 originalType.allocationElement, 1473 originalType.allocationNode,
1488 keyType.type, 1474 originalType.allocationElement,
1489 valueType.type, 1475 keyType.type,
1490 mappings); 1476 valueType.type,
1477 mappings);
1491 } else { 1478 } else {
1492 return new MapTypeMask(originalType.forwardTo, 1479 return new MapTypeMask(
1493 originalType.allocationNode, 1480 originalType.forwardTo,
1494 originalType.allocationElement, 1481 originalType.allocationNode,
1495 keyType.type, 1482 originalType.allocationElement,
1496 valueType.type); 1483 keyType.type,
1484 valueType.type);
1497 } 1485 }
1498 } 1486 }
1499 1487
1500 TypeMask computeType(TypeGraphInferrerEngine inferrer) { 1488 TypeMask computeType(TypeGraphInferrerEngine inferrer) {
1501 if (type.isDictionary != inDictionaryMode) { 1489 if (type.isDictionary != inDictionaryMode) {
1502 return toTypeMask(inferrer); 1490 return toTypeMask(inferrer);
1503 } else if (type.isDictionary) { 1491 } else if (type.isDictionary) {
1504 assert(inDictionaryMode); 1492 assert(inDictionaryMode);
1505 DictionaryTypeMask mask = type; 1493 DictionaryTypeMask mask = type;
1506 for (var key in typeInfoMap.keys) { 1494 for (var key in typeInfoMap.keys) {
1507 TypeInformation value = typeInfoMap[key]; 1495 TypeInformation value = typeInfoMap[key];
1508 if (!mask.typeMap.containsKey(key) && 1496 if (!mask.typeMap.containsKey(key) &&
1509 !value.type.containsAll(inferrer.classWorld) && 1497 !value.type.containsAll(inferrer.classWorld) &&
1510 !value.type.isNullable) { 1498 !value.type.isNullable) {
1511 return toTypeMask(inferrer); 1499 return toTypeMask(inferrer);
1512 } 1500 }
1513 if (mask.typeMap[key] != typeInfoMap[key].type) { 1501 if (mask.typeMap[key] != typeInfoMap[key].type) {
1514 return toTypeMask(inferrer); 1502 return toTypeMask(inferrer);
1515 } 1503 }
1516 } 1504 }
1517 } else if (type.isMap) { 1505 } else if (type.isMap) {
1518 MapTypeMask mask = type; 1506 MapTypeMask mask = type;
1519 if (mask.keyType != keyType.type || 1507 if (mask.keyType != keyType.type || mask.valueType != valueType.type) {
1520 mask.valueType != valueType.type) {
1521 return toTypeMask(inferrer); 1508 return toTypeMask(inferrer);
1522 } 1509 }
1523 } else { 1510 } else {
1524 return toTypeMask(inferrer); 1511 return toTypeMask(inferrer);
1525 } 1512 }
1526 1513
1527 return type; 1514 return type;
1528 } 1515 }
1529 1516
1530 TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType; 1517 TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType;
1531 1518
1532 bool hasStableType(TypeGraphInferrerEngine inferrer) { 1519 bool hasStableType(TypeGraphInferrerEngine inferrer) {
1533 return keyType.isStable && 1520 return keyType.isStable &&
1534 valueType.isStable && 1521 valueType.isStable &&
1535 super.hasStableType(inferrer); 1522 super.hasStableType(inferrer);
1536 } 1523 }
1537 1524
1538 void cleanup() { 1525 void cleanup() {
1539 super.cleanup(); 1526 super.cleanup();
1540 keyType.cleanup(); 1527 keyType.cleanup();
1541 valueType.cleanup(); 1528 valueType.cleanup();
1542 for (TypeInformation info in typeInfoMap.values) { 1529 for (TypeInformation info in typeInfoMap.values) {
1543 info.cleanup(); 1530 info.cleanup();
1544 } 1531 }
1545 _flowsInto = null; 1532 _flowsInto = null;
1546 } 1533 }
1547 1534
1548 String toString() { 1535 String toString() {
1549 return 'Map $type (K:$keyType, V:$valueType) contents $typeInfoMap'; 1536 return 'Map $type (K:$keyType, V:$valueType) contents $typeInfoMap';
1550 } 1537 }
1551 } 1538 }
1552 1539
1553 /** 1540 /**
1554 * A [KeyInMapTypeInformation] holds the common type 1541 * A [KeyInMapTypeInformation] holds the common type
1555 * for the keys in a [MapTypeInformation] 1542 * for the keys in a [MapTypeInformation]
1556 */ 1543 */
1557 class KeyInMapTypeInformation extends InferredTypeInformation { 1544 class KeyInMapTypeInformation extends InferredTypeInformation {
1558 KeyInMapTypeInformation(MemberTypeInformation context, 1545 KeyInMapTypeInformation(
1559 TypeInformation keyType) 1546 MemberTypeInformation context, TypeInformation keyType)
1560 : super(context, keyType); 1547 : super(context, keyType);
1561 1548
1562 accept(TypeInformationVisitor visitor) { 1549 accept(TypeInformationVisitor visitor) {
1563 return visitor.visitKeyInMapTypeInformation(this); 1550 return visitor.visitKeyInMapTypeInformation(this);
1564 } 1551 }
1565 1552
1566 String toString() => 'Key in Map $type'; 1553 String toString() => 'Key in Map $type';
1567 } 1554 }
1568 1555
1569 /** 1556 /**
1570 * A [ValueInMapTypeInformation] holds the common type 1557 * A [ValueInMapTypeInformation] holds the common type
1571 * for the values in a [MapTypeInformation] 1558 * for the values in a [MapTypeInformation]
1572 */ 1559 */
1573 class ValueInMapTypeInformation extends InferredTypeInformation { 1560 class ValueInMapTypeInformation extends InferredTypeInformation {
1574 // [nonNull] is set to true if this value is known to be part of the map. 1561 // [nonNull] is set to true if this value is known to be part of the map.
1575 // Note that only values assigned to a specific key value in dictionary 1562 // Note that only values assigned to a specific key value in dictionary
1576 // mode can ever be marked as [nonNull]. 1563 // mode can ever be marked as [nonNull].
1577 final bool nonNull; 1564 final bool nonNull;
1578 1565
1579 ValueInMapTypeInformation(MemberTypeInformation context, 1566 ValueInMapTypeInformation(
1580 TypeInformation valueType, [this.nonNull = false]) 1567 MemberTypeInformation context, TypeInformation valueType,
1568 [this.nonNull = false])
1581 : super(context, valueType); 1569 : super(context, valueType);
1582 1570
1583 accept(TypeInformationVisitor visitor) { 1571 accept(TypeInformationVisitor visitor) {
1584 return visitor.visitValueInMapTypeInformation(this); 1572 return visitor.visitValueInMapTypeInformation(this);
1585 } 1573 }
1586 1574
1587 TypeMask computeType(TypeGraphInferrerEngine inferrer) { 1575 TypeMask computeType(TypeGraphInferrerEngine inferrer) {
1588 return nonNull ? super.computeType(inferrer) 1576 return nonNull
1589 : super.computeType(inferrer).nullable(); 1577 ? super.computeType(inferrer)
1578 : super.computeType(inferrer).nullable();
1590 } 1579 }
1591 1580
1592 String toString() => 'Value in Map $type'; 1581 String toString() => 'Value in Map $type';
1593 } 1582 }
1594 1583
1595 /** 1584 /**
1596 * A [PhiElementTypeInformation] is an union of 1585 * A [PhiElementTypeInformation] is an union of
1597 * [ElementTypeInformation], that is local to a method. 1586 * [ElementTypeInformation], that is local to a method.
1598 */ 1587 */
1599 class PhiElementTypeInformation extends TypeInformation { 1588 class PhiElementTypeInformation extends TypeInformation {
1600 final ast.Node branchNode; 1589 final ast.Node branchNode;
1601 final bool isLoopPhi; 1590 final bool isLoopPhi;
1602 final Local variable; 1591 final Local variable;
1603 1592
1604 PhiElementTypeInformation(MemberTypeInformation context, this.branchNode, 1593 PhiElementTypeInformation(MemberTypeInformation context, this.branchNode,
1605 this.isLoopPhi, this.variable) 1594 this.isLoopPhi, this.variable)
1606 : super(context); 1595 : super(context);
1607 1596
1608 TypeMask computeType(TypeGraphInferrerEngine inferrer) { 1597 TypeMask computeType(TypeGraphInferrerEngine inferrer) {
1609 return inferrer.types.computeTypeMask(assignments); 1598 return inferrer.types.computeTypeMask(assignments);
1610 } 1599 }
1611 1600
1612 String toString() => 'Phi $variable $type'; 1601 String toString() => 'Phi $variable $type';
1613 1602
1614 accept(TypeInformationVisitor visitor) { 1603 accept(TypeInformationVisitor visitor) {
1615 return visitor.visitPhiElementTypeInformation(this); 1604 return visitor.visitPhiElementTypeInformation(this);
1616 } 1605 }
1617 } 1606 }
1618 1607
1619 class ClosureTypeInformation extends TypeInformation 1608 class ClosureTypeInformation extends TypeInformation
1620 with ApplyableTypeInformation { 1609 with ApplyableTypeInformation {
1621 final ast.Node node; 1610 final ast.Node node;
1622 final Element element; 1611 final Element element;
1623 1612
1624 ClosureTypeInformation(MemberTypeInformation context, this.node, 1613 ClosureTypeInformation(MemberTypeInformation context, this.node, this.element)
1625 this.element)
1626 : super(context); 1614 : super(context);
1627 1615
1628 TypeMask computeType(TypeGraphInferrerEngine inferrer) => safeType(inferrer); 1616 TypeMask computeType(TypeGraphInferrerEngine inferrer) => safeType(inferrer);
1629 1617
1630 TypeMask safeType(TypeGraphInferrerEngine inferrer) { 1618 TypeMask safeType(TypeGraphInferrerEngine inferrer) {
1631 return inferrer.types.functionType.type; 1619 return inferrer.types.functionType.type;
1632 } 1620 }
1633 1621
1634 String toString() => 'Closure $element'; 1622 String toString() => 'Closure $element';
1635 1623
1636 accept(TypeInformationVisitor visitor) { 1624 accept(TypeInformationVisitor visitor) {
1637 return visitor.visitClosureTypeInformation(this); 1625 return visitor.visitClosureTypeInformation(this);
1638 } 1626 }
1639 1627
1640 bool hasStableType(TypeGraphInferrerEngine inferrer) { 1628 bool hasStableType(TypeGraphInferrerEngine inferrer) {
1641 return false; 1629 return false;
1642 } 1630 }
1643 } 1631 }
1644 1632
1645 /** 1633 /**
1646 * Mixin for [TypeInformation] nodes that can bail out during tracing. 1634 * Mixin for [TypeInformation] nodes that can bail out during tracing.
1647 */ 1635 */
1648 abstract class TracedTypeInformation implements TypeInformation { 1636 abstract class TracedTypeInformation implements TypeInformation {
1649 /// Set to false once analysis has succeeded. 1637 /// Set to false once analysis has succeeded.
1650 bool bailedOut = true; 1638 bool bailedOut = true;
1639
1651 /// Set to true once analysis is completed. 1640 /// Set to true once analysis is completed.
1652 bool analyzed = false; 1641 bool analyzed = false;
1653 1642
1654 Set<TypeInformation> _flowsInto; 1643 Set<TypeInformation> _flowsInto;
1655 1644
1656 /** 1645 /**
1657 * The set of [TypeInformation] nodes where values from the traced node could 1646 * The set of [TypeInformation] nodes where values from the traced node could
1658 * flow in. 1647 * flow in.
1659 */ 1648 */
1660 Set<TypeInformation> get flowsInto { 1649 Set<TypeInformation> get flowsInto {
1661 return (_flowsInto == null) ? const ImmutableEmptySet<TypeInformation>() 1650 return (_flowsInto == null)
1662 : _flowsInto; 1651 ? const ImmutableEmptySet<TypeInformation>()
1652 : _flowsInto;
1663 } 1653 }
1664 1654
1665 /** 1655 /**
1666 * Adds [nodes] to the sets of values this [TracedTypeInformation] flows into. 1656 * Adds [nodes] to the sets of values this [TracedTypeInformation] flows into.
1667 */ 1657 */
1668 void addFlowsIntoTargets(Iterable<TypeInformation> nodes) { 1658 void addFlowsIntoTargets(Iterable<TypeInformation> nodes) {
1669 if (_flowsInto == null) { 1659 if (_flowsInto == null) {
1670 _flowsInto = nodes.toSet(); 1660 _flowsInto = nodes.toSet();
1671 } else { 1661 } else {
1672 _flowsInto.addAll(nodes); 1662 _flowsInto.addAll(nodes);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1724 } else if (annotation.isVoid) { 1714 } else if (annotation.isVoid) {
1725 otherType = compiler.typesTask.nullType; 1715 otherType = compiler.typesTask.nullType;
1726 } else { 1716 } else {
1727 assert(annotation.isInterfaceType); 1717 assert(annotation.isInterfaceType);
1728 otherType = new TypeMask.nonNullSubtype(annotation.element, compiler.world); 1718 otherType = new TypeMask.nonNullSubtype(annotation.element, compiler.world);
1729 } 1719 }
1730 if (isNullable) otherType = otherType.nullable(); 1720 if (isNullable) otherType = otherType.nullable();
1731 if (type == null) return otherType; 1721 if (type == null) return otherType;
1732 return type.intersection(otherType, compiler.world); 1722 return type.intersection(otherType, compiler.world);
1733 } 1723 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart ('k') | pkg/compiler/lib/src/info/naive_analysis_result.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698