Index: pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart |
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart |
index f314593ffe0cf628cd99e72f580c003a4a8ed659..936bd0a67b5200be13ee7cb0e5ba1bcf87a2978a 100644 |
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart |
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart |
@@ -53,11 +53,33 @@ class AccessorNode extends dependencyWalker.Node<AccessorNode> { |
AccessorNode(this._typeInferenceEngine, this.member); |
- get candidateOverrides => overrides.isNotEmpty ? overrides : crossOverrides; |
+ List<Member> get candidateOverrides { |
+ if (isTrivialSetter) { |
+ return const []; |
+ } else if (overrides.isNotEmpty) { |
+ return overrides; |
+ } else { |
+ return crossOverrides; |
+ } |
+ } |
@override |
bool get isEvaluated => state == InferenceState.Inferred; |
+ /// Indicates whether this accessor is a setter for which the only type we |
+ /// have to infer is its return type. |
+ bool get isTrivialSetter { |
+ var member = this.member; |
+ if (member is KernelProcedure && |
+ member.isSetter && |
+ member.function != null) { |
+ var parameters = member.function.positionalParameters; |
+ return parameters.length > 0 && |
+ !KernelVariableDeclaration.isImplicitlyTyped(parameters[0]); |
+ } |
+ return false; |
+ } |
+ |
@override |
List<AccessorNode> computeDependencies() { |
return _typeInferenceEngine.computeAccessorDependencies(this); |
@@ -284,28 +306,33 @@ abstract class TypeInferenceEngineImpl extends TypeInferenceEngine { |
accessorNode.state = InferenceState.Inferring; |
var member = accessorNode.member; |
if (strongMode) { |
- var inferredType = tryInferAccessorByInheritance(accessorNode); |
var typeInferrer = getMemberTypeInferrer(member); |
- if (inferredType == null) { |
- if (member is KernelField) { |
- typeInferrer.isImmediatelyEvident = true; |
- inferredType = accessorNode.isImmediatelyEvident |
- ? typeInferrer.inferDeclarationType( |
- typeInferrer.inferFieldTopLevel(member, null, true)) |
- : const DynamicType(); |
- if (!typeInferrer.isImmediatelyEvident) { |
+ if (member is KernelProcedure && member.isSetter) { |
+ KernelProcedure.inferSetterReturnType(member, this, typeInferrer.uri); |
+ } |
+ if (!accessorNode.isTrivialSetter) { |
+ var inferredType = tryInferAccessorByInheritance(accessorNode); |
+ if (inferredType == null) { |
+ if (member is KernelField) { |
+ typeInferrer.isImmediatelyEvident = true; |
+ inferredType = accessorNode.isImmediatelyEvident |
+ ? typeInferrer.inferDeclarationType( |
+ typeInferrer.inferFieldTopLevel(member, null, true)) |
+ : const DynamicType(); |
+ if (!typeInferrer.isImmediatelyEvident) { |
+ inferredType = const DynamicType(); |
+ } |
+ } else { |
inferredType = const DynamicType(); |
} |
- } else { |
- inferredType = const DynamicType(); |
} |
+ if (accessorNode.state == InferenceState.Inferred) { |
+ // A circularity must have been detected; at the time it was detected, |
+ // inference for this node was completed. |
+ return; |
+ } |
+ member.setInferredType(this, typeInferrer.uri, inferredType); |
} |
- if (accessorNode.state == InferenceState.Inferred) { |
- // A circularity must have been detected; at the time it was detected, |
- // inference for this node was completed. |
- return; |
- } |
- member.setInferredType(this, typeInferrer.uri, inferredType); |
} |
accessorNode.state = InferenceState.Inferred; |
// TODO(paulberry): if type != null, then check that the type of the |