Browse Source

Fixed overload resolution bug

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
176f97354c
  1. 58
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/OverloadResolutionTests.cs
  2. 2
      ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs
  3. 1
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  4. 1
      ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs
  5. 2
      ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs

58
ICSharpCode.NRefactory.Tests/CSharp/Resolver/OverloadResolutionTests.cs

@ -44,6 +44,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -44,6 +44,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return m;
}
DefaultParameter MakeOptionalParameter(IType type, string name)
{
return new DefaultParameter(type, name) {
DefaultValue = new SimpleConstantValue(type, null)
};
}
[Test]
public void PreferIntOverUInt()
{
@ -123,5 +130,56 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -123,5 +130,56 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Assert.IsFalse(r.IsAmbiguous);
Assert.AreSame(m1, r.BestCandidate);
}
[Test]
public void SkeetEvilOverloadResolution()
{
// http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/evil-code-overload-resolution-workaround.aspx
// static void Foo<T>(T? ignored = default(T?)) where T : struct
var m1 = MakeMethod();
m1.TypeParameters.Add(new DefaultTypeParameter(m1, 0, "T") { HasValueTypeConstraint = true });
m1.Parameters.Add(MakeOptionalParameter(
NullableType.Create(m1.TypeParameters[0], context),
"ignored"
));
// class ClassConstraint<T> where T : class {}
DefaultTypeDefinition classConstraint = new DefaultTypeDefinition(dummyClass, "ClassConstraint");
classConstraint.TypeParameters.Add(new DefaultTypeParameter(classConstraint, 0, "T") { HasReferenceTypeConstraint = true });
// static void Foo<T>(ClassConstraint<T> ignored = default(ClassConstraint<T>))
// where T : class
var m2 = MakeMethod();
m2.TypeParameters.Add(new DefaultTypeParameter(m2, 0, "T") { HasReferenceTypeConstraint = true });
m2.Parameters.Add(MakeOptionalParameter(
new ParameterizedType(classConstraint, new[] { m2.TypeParameters[0] }),
"ignored"
));
// static void Foo<T>()
var m3 = MakeMethod();
m3.TypeParameters.Add(new DefaultTypeParameter(m3, 0, "T"));
// Call: Foo<int>();
OverloadResolution o;
o = new OverloadResolution(context, new ResolveResult[0], typeArguments: new[] { typeof(int).ToTypeReference().Resolve(context) });
Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(m1));
Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyContraint, o.AddCandidate(m2));
Assert.AreSame(m1, o.BestCandidate);
// Call: Foo<string>();
o = new OverloadResolution(context, new ResolveResult[0], typeArguments: new[] { typeof(string).ToTypeReference().Resolve(context) });
Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyContraint, o.AddCandidate(m1));
Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(m2));
Assert.AreSame(m2, o.BestCandidate);
// Call: Foo<int?>();
o = new OverloadResolution(context, new ResolveResult[0], typeArguments: new[] { typeof(int?).ToTypeReference().Resolve(context) });
Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyContraint, o.AddCandidate(m1));
Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyContraint, o.AddCandidate(m2));
Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(m3));
Assert.AreSame(m3, o.BestCandidate);
}
}
}

2
ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs

@ -279,6 +279,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -279,6 +279,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (tp.HasValueTypeConstraint) {
if (typeArg.IsReferenceType != false)
ConstraintsValid = false;
if (NullableType.IsNullable(typeArg))
ConstraintsValid = false;
}
if (tp.HasDefaultConstructorConstraint) {
ITypeDefinition def = typeArg.GetDefinition();

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -292,6 +292,5 @@ @@ -292,6 +292,5 @@
<ItemGroup>
<Folder Include="CSharp\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

1
ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs

@ -17,6 +17,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -17,6 +17,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary>
/// Gets the .NET value of the constant value.
/// Possible return values are:
/// - null
/// - primitive integers
/// - float/double
/// - bool

2
ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs

@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
protected static IList<T> CopyList<T>(IList<T> inputList)
{
if (inputList.Count == 0)
if (inputList == null || inputList.Count == 0)
return null;
else
return new List<T>(inputList);

Loading…
Cancel
Save