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'; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 /// | 46 /// |
47 /// Otherwise `null`. | 47 /// Otherwise `null`. |
48 AccessorNode currentDependency; | 48 AccessorNode currentDependency; |
49 | 49 |
50 final overrides = <Member>[]; | 50 final overrides = <Member>[]; |
51 | 51 |
52 final crossOverrides = <Member>[]; | 52 final crossOverrides = <Member>[]; |
53 | 53 |
54 AccessorNode(this._typeInferenceEngine, this.member); | 54 AccessorNode(this._typeInferenceEngine, this.member); |
55 | 55 |
56 get candidateOverrides => overrides.isNotEmpty ? overrides : crossOverrides; | 56 List<Member> get candidateOverrides { |
| 57 if (isTrivialSetter) { |
| 58 return const []; |
| 59 } else if (overrides.isNotEmpty) { |
| 60 return overrides; |
| 61 } else { |
| 62 return crossOverrides; |
| 63 } |
| 64 } |
57 | 65 |
58 @override | 66 @override |
59 bool get isEvaluated => state == InferenceState.Inferred; | 67 bool get isEvaluated => state == InferenceState.Inferred; |
60 | 68 |
| 69 /// Indicates whether this accessor is a setter for which the only type we |
| 70 /// have to infer is its return type. |
| 71 bool get isTrivialSetter { |
| 72 var member = this.member; |
| 73 if (member is KernelProcedure && |
| 74 member.isSetter && |
| 75 member.function != null) { |
| 76 var parameters = member.function.positionalParameters; |
| 77 return parameters.length > 0 && |
| 78 !KernelVariableDeclaration.isImplicitlyTyped(parameters[0]); |
| 79 } |
| 80 return false; |
| 81 } |
| 82 |
61 @override | 83 @override |
62 List<AccessorNode> computeDependencies() { | 84 List<AccessorNode> computeDependencies() { |
63 return _typeInferenceEngine.computeAccessorDependencies(this); | 85 return _typeInferenceEngine.computeAccessorDependencies(this); |
64 } | 86 } |
65 | 87 |
66 @override | 88 @override |
67 String toString() => member.toString(); | 89 String toString() => member.toString(); |
68 } | 90 } |
69 | 91 |
70 /// Enum tracking the type inference state of an accessor or method. | 92 /// Enum tracking the type inference state of an accessor or method. |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 return const DynamicType(); | 299 return const DynamicType(); |
278 } | 300 } |
279 } | 301 } |
280 | 302 |
281 /// Performs type inference on the given [accessorNode]. | 303 /// Performs type inference on the given [accessorNode]. |
282 void inferAccessor(AccessorNode accessorNode) { | 304 void inferAccessor(AccessorNode accessorNode) { |
283 assert(accessorNode.state == InferenceState.NotInferredYet); | 305 assert(accessorNode.state == InferenceState.NotInferredYet); |
284 accessorNode.state = InferenceState.Inferring; | 306 accessorNode.state = InferenceState.Inferring; |
285 var member = accessorNode.member; | 307 var member = accessorNode.member; |
286 if (strongMode) { | 308 if (strongMode) { |
287 var inferredType = tryInferAccessorByInheritance(accessorNode); | |
288 var typeInferrer = getMemberTypeInferrer(member); | 309 var typeInferrer = getMemberTypeInferrer(member); |
289 if (inferredType == null) { | 310 if (member is KernelProcedure && member.isSetter) { |
290 if (member is KernelField) { | 311 KernelProcedure.inferSetterReturnType(member, this, typeInferrer.uri); |
291 typeInferrer.isImmediatelyEvident = true; | 312 } |
292 inferredType = accessorNode.isImmediatelyEvident | 313 if (!accessorNode.isTrivialSetter) { |
293 ? typeInferrer.inferDeclarationType( | 314 var inferredType = tryInferAccessorByInheritance(accessorNode); |
294 typeInferrer.inferFieldTopLevel(member, null, true)) | 315 if (inferredType == null) { |
295 : const DynamicType(); | 316 if (member is KernelField) { |
296 if (!typeInferrer.isImmediatelyEvident) { | 317 typeInferrer.isImmediatelyEvident = true; |
| 318 inferredType = accessorNode.isImmediatelyEvident |
| 319 ? typeInferrer.inferDeclarationType( |
| 320 typeInferrer.inferFieldTopLevel(member, null, true)) |
| 321 : const DynamicType(); |
| 322 if (!typeInferrer.isImmediatelyEvident) { |
| 323 inferredType = const DynamicType(); |
| 324 } |
| 325 } else { |
297 inferredType = const DynamicType(); | 326 inferredType = const DynamicType(); |
298 } | 327 } |
299 } else { | |
300 inferredType = const DynamicType(); | |
301 } | 328 } |
| 329 if (accessorNode.state == InferenceState.Inferred) { |
| 330 // A circularity must have been detected; at the time it was detected, |
| 331 // inference for this node was completed. |
| 332 return; |
| 333 } |
| 334 member.setInferredType(this, typeInferrer.uri, inferredType); |
302 } | 335 } |
303 if (accessorNode.state == InferenceState.Inferred) { | |
304 // A circularity must have been detected; at the time it was detected, | |
305 // inference for this node was completed. | |
306 return; | |
307 } | |
308 member.setInferredType(this, typeInferrer.uri, inferredType); | |
309 } | 336 } |
310 accessorNode.state = InferenceState.Inferred; | 337 accessorNode.state = InferenceState.Inferred; |
311 // TODO(paulberry): if type != null, then check that the type of the | 338 // TODO(paulberry): if type != null, then check that the type of the |
312 // initializer is assignable to it. | 339 // initializer is assignable to it. |
313 // TODO(paulberry): the following is a hack so that outlines don't contain | 340 // TODO(paulberry): the following is a hack so that outlines don't contain |
314 // initializers. But it means that we rebuild the initializers when doing | 341 // initializers. But it means that we rebuild the initializers when doing |
315 // a full compile. There should be a better way. | 342 // a full compile. There should be a better way. |
316 if (member is KernelField) { | 343 if (member is KernelField) { |
317 member.initializer = null; | 344 member.initializer = null; |
318 } | 345 } |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 } | 628 } |
602 | 629 |
603 @override | 630 @override |
604 void evaluateScc(List<AccessorNode> scc) { | 631 void evaluateScc(List<AccessorNode> scc) { |
605 // Mark every accessor as part of a circularity. | 632 // Mark every accessor as part of a circularity. |
606 for (var f in scc) { | 633 for (var f in scc) { |
607 f._typeInferenceEngine.inferAccessorCircular(f); | 634 f._typeInferenceEngine.inferAccessorCircular(f); |
608 } | 635 } |
609 } | 636 } |
610 } | 637 } |
OLD | NEW |