[mcs] Implements C# 7.2 readonly structs
[mono.git] / mcs / mcs / class.cs
index 96ac0c8db4c24aacc9f18f573adfff3d885d54da..9afb32c6fe5677d71cdd7632d08c79a43302e040 100644 (file)
@@ -22,7 +22,7 @@ using System.Text;
 using System.Diagnostics;
 using Mono.CompilerServices.SymbolWriter;
 
-#if NET_2_1
+#if MOBILE
 using XmlElement = System.Object;
 #endif
 
@@ -297,6 +297,10 @@ namespace Mono.CSharp
                                                throw new InternalErrorException (tc, e);
                                        }
                                }
+
+                               if (PartialContainer != null && PartialContainer != this) {
+                                       containers = null;
+                               }
                        }
 
                        return true;
@@ -635,6 +639,15 @@ namespace Mono.CSharp
                        }
                }
 
+               public bool HasInstanceField {
+                       get {
+                               return (caching_flags & Flags.HasInstanceField) != 0;
+                       }
+                       set {
+                               caching_flags |= Flags.HasInstanceField;
+                       }
+               }
+
                // Indicated whether container has StructLayout attribute set Explicit
                public bool HasExplicitLayout {
                        get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
@@ -844,18 +857,22 @@ namespace Mono.CSharp
                        if ((field.ModFlags & Modifiers.STATIC) != 0)
                                return true;
 
-                       var first_field = PartialContainer.first_nonstatic_field;
-                       if (first_field == null) {
+                       if (!PartialContainer.HasInstanceField) {
+                               PartialContainer.HasInstanceField = true;
                                PartialContainer.first_nonstatic_field = field;
                                return true;
                        }
 
-                       if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
-                               Report.SymbolRelatedToPreviousError (first_field.Parent);
-                               Report.Warning (282, 3, field.Location,
-                                       "struct instance field `{0}' found in different declaration from instance field `{1}'",
-                                       field.GetSignatureForError (), first_field.GetSignatureForError ());
+                       if (Kind == MemberKind.Struct) {
+                               var first_field = PartialContainer.first_nonstatic_field;
+                               if (first_field.Parent != field.Parent) {
+                                       Report.SymbolRelatedToPreviousError (first_field.Parent);
+                                       Report.Warning (282, 3, field.Location,
+                                               "struct instance field `{0}' found in different declaration from instance field `{1}'",
+                                               field.GetSignatureForError (), first_field.GetSignatureForError ());
+                               }
                        }
+
                        return true;
                }
 
@@ -1295,7 +1312,7 @@ namespace Mono.CSharp
                        //
                        // Sets .size to 1 for structs with no instance fields
                        //
-                       int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
+                       int type_size = Kind == MemberKind.Struct && !HasInstanceField && !(this is StateMachine) ? 1 : 0;
 
                        var parent_def = Parent as TypeDefinition;
                        if (parent_def == null) {
@@ -1439,7 +1456,11 @@ namespace Mono.CSharp
                                        targs.Arguments = new TypeSpec[hoisted_tparams.Length];
                                        for (int i = 0; i < hoisted_tparams.Length; ++i) {
                                                var tp = hoisted_tparams[i];
-                                               var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
+                                               var tp_name = tp.Name;
+#if DEBUG
+                                               tp_name += "_Proxy";
+#endif
+                                               var local_tp = new TypeParameter (tp, null, new MemberName (tp_name, Location), null);
                                                tparams.Add (local_tp);
 
                                                targs.Add (new SimpleName (tp.Name, Location));
@@ -1455,6 +1476,12 @@ namespace Mono.CSharp
                                        var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
                                        return_type = mutator.Mutate (return_type);
                                        local_param_types = mutator.Mutate (local_param_types);
+
+                                       var inflator = new TypeParameterInflator (this, null, hoisted_tparams, targs.Arguments);
+                                       for (int i = 0; i < hoisted_tparams.Length; ++i) {
+                                               var tp_spec = (TypeParameterSpec) targs.Arguments [i];
+                                               tp_spec.InflateConstraints (inflator, tp_spec);
+                                       }
                                } else {
                                        member_name = new MemberName (name);
                                }
@@ -1467,7 +1494,7 @@ namespace Mono.CSharp
                                        base_parameters[i].Resolve (this, i);
                                }
 
-                               var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
+                               var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, local_param_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 ();
@@ -1661,6 +1688,8 @@ namespace Mono.CSharp
 
                public override void ExpandBaseInterfaces ()
                {
+                       DoResolveTypeParameters ();
+
                        if (!IsPartialPart)
                                DoExpandBaseInterfaces ();
 
@@ -1766,8 +1795,6 @@ namespace Mono.CSharp
                protected override void DoDefineContainer ()
                {
                        DefineBaseTypes ();
-
-                       DoResolveTypeParameters ();
                }
 
                //
@@ -1791,8 +1818,10 @@ namespace Mono.CSharp
                        this.spec = spec;
                        current_type = null;
                        if (class_partial_parts != null) {
-                               foreach (var part in class_partial_parts)
+                               foreach (var part in class_partial_parts) {
                                        part.spec = spec;
+                                       part.current_type = null;
+                               }
                        }
                }
 
@@ -2142,6 +2171,14 @@ namespace Mono.CSharp
 
                public override void Emit ()
                {
+                       if (Interfaces != null) {
+                               foreach (var iface in Interfaces) {
+                                       if (iface.HasNamedTupleElement) {
+                                               throw new NotImplementedException ("named tuples for .interfaceimpl");
+                                       }
+                               }
+                       }
+
                        if (OptAttributes != null)
                                OptAttributes.Emit ();
 
@@ -2198,6 +2235,10 @@ namespace Mono.CSharp
                                Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
 
 #if STATIC
+                       if (Kind == MemberKind.Struct && !HasStructLayout && HasInstanceField) {
+                               TypeBuilder.__SetLayout (0, 0);
+                       }
+
                        if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
                                TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
 #endif
@@ -2500,7 +2541,7 @@ namespace Mono.CSharp
                        //      return null;
 
                        var container = PartialContainer.CurrentType;
-                       return MemberCache.FindNestedType (container, name, arity);
+                       return MemberCache.FindNestedType (container, name, arity, false);
                }
 
                public void Mark_HasEquals ()
@@ -2868,8 +2909,11 @@ namespace Mono.CSharp
                        if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
                                Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
 
-                       if (base_type != null && base_type.HasDynamicElement) {
-                               Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
+                       if (base_type != null) {
+                               if (base_type.HasDynamicElement)
+                                       Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
+                               if (base_type.HasNamedTupleElement)
+                                       Module.PredefinedAttributes.TupleElementNames.EmitAttribute (TypeBuilder, base_type, Location);
                        }
                }
 
@@ -2978,7 +3022,8 @@ namespace Mono.CSharp
                        Modifiers.PROTECTED |
                        Modifiers.INTERNAL  |
                        Modifiers.UNSAFE    |
-                       Modifiers.PRIVATE;
+                       Modifiers.PRIVATE   |
+                       Modifiers.READONLY;
 
                public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
                        : base (parent, name, attrs, MemberKind.Struct)
@@ -3091,6 +3136,9 @@ namespace Mono.CSharp
 
                public override void Emit ()
                {
+                       if ((ModFlags & Modifiers.READONLY) != 0)
+                               Module.PredefinedAttributes.IsReadOnly.EmitAttribute (TypeBuilder);
+
                        CheckStructCycles ();
 
                        base.Emit ();
@@ -3130,7 +3178,7 @@ namespace Mono.CSharp
                                return false;
                        }
 
-                       if (first_nonstatic_field != null) {
+                       if (HasInstanceField) {
                                requires_delayed_unmanagedtype_check = true;
 
                                foreach (var member in Members) {
@@ -3480,10 +3528,13 @@ namespace Mono.CSharp
                                ok = false;
                        }
 
-                       var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
+                       var base_member_type = ((IInterfaceMemberSpec)base_member).MemberType;
                        if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
                                Report.SymbolRelatedToPreviousError (base_member);
-                               if (this is PropertyBasedMember) {
+                               if (((base_member_type.Kind ^ MemberType.Kind) & MemberKind.ByRef) != 0) {
+                                       Report.Error (8148, Location, "`{0}': must {2}return by reference to match overridden member `{1}'",
+                                                     GetSignatureForError (), base_member.GetSignatureForError (), base_member_type.Kind == MemberKind.ByRef ? "" : "not ");
+                               } else if (this is PropertyBasedMember) {
                                        Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
                                                GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
                                } else {
@@ -3491,6 +3542,20 @@ namespace Mono.CSharp
                                                GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
                                }
                                ok = false;
+                       } else if (!NamedTupleSpec.CheckOverrideName (MemberType, base_member_type)) {
+                               // CSC: Should be different error code
+                               Report.Error (8139, Location, "`{0}': cannot change return type tuple element names when overriding inherited member `{1}'",
+                                                         GetSignatureForError (), base_member.GetSignatureForError ());
+                               ok = false;
+                       }
+
+                       var base_params = base_member as IParametersMember;
+                       if (base_params != null) {
+                               if (!NamedTupleSpec.CheckOverrideName ((IParametersMember)this, base_params)) {
+                                       Report.Error (8139, Location, "`{0}': cannot change tuple element names when overriding inherited member `{1}'",
+                                                                 GetSignatureForError (), base_member.GetSignatureForError ());
+                                       ok = false;
+                               }
                        }
 
                        return ok;