OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 dart2js.world; | 5 library dart2js.world; |
6 | 6 |
| 7 import 'cache_strategy.dart'; |
7 import 'closure.dart' show SynthesizedCallMethodElementX; | 8 import 'closure.dart' show SynthesizedCallMethodElementX; |
8 import 'common/backend_api.dart' show BackendClasses; | 9 import 'common/backend_api.dart' show BackendClasses; |
9 import 'common.dart'; | 10 import 'common.dart'; |
10 import 'compiler.dart' show Compiler; | |
11 import 'core_types.dart' show CoreClasses; | 11 import 'core_types.dart' show CoreClasses; |
12 import 'dart_types.dart'; | 12 import 'dart_types.dart'; |
13 import 'elements/elements.dart' | 13 import 'elements/elements.dart' |
14 show | 14 show |
15 ClassElement, | 15 ClassElement, |
16 Element, | 16 Element, |
17 FunctionElement, | 17 FunctionElement, |
18 MixinApplicationElement, | 18 MixinApplicationElement, |
19 TypedefElement, | 19 TypedefElement, |
20 FieldElement; | 20 FieldElement; |
21 import 'js_backend/backend.dart' show JavaScriptBackend; | 21 import 'js_backend/backend.dart' show JavaScriptBackend; |
22 import 'ordered_typeset.dart'; | 22 import 'ordered_typeset.dart'; |
23 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask; | 23 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask; |
24 import 'universe/class_set.dart'; | 24 import 'universe/class_set.dart'; |
25 import 'universe/function_set.dart' show FunctionSet; | 25 import 'universe/function_set.dart' show FunctionSet; |
26 import 'universe/selector.dart' show Selector; | 26 import 'universe/selector.dart' show Selector; |
27 import 'universe/side_effects.dart' show SideEffects; | 27 import 'universe/side_effects.dart' show SideEffects; |
| 28 import 'universe/world_builder.dart' show ResolutionWorldBuilder; |
28 import 'util/enumset.dart'; | 29 import 'util/enumset.dart'; |
29 import 'util/util.dart' show Link; | 30 import 'util/util.dart' show Link; |
30 | 31 |
31 /// Common superinterface for [OpenWorld] and [ClosedWorld]. | 32 /// Common superinterface for [OpenWorld] and [ClosedWorld]. |
32 abstract class World {} | 33 abstract class World {} |
33 | 34 |
34 /// The [ClosedWorld] represents the information known about a program when | 35 /// The [ClosedWorld] represents the information known about a program when |
35 /// compiling with closed-world semantics. | 36 /// compiling with closed-world semantics. |
36 /// | 37 /// |
37 /// Given the entrypoint of an application, we can track what's reachable from | 38 /// Given the entrypoint of an application, we can track what's reachable from |
38 /// it, what functions are called, what classes are allocated, which native | 39 /// it, what functions are called, what classes are allocated, which native |
39 /// JavaScript types are touched, what language features are used, and so on. | 40 /// JavaScript types are touched, what language features are used, and so on. |
40 /// This precise knowledge about what's live in the program is later used in | 41 /// This precise knowledge about what's live in the program is later used in |
41 /// optimizations and other compiler decisions during code generation. | 42 /// optimizations and other compiler decisions during code generation. |
42 abstract class ClosedWorld implements World { | 43 abstract class ClosedWorld implements World { |
43 /// Access to core classes used by the backend. | 44 /// Access to core classes used by the backend. |
44 BackendClasses get backendClasses; | 45 BackendClasses get backendClasses; |
45 | 46 |
46 /// Access to core classes used in the Dart language. | 47 /// Access to core classes used in the Dart language. |
47 CoreClasses get coreClasses; | 48 CoreClasses get coreClasses; |
48 | 49 |
| 50 CommonMasks get commonMasks; |
| 51 |
49 /// Returns `true` if [cls] is either directly or indirectly instantiated. | 52 /// Returns `true` if [cls] is either directly or indirectly instantiated. |
50 bool isInstantiated(ClassElement cls); | 53 bool isInstantiated(ClassElement cls); |
51 | 54 |
52 /// Returns `true` if [cls] is directly instantiated. This means that at | 55 /// Returns `true` if [cls] is directly instantiated. This means that at |
53 /// runtime instances of exactly [cls] are assumed to exist. | 56 /// runtime instances of exactly [cls] are assumed to exist. |
54 bool isDirectlyInstantiated(ClassElement cls); | 57 bool isDirectlyInstantiated(ClassElement cls); |
55 | 58 |
56 /// Returns `true` if [cls] is abstractly instantiated. This means that at | 59 /// Returns `true` if [cls] is abstractly instantiated. This means that at |
57 /// runtime instances of [cls] or unknown subclasses of [cls] are assumed to | 60 /// runtime instances of [cls] or unknown subclasses of [cls] are assumed to |
58 /// exist. | 61 /// exist. |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 abstract class OpenWorld implements World { | 330 abstract class OpenWorld implements World { |
328 /// Called to add [cls] to the set of known classes. | 331 /// Called to add [cls] to the set of known classes. |
329 /// | 332 /// |
330 /// This ensures that class hierarchy queries can be performed on [cls] and | 333 /// This ensures that class hierarchy queries can be performed on [cls] and |
331 /// classes that extend or implement it. | 334 /// classes that extend or implement it. |
332 void registerClass(ClassElement cls); | 335 void registerClass(ClassElement cls); |
333 | 336 |
334 void registerUsedElement(Element element); | 337 void registerUsedElement(Element element); |
335 void registerTypedef(TypedefElement typedef); | 338 void registerTypedef(TypedefElement typedef); |
336 | 339 |
337 ClosedWorld closeWorld(); | 340 ClosedWorld closeWorld(DiagnosticReporter reporter); |
338 | 341 |
339 /// Returns an iterable over all mixin applications that mixin [cls]. | 342 /// Returns an iterable over all mixin applications that mixin [cls]. |
340 Iterable<MixinApplicationElement> allMixinUsesOf(ClassElement cls); | 343 Iterable<MixinApplicationElement> allMixinUsesOf(ClassElement cls); |
341 } | 344 } |
342 | 345 |
343 class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { | 346 class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { |
344 bool _closed = false; | 347 bool _closed = false; |
345 | 348 |
346 TypeMask getCachedMask(ClassElement base, int flags, TypeMask createMask()) { | 349 TypeMask getCachedMask(ClassElement base, int flags, TypeMask createMask()) { |
347 Map<ClassElement, TypeMask> cachedMasks = | 350 Map<ClassElement, TypeMask> cachedMasks = |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; | 433 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; |
431 return node != null && node.isIndirectlyInstantiated; | 434 return node != null && node.isIndirectlyInstantiated; |
432 } | 435 } |
433 | 436 |
434 @override | 437 @override |
435 bool isAbstract(ClassElement cls) => cls.isAbstract; | 438 bool isAbstract(ClassElement cls) => cls.isAbstract; |
436 | 439 |
437 /// Returns `true` if [cls] is implemented by an instantiated class. | 440 /// Returns `true` if [cls] is implemented by an instantiated class. |
438 bool isImplemented(ClassElement cls) { | 441 bool isImplemented(ClassElement cls) { |
439 assert(isClosed); | 442 assert(isClosed); |
440 return _compiler.resolverWorld.isImplemented(cls); | 443 return resolverWorld.isImplemented(cls); |
441 } | 444 } |
442 | 445 |
443 /// Returns an iterable over the directly instantiated classes that extend | 446 /// Returns an iterable over the directly instantiated classes that extend |
444 /// [cls] possibly including [cls] itself, if it is live. | 447 /// [cls] possibly including [cls] itself, if it is live. |
445 Iterable<ClassElement> subclassesOf(ClassElement cls) { | 448 Iterable<ClassElement> subclassesOf(ClassElement cls) { |
446 assert(isClosed); | 449 assert(isClosed); |
447 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; | 450 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; |
448 if (hierarchy == null) return const <ClassElement>[]; | 451 if (hierarchy == null) return const <ClassElement>[]; |
449 return hierarchy | 452 return hierarchy |
450 .subclassesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED); | 453 .subclassesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED); |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
829 return subclassesNeedNoSuchMethod(node); | 832 return subclassesNeedNoSuchMethod(node); |
830 } else { | 833 } else { |
831 if (subclassesNeedNoSuchMethod(node)) return true; | 834 if (subclassesNeedNoSuchMethod(node)) return true; |
832 for (ClassHierarchyNode subtypeNode in classSet.subtypeNodes) { | 835 for (ClassHierarchyNode subtypeNode in classSet.subtypeNodes) { |
833 if (subclassesNeedNoSuchMethod(subtypeNode)) return true; | 836 if (subclassesNeedNoSuchMethod(subtypeNode)) return true; |
834 } | 837 } |
835 return false; | 838 return false; |
836 } | 839 } |
837 } | 840 } |
838 | 841 |
839 final Compiler _compiler; | 842 final JavaScriptBackend _backend; |
840 BackendClasses get backendClasses => _backend.backendClasses; | 843 BackendClasses get backendClasses => _backend.backendClasses; |
841 JavaScriptBackend get _backend => _compiler.backend; | 844 FunctionSet _allFunctions; |
842 CommonMasks get commonMasks => _compiler.commonMasks; | |
843 final FunctionSet allFunctions; | |
844 final Set<Element> functionsCalledInLoop = new Set<Element>(); | 845 final Set<Element> functionsCalledInLoop = new Set<Element>(); |
845 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>(); | 846 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>(); |
846 | 847 |
847 final Set<TypedefElement> _allTypedefs = new Set<TypedefElement>(); | 848 final Set<TypedefElement> _allTypedefs = new Set<TypedefElement>(); |
848 | 849 |
849 final Map<ClassElement, Set<MixinApplicationElement>> _mixinUses = | 850 final Map<ClassElement, Set<MixinApplicationElement>> _mixinUses = |
850 new Map<ClassElement, Set<MixinApplicationElement>>(); | 851 new Map<ClassElement, Set<MixinApplicationElement>>(); |
851 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses; | 852 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses; |
852 | 853 |
853 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses = | 854 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses = |
(...skipping 10 matching lines...) Expand all Loading... |
864 | 865 |
865 final Set<Element> sideEffectsFreeElements = new Set<Element>(); | 866 final Set<Element> sideEffectsFreeElements = new Set<Element>(); |
866 | 867 |
867 final Set<Element> elementsThatCannotThrow = new Set<Element>(); | 868 final Set<Element> elementsThatCannotThrow = new Set<Element>(); |
868 | 869 |
869 final Set<Element> functionsThatMightBePassedToApply = | 870 final Set<Element> functionsThatMightBePassedToApply = |
870 new Set<FunctionElement>(); | 871 new Set<FunctionElement>(); |
871 | 872 |
872 final Set<Element> alreadyPopulated; | 873 final Set<Element> alreadyPopulated; |
873 | 874 |
| 875 CommonMasks _commonMasks; |
| 876 |
| 877 final CoreClasses coreClasses; |
| 878 |
| 879 final CacheStrategy cacheStrategy; |
| 880 |
| 881 final ResolutionWorldBuilder resolverWorld; |
| 882 |
874 bool get isClosed => _closed; | 883 bool get isClosed => _closed; |
875 | 884 |
876 Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) { | 885 Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) { |
877 return _typesImplementedBySubclasses[cls.declaration]; | 886 return _typesImplementedBySubclasses[cls.declaration]; |
878 } | 887 } |
879 | 888 |
880 WorldImpl(Compiler compiler) | 889 WorldImpl(this.resolverWorld, this._backend, this.coreClasses, |
881 : allFunctions = new FunctionSet(compiler), | 890 CacheStrategy cacheStrategy) |
882 this._compiler = compiler, | 891 : this.cacheStrategy = cacheStrategy, |
883 alreadyPopulated = compiler.cacheStrategy.newSet(); | 892 alreadyPopulated = cacheStrategy.newSet() { |
| 893 _allFunctions = new FunctionSet(this); |
| 894 } |
884 | 895 |
885 CoreClasses get coreClasses => _compiler.coreClasses; | 896 FunctionSet get allFunctions => _allFunctions; |
886 | 897 |
887 DiagnosticReporter get reporter => _compiler.reporter; | 898 CommonMasks get commonMasks { |
| 899 assert(isClosed); |
| 900 return _commonMasks; |
| 901 } |
888 | 902 |
889 /// Called to add [cls] to the set of known classes. | 903 /// Called to add [cls] to the set of known classes. |
890 /// | 904 /// |
891 /// This ensures that class hierarchy queries can be performed on [cls] and | 905 /// This ensures that class hierarchy queries can be performed on [cls] and |
892 /// classes that extend or implement it. | 906 /// classes that extend or implement it. |
893 void registerClass(ClassElement cls) => _registerClass(cls); | 907 void registerClass(ClassElement cls) => _registerClass(cls); |
894 | 908 |
895 void registerClosureClass(ClassElement cls) { | 909 void registerClosureClass(ClassElement cls) { |
896 _registerClass(cls, isDirectlyInstantiated: true); | 910 _registerClass(cls, isDirectlyInstantiated: true); |
897 } | 911 } |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
972 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); | 986 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); |
973 subtypeSet.addSubtype(node); | 987 subtypeSet.addSubtype(node); |
974 } | 988 } |
975 if (!node.isInstantiated && node.parentNode != null) { | 989 if (!node.isInstantiated && node.parentNode != null) { |
976 _updateSuperClassHierarchyNodeForClass(node.parentNode); | 990 _updateSuperClassHierarchyNodeForClass(node.parentNode); |
977 } | 991 } |
978 } | 992 } |
979 | 993 |
980 void _updateClassHierarchyNodeForClass(ClassElement cls, | 994 void _updateClassHierarchyNodeForClass(ClassElement cls, |
981 {bool directlyInstantiated: false, bool abstractlyInstantiated: false}) { | 995 {bool directlyInstantiated: false, bool abstractlyInstantiated: false}) { |
982 ClassHierarchyNode node = getClassHierarchyNode(cls); | 996 ClassHierarchyNode node = _ensureClassHierarchyNode(cls); |
983 _updateSuperClassHierarchyNodeForClass(node); | 997 _updateSuperClassHierarchyNodeForClass(node); |
984 if (directlyInstantiated) { | 998 if (directlyInstantiated) { |
985 node.isDirectlyInstantiated = true; | 999 node.isDirectlyInstantiated = true; |
986 } | 1000 } |
987 if (abstractlyInstantiated) { | 1001 if (abstractlyInstantiated) { |
988 node.isAbstractlyInstantiated = true; | 1002 node.isAbstractlyInstantiated = true; |
989 } | 1003 } |
990 } | 1004 } |
991 | 1005 |
992 ClosedWorld closeWorld() { | 1006 ClosedWorld closeWorld(DiagnosticReporter reporter) { |
993 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` | 1007 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` |
994 /// properties of the [ClassHierarchyNode] for [cls]. | 1008 /// properties of the [ClassHierarchyNode] for [cls]. |
995 | 1009 |
996 void addSubtypes(ClassElement cls, EnumSet<Instantiation> instantiations) { | 1010 void addSubtypes(ClassElement cls, EnumSet<Instantiation> instantiations) { |
997 if (_compiler.options.hasIncrementalSupport && | 1011 if (cacheStrategy.hasIncrementalSupport && !alreadyPopulated.add(cls)) { |
998 !alreadyPopulated.add(cls)) { | |
999 return; | 1012 return; |
1000 } | 1013 } |
1001 assert(cls.isDeclaration); | 1014 assert(cls.isDeclaration); |
1002 if (!cls.isResolved) { | 1015 if (!cls.isResolved) { |
1003 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); | 1016 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); |
1004 } | 1017 } |
1005 | 1018 |
1006 _updateClassHierarchyNodeForClass(cls, | 1019 _updateClassHierarchyNodeForClass(cls, |
1007 directlyInstantiated: | 1020 directlyInstantiated: |
1008 instantiations.contains(Instantiation.DIRECTLY_INSTANTIATED), | 1021 instantiations.contains(Instantiation.DIRECTLY_INSTANTIATED), |
(...skipping 11 matching lines...) Expand all Loading... |
1020 typesImplementedBySubclassesOfCls.add(current.element); | 1033 typesImplementedBySubclassesOfCls.add(current.element); |
1021 } | 1034 } |
1022 superclass = superclass.superclass; | 1035 superclass = superclass.superclass; |
1023 } | 1036 } |
1024 } | 1037 } |
1025 | 1038 |
1026 // Use the [:seenClasses:] set to include non-instantiated | 1039 // Use the [:seenClasses:] set to include non-instantiated |
1027 // classes: if the superclass of these classes require RTI, then | 1040 // classes: if the superclass of these classes require RTI, then |
1028 // they also need RTI, so that a constructor passes the type | 1041 // they also need RTI, so that a constructor passes the type |
1029 // variables to the super constructor. | 1042 // variables to the super constructor. |
1030 _compiler.resolverWorld.forEachInstantiatedClass(addSubtypes); | 1043 resolverWorld.forEachInstantiatedClass(addSubtypes); |
1031 | 1044 |
1032 _closed = true; | 1045 _closed = true; |
| 1046 _commonMasks = new CommonMasks(this); |
1033 return this; | 1047 return this; |
1034 } | 1048 } |
1035 | 1049 |
1036 @override | 1050 @override |
1037 String dump([ClassElement cls]) { | 1051 String dump([ClassElement cls]) { |
1038 StringBuffer sb = new StringBuffer(); | 1052 StringBuffer sb = new StringBuffer(); |
1039 if (cls != null) { | 1053 if (cls != null) { |
1040 sb.write("Classes in the closed world related to $cls:\n"); | 1054 sb.write("Classes in the closed world related to $cls:\n"); |
1041 } else { | 1055 } else { |
1042 sb.write("Instantiated classes in the closed world:\n"); | 1056 sb.write("Instantiated classes in the closed world:\n"); |
(...skipping 22 matching lines...) Expand all Loading... |
1065 allFunctions.add(element); | 1079 allFunctions.add(element); |
1066 } | 1080 } |
1067 } | 1081 } |
1068 | 1082 |
1069 FieldElement locateSingleField(Selector selector, TypeMask mask) { | 1083 FieldElement locateSingleField(Selector selector, TypeMask mask) { |
1070 Element result = locateSingleElement(selector, mask); | 1084 Element result = locateSingleElement(selector, mask); |
1071 return (result != null && result.isField) ? result : null; | 1085 return (result != null && result.isField) ? result : null; |
1072 } | 1086 } |
1073 | 1087 |
1074 Element locateSingleElement(Selector selector, TypeMask mask) { | 1088 Element locateSingleElement(Selector selector, TypeMask mask) { |
| 1089 assert(isClosed); |
1075 mask ??= commonMasks.dynamicType; | 1090 mask ??= commonMasks.dynamicType; |
1076 return mask.locateSingleElement(selector, _compiler); | 1091 return mask.locateSingleElement(selector, this); |
1077 } | 1092 } |
1078 | 1093 |
1079 TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) { | 1094 TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) { |
| 1095 assert(isClosed); |
1080 bool canReachAll = true; | 1096 bool canReachAll = true; |
1081 if (mask != null) { | 1097 if (mask != null) { |
1082 canReachAll = _compiler.enabledInvokeOn && | 1098 canReachAll = _backend.hasInvokeOnSupport && |
1083 mask.needsNoSuchMethodHandling(selector, this); | 1099 mask.needsNoSuchMethodHandling(selector, this); |
1084 } | 1100 } |
1085 return canReachAll ? commonMasks.dynamicType : mask; | 1101 return canReachAll ? commonMasks.dynamicType : mask; |
1086 } | 1102 } |
1087 | 1103 |
1088 void addFunctionCalledInLoop(Element element) { | 1104 void addFunctionCalledInLoop(Element element) { |
1089 functionsCalledInLoop.add(element.declaration); | 1105 functionsCalledInLoop.add(element.declaration); |
1090 } | 1106 } |
1091 | 1107 |
1092 bool isCalledInLoop(Element element) { | 1108 bool isCalledInLoop(Element element) { |
1093 return functionsCalledInLoop.contains(element.declaration); | 1109 return functionsCalledInLoop.contains(element.declaration); |
1094 } | 1110 } |
1095 | 1111 |
1096 bool fieldNeverChanges(Element element) { | 1112 bool fieldNeverChanges(Element element) { |
1097 if (!element.isField) return false; | 1113 if (!element.isField) return false; |
1098 if (_backend.isNative(element)) { | 1114 if (_backend.isNative(element)) { |
1099 // Some native fields are views of data that may be changed by operations. | 1115 // Some native fields are views of data that may be changed by operations. |
1100 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). | 1116 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). |
1101 // TODO(sra): Refine the effect classification so that native effects are | 1117 // TODO(sra): Refine the effect classification so that native effects are |
1102 // distinct from ordinary Dart effects. | 1118 // distinct from ordinary Dart effects. |
1103 return false; | 1119 return false; |
1104 } | 1120 } |
1105 | 1121 |
1106 if (element.isFinal || element.isConst) { | 1122 if (element.isFinal || element.isConst) { |
1107 return true; | 1123 return true; |
1108 } | 1124 } |
1109 if (element.isInstanceMember) { | 1125 if (element.isInstanceMember) { |
1110 return !_compiler.resolverWorld.hasInvokedSetter(element, this) && | 1126 return !resolverWorld.hasInvokedSetter(element, this) && |
1111 !_compiler.resolverWorld.fieldSetters.contains(element); | 1127 !resolverWorld.fieldSetters.contains(element); |
1112 } | 1128 } |
1113 return false; | 1129 return false; |
1114 } | 1130 } |
1115 | 1131 |
1116 SideEffects getSideEffectsOfElement(Element element) { | 1132 SideEffects getSideEffectsOfElement(Element element) { |
1117 // The type inferrer (where the side effects are being computed), | 1133 // The type inferrer (where the side effects are being computed), |
1118 // does not see generative constructor bodies because they are | 1134 // does not see generative constructor bodies because they are |
1119 // created by the backend. Also, it does not make any distinction | 1135 // created by the backend. Also, it does not make any distinction |
1120 // between a constructor and its body for side effects. This | 1136 // between a constructor and its body for side effects. This |
1121 // implies that currently, the side effects of a constructor body | 1137 // implies that currently, the side effects of a constructor body |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1202 /// Only the class itself is included. | 1218 /// Only the class itself is included. |
1203 EXACT, | 1219 EXACT, |
1204 | 1220 |
1205 /// The class and all subclasses (transitively) are included. | 1221 /// The class and all subclasses (transitively) are included. |
1206 SUBCLASS, | 1222 SUBCLASS, |
1207 | 1223 |
1208 /// The class and all classes that implement or subclass it (transitively) | 1224 /// The class and all classes that implement or subclass it (transitively) |
1209 /// are included. | 1225 /// are included. |
1210 SUBTYPE, | 1226 SUBTYPE, |
1211 } | 1227 } |
OLD | NEW |