[mcs] New property/indexer cannot have accessors implementing an interface in base...
authorMarek Safar <marek.safar@gmail.com>
Mon, 29 May 2017 21:55:47 +0000 (23:55 +0200)
committerMarek Safar <marek.safar@gmail.com>
Mon, 29 May 2017 21:57:00 +0000 (23:57 +0200)
mcs/errors/cs0535-7.cs [new file with mode: 0644]
mcs/errors/cs0535-8.cs [new file with mode: 0644]
mcs/mcs/import.cs
mcs/mcs/pending.cs
mcs/mcs/property.cs

diff --git a/mcs/errors/cs0535-7.cs b/mcs/errors/cs0535-7.cs
new file mode 100644 (file)
index 0000000..11a7670
--- /dev/null
@@ -0,0 +1,40 @@
+// CS0535: `CC' does not implement interface member `IA.Coordinate.set'
+// Line: 33
+
+using System;
+
+public interface IA
+{
+       object Coordinate {
+               get;
+               set;
+       }
+}
+
+public abstract class CA : IA
+{
+       public abstract object Coordinate {
+               get;
+               set;
+       }
+}
+
+public  partial class CB : CA
+{
+       public override object Coordinate {
+               get {
+                       throw new NotImplementedException ();
+               }
+               set {
+               }
+       }
+}
+
+public class CC : CB, IA
+{
+       public new object Coordinate {
+               get {
+                       throw new NotImplementedException ();
+               }
+       }
+}
diff --git a/mcs/errors/cs0535-8.cs b/mcs/errors/cs0535-8.cs
new file mode 100644 (file)
index 0000000..853794e
--- /dev/null
@@ -0,0 +1,40 @@
+// CS0535: `CC' does not implement interface member `IA.this[int].set'
+// Line: 33
+
+using System;
+
+public interface IA
+{
+       object this[int arg] {
+               get;
+               set;
+       }
+}
+
+public abstract class CA : IA
+{
+       public abstract object this[int arg] {
+               get;
+               set;
+       }
+}
+
+public  partial class CB : CA
+{
+       public override object this[int arg] {
+               get {
+                       throw new NotImplementedException ();
+               }
+               set {
+               }
+       }
+}
+
+public class CC : CB, IA
+{
+       public new object this[int arg] {
+               get {
+                       throw new NotImplementedException ();
+               }
+       }
+}
index 359a738a555e788610b317d88b79e87e82ec31e9..dbec2c0469f603bce116c228d4a3252b2abc85be 100644 (file)
@@ -645,14 +645,7 @@ namespace Mono.CSharp
                                        if (set_param_count == 0) {
                                                set_based_param = ParametersCompiled.EmptyReadOnlyParameters;
                                        } else {
-                                               //
-                                               // Create indexer parameters based on setter method parameters (the last parameter has to be removed)
-                                               //
-                                               var data = new IParameterData[set_param_count];
-                                               var types = new TypeSpec[set_param_count];
-                                               Array.Copy (set.Parameters.FixedParameters, data, set_param_count);
-                                               Array.Copy (set.Parameters.Types, types, set_param_count);
-                                               set_based_param = new ParametersImported (data, types, set.Parameters.HasParams);
+                                               set_based_param = IndexerSpec.CreateParametersFromSetter (set, set_param_count);
                                        }
 
                                        mod = set.Modifiers;
index 661142822f802a9f55ed7560eb510ca5c30c1f50..507b937e2c904310786e8798ee2196d2ef52dcb2 100644 (file)
@@ -147,7 +147,6 @@ namespace Mono.CSharp {
                        int i = 0;
                        if (abstract_methods != null) {
                                int count = abstract_methods.Length;
-                               pending_implementations [i].methods = new MethodSpec [count];
                                pending_implementations [i].need_proxy = new MethodSpec [count];
 
                                pending_implementations [i].methods = abstract_methods;
@@ -527,7 +526,47 @@ namespace Mono.CSharp {
                bool BaseImplements (TypeSpec iface_type, MethodSpec mi, out MethodSpec base_method)
                {
                        base_method = null;
-                       var base_type = container.BaseType;
+                       bool base_can_implement = true;
+                       TypeSpec lookup_type;
+
+                       //
+                       // Special handling for properties/indexers which cannot have accessors
+                       // implementing an interface found in different types (e.g. current and base)
+                       //
+                       if (mi.IsAccessor && container.Interfaces != null) {
+
+                               bool new_implementation = false;
+                               foreach (var iface in container.Interfaces) {
+                                       if (TypeSpecComparer.IsEqual (iface, iface_type)) {
+                                               new_implementation = true;
+                                               break;
+                                       }
+                               }
+
+                               if (new_implementation) {
+                                       MemberFilter filter;
+                                       if (mi.Parameters.Count > 1) {
+                                               var indexer_params = mi.Name [0] == 'g' ? mi.Parameters : IndexerSpec.CreateParametersFromSetter (mi, mi.Parameters.Count - 1);
+                                               filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, MemberKind.Indexer, indexer_params, null);
+                                       } else {
+                                               var pname = mi.Name.Substring (4);
+                                               filter = MemberFilter.Property (pname, null);
+                                       }
+
+                                       var prop = MemberCache.FindMember (container.CurrentType, filter, BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly);
+                                       if (prop != null && (prop.Modifiers & Modifiers.NEW) != 0)
+                                               base_can_implement = false;
+                               }
+                       }
+
+                       if (base_can_implement) {
+                               lookup_type = container.BaseType;
+
+                               if (lookup_type.ImplementsInterface (iface_type, false))
+                                       return true;
+                       } else {
+                               lookup_type = container.CurrentType;
+                       }
 
                        //
                        // Setup filter with no return type to give better error message
@@ -537,7 +576,7 @@ namespace Mono.CSharp {
                        MethodSpec close_match = null;
 
                        while (true) {
-                               var candidates = MemberCache.FindMembers (base_type, mi.Name, false);
+                               var candidates = MemberCache.FindMembers (lookup_type, mi.Name, !base_can_implement);
                                if (candidates == null) {
                                        base_method = close_match;
                                        return false;
@@ -630,8 +669,11 @@ namespace Mono.CSharp {
                                        break;
                                }
 
-                               base_type = candidates[0].DeclaringType.BaseType;
-                               if (base_type == null) {
+                               if (!base_can_implement)
+                                       return false;
+
+                               lookup_type = candidates[0].DeclaringType.BaseType;
+                               if (lookup_type == null) {
                                        base_method = close_match;
                                        return false;
                                }
@@ -668,10 +710,6 @@ namespace Mono.CSharp {
                        for (i = 0; i < top; i++){
                                TypeSpec type = pending_implementations [i].type;
 
-                               bool base_implements_type = type.IsInterface &&
-                                       container.BaseType != null &&
-                                       container.BaseType.ImplementsInterface (type, false);
-
                                for (int j = 0; j < pending_implementations [i].methods.Count; ++j) {
                                        var mi = pending_implementations[i].methods[j];
                                        if (mi == null)
@@ -686,11 +724,8 @@ namespace Mono.CSharp {
                                                        continue;
                                                }
 
-                                               if (pending_implementations [i].optional)
-                                                       continue;
-
                                                MethodSpec candidate;
-                                               if (base_implements_type || BaseImplements (type, mi, out candidate))
+                                               if (BaseImplements (type, mi, out candidate))
                                                        continue;
 
                                                if (candidate == null) {
index 5d831e940b523b144287c7e0d47f0394e3677147..0d4efedbd1e6465e4df5f4e50eaa67e07e86db7b 100644 (file)
@@ -1793,6 +1793,18 @@ namespace Mono.CSharp
                }
                #endregion
 
+               public static ParametersImported CreateParametersFromSetter (MethodSpec setter, int set_param_count)
+               {
+                       //
+                       // Creates indexer parameters based on setter method parameters (the last parameter has to be removed)
+                       //
+                       var data = new IParameterData [set_param_count];
+                       var types = new TypeSpec [set_param_count];
+                       Array.Copy (setter.Parameters.FixedParameters, data, set_param_count);
+                       Array.Copy (setter.Parameters.Types, types, set_param_count);
+                       return new ParametersImported (data, types, setter.Parameters.HasParams);
+               }
+
                public override string GetSignatureForDocumentation ()
                {
                        return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation ();