[mcs] Initial by ref returns and variables support
[mono.git] / mcs / mcs / generic.cs
index e63e999dc79dd325b8e42d7a1ab839be35de00fd..625cd0c773f0588fefcd0b3055c1ddbc20d0e44a 100644 (file)
@@ -428,13 +428,13 @@ namespace Mono.CSharp {
                public TypeParameter (TypeParameterSpec spec, TypeSpec parentSpec, MemberName name, Attributes attrs)
                        : base (null, name, attrs)
                {
-                       this.spec = new TypeParameterSpec (parentSpec, spec.DeclaredPosition, spec.MemberDefinition, spec.SpecialConstraint, spec.Variance, null) {
+                       this.spec = new TypeParameterSpec (parentSpec, spec.DeclaredPosition, this, spec.SpecialConstraint, spec.Variance, null) {
                                BaseType = spec.BaseType,
                                InterfacesDefined = spec.InterfacesDefined,
                                TypeArguments = spec.TypeArguments
                        };
                }
-               
+
                #region Properties
 
                public override AttributeTargets AttributeTargets {
@@ -773,6 +773,7 @@ namespace Mono.CSharp {
                TypeSpec[] targs;
                TypeSpec[] ifaces_defined;
                TypeSpec effective_base;
+               MemberCache interface_cache;
 
                //
                // Creates type owned type parameter
@@ -882,6 +883,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public MemberCache InterfaceCache {
+                       get {
+                               return interface_cache;
+                       }
+               }
+
                //
                // Unexpanded interfaces list
                //
@@ -1138,7 +1145,7 @@ namespace Mono.CSharp {
                                //
                                // Iterate over inflated interfaces
                                //
-                               foreach (var iface in Interfaces) {
+                               foreach (var iface in InterfacesDefined) {
                                        found = false;
                                        if (other.InterfacesDefined != null) {
                                                foreach (var oiface in other.Interfaces) {
@@ -1171,7 +1178,7 @@ namespace Mono.CSharp {
                                //
                                // Iterate over inflated interfaces
                                //
-                               foreach (var oiface in other.Interfaces) {
+                               foreach (var oiface in other.InterfacesDefined) {
                                        found = false;
 
                                        if (InterfacesDefined != null) {
@@ -1351,13 +1358,27 @@ namespace Mono.CSharp {
                        // For a type parameter the membercache is the union of the sets of members of the types
                        // specified as a primary constraint or secondary constraint
                        //
+                       bool has_user_base_type = false;
                        if (BaseType.BuiltinType != BuiltinTypeSpec.Type.Object && BaseType.BuiltinType != BuiltinTypeSpec.Type.ValueType) {
                                cache.AddBaseType (BaseType);
+                               has_user_base_type = true;
                        }
 
                        if (InterfacesDefined != null) {
+                               var icache = cache;
+                               if (has_user_base_type) {
+                                       //
+                                       // type-parameter lookup rules are more complicated that other types lookup rules.
+                                       // Effective base class and its base types member have priority over interface
+                                       // constraints which means we cannot lookup interface members before class members
+                                       // hence we setup secondary cache for such cases.
+                                       //
+                                       interface_cache = new MemberCache ();
+                                       icache = interface_cache;
+                               }
+
                                foreach (var iface_type in InterfacesDefined) {
-                                       cache.AddInterface (iface_type);
+                                       icache.AddInterface (iface_type);
                                }
                        }
 
@@ -1370,8 +1391,14 @@ namespace Mono.CSharp {
                                        var ifaces = tps == null ? ta.Interfaces : tps.InterfacesDefined;
 
                                        if (ifaces != null) {
+                                               var icache = cache;
+                                               if (has_user_base_type) {
+                                                       interface_cache = new MemberCache ();
+                                                       icache = interface_cache;
+                                               }
+
                                                foreach (var iface_type in ifaces) {
-                                                       cache.AddInterface (iface_type);
+                                                       icache.AddInterface (iface_type);
                                                }
                                        }
                                }
@@ -1516,6 +1543,9 @@ namespace Mono.CSharp {
                                        if (ec is PointerContainer)
                                                return PointerContainer.MakeType (context.Module, et);
 
+                                       if (ec is ReferenceContainer)
+                                               return ReferenceContainer.MakeType (context.Module, et);
+                                       
                                        throw new NotImplementedException ();
                                }
 
@@ -1551,7 +1581,7 @@ namespace Mono.CSharp {
                                // Parent was inflated, find the same type on inflated type
                                // to use same cache for nested types on same generic parent
                                //
-                               type = MemberCache.FindNestedType (parent, type.Name, type.Arity);
+                               type = MemberCache.FindNestedType (parent, type.Name, type.Arity, false);
 
                                //
                                // Handle the tricky case where parent shares local type arguments
@@ -1745,7 +1775,10 @@ namespace Mono.CSharp {
                        foreach (var arg in targs) {
                                if (arg.HasDynamicElement || arg.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
                                        state |= StateFlags.HasDynamicElement;
-                                       break;
+                               }
+
+                               if (arg.HasNamedTupleElement) {
+                                       state |= StateFlags.HasNamedTupleElement;
                                }
                        }
 
@@ -1825,6 +1858,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override bool IsTupleType {
+                       get {
+                               return (open_type.state & StateFlags.Tuple) != 0;
+                       }
+               }
+
                //
                // Types used to inflate the generic  type
                //
@@ -2135,6 +2174,10 @@ namespace Mono.CSharp {
                                return this;
 
                        var mutated = (InflatedTypeSpec) MemberwiseClone ();
+#if DEBUG
+                       mutated.ID += 1000000;
+#endif
+
                        if (decl != DeclaringType) {
                                // Gets back MethodInfo in case of metaInfo was inflated
                                //mutated.info = MemberCache.GetMember<TypeSpec> (DeclaringType.GetDefinition (), this).info;
@@ -3060,7 +3103,11 @@ namespace Mono.CSharp {
                        // Some types cannot be used as type arguments
                        //
                        if ((bound.Type.Kind == MemberKind.Void && !voidAllowed) || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType ||
-                               bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod || bound.Type == InternalType.VarOutType)
+                           bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod || bound.Type == InternalType.VarOutType ||
+                           bound.Type == InternalType.ThrowExpr)
+                               return;
+
+                       if (bound.Type.IsTupleType && TupleLiteral.ContainsNoTypeElement (bound.Type))
                                return;
 
                        var a = bounds [index];
@@ -3111,21 +3158,36 @@ namespace Mono.CSharp {
                                return ExactInference (ac_u.Element, ac_v.Element);
                        }
 
-                       // If V is constructed type and U is constructed type
+                       //
+                       // If V is constructed type and U is constructed type or dynamic
+                       //
                        if (TypeManager.IsGenericType (v)) {
-                               if (!TypeManager.IsGenericType (u) || v.MemberDefinition != u.MemberDefinition)
-                                       return 0;
+                               if (u.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
-                               TypeSpec [] ga_u = TypeManager.GetTypeArguments (u);
-                               TypeSpec [] ga_v = TypeManager.GetTypeArguments (v);
-                               if (ga_u.Length != ga_v.Length)
-                                       return 0;
+                                       var ga_v = v.TypeArguments;
+
+                                       int score = 0;
+                                       for (int i = 0; i < ga_v.Length; ++i)
+                                               score += ExactInference (u, ga_v [i]);
+
+                                       return System.Math.Min (1, score);
+
+                               } else {
+                                       if (!TypeManager.IsGenericType (u) || v.MemberDefinition != u.MemberDefinition)
+                                               return 0;
 
-                               int score = 0;
-                               for (int i = 0; i < ga_u.Length; ++i)
-                                       score += ExactInference (ga_u [i], ga_v [i]);
+                                       var ga_u = u.TypeArguments;
+                                       var ga_v = v.TypeArguments;
 
-                               return System.Math.Min (1, score);
+                                       if (u.TypeArguments.Length != v.TypeArguments.Length)
+                                               return 0;
+
+                                       int score = 0;
+                                       for (int i = 0; i < ga_v.Length; ++i)
+                                               score += ExactInference (ga_u [i], ga_v [i]);
+
+                                       return System.Math.Min (1, score);
+                               }
                        }
 
                        // If V is one of the unfixed type arguments