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

Side by Side Diff: pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart

Issue 2952873002: In strong mode, properly infer the return types of setters as `void` (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE.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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698