Skip to content

Commit

Permalink
Don't report user operator error during probing user conversions. Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
marek-safar committed Feb 9, 2013
1 parent eb0d7ef commit ff813f6
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 18 deletions.
50 changes: 32 additions & 18 deletions mcs/mcs/convert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ public static bool ImplicitConversionExists (ResolveContext ec, Expression expr,
if (expr.Type == InternalType.Arglist)
return target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec;

return ImplicitUserConversion (ec, expr, target_type, Location.Null) != null;
return UserDefinedConversion (ec, expr, target_type, true, true, Location.Null) != null;
}

//
Expand Down Expand Up @@ -917,17 +917,20 @@ static TypeSpec FindMostEncompassingType (IList<TypeSpec> types)
//
static TypeSpec FindMostSpecificSource (List<MethodSpec> list, TypeSpec sourceType, Expression source, bool apply_explicit_conv_rules)
{
var src_types_set = new TypeSpec [list.Count];
TypeSpec[] src_types_set = null;

//
// Try exact match first, if any operator converts from S then Sx = S
//
for (int i = 0; i < src_types_set.Length; ++i) {
for (int i = 0; i < list.Count; ++i) {
TypeSpec param_type = list [i].Parameters.Types [0];

if (param_type == sourceType)
return param_type;

if (src_types_set == null)
src_types_set = new TypeSpec [list.Count];

src_types_set [i] = param_type;
}

Expand Down Expand Up @@ -961,7 +964,7 @@ static TypeSpec FindMostSpecificSource (List<MethodSpec> list, TypeSpec sourceTy
static public TypeSpec FindMostSpecificTarget (IList<MethodSpec> list,
TypeSpec target, bool apply_explicit_conv_rules)
{
var tgt_types_set = new List<TypeSpec> ();
List<TypeSpec> tgt_types_set = null;

//
// If any operator converts to T then Tx = T
Expand All @@ -971,6 +974,12 @@ static public TypeSpec FindMostSpecificTarget (IList<MethodSpec> list,
if (ret_type == target)
return ret_type;

if (tgt_types_set == null) {
tgt_types_set = new List<TypeSpec> (list.Count);
} else if (tgt_types_set.Contains (ret_type)) {
continue;
}

tgt_types_set.Add (ret_type);
}

Expand Down Expand Up @@ -1005,15 +1014,15 @@ static public TypeSpec FindMostSpecificTarget (IList<MethodSpec> list,
/// </summary>
static public Expression ImplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
{
return UserDefinedConversion (ec, source, target, true, loc);
return UserDefinedConversion (ec, source, target, true, false, loc);
}

/// <summary>
/// User-defined Explicit conversions
/// </summary>
static Expression ExplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc)
{
return UserDefinedConversion (ec, source, target, false, loc);
return UserDefinedConversion (ec, source, target, false, false, loc);
}

static void FindApplicableUserDefinedConversionOperators (IList<MemberSpec> operators, Expression source, TypeSpec target, bool implicitOnly, ref List<MethodSpec> candidates)
Expand Down Expand Up @@ -1077,7 +1086,7 @@ static void FindApplicableUserDefinedConversionOperators (IList<MemberSpec> oper
//
// User-defined conversions
//
static Expression UserDefinedConversion (ResolveContext ec, Expression source, TypeSpec target, bool implicitOnly, Location loc)
static Expression UserDefinedConversion (ResolveContext ec, Expression source, TypeSpec target, bool implicitOnly, bool probingOnly, Location loc)
{
List<MethodSpec> candidates = null;

Expand Down Expand Up @@ -1173,19 +1182,24 @@ static Expression UserDefinedConversion (ResolveContext ec, Expression source, T
}

if (most_specific_operator == null) {
MethodSpec ambig_arg = null;
foreach (var candidate in candidates) {
if (candidate.ReturnType == t_x)
most_specific_operator = candidate;
else if (candidate.Parameters.Types[0] == s_x)
ambig_arg = candidate;
//
// Unless running in probing more
//
if (!probingOnly) {
MethodSpec ambig_arg = null;
foreach (var candidate in candidates) {
if (candidate.ReturnType == t_x)
most_specific_operator = candidate;
else if (candidate.Parameters.Types[0] == s_x)
ambig_arg = candidate;
}

ec.Report.Error (457, loc,
"Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'",
ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (),
source.Type.GetSignatureForError (), target.GetSignatureForError ());
}

ec.Report.Error (457, loc,
"Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'",
ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (),
source.Type.GetSignatureForError (), target.GetSignatureForError ());

return ErrorExpression.Instance;
}
}
Expand Down
57 changes: 57 additions & 0 deletions mcs/tests/test-864.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
class MainClass
{
static int Foo (double d)
{
return 0;
}

static int Foo (int d)
{
return 100;
}

public static int Main ()
{
decimal a = new A ();
long b = new B ();
if (b != 7)
return 1;

if (Foo (new B2 ()) != 100)
return 1;

return 0;
}
}

public class A
{
public static implicit operator int (A a)
{
return 6;
}
}

public class B : A
{
public static implicit operator int (B b)
{
return 7;
}
}

public class A2
{
public static implicit operator double (A2 a)
{
return 2;
}
}

public class B2 : A2
{
public static implicit operator int (B2 b)
{
return 3;
}
}
48 changes: 48 additions & 0 deletions mcs/tests/ver-il-net_4_5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46513,6 +46513,54 @@
</method>
</type>
</test>
<test name="test-864.cs">
<type name="MainClass">
<method name="Int32 Foo(Double)" attrs="145">
<size>10</size>
</method>
<method name="Int32 Foo(Int32)" attrs="145">
<size>11</size>
</method>
<method name="Int32 Main()" attrs="150">
<size>82</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
</type>
<type name="A">
<method name="Int32 op_Implicit(A)" attrs="2198">
<size>10</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
</type>
<type name="B">
<method name="Int32 op_Implicit(B)" attrs="2198">
<size>10</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
</type>
<type name="A2">
<method name="Double op_Implicit(A2)" attrs="2198">
<size>18</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
</type>
<type name="B2">
<method name="Int32 op_Implicit(B2)" attrs="2198">
<size>10</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
</type>
</test>
<test name="test-87.cs">
<type name="Top">
<method name="Int32 Main()" attrs="150">
Expand Down

0 comments on commit ff813f6

Please sign in to comment.