Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/mcs
diff options
context:
space:
mode:
authorMarek Safar <marek.safar@gmail.com>2013-07-04 16:51:00 +0400
committerMarek Safar <marek.safar@gmail.com>2013-07-10 17:43:23 +0400
commit9f4d1dc49fa441741aeae72ab60e07dfb6d1549b (patch)
tree28d8bb1ff05ffe673873787596ef14561b0045d1 /mcs
parentfbfd2ab4068167810e2676f60652810adc8b8979 (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.cs60
-rw-r--r--mcs/tests/gtest-589.cs40
-rw-r--r--mcs/tests/ver-il-net_4_5.xml32
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&lt;Z&gt;.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&lt;int&gt;.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">