Browse Source

Fixed type inference bug introduced in 2e40a34 - array covariance was ignored.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
4f47170535
  1. 27
      ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs
  2. 17
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs
  3. 22
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs

27
ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs

@ -629,12 +629,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -629,12 +629,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// Handle array types:
ArrayType arrU = U as ArrayType;
ArrayType arrV = V as ArrayType;
ParameterizedType pV = V as ParameterizedType;
if (arrU != null && arrV != null && arrU.Dimensions == arrV.Dimensions) {
MakeLowerBoundInference(arrU.ElementType, arrV.ElementType);
return;
} else if (arrU != null && IsGenericInterfaceImplementedByArray(pV) && arrU.Dimensions == 1) {
MakeLowerBoundInference(arrU.ElementType, pV.GetTypeArgument(0));
return;
}
// Handle parameterized types:
ParameterizedType pV = V as ParameterizedType;
if (pV != null) {
ParameterizedType uniqueBaseType = null;
foreach (IType baseU in U.GetAllBaseTypes()) {
@ -674,6 +677,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -674,6 +677,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Log.Unindent();
}
}
static bool IsGenericInterfaceImplementedByArray(ParameterizedType rt)
{
if (rt == null || rt.TypeParameterCount != 1)
return false;
switch (rt.GetDefinition().FullName) {
case "System.Collections.Generic.IEnumerable":
case "System.Collections.Generic.ICollection":
case "System.Collections.Generic.IList":
case "System.Collections.Generic.IReadOnlyList":
return true;
default:
return false;
}
}
#endregion
#region MakeUpperBoundInference (§7.5.2.10)
@ -696,12 +714,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -696,12 +714,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// Handle array types:
ArrayType arrU = U as ArrayType;
ArrayType arrV = V as ArrayType;
ParameterizedType pU = U as ParameterizedType;
if (arrV != null && arrU != null && arrU.Dimensions == arrV.Dimensions) {
MakeUpperBoundInference(arrU.ElementType, arrV.ElementType);
return;
}
} else if (arrV != null && IsGenericInterfaceImplementedByArray(pU) && arrV.Dimensions == 1) {
MakeUpperBoundInference(pU.GetTypeArgument(0), arrV.ElementType);
return;
}
// Handle parameterized types:
ParameterizedType pU = U as ParameterizedType;
if (pU != null) {
ParameterizedType uniqueBaseType = null;
foreach (IType baseV in V.GetAllBaseTypes()) {

17
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs

@ -101,5 +101,22 @@ public static class XC { @@ -101,5 +101,22 @@ public static class XC {
Assert.AreEqual("XC.Filter", mrr.Member.FullName);
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", mrr.Type.ReflectionName);
}
[Test]
public void FirstIsEligibleExtensionMethod()
{
string program = @"using System; using System.Collections.Generic;
public static class XC {
$public static TSource First<TSource>(this IEnumerable<TSource> source) {}$
}
";
var mrr = Resolve<MemberResolveResult>(program);
var targetType = compilation.FindType(typeof(string[]));
IType[] inferredTypes;
bool isEligible = CSharpResolver.IsEligibleExtensionMethod(targetType, (IMethod)mrr.Member, true, out inferredTypes);
Assert.IsTrue(isEligible);
Assert.AreEqual(1, inferredTypes.Length);
Assert.AreEqual("System.String", inferredTypes[0].ReflectionName);
}
}
}

22
ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs

@ -126,6 +126,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -126,6 +126,28 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
out success));
Assert.IsTrue(success);
}
[Test]
public void ArrayToListWithArrayCovariance()
{
ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T");
IType objectType = compilation.FindType(KnownTypeCode.Object);
IType stringType = compilation.FindType(KnownTypeCode.String);
ITypeDefinition listType = compilation.FindType(KnownTypeCode.IListOfT).GetDefinition();
// void M<T>(IList<T> a, T b);
// M(new string[0], new object());
bool success;
Assert.AreEqual(
new [] { objectType },
ti.InferTypeArguments(
new [] { tp },
new [] { new ResolveResult(new ArrayType(compilation, stringType)), new ResolveResult(objectType) },
new [] { new ParameterizedType(listType, new [] { tp }), (IType)tp },
out success));
Assert.IsTrue(success);
}
#endregion
#region Inference with Method Groups

Loading…
Cancel
Save