GetInferredReturnType() public abstract method

Gets the return type inferred when the parameter types are inferred to be parameterTypes
This method determines the return type inferred from the lambda body, which is used as part of C# type inference. Use the ReturnType property to retrieve the actual return type as determined by the target delegate type.
public abstract GetInferredReturnType ( IType parameterTypes ) : IType
parameterTypes IType
return IType
Beispiel #1
0
        /// <summary>
        /// Gets the better conversion (C# 4.0 spec, §7.5.3.3)
        /// </summary>
        /// <returns>0 = neither is better; 1 = t1 is better; 2 = t2 is better</returns>
        public int BetterConversion(ResolveResult resolveResult, IType t1, IType t2)
        {
            LambdaResolveResult lambda = resolveResult as LambdaResolveResult;

            if (lambda != null)
            {
                if (!lambda.IsAnonymousMethod)
                {
                    t1 = UnpackExpressionTreeType(t1);
                    t2 = UnpackExpressionTreeType(t2);
                }
                IMethod m1 = t1.GetDelegateInvokeMethod();
                IMethod m2 = t2.GetDelegateInvokeMethod();
                if (m1 == null || m2 == null)
                {
                    return(0);
                }
                int r = BetterConversionTarget(t1, t2);
                if (r != 0)
                {
                    return(r);
                }
                if (m1.Parameters.Count != m2.Parameters.Count)
                {
                    return(0);
                }
                IType[] parameterTypes = new IType[m1.Parameters.Count];
                for (int i = 0; i < parameterTypes.Length; i++)
                {
                    parameterTypes[i] = m1.Parameters[i].Type.Resolve(context);
                    if (!parameterTypes[i].Equals(m2.Parameters[i].Type.Resolve(context)))
                    {
                        return(0);
                    }
                }
                if (lambda.HasParameterList && parameterTypes.Length != lambda.Parameters.Count)
                {
                    return(0);
                }

                IType ret1 = m1.ReturnType.Resolve(context);
                IType ret2 = m2.ReturnType.Resolve(context);
                if (ret1.Kind == TypeKind.Void && ret2.Kind != TypeKind.Void)
                {
                    return(1);
                }
                if (ret1.Kind != TypeKind.Void && ret2.Kind == TypeKind.Void)
                {
                    return(2);
                }

                IType inferredRet = lambda.GetInferredReturnType(parameterTypes);
                return(BetterConversion(inferredRet, ret1, ret2));
            }
            else
            {
                return(BetterConversion(resolveResult.Type, t1, t2));
            }
        }
Beispiel #2
0
        void MakeOutputTypeInference(ResolveResult e, IType t)
        {
            Log.WriteLine(" MakeOutputTypeInference from " + e + " to " + t);
            // If E is an anonymous function with inferred return type  U (§7.5.2.12) and T is a delegate type or expression
            // tree type with return type Tb, then a lower-bound inference (§7.5.2.9) is made from U to Tb.
            LambdaResolveResult lrr = e as LambdaResolveResult;

            if (lrr != null)
            {
                IMethod m = GetDelegateOrExpressionTreeSignature(t);
                if (m != null)
                {
                    IType inferredReturnType;
                    if (lrr.IsImplicitlyTyped)
                    {
                        if (m.Parameters.Count != lrr.Parameters.Count)
                        {
                            return;                             // cannot infer due to mismatched parameter lists
                        }
                        TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs();
                        IType[] inferredParameterTypes         = new IType[m.Parameters.Count];
                        for (int i = 0; i < inferredParameterTypes.Length; i++)
                        {
                            IType parameterType = m.Parameters[i].Type;
                            inferredParameterTypes[i] = parameterType.AcceptVisitor(substitution);
                        }
                        inferredReturnType = lrr.GetInferredReturnType(inferredParameterTypes);
                    }
                    else
                    {
                        inferredReturnType = lrr.GetInferredReturnType(null);
                    }
                    MakeLowerBoundInference(inferredReturnType, m.ReturnType);
                    return;
                }
            }
            // Otherwise, if E is a method group and T is a delegate type or expression tree type
            // with parameter types T1…Tk and return type Tb, and overload resolution
            // of E with the types T1…Tk yields a single method with return type U, then a lower­-bound
            // inference is made from U to Tb.
            MethodGroupResolveResult mgrr = e as MethodGroupResolveResult;

            if (mgrr != null)
            {
                IMethod m = GetDelegateOrExpressionTreeSignature(t);
                if (m != null)
                {
                    ResolveResult[]           args         = new ResolveResult[m.Parameters.Count];
                    TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs();
                    for (int i = 0; i < args.Length; i++)
                    {
                        IParameter param         = m.Parameters[i];
                        IType      parameterType = param.Type.AcceptVisitor(substitution);
                        if ((param.IsRef || param.IsOut) && parameterType.Kind == TypeKind.ByReference)
                        {
                            parameterType = ((ByReferenceType)parameterType).ElementType;
                            args[i]       = new ByReferenceResolveResult(parameterType, param.IsOut);
                        }
                        else
                        {
                            args[i] = new ResolveResult(parameterType);
                        }
                    }
                    var or = mgrr.PerformOverloadResolution(compilation,
                                                            args,
                                                            allowExpandingParams: false, allowOptionalParameters: false);
                    if (or.FoundApplicableCandidate && or.BestCandidateAmbiguousWith == null)
                    {
                        IType returnType = or.GetBestCandidateWithSubstitutedTypeArguments().ReturnType;
                        MakeLowerBoundInference(returnType, m.ReturnType);
                    }
                }
                return;
            }
            // Otherwise, if E is an expression with type U, then a lower-bound inference is made from U to T.
            if (IsValidType(e.Type))
            {
                MakeLowerBoundInference(e.Type, t);
            }
        }
        static MethodDeclaration GetMethod(RefactoringContext context, LambdaResolveResult lambda, BlockStatement body,
			bool noReturnValue = false)
        {
            var method = new MethodDeclaration { Name = "Method" };

            if (noReturnValue) {
                method.ReturnType = new PrimitiveType ("void");
            } else {
                var type = lambda.GetInferredReturnType (lambda.Parameters.Select (p => p.Type).ToArray ());
                method.ReturnType = type.Name == "?" ? new PrimitiveType ("void") : context.CreateShortType (type);
            }

            foreach (var param in lambda.Parameters)
                method.Parameters.Add (new ParameterDeclaration (context.CreateShortType (param.Type), param.Name));

            method.Body = body;
            if (lambda.IsAsync)
                method.Modifiers |= Modifiers.Async;

            return method;
        }