| 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
|
|
|