Merge pull request #606 from sesef/master
[mono.git] / mcs / mcs / class.cs
index 216548b0c5c2e5c0ec50920dc29a642cf8c3ba9b..a13adb2ef79335f5e47d7394c9d4d7cea8832dd0 100644 (file)
@@ -17,7 +17,6 @@ using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Security;
 using System.Security.Permissions;
-using System.Linq;
 using System.Text;
 using System.Diagnostics;
 using Mono.CompilerServices.SymbolWriter;
@@ -298,6 +297,15 @@ namespace Mono.CSharp
                        return true;
                }
 
+               public virtual void ExpandBaseInterfaces ()
+               {
+                       if (containers != null) {
+                               foreach (TypeContainer tc in containers) {
+                                       tc.ExpandBaseInterfaces ();
+                               }
+                       }
+               }
+
                protected virtual void DefineNamespace ()
                {
                        if (containers != null) {
@@ -346,12 +354,28 @@ namespace Mono.CSharp
                        return MemberName.GetSignatureForError ();
                }
 
+               public string GetSignatureForMetadata ()
+               {
+#if STATIC
+                       if (Parent is TypeDefinition) {
+                               return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (MemberName.Basename);
+                       }
+
+                       var sb = new StringBuilder ();
+                       CreateMetadataName (sb);
+                       return sb.ToString ();
+#else
+                       throw new NotImplementedException ();
+#endif
+               }
+
                public virtual void RemoveContainer (TypeContainer cont)
                {
                        if (containers != null)
                                containers.Remove (cont);
 
-                       defined_names.Remove (cont.Basename);
+                       var tc = Parent == Module ? Module : this;
+                       tc.defined_names.Remove (cont.Basename);
                }
 
                public virtual void VerifyMembers ()
@@ -519,6 +543,7 @@ namespace Mono.CSharp
 
                public int DynamicSitesCounter;
                public int AnonymousMethodsCounter;
+               public int MethodGroupsCounter;
 
                static readonly string[] attribute_targets = new string[] { "type" };
 
@@ -654,6 +679,12 @@ namespace Mono.CSharp
                        }
                }
 
+               bool ITypeDefinition.IsTypeForwarder {
+                       get {
+                               return false;
+                       }
+               }
+
                //
                // Returns true for secondary partial containers
                //
@@ -989,6 +1020,9 @@ namespace Mono.CSharp
 
                internal override void GenerateDocComment (DocumentationBuilder builder)
                {
+                       if (IsPartialPart)
+                               return;
+
                        base.GenerateDocComment (builder);
 
                        foreach (var member in members)
@@ -1196,7 +1230,7 @@ namespace Mono.CSharp
                        //
                        // Sets .size to 1 for structs with no instance fields
                        //
-                       int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null ? 1 : 0;
+                       int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
 
                        var parent_def = Parent as TypeDefinition;
                        if (parent_def == null) {
@@ -1309,22 +1343,12 @@ namespace Mono.CSharp
 
                        if (proxy_method == null) {
                                string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
-                               var base_parameters = new Parameter[method.Parameters.Count];
-                               for (int i = 0; i < base_parameters.Length; ++i) {
-                                       var base_param = method.Parameters.FixedParameters[i];
-                                       base_parameters[i] = new Parameter (new TypeExpression (method.Parameters.Types[i], Location),
-                                               base_param.Name, base_param.ModFlags, null, Location);
-                                       base_parameters[i].Resolve (this, i);
-                               }
-
-                               var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
-                               if (method.Parameters.HasArglist) {
-                                       cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
-                                       cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
-                               }
 
                                MemberName member_name;
                                TypeArguments targs = null;
+                               TypeSpec return_type = method.ReturnType;
+                               var local_param_types = method.Parameters.Types;
+
                                if (method.IsGeneric) {
                                        //
                                        // Copy all base generic method type parameters info
@@ -1336,19 +1360,42 @@ namespace Mono.CSharp
                                        targs.Arguments = new TypeSpec[hoisted_tparams.Length];
                                        for (int i = 0; i < hoisted_tparams.Length; ++i) {
                                                var tp = hoisted_tparams[i];
-                                               tparams.Add (new TypeParameter (tp, null, new MemberName (tp.Name, Location), null));
+                                               var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
+                                               tparams.Add (local_tp);
 
                                                targs.Add (new SimpleName (tp.Name, Location));
-                                               targs.Arguments[i] = tp;
+                                               targs.Arguments[i] = local_tp.Type;
                                        }
 
                                        member_name = new MemberName (name, tparams, Location);
+
+                                       //
+                                       // Mutate any method type parameters from original
+                                       // to newly created hoisted version
+                                       //
+                                       var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
+                                       return_type = mutator.Mutate (return_type);
+                                       local_param_types = mutator.Mutate (local_param_types);
                                } else {
                                        member_name = new MemberName (name);
                                }
 
+                               var base_parameters = new Parameter[method.Parameters.Count];
+                               for (int i = 0; i < base_parameters.Length; ++i) {
+                                       var base_param = method.Parameters.FixedParameters[i];
+                                       base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
+                                               base_param.Name, base_param.ModFlags, null, Location);
+                                       base_parameters[i].Resolve (this, i);
+                               }
+
+                               var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
+                               if (method.Parameters.HasArglist) {
+                                       cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
+                                       cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
+                               }
+
                                // Compiler generated proxy
-                               proxy_method = new Method (this, new TypeExpression (method.ReturnType, Location),
+                               proxy_method = new Method (this, new TypeExpression (return_type, Location),
                                        Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
                                        member_name, cloned_params, null);
 
@@ -1441,12 +1488,14 @@ namespace Mono.CSharp
                                            GetSignatureForError (), cycle.GetSignatureForError ());
 
                                        iface_exprs = null;
+                                       PartialContainer.iface_exprs = null;
                                } else {
                                        Report.Error (146, Location,
                                                "Circular base class dependency involving `{0}' and `{1}'",
                                                GetSignatureForError (), cycle.GetSignatureForError ());
 
                                        base_type = null;
+                                       PartialContainer.base_type = null;
                                }
                        }
 
@@ -1460,26 +1509,6 @@ namespace Mono.CSharp
                                                continue;
 
                                        TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
-
-                                       // Ensure the base is always setup
-                                       var compiled_iface = iface_type.MemberDefinition as Interface;
-                                       if (compiled_iface != null) {
-                                               // TODO: Need DefineBaseType only
-                                               compiled_iface.DefineContainer ();
-                                       }
-
-                                       if (iface_type.Interfaces != null) {
-                                               var base_ifaces = new List<TypeSpec> (iface_type.Interfaces);
-                                               for (int i = 0; i < base_ifaces.Count; ++i) {
-                                                       var ii_iface_type = base_ifaces[i];
-                                                       if (spec.AddInterfaceDefined (ii_iface_type)) {
-                                                               TypeBuilder.AddInterfaceImplementation (ii_iface_type.GetMetaInfo ());
-
-                                                               if (ii_iface_type.Interfaces != null)
-                                                                       base_ifaces.AddRange (ii_iface_type.Interfaces);
-                                                       }
-                                               }
-                                       }
                                }
                        }
 
@@ -1502,6 +1531,70 @@ namespace Mono.CSharp
                        return true;
                }
 
+               public override void ExpandBaseInterfaces ()
+               {
+                       if (!IsPartialPart)
+                               DoExpandBaseInterfaces ();
+
+                       base.ExpandBaseInterfaces ();
+               }
+
+               public void DoExpandBaseInterfaces ()
+               {
+                       if ((caching_flags & Flags.InterfacesExpanded) != 0)
+                               return;
+
+                       caching_flags |= Flags.InterfacesExpanded;
+
+                       //
+                       // Expand base interfaces. It cannot be done earlier because all partial
+                       // interface parts need to be defined before the type they are used from
+                       //
+                       if (iface_exprs != null) {
+                               foreach (var iface in iface_exprs) {
+                                       if (iface == null)
+                                               continue;
+
+                                       var td = iface.MemberDefinition as TypeDefinition;
+                                       if (td != null)
+                                               td.DoExpandBaseInterfaces ();
+
+                                       if (iface.Interfaces == null)
+                                               continue;
+
+                                       foreach (var biface in iface.Interfaces) {
+                                               if (spec.AddInterfaceDefined (biface)) {
+                                                       TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
+                                               }
+                                       }
+                               }
+                       }
+
+                       //
+                       // Include all base type interfaces too, see ImportTypeBase for details
+                       //
+                       if (base_type != null) {
+                               var td = base_type.MemberDefinition as TypeDefinition;
+                               if (td != null)
+                                       td.DoExpandBaseInterfaces ();
+
+                               //
+                               // Simply use base interfaces only, they are all expanded which makes
+                               // it easy to handle generic type argument propagation with single
+                               // inflator only.
+                               //
+                               // interface IA<T> : IB<T>
+                               // interface IB<U> : IC<U>
+                               // interface IC<V>
+                               //
+                               if (base_type.Interfaces != null) {
+                                       foreach (var iface in base_type.Interfaces) {
+                                               spec.AddInterfaceDefined (iface);
+                                       }
+                               }
+                       }
+               }
+
                public override void PrepareEmit ()
                {
                        if ((caching_flags & Flags.CloseTypeCreated) != 0)
@@ -1685,9 +1778,6 @@ namespace Mono.CSharp
                                        if (compiled_iface != null)
                                                compiled_iface.Define ();
 
-                                       if (Kind == MemberKind.Interface)
-                                               MemberCache.AddInterface (iface_type);
-
                                        ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
                                        if (oa != null && !IsObsolete)
                                                AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
@@ -1705,21 +1795,25 @@ namespace Mono.CSharp
                                        }
 
                                        if (iface_type.IsGenericOrParentIsGeneric) {
-                                               if (spec.Interfaces != null) {
-                                                       foreach (var prev_iface in iface_exprs) {
-                                                               if (prev_iface == iface_type)
-                                                                       break;
-
-                                                               if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
-                                                                       continue;
-
-                                                               Report.Error (695, Location,
-                                                                       "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
-                                                                       GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
-                                                       }
+                                               foreach (var prev_iface in iface_exprs) {
+                                                       if (prev_iface == iface_type || prev_iface == null)
+                                                               break;
+
+                                                       if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
+                                                               continue;
+
+                                                       Report.Error (695, Location,
+                                                               "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
+                                                               GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
                                                }
                                        }
                                }
+
+                               if (Kind == MemberKind.Interface) {
+                                       foreach (var iface in spec.Interfaces) {
+                                               MemberCache.AddInterface (iface);
+                                       }
+                               }
                        }
 
                        if (base_type != null) {
@@ -1738,11 +1832,6 @@ namespace Mono.CSharp
                                        }
                                }
 
-                               if (base_type.Interfaces != null) {
-                                       foreach (var iface in base_type.Interfaces)
-                                               spec.AddInterface (iface);
-                               }
-
                                var baseContainer = base_type.MemberDefinition as ClassOrStruct;
                                if (baseContainer != null) {
                                        baseContainer.Define ();
@@ -1821,13 +1910,20 @@ namespace Mono.CSharp
                                return;
 
                        string class_indexer_name = null;
-                       has_normal_indexers = true;
 
                        //
                        // Check normal indexers for consistent name, explicit interface implementation
                        // indexers are ignored
                        //
                        foreach (var indexer in indexers) {
+                               //
+                               // FindMembers can return unfiltered full hierarchy names
+                               //
+                               if (indexer.DeclaringType != spec)
+                                       continue;
+
+                               has_normal_indexers = true;
+
                                if (class_indexer_name == null) {
                                        indexer_name = class_indexer_name = indexer.Name;
                                        continue;
@@ -2406,7 +2502,7 @@ namespace Mono.CSharp
                /// <summary>
                /// Defines the default constructors 
                /// </summary>
-               protected Constructor DefineDefaultConstructor (bool is_static)
+               protected virtual Constructor DefineDefaultConstructor (bool is_static)
                {
                        // The default instance constructor is public
                        // If the class is abstract, the default constructor is protected
@@ -3295,7 +3391,7 @@ namespace Mono.CSharp
                {
                        // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
                        // We are more strict than csc and report this as an error because SRE does not allow emit that
-                       if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) {
+                       if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
                                if (this is Constructor) {
                                        Report.Warning (824, 1, Location,
                                                "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
@@ -3403,6 +3499,16 @@ namespace Mono.CSharp
                        get { return IsExplicitImpl || base.IsUsed; }
                }
 
+               public override void SetConstraints (List<Constraints> constraints_list)
+               {
+                       if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
+                               Report.Error (460, Location,
+                                       "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
+                                       GetSignatureForError ());
+                       }
+
+                       base.SetConstraints (constraints_list);
+               }
        }
 
        public abstract class MemberBase : MemberCore
@@ -3416,7 +3522,9 @@ namespace Mono.CSharp
                {
                        this.Parent = parent;
                        this.type_expr = type;
-                       ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
+
+                       if (name != MemberName.Null)
+                               ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
                }
 
                #region Properties