diff options
author | Marek Safar <marek.safar@gmail.com> | 2013-07-04 16:51:00 +0400 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2013-07-10 17:43:23 +0400 |
commit | 9f4d1dc49fa441741aeae72ab60e07dfb6d1549b (patch) | |
tree | 28d8bb1ff05ffe673873787596ef14561b0045d1 /mcs | |
parent | fbfd2ab4068167810e2676f60652810adc8b8979 (diff) |
Interface members are hidden by class members if a type parameter has an effective base other than object
Diffstat (limited to 'mcs')
-rw-r--r-- | mcs/mcs/ecore.cs | 60 | ||||
-rw-r--r-- | mcs/tests/gtest-589.cs | 40 | ||||
-rw-r--r-- | mcs/tests/ver-il-net_4_5.xml | 32 |
3 files changed, 131 insertions, 1 deletions
diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index e24e008e809..b9e4f48c052 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -778,8 +778,18 @@ namespace Mono.CSharp { } if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) { - if (member is MethodSpec) + if (member is MethodSpec) { + // + // Interface members that are hidden by class members are removed from the set. This + // step only has an effect if T is a type parameter and T has both an effective base + // class other than object and a non-empty effective interface set + // + var tps = queried_type as TypeParameterSpec; + if (tps != null && tps.HasTypeConstraint) + members = RemoveHiddenTypeParameterMethods (members); + return new MethodGroupExpr (members, queried_type, loc); + } if (!Invocation.IsMemberInvocable (member)) continue; @@ -834,6 +844,54 @@ namespace Mono.CSharp { return null; } + static IList<MemberSpec> RemoveHiddenTypeParameterMethods (IList<MemberSpec> members) + { + if (members.Count < 2) + return members; + + // + // If M is a method, then all non-method members declared in an interface declaration + // are removed from the set, and all methods with the same signature as M declared in + // an interface declaration are removed from the set + // + + bool copied = false; + for (int i = 0; i < members.Count; ++i) { + var method = members[i] as MethodSpec; + if (method == null) { + if (!copied) { + copied = true; + members = new List<MemberSpec> (members); + } + + members.RemoveAt (i--); + continue; + } + + if (!method.DeclaringType.IsInterface) + continue; + + for (int ii = 0; ii < members.Count; ++ii) { + var candidate = members[ii] as MethodSpec; + if (candidate == null || !candidate.DeclaringType.IsClass) + continue; + + if (!TypeSpecComparer.Override.IsEqual (candidate.Parameters, method.Parameters)) + continue; + + if (!copied) { + copied = true; + members = new List<MemberSpec> (members); + } + + members.RemoveAt (i--); + break; + } + } + + return members; + } + protected virtual void Error_NegativeArrayIndex (ResolveContext ec, Location loc) { throw new NotImplementedException (); diff --git a/mcs/tests/gtest-589.cs b/mcs/tests/gtest-589.cs new file mode 100644 index 00000000000..4599fe2fbd6 --- /dev/null +++ b/mcs/tests/gtest-589.cs @@ -0,0 +1,40 @@ +using System; + +public class Z : IGenericInterface<Z> +{ + public Z Start () + { + return this; + } + + Z IGenericInterface<Z>.Start () + { + throw new ApplicationException (); + } +} + +public interface IGenericInterface<T> +{ + T Start (); +} + +public class A<T> where T : Z, IGenericInterface<int> +{ + public void SomeOperation (T t) + { + t.Start (); + } +} + +public class C : Z, IGenericInterface<int> +{ + int IGenericInterface<int>.Start () + { + throw new NotImplementedException (); + } + + public static void Main () + { + new A<C> ().SomeOperation (new C ()); + } +}
\ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml index 70906f33b41..a317e7489b5 100644 --- a/mcs/tests/ver-il-net_4_5.xml +++ b/mcs/tests/ver-il-net_4_5.xml @@ -18346,6 +18346,38 @@ </method>
</type>
</test>
+ <test name="gtest-589.cs">
+ <type name="Z">
+ <method name="Z Start()" attrs="134">
+ <size>10</size>
+ </method>
+ <method name="Z IGenericInterface<Z>.Start()" attrs="481">
+ <size>7</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="A`1[T]">
+ <method name="Void SomeOperation(T)" attrs="134">
+ <size>16</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="C">
+ <method name="Int32 IGenericInterface<int>.Start()" attrs="481">
+ <size>7</size>
+ </method>
+ <method name="Void Main()" attrs="150">
+ <size>17</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="gtest-anontype-01.cs">
<type name="Test">
<method name="Int32 Main()" attrs="150">
|