Browse Source

Move the fix for #94 into CSharpConversions.IsConstraintConvertible.

Also added a couple of additional unit tests for constraint validation.
newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
c403f389b7
  1. 11
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs
  2. 2
      ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs
  3. 52
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs

11
ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs

@ -186,8 +186,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return true; return true;
if (ImplicitReferenceConversion(fromType, toType, 0)) if (ImplicitReferenceConversion(fromType, toType, 0))
return true; return true;
if (IsBoxingConversion(fromType, toType) && !NullableType.IsNullable(fromType)) if (NullableType.IsNullable(fromType)) {
return true; // An 'object' constraint still allows nullable value types
// (object constraints don't exist in C#, but are inserted by DefaultResolvedTypeParameter.DirectBaseTypes)
if (toType.IsKnownType(KnownTypeCode.Object))
return true;
} else {
if (IsBoxingConversion(fromType, toType))
return true;
}
if (ImplicitTypeParameterConversion(fromType, toType)) if (ImplicitTypeParameterConversion(fromType, toType))
return true; return true;
return false; return false;

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

@ -507,7 +507,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (!ctors.Any()) if (!ctors.Any())
return false; return false;
} }
foreach (IType constraintType in typeParameter.DirectBaseTypes.Where(tp => !tp.IsKnownType(KnownTypeCode.Object))) { foreach (IType constraintType in typeParameter.DirectBaseTypes) {
IType c = constraintType; IType c = constraintType;
if (substitution != null) if (substitution != null)
c = c.AcceptVisitor(substitution); c = c.AcceptVisitor(substitution);

52
ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs

@ -670,6 +670,58 @@ public class C {
Assert.IsFalse(rr.IsError); Assert.IsFalse(rr.IsError);
} }
[Test]
public void MethodCanBeInvokedWithNullableTypeArgument3() {
string program = @"
public class C {
static T F<T, U>() where T : U {
return default(T);
}
void M() {
$F<int?, object>()$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.IsFalse(rr.IsError);
}
[Test]
public void MethodWithStructContraintCanBeInvokedWithValueType() {
string program = @"
public class C {
static T F<T>() where T : struct {
return default(T);
}
void M() {
$F<int>()$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.IsFalse(rr.IsError);
}
[Test]
public void MethodWithStructContraintCannotBeInvokedWithNullableValueType() {
string program = @"
public class C {
static T F<T>() where T : struct {
return default(T);
}
void M() {
$F<int?>()$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.IsTrue(rr.IsError);
Assert.AreEqual(OverloadResolutionErrors.MethodConstraintsNotSatisfied, rr.OverloadResolutionErrors);
}
[Test] [Test]
public void CanConstructGenericTypeWithNullableTypeArgument() { public void CanConstructGenericTypeWithNullableTypeArgument() {
string program = @" string program = @"

Loading…
Cancel
Save