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); } }
void CheckApplicability(Candidate candidate) { // C# 4.0 spec: §7.5.3.1 Applicable function member // Test whether parameters were mapped the correct number of arguments: int[] argumentCountPerParameter = new int[candidate.ParameterTypes.Length]; foreach (int parameterIndex in candidate.ArgumentToParameterMap) { if (parameterIndex >= 0) { argumentCountPerParameter[parameterIndex]++; } } for (int i = 0; i < argumentCountPerParameter.Length; i++) { if (candidate.IsExpandedForm && i == argumentCountPerParameter.Length - 1) { continue; // any number of arguments is fine for the params-array } if (argumentCountPerParameter[i] == 0) { if (candidate.Parameters[i].IsOptional) { candidate.HasUnmappedOptionalParameters = true; } else { candidate.AddError(OverloadResolutionErrors.MissingArgumentForRequiredParameter); } } else if (argumentCountPerParameter[i] > 1) { candidate.AddError(OverloadResolutionErrors.MultipleArgumentsForSingleParameter); } } candidate.ArgumentConversions = new Conversion[arguments.Length]; // Test whether argument passing mode matches the parameter passing mode for (int i = 0; i < arguments.Length; i++) { int parameterIndex = candidate.ArgumentToParameterMap[i]; if (parameterIndex < 0) { continue; } ByReferenceResolveResult brrr = arguments[i] as ByReferenceResolveResult; if (brrr != null) { if ((brrr.IsOut && !candidate.Parameters[parameterIndex].IsOut) || (brrr.IsRef && !candidate.Parameters[parameterIndex].IsRef)) { candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch); } } else { if (candidate.Parameters[parameterIndex].IsOut || candidate.Parameters[parameterIndex].IsRef) { candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch); } } IType parameterType = candidate.ParameterTypes[parameterIndex]; Conversion c = conversions.ImplicitConversion(arguments[i], parameterType); candidate.ArgumentConversions[i] = c; if (IsExtensionMethodInvocation && parameterIndex == 0) { // First parameter to extension method must be an identity, reference or boxing conversion if (!(c == Conversion.IdentityConversion || c == Conversion.ImplicitReferenceConversion || c == Conversion.BoxingConversion)) { candidate.AddError(OverloadResolutionErrors.ArgumentTypeMismatch); } } else { if (!c.IsValid) { candidate.AddError(OverloadResolutionErrors.ArgumentTypeMismatch); } } } }
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.Resolve(context); inferredParameterTypes[i] = parameterType.AcceptVisitor(substitution); } inferredReturnType = lrr.GetInferredReturnType(inferredParameterTypes); } else { inferredReturnType = lrr.GetInferredReturnType(null); } MakeLowerBoundInference(inferredReturnType, m.ReturnType.Resolve(context)); 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.Resolve(context); parameterType = parameterType.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(context, args, allowExtensionMethods: false, allowExpandingParams: false); if (or.FoundApplicableCandidate && or.BestCandidateAmbiguousWith == null) { IType returnType = or.BestCandidate.ReturnType.Resolve(context); MakeLowerBoundInference(returnType, m.ReturnType.Resolve(context)); } } return; } // Otherwise, if E is an expression with type U, then a lower-bound inference is made from U to T. if (e.Type != SharedTypes.UnknownType) { MakeLowerBoundInference(e.Type, t); } }