OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
4 | 4 |
5 import 'package:front_end/src/base/instrumentation.dart'; | 5 import 'package:front_end/src/base/instrumentation.dart'; |
6 import 'package:front_end/src/dependency_walker.dart' as dependencyWalker; | 6 import 'package:front_end/src/dependency_walker.dart' as dependencyWalker; |
7 import 'package:front_end/src/fasta/errors.dart'; | 7 import 'package:front_end/src/fasta/errors.dart'; |
8 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'; | 8 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'; |
9 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart'
; | 9 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart'
; |
10 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart'; | 10 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart'; |
11 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart'
; | 11 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart'
; |
12 import 'package:kernel/ast.dart' | 12 import 'package:kernel/ast.dart' |
13 show Class, DartType, DynamicType, Field, InterfaceType, Member, Procedure; | 13 show Class, DartType, DynamicType, Field, InterfaceType, Member, Procedure; |
14 import 'package:kernel/class_hierarchy.dart'; | 14 import 'package:kernel/class_hierarchy.dart'; |
15 import 'package:kernel/core_types.dart'; | 15 import 'package:kernel/core_types.dart'; |
16 import 'package:kernel/type_algebra.dart'; | 16 import 'package:kernel/type_algebra.dart'; |
17 | 17 |
18 /// Data structure for tracking dependencies among fields, getters, and setters | 18 /// Data structure for tracking dependencies among fields, getters, and setters |
19 /// that require type inference. | 19 /// that require type inference. |
20 /// | 20 /// |
21 /// TODO(paulberry): see if it's possible to make this class more lightweight | 21 /// TODO(paulberry): see if it's possible to make this class more lightweight |
22 /// by changing the API so that the walker is passed to computeDependencies(). | 22 /// by changing the API so that the walker is passed to computeDependencies(). |
23 /// (This should allow us to drop the _typeInferenceEngine field). | 23 /// (This should allow us to drop the _typeInferenceEngine field). |
24 class FieldNode extends dependencyWalker.Node<FieldNode> { | 24 class AccessorNode extends dependencyWalker.Node<AccessorNode> { |
25 final TypeInferenceEngineImpl _typeInferenceEngine; | 25 final TypeInferenceEngineImpl _typeInferenceEngine; |
26 | 26 |
27 final KernelMember member; | 27 final KernelMember member; |
28 | 28 |
29 bool isImmediatelyEvident = false; | 29 bool isImmediatelyEvident = false; |
30 | 30 |
31 FieldState state = FieldState.NotInferredYet; | 31 AccessorState state = AccessorState.NotInferredYet; |
32 | 32 |
33 /// If [state] is [FieldState.Inferring], and type inference for this field | 33 /// If [state] is [AccessorState.Inferring], and type inference for this |
34 /// is waiting on type inference of some other field, the field that is being | 34 /// accessor is waiting on type inference of some other accessor, the accessor |
35 /// waited on. | 35 /// that is being waited on. |
36 /// | 36 /// |
37 /// Otherwise `null`. | 37 /// Otherwise `null`. |
38 FieldNode currentDependency; | 38 AccessorNode currentDependency; |
39 | 39 |
40 final overrides = <Member>[]; | 40 final overrides = <Member>[]; |
41 | 41 |
42 FieldNode(this._typeInferenceEngine, this.member); | 42 AccessorNode(this._typeInferenceEngine, this.member); |
43 | 43 |
44 @override | 44 @override |
45 bool get isEvaluated => state == FieldState.Inferred; | 45 bool get isEvaluated => state == AccessorState.Inferred; |
46 | 46 |
47 @override | 47 @override |
48 List<FieldNode> computeDependencies() { | 48 List<AccessorNode> computeDependencies() { |
49 return _typeInferenceEngine.computeFieldDependencies(this); | 49 return _typeInferenceEngine.computeAccessorDependencies(this); |
50 } | 50 } |
51 | 51 |
52 @override | 52 @override |
53 String toString() => member.toString(); | 53 String toString() => member.toString(); |
54 } | 54 } |
55 | 55 |
56 /// Enum tracking the type inference state of a field. | 56 /// Enum tracking the type inference state of an accessor. |
57 enum FieldState { | 57 enum AccessorState { |
58 /// The field's type has not been inferred yet. | 58 /// The accessor's type has not been inferred yet. |
59 NotInferredYet, | 59 NotInferredYet, |
60 | 60 |
61 /// Type inference is in progress for the field. | 61 /// Type inference is in progress for the accessor. |
62 /// | 62 /// |
63 /// This means that code is currently on the stack which is attempting to | 63 /// This means that code is currently on the stack which is attempting to |
64 /// determine the type of the field. | 64 /// determine the type of the accessor. |
65 Inferring, | 65 Inferring, |
66 | 66 |
67 /// The field's type has been inferred. | 67 /// The accessor's type has been inferred. |
68 Inferred | 68 Inferred |
69 } | 69 } |
70 | 70 |
71 /// Keeps track of the global state for the type inference that occurs outside | 71 /// Keeps track of the global state for the type inference that occurs outside |
72 /// of method bodies and initalizers. | 72 /// of method bodies and initalizers. |
73 /// | 73 /// |
74 /// This class describes the interface for use by clients of type inference | 74 /// This class describes the interface for use by clients of type inference |
75 /// (e.g. DietListener). Derived classes should derive from | 75 /// (e.g. DietListener). Derived classes should derive from |
76 /// [TypeInferenceEngineImpl]. | 76 /// [TypeInferenceEngineImpl]. |
77 abstract class TypeInferenceEngine { | 77 abstract class TypeInferenceEngine { |
78 ClassHierarchy get classHierarchy; | 78 ClassHierarchy get classHierarchy; |
79 | 79 |
80 CoreTypes get coreTypes; | 80 CoreTypes get coreTypes; |
81 | 81 |
82 /// Creates a type inferrer for use inside of a method body declared in a file | 82 /// Creates a type inferrer for use inside of a method body declared in a file |
83 /// with the given [uri]. | 83 /// with the given [uri]. |
84 TypeInferrer createLocalTypeInferrer( | 84 TypeInferrer createLocalTypeInferrer( |
85 Uri uri, TypeInferenceListener listener, InterfaceType thisType); | 85 Uri uri, TypeInferenceListener listener, InterfaceType thisType); |
86 | 86 |
87 /// Creates a [TypeInferrer] object which is ready to perform type inference | 87 /// Creates a [TypeInferrer] object which is ready to perform type inference |
88 /// on the given [field]. | 88 /// on the given [field]. |
89 TypeInferrer createTopLevelTypeInferrer(TypeInferenceListener listener, | 89 TypeInferrer createTopLevelTypeInferrer(TypeInferenceListener listener, |
90 InterfaceType thisType, KernelMember member); | 90 InterfaceType thisType, KernelMember member); |
91 | 91 |
92 /// Performs the second phase of top level initializer inference, which is to | 92 /// Performs the second phase of top level initializer inference, which is to |
93 /// visit all fields and top level variables that were passed to [recordField] | 93 /// visit all accessors and top level variables that were passed to |
94 /// in topologically-sorted order and assign their types. | 94 /// [recordAccessor] in topologically-sorted order and assign their types. |
95 void finishTopLevel(); | 95 void finishTopLevel(); |
96 | 96 |
97 /// Gets ready to do top level type inference for the program having the given | 97 /// Gets ready to do top level type inference for the program having the given |
98 /// [hierarchy], using the given [coreTypes]. | 98 /// [hierarchy], using the given [coreTypes]. |
99 void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy); | 99 void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy); |
100 | 100 |
101 /// Records that the given initializing [formal] will need top level type | 101 /// Records that the given initializing [formal] will need top level type |
102 /// inference. | 102 /// inference. |
103 void recordInitializingFormal(KernelVariableDeclaration formal); | 103 void recordInitializingFormal(KernelVariableDeclaration formal); |
104 | 104 |
(...skipping 28 matching lines...) Expand all Loading... |
133 /// field's inferred type to depend on the type of an instance field (provided | 133 /// field's inferred type to depend on the type of an instance field (provided |
134 /// there are no circular dependencies). | 134 /// there are no circular dependencies). |
135 /// | 135 /// |
136 /// Requires [fusedTopLevelInference] to be `true`. | 136 /// Requires [fusedTopLevelInference] to be `true`. |
137 static const bool fullTopLevelInference = true; | 137 static const bool fullTopLevelInference = true; |
138 | 138 |
139 final Instrumentation instrumentation; | 139 final Instrumentation instrumentation; |
140 | 140 |
141 final bool strongMode; | 141 final bool strongMode; |
142 | 142 |
143 final fieldNodes = <FieldNode>[]; | 143 final accessorNodes = <AccessorNode>[]; |
144 | 144 |
145 final initializingFormals = <KernelVariableDeclaration>[]; | 145 final initializingFormals = <KernelVariableDeclaration>[]; |
146 | 146 |
147 @override | 147 @override |
148 CoreTypes coreTypes; | 148 CoreTypes coreTypes; |
149 | 149 |
150 @override | 150 @override |
151 ClassHierarchy classHierarchy; | 151 ClassHierarchy classHierarchy; |
152 | 152 |
153 TypeSchemaEnvironment typeSchemaEnvironment; | 153 TypeSchemaEnvironment typeSchemaEnvironment; |
154 | 154 |
155 TypeInferenceEngineImpl(this.instrumentation, this.strongMode); | 155 TypeInferenceEngineImpl(this.instrumentation, this.strongMode); |
156 | 156 |
157 /// Computes type inference dependencies for the given [field]. | 157 /// Computes type inference dependencies for the given [accessorNode]. |
158 List<FieldNode> computeFieldDependencies(FieldNode fieldNode) { | 158 List<AccessorNode> computeAccessorDependencies(AccessorNode accessorNode) { |
159 // If the field's type is going to be determined by inheritance, then its | 159 // If the accessor's type is going to be determined by inheritance, then its |
160 // dependencies are determined by inheritance too. | 160 // dependencies are determined by inheritance too. |
161 if (fieldNode.overrides.isNotEmpty) { | 161 if (accessorNode.overrides.isNotEmpty) { |
162 var dependencies = <FieldNode>[]; | 162 var dependencies = <AccessorNode>[]; |
163 for (var override in fieldNode.overrides) { | 163 for (var override in accessorNode.overrides) { |
164 // TODO(paulberry): support dependencies on getters/setters too. | 164 // TODO(paulberry): support dependencies on getters/setters too. |
165 var dep = KernelMember.getFieldNode(override); | 165 var dep = KernelMember.getAccessorNode(override); |
166 if (dep != null) dependencies.add(dep); | 166 if (dep != null) dependencies.add(dep); |
167 } | 167 } |
168 fieldNode.isImmediatelyEvident = true; | 168 accessorNode.isImmediatelyEvident = true; |
169 return dependencies; | 169 return dependencies; |
170 } | 170 } |
171 | 171 |
172 // Otherwise its dependencies are based on the initializer expression. | 172 // Otherwise its dependencies are based on the initializer expression. |
173 var member = fieldNode.member; | 173 var member = accessorNode.member; |
174 if (member is KernelField) { | 174 if (member is KernelField) { |
175 if (expandedTopLevelInference) { | 175 if (expandedTopLevelInference) { |
176 // In expanded top level inference, we determine the dependencies by | 176 // In expanded top level inference, we determine the dependencies by |
177 // doing a "dry run" of top level inference and recording which static | 177 // doing a "dry run" of top level inference and recording which static |
178 // fields were accessed. | 178 // fields were accessed. |
179 var typeInferrer = getFieldTypeInferrer(member); | 179 var typeInferrer = getMemberTypeInferrer(member); |
180 if (typeInferrer == null) { | 180 if (typeInferrer == null) { |
181 // This can happen when there are errors in the field declaration. | 181 // This can happen when there are errors in the field declaration. |
182 return const []; | 182 return const []; |
183 } else { | 183 } else { |
184 typeInferrer.startDryRun(); | 184 typeInferrer.startDryRun(); |
185 typeInferrer.listener.dryRunEnter(member.initializer); | 185 typeInferrer.listener.dryRunEnter(member.initializer); |
186 typeInferrer.inferFieldTopLevel(member, null, true); | 186 typeInferrer.inferFieldTopLevel(member, null, true); |
187 typeInferrer.listener.dryRunExit(member.initializer); | 187 typeInferrer.listener.dryRunExit(member.initializer); |
188 fieldNode.isImmediatelyEvident = true; | 188 accessorNode.isImmediatelyEvident = true; |
189 return typeInferrer.finishDryRun(); | 189 return typeInferrer.finishDryRun(); |
190 } | 190 } |
191 } else { | 191 } else { |
192 // In non-expanded top level inference, we determine the dependencies by | 192 // In non-expanded top level inference, we determine the dependencies by |
193 // calling `collectDependencies`; as a side effect this flags any | 193 // calling `collectDependencies`; as a side effect this flags any |
194 // expressions that are not "immediately evident". | 194 // expressions that are not "immediately evident". |
195 // TODO(paulberry): get rid of this mode once we are sure we no longer | 195 // TODO(paulberry): get rid of this mode once we are sure we no longer |
196 // need it. | 196 // need it. |
197 var collector = new KernelDependencyCollector(); | 197 var collector = new KernelDependencyCollector(); |
198 collector.collectDependencies(member.initializer); | 198 collector.collectDependencies(member.initializer); |
199 fieldNode.isImmediatelyEvident = collector.isImmediatelyEvident; | 199 accessorNode.isImmediatelyEvident = collector.isImmediatelyEvident; |
200 return collector.dependencies; | 200 return collector.dependencies; |
201 } | 201 } |
202 } else { | 202 } else { |
203 // Member is a getter/setter that doesn't override anything, so we can't | 203 // Member is a getter/setter that doesn't override anything, so we can't |
204 // infer a type for it; therefore it has no dependencies. | 204 // infer a type for it; therefore it has no dependencies. |
205 return const []; | 205 return const []; |
206 } | 206 } |
207 } | 207 } |
208 | 208 |
209 /// Creates a [FieldNode] to track dependencies of the given [field]. | 209 /// Creates an [AccessorNode] to track dependencies of the given [member]. |
210 FieldNode createFieldNode(KernelField field); | 210 AccessorNode createAccessorNode(KernelMember member); |
211 | 211 |
212 @override | 212 @override |
213 void finishTopLevel() { | 213 void finishTopLevel() { |
214 for (var fieldNode in fieldNodes) { | 214 for (var accessorNode in accessorNodes) { |
215 if (fusedTopLevelInference) { | 215 if (fusedTopLevelInference) { |
216 assert(expandedTopLevelInference); | 216 assert(expandedTopLevelInference); |
217 inferFieldFused(fieldNode, null); | 217 inferAccessorFused(accessorNode, null); |
218 } else { | 218 } else { |
219 if (fieldNode.isEvaluated) continue; | 219 if (accessorNode.isEvaluated) continue; |
220 new _FieldWalker().walk(fieldNode); | 220 new _AccessorWalker().walk(accessorNode); |
221 } | 221 } |
222 } | 222 } |
223 for (var formal in initializingFormals) { | 223 for (var formal in initializingFormals) { |
224 formal.type = _inferInitializingFormalType(formal); | 224 formal.type = _inferInitializingFormalType(formal); |
225 } | 225 } |
226 } | 226 } |
227 | 227 |
228 /// Retrieve the [TypeInferrer] for the given [member], which was created by | 228 /// Retrieve the [TypeInferrer] for the given [member], which was created by |
229 /// a previous call to [createTopLevelTypeInferrer]. | 229 /// a previous call to [createTopLevelTypeInferrer]. |
230 TypeInferrerImpl getFieldTypeInferrer(KernelMember member); | 230 TypeInferrerImpl getMemberTypeInferrer(KernelMember member); |
231 | 231 |
232 /// Performs type inference on the given [field]. | 232 /// Performs type inference on the given [accessorNode]. |
233 void inferField(FieldNode fieldNode) { | 233 void inferAccessor(AccessorNode accessorNode) { |
234 assert(fieldNode.state == FieldState.NotInferredYet); | 234 assert(accessorNode.state == AccessorState.NotInferredYet); |
235 fieldNode.state = FieldState.Inferring; | 235 accessorNode.state = AccessorState.Inferring; |
236 var member = fieldNode.member; | 236 var member = accessorNode.member; |
237 if (strongMode) { | 237 if (strongMode) { |
238 var inferredType = tryInferFieldByInheritance(fieldNode); | 238 var inferredType = tryInferAccessorByInheritance(accessorNode); |
239 var typeInferrer = getFieldTypeInferrer(member); | 239 var typeInferrer = getMemberTypeInferrer(member); |
240 if (inferredType == null) { | 240 if (inferredType == null) { |
241 if (member is KernelField) { | 241 if (member is KernelField) { |
242 typeInferrer.isImmediatelyEvident = true; | 242 typeInferrer.isImmediatelyEvident = true; |
243 inferredType = fieldNode.isImmediatelyEvident | 243 inferredType = accessorNode.isImmediatelyEvident |
244 ? typeInferrer.inferDeclarationType( | 244 ? typeInferrer.inferDeclarationType( |
245 typeInferrer.inferFieldTopLevel(member, null, true)) | 245 typeInferrer.inferFieldTopLevel(member, null, true)) |
246 : const DynamicType(); | 246 : const DynamicType(); |
247 if (!typeInferrer.isImmediatelyEvident) { | 247 if (!typeInferrer.isImmediatelyEvident) { |
248 inferredType = const DynamicType(); | 248 inferredType = const DynamicType(); |
249 } | 249 } |
250 } else { | 250 } else { |
251 inferredType = const DynamicType(); | 251 inferredType = const DynamicType(); |
252 } | 252 } |
253 } | 253 } |
254 if (fieldNode.state == FieldState.Inferred) { | 254 if (accessorNode.state == AccessorState.Inferred) { |
255 // A circularity must have been detected; at the time it was detected, | 255 // A circularity must have been detected; at the time it was detected, |
256 // inference for this node was completed. | 256 // inference for this node was completed. |
257 return; | 257 return; |
258 } | 258 } |
259 member.setInferredType(this, typeInferrer.uri, inferredType); | 259 member.setInferredType(this, typeInferrer.uri, inferredType); |
260 } | 260 } |
261 fieldNode.state = FieldState.Inferred; | 261 accessorNode.state = AccessorState.Inferred; |
262 // TODO(paulberry): if type != null, then check that the type of the | 262 // TODO(paulberry): if type != null, then check that the type of the |
263 // initializer is assignable to it. | 263 // initializer is assignable to it. |
264 // TODO(paulberry): the following is a hack so that outlines don't contain | 264 // TODO(paulberry): the following is a hack so that outlines don't contain |
265 // initializers. But it means that we rebuild the initializers when doing | 265 // initializers. But it means that we rebuild the initializers when doing |
266 // a full compile. There should be a better way. | 266 // a full compile. There should be a better way. |
267 if (member is KernelField) { | 267 if (member is KernelField) { |
268 member.initializer = null; | 268 member.initializer = null; |
269 } | 269 } |
270 } | 270 } |
271 | 271 |
272 /// Makes a note that the given [field] is part of a circularity, so its type | 272 /// Makes a note that the given [accessorNode] is part of a circularity, so |
273 /// can't be inferred. | 273 /// its type can't be inferred. |
274 void inferFieldCircular(FieldNode fieldNode) { | 274 void inferAccessorCircular(AccessorNode accessorNode) { |
275 var member = fieldNode.member; | 275 var member = accessorNode.member; |
276 // TODO(paulberry): report the appropriate error. | 276 // TODO(paulberry): report the appropriate error. |
277 var uri = getFieldTypeInferrer(member).uri; | 277 var uri = getMemberTypeInferrer(member).uri; |
278 fieldNode.state = FieldState.Inferred; | 278 accessorNode.state = AccessorState.Inferred; |
279 member.setInferredType(this, uri, const DynamicType()); | 279 member.setInferredType(this, uri, const DynamicType()); |
280 // TODO(paulberry): the following is a hack so that outlines don't contain | 280 // TODO(paulberry): the following is a hack so that outlines don't contain |
281 // initializers. But it means that we rebuild the initializers when doing | 281 // initializers. But it means that we rebuild the initializers when doing |
282 // a full compile. There should be a better way. | 282 // a full compile. There should be a better way. |
283 if (member is KernelField) { | 283 if (member is KernelField) { |
284 member.initializer = null; | 284 member.initializer = null; |
285 } | 285 } |
286 } | 286 } |
287 | 287 |
288 /// Performs fused type inference on the given [field]. | 288 /// Performs fused type inference on the given [accessorNode]. |
289 void inferFieldFused(FieldNode fieldNode, FieldNode dependant) { | 289 void inferAccessorFused(AccessorNode accessorNode, AccessorNode dependant) { |
290 switch (fieldNode.state) { | 290 switch (accessorNode.state) { |
291 case FieldState.Inferred: | 291 case AccessorState.Inferred: |
292 // Already inferred. Nothing to do. | 292 // Already inferred. Nothing to do. |
293 break; | 293 break; |
294 case FieldState.Inferring: | 294 case AccessorState.Inferring: |
295 // A field depends on itself (possibly by way of intermediate fields). | 295 // An accessor depends on itself (possibly by way of intermediate |
296 // Mark all fields involved as circular and infer a type of `dynamic` | 296 // accessors). Mark all accessors involved as circular and infer a type |
297 // for them. | 297 // of `dynamic` for them. |
298 var node = fieldNode; | 298 var node = accessorNode; |
299 while (node != null) { | 299 while (node != null) { |
300 var nextNode = node.currentDependency; | 300 var nextNode = node.currentDependency; |
301 inferFieldCircular(node); | 301 inferAccessorCircular(node); |
302 node.currentDependency = null; | 302 node.currentDependency = null; |
303 node = nextNode; | 303 node = nextNode; |
304 } | 304 } |
305 break; | 305 break; |
306 case FieldState.NotInferredYet: | 306 case AccessorState.NotInferredYet: |
307 // Mark the "dependant" field (if any) as depending on this one, and | 307 // Mark the "dependant" accessor (if any) as depending on this one, and |
308 // invoke field inference for this node. | 308 // invoke accessor inference for this node. |
309 dependant?.currentDependency = fieldNode; | 309 dependant?.currentDependency = accessorNode; |
310 // All fields are "immediately evident" when doing fused inference. | 310 // All accessors are "immediately evident" when doing fused inference. |
311 fieldNode.isImmediatelyEvident = true; | 311 accessorNode.isImmediatelyEvident = true; |
312 inferField(fieldNode); | 312 inferAccessor(accessorNode); |
313 dependant?.currentDependency = null; | 313 dependant?.currentDependency = null; |
314 break; | 314 break; |
315 } | 315 } |
316 } | 316 } |
317 | 317 |
318 @override | 318 @override |
319 void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy) { | 319 void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy) { |
320 this.coreTypes = coreTypes; | 320 this.coreTypes = coreTypes; |
321 this.classHierarchy = hierarchy; | 321 this.classHierarchy = hierarchy; |
322 this.typeSchemaEnvironment = | 322 this.typeSchemaEnvironment = |
323 new TypeSchemaEnvironment(coreTypes, hierarchy, strongMode); | 323 new TypeSchemaEnvironment(coreTypes, hierarchy, strongMode); |
324 } | 324 } |
325 | 325 |
326 @override | 326 @override |
327 void recordInitializingFormal(KernelVariableDeclaration formal) { | 327 void recordInitializingFormal(KernelVariableDeclaration formal) { |
328 initializingFormals.add(formal); | 328 initializingFormals.add(formal); |
329 } | 329 } |
330 | 330 |
331 @override | 331 @override |
332 void recordMember(KernelMember member) { | 332 void recordMember(KernelMember member) { |
333 fieldNodes.add(createFieldNode(member)); | 333 accessorNodes.add(createAccessorNode(member)); |
334 } | 334 } |
335 | 335 |
336 DartType tryInferFieldByInheritance(FieldNode fieldNode) { | 336 DartType tryInferAccessorByInheritance(AccessorNode accessorNode) { |
337 DartType inferredType; | 337 DartType inferredType; |
338 for (var override in fieldNode.overrides) { | 338 for (var override in accessorNode.overrides) { |
339 var nextInferredType = _computeOverriddenFieldType(override, fieldNode); | 339 var nextInferredType = |
| 340 _computeOverriddenAccessorType(override, accessorNode); |
340 if (inferredType == null) { | 341 if (inferredType == null) { |
341 inferredType = nextInferredType; | 342 inferredType = nextInferredType; |
342 } else if (inferredType != nextInferredType) { | 343 } else if (inferredType != nextInferredType) { |
343 // Overrides don't have matching types. | 344 // Overrides don't have matching types. |
344 // TODO(paulberry): report an error | 345 // TODO(paulberry): report an error |
345 return const DynamicType(); | 346 return const DynamicType(); |
346 } | 347 } |
347 } | 348 } |
348 return inferredType; | 349 return inferredType; |
349 } | 350 } |
350 | 351 |
351 DartType _computeOverriddenFieldType(Member override, FieldNode fieldNode) { | 352 DartType _computeOverriddenAccessorType( |
| 353 Member override, AccessorNode accessorNode) { |
352 if (fusedTopLevelInference) { | 354 if (fusedTopLevelInference) { |
353 FieldNode dependency = KernelMember.getFieldNode(override); | 355 AccessorNode dependency = KernelMember.getAccessorNode(override); |
354 if (dependency != null) { | 356 if (dependency != null) { |
355 inferFieldFused(dependency, fieldNode); | 357 inferAccessorFused(dependency, accessorNode); |
356 } | 358 } |
357 } | 359 } |
358 DartType overriddenType; | 360 DartType overriddenType; |
359 if (override is Field) { | 361 if (override is Field) { |
360 overriddenType = override.type; | 362 overriddenType = override.type; |
361 } else if (override is Procedure) { | 363 } else if (override is Procedure) { |
362 // TODO(paulberry): handle the case where override needs its type | 364 // TODO(paulberry): handle the case where override needs its type |
363 // inferred first. | 365 // inferred first. |
364 if (override.isGetter) { | 366 if (override.isGetter) { |
365 overriddenType = override.getterType; | 367 overriddenType = override.getterType; |
366 } else { | 368 } else { |
367 overriddenType = override.setterType; | 369 overriddenType = override.setterType; |
368 } | 370 } |
369 } else { | 371 } else { |
370 throw internalError( | 372 throw internalError( |
371 'Unexpected overridden member type: ${override.runtimeType}'); | 373 'Unexpected overridden member type: ${override.runtimeType}'); |
372 } | 374 } |
373 var superclass = override.enclosingClass; | 375 var superclass = override.enclosingClass; |
374 if (superclass.typeParameters.isEmpty) return overriddenType; | 376 if (superclass.typeParameters.isEmpty) return overriddenType; |
375 var thisClass = fieldNode.member.enclosingClass; | 377 var thisClass = accessorNode.member.enclosingClass; |
376 var superclassInstantiation = classHierarchy | 378 var superclassInstantiation = classHierarchy |
377 .getClassAsInstanceOf(thisClass, superclass) | 379 .getClassAsInstanceOf(thisClass, superclass) |
378 .asInterfaceType; | 380 .asInterfaceType; |
379 return Substitution | 381 return Substitution |
380 .fromInterfaceType(superclassInstantiation) | 382 .fromInterfaceType(superclassInstantiation) |
381 .substituteType(overriddenType); | 383 .substituteType(overriddenType); |
382 } | 384 } |
383 | 385 |
384 DartType _inferInitializingFormalType(KernelVariableDeclaration formal) { | 386 DartType _inferInitializingFormalType(KernelVariableDeclaration formal) { |
385 assert(KernelVariableDeclaration.isImplicitlyTyped(formal)); | 387 assert(KernelVariableDeclaration.isImplicitlyTyped(formal)); |
386 Class enclosingClass = formal.parent.parent.parent; | 388 Class enclosingClass = formal.parent.parent.parent; |
387 for (var field in enclosingClass.fields) { | 389 for (var field in enclosingClass.fields) { |
388 if (field.name.name == formal.name) { | 390 if (field.name.name == formal.name) { |
389 return field.type; | 391 return field.type; |
390 } | 392 } |
391 } | 393 } |
392 // No matching field. The error should be reported elsewhere. | 394 // No matching field. The error should be reported elsewhere. |
393 return const DynamicType(); | 395 return const DynamicType(); |
394 } | 396 } |
395 } | 397 } |
396 | 398 |
397 /// Subtype of [dependencyWalker.DependencyWalker] which is specialized to | 399 /// Subtype of [dependencyWalker.DependencyWalker] which is specialized to |
398 /// perform top level type inference. | 400 /// perform top level type inference. |
399 class _FieldWalker extends dependencyWalker.DependencyWalker<FieldNode> { | 401 class _AccessorWalker extends dependencyWalker.DependencyWalker<AccessorNode> { |
400 _FieldWalker(); | 402 _AccessorWalker(); |
401 | 403 |
402 @override | 404 @override |
403 void evaluate(FieldNode f) { | 405 void evaluate(AccessorNode f) { |
404 f._typeInferenceEngine.inferField(f); | 406 f._typeInferenceEngine.inferAccessor(f); |
405 } | 407 } |
406 | 408 |
407 @override | 409 @override |
408 void evaluateScc(List<FieldNode> scc) { | 410 void evaluateScc(List<AccessorNode> scc) { |
409 // Mark every field as part of a circularity. | 411 // Mark every accessor as part of a circularity. |
410 for (var f in scc) { | 412 for (var f in scc) { |
411 f._typeInferenceEngine.inferFieldCircular(f); | 413 f._typeInferenceEngine.inferAccessorCircular(f); |
412 } | 414 } |
413 } | 415 } |
414 } | 416 } |
OLD | NEW |