private TypeSymbol InferReturnType(ref HashSet <DiagnosticInfo> useSiteDiagnostics, out bool inferredFromSingeType) { int numberOfDistinctReturns; var resultTypes = BlockReturns.GetReturnTypes(this.Body, out numberOfDistinctReturns); inferredFromSingeType = numberOfDistinctReturns < 2; TypeSymbol bestResultType; if (resultTypes.IsDefaultOrEmpty) { bestResultType = null; } else if (resultTypes.Length == 1) { bestResultType = resultTypes[0]; } else { bestResultType = BestTypeInferrer.InferBestType(resultTypes, this.Binder.Conversions, ref useSiteDiagnostics); } if (!Symbol.IsAsync) { return(bestResultType); } // Async: if (resultTypes.IsEmpty) { // No return statements have expressions; inferred type Task: return(this.Binder.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task)); } if ((object)bestResultType == null || bestResultType.SpecialType == SpecialType.System_Void) { // If the best type was 'void', ERR_CantReturnVoid is reported while binding the "return void" // statement(s). return(null); } // Some non-void best type T was found; infer type Task<T>: return(this.Binder.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T).Construct(bestResultType)); }
private static TypeSymbol InferReturnType( BoundBlock block, Binder binder, TypeSymbol delegateType, bool isAsync, ref HashSet <DiagnosticInfo> useSiteDiagnostics, out RefKind refKind, out bool inferredFromSingleType) { int numberOfDistinctReturns; var resultTypes = BlockReturns.GetReturnTypes(block, out refKind, out numberOfDistinctReturns); inferredFromSingleType = numberOfDistinctReturns < 2; TypeSymbol bestResultType; if (resultTypes.IsDefaultOrEmpty) { bestResultType = null; } else if (resultTypes.Length == 1) { bestResultType = resultTypes[0]; } else { bestResultType = BestTypeInferrer.InferBestType(resultTypes, binder.Conversions, ref useSiteDiagnostics); } if (!isAsync) { return(bestResultType); } // For async lambdas, the return type is the return type of the // delegate Invoke method if Invoke has a Task-like return type. // Otherwise the return type is Task or Task<T>. NamedTypeSymbol taskType = null; var delegateReturnType = delegateType?.GetDelegateType()?.DelegateInvokeMethod?.ReturnType as NamedTypeSymbol; if ((object)delegateReturnType != null) { NamedTypeSymbol builderType; MethodSymbol createBuilderMethod; if (delegateReturnType.IsCustomTaskType(out builderType, out createBuilderMethod)) { taskType = delegateReturnType; } } if (resultTypes.IsEmpty) { // No return statements have expressions; use delegate InvokeMethod // or infer type Task if delegate type not available. return((object)taskType != null && taskType.Arity == 0 ? taskType : binder.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task)); } if ((object)bestResultType == null || bestResultType.SpecialType == SpecialType.System_Void) { // If the best type was 'void', ERR_CantReturnVoid is reported while binding the "return void" // statement(s). return(null); } // Some non-void best type T was found; use delegate InvokeMethod // or infer type Task<T> if delegate type not available. var taskTypeT = (object)taskType != null && taskType.Arity == 1 ? delegateReturnType.ConstructedFrom : binder.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T); return(taskTypeT.Construct(bestResultType)); }