示例#1
0
            public static ImmutableArray <TypeSymbol> GetReturnTypes(BoundBlock block, out int numberOfDistinctReturns)
            {
                var inferrer = new BlockReturns();

                inferrer.Visit(block);
                var result = inferrer.types.ToImmutableAndFree();

                numberOfDistinctReturns = result.Length;
                if (inferrer.hasReturnWithoutArgument)
                {
                    numberOfDistinctReturns += 1;
                }

                return(result);
            }
示例#2
0
        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));
        }
示例#3
0
        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));
        }
示例#4
0
            public static ImmutableArray<TypeSymbol> GetReturnTypes(BoundBlock block, out int numberOfDistinctReturns)
            {
                var inferrer = new BlockReturns();
                inferrer.Visit(block);
                var result = inferrer._types.ToImmutableAndFree();
                numberOfDistinctReturns = result.Length;
                if (inferrer._hasReturnWithoutArgument)
                {
                    numberOfDistinctReturns += 1;
                }

                return result;
            }