//
// Uwrap delegate from Expression<T>
//
- q = TypeManager.GetTypeArguments (q)[0];
- p = TypeManager.GetTypeArguments (p)[0];
+ q = TypeManager.GetTypeArguments (q) [0];
+ p = TypeManager.GetTypeArguments (p) [0];
}
var p_m = Delegate.GetInvokeMethod (p);
// if p has a return type Y, and q is void returning, then C1 is the better conversion.
//
if (q.Kind == MemberKind.Void) {
- return p.Kind != MemberKind.Void ? 1: 0;
+ return p.Kind != MemberKind.Void ? 1 : 0;
}
- var am = (AnonymousMethodExpression) a.Expr;
+ var am = (AnonymousMethodExpression)a.Expr;
//
// When anonymous method is an asynchronous, and P has a return type Task<Y1>, and Q has a return type Task<Y2>
//
if (p.IsGenericTask || q.IsGenericTask) {
if (am.Block.IsAsync && p.IsGenericTask && q.IsGenericTask) {
- q = q.TypeArguments[0];
- p = p.TypeArguments[0];
+ q = q.TypeArguments [0];
+ p = p.TypeArguments [0];
}
}
if (argument_type == q)
return 2;
- //
- // The parameters are identicial and return type is not void, use better type conversion
- // on return type to determine better one
- //
- return BetterTypeConversion (ec, p, q);
+ return IsBetterConversionTarget (ec, p, q);
+ }
+
+ static int IsBetterConversionTarget (ResolveContext rc, TypeSpec p, TypeSpec q)
+ {
+ if ((p.Kind == MemberKind.Delegate || p.IsExpressionTreeType) && (q.Kind == MemberKind.Delegate || q.IsExpressionTreeType)) {
+
+ if (p.Kind != MemberKind.Delegate) {
+ p = TypeManager.GetTypeArguments (p) [0];
+ }
+
+ if (q.Kind != MemberKind.Delegate) {
+ q = TypeManager.GetTypeArguments (q) [0];
+ }
+
+ var p_m = Delegate.GetInvokeMethod (p);
+ var q_m = Delegate.GetInvokeMethod (q);
+
+ p = p_m.ReturnType;
+ q = q_m.ReturnType;
+
+ //
+ // if p is void returning, and q has a return type Y, then C2 is the better conversion.
+ //
+ if (p.Kind == MemberKind.Void) {
+ return q.Kind != MemberKind.Void ? 2 : 0;
+ }
+
+ //
+ // if p has a return type Y, and q is void returning, then C1 is the better conversion.
+ //
+ if (q.Kind == MemberKind.Void) {
+ return p.Kind != MemberKind.Void ? 1 : 0;
+ }
+
+ return IsBetterConversionTarget (rc, p, q);
+ }
+
+ if (p.IsGenericTask && q.IsGenericTask) {
+ q = q.TypeArguments [0];
+ p = p.TypeArguments [0];
+ return IsBetterConversionTarget (rc, p, q);
+ }
+
+ if (p.IsNullableType) {
+ p = Nullable.NullableInfo.GetUnderlyingType (p);
+ if (!BuiltinTypeSpec.IsPrimitiveType (p))
+ return 0;
+ }
+
+ if (q.IsNullableType) {
+ q = Nullable.NullableInfo.GetUnderlyingType (q);
+ if (!BuiltinTypeSpec.IsPrimitiveType (q))
+ return 0;
+ }
+
+ return BetterTypeConversion (rc, p, q);
}
//
return 1;
}
- // FIXME: handle lifted operators
-
// TODO: this is expensive
Expression p_tmp = new EmptyExpression (p);
Expression q_tmp = new EmptyExpression (q);
--- /dev/null
+using System;
+using System.Threading.Tasks;
+using System.Linq.Expressions;
+
+public static class Program
+{
+ public delegate void DelegateVoid (int arg);
+ public delegate int DelegateInt (string arg);
+
+ public static int Main ()
+ {
+ Foo (Bar);
+
+ TT (null);
+ NN (0);
+ NN2 (1);
+ Complex (null);
+ return 0;
+ }
+
+ static void TT (Task<string> a)
+ {
+ }
+
+ static void TT (Task<object> b)
+ {
+ throw new ApplicationException ("wrong overload");
+ }
+
+ static void NN (sbyte a)
+ {
+ }
+
+ static void NN (uint? b)
+ {
+ throw new ApplicationException ("wrong overload");
+ }
+
+ static void NN2 (sbyte? a)
+ {
+ }
+
+ static void NN2 (uint? b)
+ {
+ throw new ApplicationException ("wrong overload");
+ }
+
+ public static void Bar (int arg)
+ {
+ }
+
+ public static int Bar (string arg)
+ {
+ return 2;
+ }
+
+ public static void Foo (DelegateVoid input)
+ {
+ throw new ApplicationException ("wrong overload");
+ }
+
+ public static void Foo (DelegateInt input)
+ {
+ }
+
+ static void Complex (Expression<Func<Task<short>>> arg)
+ {
+ }
+
+ static void Complex (Expression<Func<Task<ulong>>> arg)
+ {
+ throw new ApplicationException ("wrong overload");
+ }
+}
\ No newline at end of file
</method>
</type>
</test>
+ <test name="test-935.cs">
+ <type name="Program">
+ <method name="Int32 Main()" attrs="150">
+ <size>73</size>
+ </method>
+ <method name="Void TT(System.Threading.Tasks.Task`1[System.String])" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="Void TT(System.Threading.Tasks.Task`1[System.Object])" attrs="145">
+ <size>12</size>
+ </method>
+ <method name="Void NN(SByte)" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="Void NN(System.Nullable`1[System.UInt32])" attrs="145">
+ <size>12</size>
+ </method>
+ <method name="Void NN2(System.Nullable`1[System.SByte])" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="Void NN2(System.Nullable`1[System.UInt32])" attrs="145">
+ <size>12</size>
+ </method>
+ <method name="Void Bar(Int32)" attrs="150">
+ <size>2</size>
+ </method>
+ <method name="Int32 Bar(System.String)" attrs="150">
+ <size>10</size>
+ </method>
+ <method name="Void Foo(DelegateVoid)" attrs="150">
+ <size>12</size>
+ </method>
+ <method name="Void Foo(DelegateInt)" attrs="150">
+ <size>2</size>
+ </method>
+ <method name="Void Complex(System.Linq.Expressions.Expression`1[System.Func`1[System.Threading.Tasks.Task`1[System.Int16]]])" attrs="145">
+ <size>2</size>
+ </method>
+ <method name="Void Complex(System.Linq.Expressions.Expression`1[System.Func`1[System.Threading.Tasks.Task`1[System.UInt64]]])" attrs="145">
+ <size>12</size>
+ </method>
+ </type>
+ <type name="Program+DelegateVoid">
+ <method name="Void Invoke(Int32)" attrs="454">
+ <size>0</size>
+ </method>
+ <method name="System.IAsyncResult BeginInvoke(Int32, System.AsyncCallback, System.Object)" attrs="454">
+ <size>0</size>
+ </method>
+ <method name="Void EndInvoke(System.IAsyncResult)" attrs="454">
+ <size>0</size>
+ </method>
+ <method name="Void .ctor(Object, IntPtr)" attrs="6278">
+ <size>0</size>
+ </method>
+ </type>
+ <type name="Program+DelegateInt">
+ <method name="Int32 Invoke(System.String)" attrs="454">
+ <size>0</size>
+ </method>
+ <method name="System.IAsyncResult BeginInvoke(System.String, System.AsyncCallback, System.Object)" attrs="454">
+ <size>0</size>
+ </method>
+ <method name="Int32 EndInvoke(System.IAsyncResult)" attrs="454">
+ <size>0</size>
+ </method>
+ <method name="Void .ctor(Object, IntPtr)" attrs="6278">
+ <size>0</size>
+ </method>
+ </type>
+ </test>
<test name="test-94.cs">
<type name="Base">
<method name="Int32 IVehicle.Start()" attrs="481">