From: Marek Safar Date: Wed, 20 Oct 2010 08:09:22 +0000 (+0100) Subject: More work on ambiguous named arguments X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=3e86b47fd4c0c9e9e67e9897ade8fce78a003bc1;hp=9fa1aa9f490713c0aecfb49873568cb0fdee1b78;p=mono.git More work on ambiguous named arguments --- diff --git a/mcs/errors/cs0121-13.cs b/mcs/errors/cs0121-13.cs new file mode 100644 index 00000000000..0d33c836a70 --- /dev/null +++ b/mcs/errors/cs0121-13.cs @@ -0,0 +1,19 @@ +// CS0121: The call is ambiguous between the following methods or properties: `C.Foo(int, long, params string[])' and `C.Foo(long, int, params string[])' +// Line: 9 + +class C +{ + public static void Main () + { + var d = new C (); + d.Foo (b: 1, x: "", a : 2); + } + + public void Foo (int a, long b, params string[] x) + { + } + + public void Foo (long b, int a, params string[] x) + { + } +} diff --git a/mcs/errors/cs0121-14.cs b/mcs/errors/cs0121-14.cs new file mode 100644 index 00000000000..95780309048 --- /dev/null +++ b/mcs/errors/cs0121-14.cs @@ -0,0 +1,19 @@ +// CS0121: The call is ambiguous between the following methods or properties: `C.Foo(int, params string[])' and `C.Foo(string[], int)' +// Line: 9 + +class C +{ + public static void Main () + { + var d = new C (); + d.Foo (x: 1, y: new [] { "" }); + } + + public void Foo (int x, params string[] y) + { + } + + public void Foo (string[] y, int x) + { + } +} diff --git a/mcs/errors/cs0121-15.cs b/mcs/errors/cs0121-15.cs new file mode 100644 index 00000000000..ccef7a60269 --- /dev/null +++ b/mcs/errors/cs0121-15.cs @@ -0,0 +1,29 @@ +// CS0121: The call is ambiguous between the following methods or properties: `A.Foo(int, string)' and `A.Foo(string, int)' +// Line: 27 + +class A +{ + public virtual void Foo (int a2, string b2) + { + } + + public void Foo (string b, int a) + { + } +} + +class B : A +{ + public override void Foo (int a, string b) + { + } +} + +class C +{ + public static void Main () + { + B b = new B (); + b.Foo (a: 1, b: "x"); + } +} diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index a312c35864b..98f67001bbd 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -3228,10 +3228,12 @@ namespace Mono.CSharp { { public readonly MemberSpec Member; public readonly bool Expanded; + public readonly AParametersCollection Parameters; - public AmbiguousCandidate (MemberSpec member, bool expanded) + public AmbiguousCandidate (MemberSpec member, AParametersCollection parameters, bool expanded) { Member = member; + Parameters = parameters; Expanded = expanded; } } @@ -3430,8 +3432,8 @@ namespace Mono.CSharp { /// false if candidate ain't better /// true if candidate is better than the current best match /// - static bool BetterFunction (ResolveContext ec, Arguments args, MemberSpec candidate, bool candidate_params, - MemberSpec best, bool best_params) + static bool BetterFunction (ResolveContext ec, Arguments args, MemberSpec candidate, AParametersCollection cparam, bool candidate_params, + MemberSpec best, AParametersCollection bparam, bool best_params) { AParametersCollection candidate_pd = ((IParametersMember) candidate).Parameters; AParametersCollection best_pd = ((IParametersMember) best).Parameters; @@ -3440,6 +3442,7 @@ namespace Mono.CSharp { bool same = true; int args_count = args == null ? 0 : args.Count; int j = 0; + TypeSpec ct, bt; for (int c_idx = 0, b_idx = 0; j < args_count; ++j, ++c_idx, ++b_idx) { Argument a = args[j]; @@ -3447,17 +3450,34 @@ namespace Mono.CSharp { if (a.IsDefaultArgument) break; - TypeSpec ct = candidate_pd.Types[c_idx]; - TypeSpec bt = best_pd.Types[b_idx]; + // + // When comparing named argument the parameter type index has to be looked up + // in original parameter set (override version for virtual members) + // + NamedArgument na = a as NamedArgument; + if (na != null) { + int idx = cparam.GetParameterIndexByName (na.Name); + ct = candidate_pd.Types[idx]; + if (candidate_params && candidate_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS) + ct = TypeManager.GetElementType (ct); + + idx = bparam.GetParameterIndexByName (na.Name); + bt = best_pd.Types[idx]; + if (best_params && best_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS) + bt = TypeManager.GetElementType (bt); + } else { + ct = candidate_pd.Types[c_idx]; + bt = best_pd.Types[b_idx]; - if (candidate_params && candidate_pd.FixedParameters[c_idx].ModFlags == Parameter.Modifier.PARAMS) { - ct = TypeManager.GetElementType (ct); - --c_idx; - } + if (candidate_params && candidate_pd.FixedParameters[c_idx].ModFlags == Parameter.Modifier.PARAMS) { + ct = TypeManager.GetElementType (ct); + --c_idx; + } - if (best_params && best_pd.FixedParameters[b_idx].ModFlags == Parameter.Modifier.PARAMS) { - bt = TypeManager.GetElementType (bt); - --b_idx; + if (best_params && best_pd.FixedParameters[b_idx].ModFlags == Parameter.Modifier.PARAMS) { + bt = TypeManager.GetElementType (bt); + --b_idx; + } } if (ct == bt) @@ -3505,6 +3525,7 @@ namespace Mono.CSharp { // Prefer non-optional version // // LAMESPEC: Specification claims this should be done at last but the opposite is true + // if (candidate_params == best_params && candidate_pd.Count != best_pd.Count) { if (candidate_pd.Count >= best_pd.Count) return false; @@ -3550,8 +3571,15 @@ namespace Mono.CSharp { bool specific_at_least_once = false; for (j = 0; j < candidate_param_count; ++j) { - var ct = candidate_def_pd.Types[j]; - var bt = best_def_pd.Types[j]; + NamedArgument na = args_count == 0 ? null : args [j] as NamedArgument; + if (na != null) { + ct = candidate_def_pd.Types[cparam.GetParameterIndexByName (na.Name)]; + bt = best_def_pd.Types[bparam.GetParameterIndexByName (na.Name)]; + } else { + ct = candidate_def_pd.Types[j]; + bt = best_def_pd.Types[j]; + } + if (ct == bt) continue; TypeSpec specific = MoreSpecific (ct, bt); @@ -4053,7 +4081,7 @@ namespace Mono.CSharp { } // Is the new candidate better - if (BetterFunction (rc, candidate_args, member, params_expanded_form, best_candidate, best_candidate_params)) { + if (BetterFunction (rc, candidate_args, member, pm.Parameters, params_expanded_form, best_candidate, best_parameter_member.Parameters, best_candidate_params)) { best_candidate = member; best_candidate_args = candidate_args; best_candidate_params = params_expanded_form; @@ -4064,7 +4092,7 @@ namespace Mono.CSharp { if (ambiguous_candidates == null) ambiguous_candidates = new List (); - ambiguous_candidates.Add (new AmbiguousCandidate (member, params_expanded_form)); + ambiguous_candidates.Add (new AmbiguousCandidate (member, pm.Parameters, params_expanded_form)); } } @@ -4136,7 +4164,7 @@ namespace Mono.CSharp { for (int ix = 0; ix < ambiguous_candidates.Count; ix++) { var candidate = ambiguous_candidates [ix]; - if (!BetterFunction (rc, candidate_args, best_candidate, best_candidate_params, candidate.Member, candidate.Expanded)) { + if (!BetterFunction (rc, candidate_args, best_candidate, best_parameter_member.Parameters, best_candidate_params, candidate.Member, candidate.Parameters, candidate.Expanded)) { var ambiguous = candidate.Member; if (custom_errors == null || !custom_errors.AmbiguousCandidates (rc, best_candidate, ambiguous)) { rc.Report.SymbolRelatedToPreviousError (best_candidate); diff --git a/mcs/tests/test-named-06.cs b/mcs/tests/test-named-06.cs new file mode 100644 index 00000000000..773d3690f26 --- /dev/null +++ b/mcs/tests/test-named-06.cs @@ -0,0 +1,26 @@ +class C +{ + public static int Main () + { + var d = new C (); + if (d.Foo (x: 1, y : 2) != 3) + return 1; + + return 0; + } + + public int Foo (int x, long y, string a = "a") + { + return 1; + } + + public int Foo (int x, long y, params string[] args) + { + return 2; + } + + public int Foo (long y, int x) + { + return 3; + } +} diff --git a/mcs/tests/ver-il-dmcs.xml b/mcs/tests/ver-il-dmcs.xml index d43631c72e2..6ea89868af7 100644 --- a/mcs/tests/ver-il-dmcs.xml +++ b/mcs/tests/ver-il-dmcs.xml @@ -2582,6 +2582,36 @@ + + + + 7 + + + 7 + + + 7 + + + + + 2 + + + 1 + + + 2 + + + 854 + + + 7 + + + @@ -26590,7 +26620,7 @@ 2 - 90 + 211 7 @@ -51201,6 +51231,25 @@ + + + + 25 + + + 2 + + + 2 + + + 2 + + + 7 + + + diff --git a/mcs/tests/ver-il-gmcs.xml b/mcs/tests/ver-il-gmcs.xml index b4c9de5f6fb..91f184a96b0 100644 --- a/mcs/tests/ver-il-gmcs.xml +++ b/mcs/tests/ver-il-gmcs.xml @@ -24009,7 +24009,7 @@ 2 - 90 + 211 7 @@ -48620,6 +48620,25 @@ + + + + 25 + + + 2 + + + 2 + + + 2 + + + 7 + + +