public void ArrayToEnumerable() { ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T"); IType stringType = compilation.FindType(KnownTypeCode.String); ITypeDefinition enumerableType = compilation.FindType(KnownTypeCode.IEnumerableOfT).GetDefinition(); bool success; Assert.AreEqual( new [] { stringType }, ti.InferTypeArguments(new [] { tp }, new [] { new ResolveResult(new ArrayType(compilation, stringType)) }, new [] { new ParameterizedType(enumerableType, new [] { tp }) }, out success)); Assert.IsTrue(success); }
void RunTypeInference(Candidate candidate) { IMethod method = candidate.Member as IMethod; if (method == null || method.TypeParameters.Count == 0) { if (explicitlyGivenTypeArguments != null) { // method does not expect type arguments, but was given some candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments); } return; } // The method is generic: if (explicitlyGivenTypeArguments != null) { if (explicitlyGivenTypeArguments.Length == method.TypeParameters.Count) { candidate.InferredTypes = explicitlyGivenTypeArguments; } else { candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments); // wrong number of type arguments given, so truncate the list or pad with UnknownType candidate.InferredTypes = new IType[method.TypeParameters.Count]; for (int i = 0; i < candidate.InferredTypes.Length; i++) { if (i < explicitlyGivenTypeArguments.Length) { candidate.InferredTypes[i] = explicitlyGivenTypeArguments[i]; } else { candidate.InferredTypes[i] = SharedTypes.UnknownType; } } } } else { TypeInference ti = new TypeInference(context, conversions); bool success; candidate.InferredTypes = ti.InferTypeArguments(method.TypeParameters, arguments, candidate.ParameterTypes, out success); if (!success) { candidate.AddError(OverloadResolutionErrors.TypeInferenceFailed); } } // Now substitute in the formal parameters: var substitution = new ConstraintValidatingSubstitution(candidate.InferredTypes, this); for (int i = 0; i < candidate.ParameterTypes.Length; i++) { candidate.ParameterTypes[i] = candidate.ParameterTypes[i].AcceptVisitor(substitution); } if (!substitution.ConstraintsValid) { candidate.AddError(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint); } }
public void ArrayToEnumerable() { ITypeParameter tp = new DefaultTypeParameter(EntityType.Method, 0, "T"); IType stringType = KnownTypeReference.String.Resolve(ctx); ITypeDefinition enumerableType = ctx.GetTypeDefinition(typeof(IEnumerable <>)); bool success; Assert.AreEqual( new [] { stringType }, ti.InferTypeArguments(new [] { tp }, new [] { new ResolveResult(new ArrayType(stringType)) }, new [] { new ParameterizedType(enumerableType, new [] { tp }) }, out success)); Assert.IsTrue(success); }
void RunTypeInference(Candidate candidate) { if (candidate.TypeParameters == null) { if (explicitlyGivenTypeArguments != null) { // method does not expect type arguments, but was given some candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments); } // Grab new parameter types: ResolveParameterTypes(candidate, true); return; } ParameterizedType parameterizedDeclaringType = candidate.Member.DeclaringType as ParameterizedType; IList <IType> classTypeArguments; if (parameterizedDeclaringType != null) { classTypeArguments = parameterizedDeclaringType.TypeArguments; } else { classTypeArguments = null; } // The method is generic: if (explicitlyGivenTypeArguments != null) { if (explicitlyGivenTypeArguments.Length == candidate.TypeParameters.Count) { candidate.InferredTypes = explicitlyGivenTypeArguments; } else { candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments); // wrong number of type arguments given, so truncate the list or pad with UnknownType candidate.InferredTypes = new IType[candidate.TypeParameters.Count]; for (int i = 0; i < candidate.InferredTypes.Length; i++) { if (i < explicitlyGivenTypeArguments.Length) { candidate.InferredTypes[i] = explicitlyGivenTypeArguments[i]; } else { candidate.InferredTypes[i] = SpecialType.UnknownType; } } } } else { TypeInference ti = new TypeInference(compilation, conversions); bool success; candidate.InferredTypes = ti.InferTypeArguments(candidate.TypeParameters, arguments, candidate.ParameterTypes, out success, classTypeArguments); if (!success) { candidate.AddError(OverloadResolutionErrors.TypeInferenceFailed); } } // Now substitute in the formal parameters: var substitution = new ConstraintValidatingSubstitution(classTypeArguments, candidate.InferredTypes, this); for (int i = 0; i < candidate.ParameterTypes.Length; i++) { candidate.ParameterTypes[i] = candidate.ParameterTypes[i].AcceptVisitor(substitution); } if (!substitution.ConstraintsValid) { candidate.AddError(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint); } }
void RunTypeInference(Candidate candidate) { IMethod method = candidate.Member as IMethod; if (method == null || method.TypeParameters.Count == 0) { if (explicitlyGivenTypeArguments != null) { // method does not expect type arguments, but was given some candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments); } return; } ParameterizedType parameterizedDeclaringType = candidate.Member.DeclaringType as ParameterizedType; IList<IType> classTypeArguments; if (parameterizedDeclaringType != null) { classTypeArguments = parameterizedDeclaringType.TypeArguments; } else { classTypeArguments = null; } // The method is generic: if (explicitlyGivenTypeArguments != null) { if (explicitlyGivenTypeArguments.Length == method.TypeParameters.Count) { candidate.InferredTypes = explicitlyGivenTypeArguments; } else { candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments); // wrong number of type arguments given, so truncate the list or pad with UnknownType candidate.InferredTypes = new IType[method.TypeParameters.Count]; for (int i = 0; i < candidate.InferredTypes.Length; i++) { if (i < explicitlyGivenTypeArguments.Length) candidate.InferredTypes[i] = explicitlyGivenTypeArguments[i]; else candidate.InferredTypes[i] = SpecialType.UnknownType; } } } else { TypeInference ti = new TypeInference(compilation, conversions); bool success; candidate.InferredTypes = ti.InferTypeArguments(candidate.TypeParameters, arguments, candidate.ParameterTypes, out success, classTypeArguments); if (!success) candidate.AddError(OverloadResolutionErrors.TypeInferenceFailed); } // Now substitute in the formal parameters: var substitution = new ConstraintValidatingSubstitution(classTypeArguments, candidate.InferredTypes, this); for (int i = 0; i < candidate.ParameterTypes.Length; i++) { candidate.ParameterTypes[i] = candidate.ParameterTypes[i].AcceptVisitor(substitution); } if (!substitution.ConstraintsValid) candidate.AddError(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint); }
static bool IsEligibleExtensionMethod(ICompilation compilation, CSharpConversions conversions, IType targetType, IMethod method, bool useTypeInference, out IType[] outInferredTypes) { outInferredTypes = null; if (targetType == null) return true; if (method.Parameters.Count == 0) return false; IType thisParameterType = method.Parameters[0].Type; if (useTypeInference && method.TypeParameters.Count > 0) { // We need to infer type arguments from targetType: TypeInference ti = new TypeInference(compilation, conversions); ResolveResult[] arguments = { new ResolveResult(targetType) }; IType[] parameterTypes = { method.Parameters[0].Type }; bool success; var inferredTypes = ti.InferTypeArguments(method.TypeParameters, arguments, parameterTypes, out success); var substitution = new TypeParameterSubstitution(null, inferredTypes); // Validate that the types that could be inferred (aren't unknown) satisfy the constraints: bool hasInferredTypes = false; for (int i = 0; i < inferredTypes.Length; i++) { if (inferredTypes[i].Kind != TypeKind.Unknown && inferredTypes[i].Kind != TypeKind.UnboundTypeArgument) { hasInferredTypes = true; if (!OverloadResolution.ValidateConstraints(method.TypeParameters[i], inferredTypes[i], substitution, conversions)) return false; } else { inferredTypes[i] = method.TypeParameters[i]; // do not substitute types that could not be inferred } } if (hasInferredTypes) outInferredTypes = inferredTypes; thisParameterType = thisParameterType.AcceptVisitor(substitution); } Conversion c = conversions.ImplicitConversion(targetType, thisParameterType); return c.IsValid && (c.IsIdentityConversion || c.IsReferenceConversion || c.IsBoxingConversion); }