X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fgeneric.cs;h=ad69957df20d8196ec18c990fd533164084b325d;hb=b16cf37a8d93db28650210c829d53dc2b339e4e7;hp=44f4586dd90e55c2605ddbd99c4d390af882df10;hpb=fea7056e24cc13651dbd7646f5d08e0efc3be10e;p=mono.git diff --git a/mcs/gmcs/generic.cs b/mcs/gmcs/generic.cs index 44f4586dd90..ad69957df20 100644 --- a/mcs/gmcs/generic.cs +++ b/mcs/gmcs/generic.cs @@ -156,6 +156,11 @@ namespace Mono.CSharp { } } + public Constraints Clone () + { + return new Constraints (name, constraints, loc); + } + GenericParameterAttributes attrs; TypeExpr class_constraint; ArrayList iface_constraints; @@ -182,7 +187,7 @@ namespace Mono.CSharp { foreach (object obj in constraints) { if (HasConstructorConstraint) { Report.Error (401, loc, - "The new() constraint must be last."); + "The new() constraint must be the last constraint specified"); return false; } @@ -195,17 +200,14 @@ namespace Mono.CSharp { continue; } - Report.Error ( - 451, loc, "The new () constraint " + - "cannot be used with the `struct' " + - "constraint."); + Report.Error (451, loc, "The `new()' constraint " + + "cannot be used with the `struct' constraint"); return false; } if ((num_constraints > 0) || HasReferenceTypeConstraint || HasValueTypeConstraint) { - Report.Error (449, loc, - "The `class' or `struct' " + - "constraint must be first"); + Report.Error (449, loc, "The `class' or `struct' " + + "constraint must be the first constraint specified"); return false; } @@ -223,7 +225,7 @@ namespace Mono.CSharp { if (errors != Report.Errors) return false; - Report.Error (246, loc, "Cannot find type '{0}'", ((Expression) obj).GetSignatureForError ()); + NamespaceEntry.Error_NamespaceNotFound (loc, ((Expression)obj).GetSignatureForError ()); return false; } @@ -235,11 +237,20 @@ namespace Mono.CSharp { expr = cexpr; } else - expr = fn.ResolveAsTypeTerminal (ec, false); + expr = ((Expression) obj).ResolveAsTypeTerminal (ec, false); if ((expr == null) || (expr.Type == null)) return false; + // TODO: It's aleady done in ResolveAsBaseTerminal + if (!ec.GenericDeclContainer.AsAccessible (fn.Type, ec.GenericDeclContainer.ModFlags)) { + Report.SymbolRelatedToPreviousError (fn.Type); + Report.Error (703, loc, + "Inconsistent accessibility: constraint type `{0}' is less accessible than `{1}'", + fn.GetSignatureForError (), ec.GenericDeclContainer.GetSignatureForError ()); + return false; + } + TypeParameterExpr texpr = expr as TypeParameterExpr; if (texpr != null) type_param_constraints.Add (expr); @@ -254,7 +265,7 @@ namespace Mono.CSharp { } else if (HasReferenceTypeConstraint || HasValueTypeConstraint) { Report.Error (450, loc, "`{0}': cannot specify both " + "a constraint class and the `class' " + - "or `struct' constraint.", expr.Name); + "or `struct' constraint", expr.GetSignatureForError ()); return false; } else class_constraint = expr; @@ -301,10 +312,16 @@ namespace Mono.CSharp { return false; if (class_constraint_type.IsSealed) { - Report.Error (701, loc, - "`{0}' is not a valid bound. Bounds " + - "must be interfaces or non sealed " + - "classes", TypeManager.CSharpName (class_constraint_type)); + if (class_constraint_type.IsAbstract) + { + Report.Error (717, loc, "`{0}' is not a valid constraint. Static classes cannot be used as constraints", + TypeManager.CSharpName (class_constraint_type)); + } + else + { + Report.Error (701, loc, "`{0}' is not a valid constraint. A constraint must be an interface, " + + "a non-sealed class or a type parameter", TypeManager.CSharpName(class_constraint_type)); + } return false; } @@ -504,6 +521,12 @@ namespace Mono.CSharp { return false; } + public Location Location { + get { + return loc; + } + } + /// /// This is used when we're implementing a generic interface method. /// Each method type parameter in implementing method must have the same @@ -544,6 +567,27 @@ namespace Mono.CSharp { return true; } + + public void VerifyClsCompliance () + { + if (class_constraint_type != null && !AttributeTester.IsClsCompliant (class_constraint_type)) + Warning_ConstrainIsNotClsCompliant (class_constraint_type, class_constraint.Location); + + if (iface_constraint_types != null) { + for (int i = 0; i < iface_constraint_types.Length; ++i) { + if (!AttributeTester.IsClsCompliant (iface_constraint_types [i])) + Warning_ConstrainIsNotClsCompliant (iface_constraint_types [i], + ((TypeExpr)iface_constraints [i]).Location); + } + } + } + + void Warning_ConstrainIsNotClsCompliant (Type t, Location loc) + { + Report.SymbolRelatedToPreviousError (t); + Report.Warning (3024, 1, loc, "Constraint type `{0}' is not CLS-compliant", + TypeManager.CSharpName (t)); + } } /// @@ -568,41 +612,23 @@ namespace Mono.CSharp { } public GenericConstraints GenericConstraints { - get { - return gc != null ? gc : constraints; - } + get { return gc != null ? gc : constraints; } } public Constraints Constraints { - get { - return constraints; - } + get { return constraints; } } public bool HasConstructorConstraint { - get { - if (constraints != null) - return constraints.HasConstructorConstraint; - - return false; - } + get { return constraints != null && constraints.HasConstructorConstraint; } } public DeclSpace DeclSpace { - get { - return decl; - } + get { return decl; } } public Type Type { - get { - return type; - } - } - - // FIXME: This should be removed once we fix the handling of RootContext.Tree.Types - public override DeclSpace DeclContainer { - get { return DeclSpace; } + get { return type; } } /// @@ -696,11 +722,9 @@ namespace Mono.CSharp { if (implementing != null) { if (is_override && (constraints != null)) { - Report.Error ( - 460, loc, "Constraints for override and " + - "explicit interface implementation methods " + - "are inherited from the base method so they " + - "cannot be specified directly"); + Report.Error (460, loc, + "`{0}': Cannot specify constraints for overrides or explicit interface implementation methods", + TypeManager.CSharpSignature (builder)); return false; } @@ -739,7 +763,7 @@ namespace Mono.CSharp { TypeManager.CSharpName (mparam), TypeManager.CSharpSignature (mb)); return false; } - } else if (DeclSpace is Iterator) { + } else if (DeclSpace is CompilerGeneratedClass) { TypeParameter[] tparams = DeclSpace.TypeParameters; Type[] types = new Type [tparams.Length]; for (int i = 0; i < tparams.Length; i++) @@ -877,7 +901,7 @@ namespace Mono.CSharp { public MemberList FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria) { - if (constraints == null) + if (gc == null) return MemberList.Empty; ArrayList members = new ArrayList (); @@ -1073,7 +1097,7 @@ namespace Mono.CSharp { public void Error_CannotUseAsUnmanagedType (Location loc) { - Report.Error (-203, loc, "Can not use type parameter as unamanged type"); + Report.Error (-203, loc, "Can not use type parameter as unmanaged type"); } } @@ -1193,6 +1217,19 @@ namespace Mono.CSharp { return s.ToString (); } + public string GetSignatureForError() + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < Count; ++i) + { + Expression expr = (Expression)args [i]; + sb.Append(expr.GetSignatureForError()); + if (i + 1 < Count) + sb.Append(','); + } + return sb.ToString(); + } + /// /// Resolve the type arguments. /// @@ -1212,13 +1249,21 @@ namespace Mono.CSharp { if (te is TypeParameterExpr) has_type_args = true; +#if !MS_COMPATIBLE + if (te.Type.IsSealed && te.Type.IsAbstract) { + Report.Error (718, Location, "`{0}': static classes cannot be used as generic arguments", + te.GetSignatureForError ()); + return false; + } +#endif if (te.Type.IsPointer) { Report.Error (306, Location, "The type `{0}' may not be used " + - "as a type argument.", TypeManager.CSharpName (te.Type)); + "as a type argument", TypeManager.CSharpName (te.Type)); return false; - } else if (te.Type == TypeManager.void_type) { - Report.Error (1547, Location, - "Keyword `void' cannot be used in this context"); + } + + if (te.Type == TypeManager.void_type) { + Expression.Error_VoidInvalidInTheContext (Location); return false; } @@ -1319,7 +1364,7 @@ namespace Mono.CSharp { public override string GetSignatureForError () { - return TypeManager.CSharpName (gt); + return TypeManager.RemoveGenericArity (gt.FullName) + "<" + args.GetSignatureForError () + ">"; } protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) @@ -1410,6 +1455,11 @@ namespace Mono.CSharp { public override bool AsAccessible (DeclSpace ds, int flags) { + foreach (Type t in atypes) { + if (!ds.AsAccessible (t, flags)) + return false; + } + return ds.AsAccessible (gt, flags); } @@ -1452,7 +1502,6 @@ namespace Mono.CSharp { } } - public override string FullName { get { return full_name; @@ -1507,8 +1556,8 @@ namespace Mono.CSharp { if (agc != null) { if (agc is Constraints) ((Constraints) agc).Resolve (ec); - is_class = agc.HasReferenceTypeConstraint; - is_struct = agc.HasValueTypeConstraint; + is_class = agc.IsReferenceType; + is_struct = agc.IsValueType; } else { is_class = is_struct = false; } @@ -1781,14 +1830,28 @@ namespace Mono.CSharp { /// Define and resolve the type parameters. /// We're called from Method.Define(). /// - public bool Define (MethodBuilder mb) + public bool Define (MethodBuilder mb, ToplevelBlock block) { - GenericTypeParameterBuilder[] gen_params; TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations (); string[] snames = new string [names.Length]; - for (int i = 0; i < names.Length; i++) - snames [i] = names [i].Name; - gen_params = mb.DefineGenericParameters (snames); + for (int i = 0; i < names.Length; i++) { + string type_argument_name = names[i].Name; + Parameter p = parameters.GetParameterByName (type_argument_name); + if (p != null) { + Error_ParameterNameCollision (p.Location, type_argument_name, "method parameter"); + return false; + } + if (block != null) { + LocalInfo li = (LocalInfo)block.Variables[type_argument_name]; + if (li != null) { + Error_ParameterNameCollision (li.Location, type_argument_name, "local variable"); + return false; + } + } + snames[i] = type_argument_name; + } + + GenericTypeParameterBuilder[] gen_params = mb.DefineGenericParameters (snames); for (int i = 0; i < TypeParameters.Length; i++) TypeParameters [i].Define (gen_params [i]); @@ -1803,6 +1866,12 @@ namespace Mono.CSharp { return true; } + static void Error_ParameterNameCollision (Location loc, string name, string collisionWith) + { + Report.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'", + name, collisionWith); + } + /// /// We're called from MethodData.Define() after creating the MethodBuilder. /// @@ -1851,11 +1920,6 @@ namespace Mono.CSharp { } } - public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb) - { - base.ApplyAttributeBuilder (a, cb); - } - public override AttributeTargets AttributeTargets { get { return AttributeTargets.Method | AttributeTargets.ReturnValue; @@ -1865,6 +1929,16 @@ namespace Mono.CSharp { public override string DocCommentHeader { get { return "M:"; } } + + public new void VerifyClsCompliance () + { + foreach (TypeParameter tp in TypeParameters) { + if (tp.Constraints == null) + continue; + + tp.Constraints.VerifyClsCompliance (); + } + } } public class DefaultValueExpression : Expression @@ -1885,20 +1959,37 @@ namespace Mono.CSharp { type = texpr.Type; + if (type == TypeManager.void_type) { + Error_VoidInvalidInTheContext (loc); + return null; + } + + if (type.IsGenericParameter) + { + GenericConstraints constraints = TypeManager.GetTypeParameterConstraints(type); + if (constraints != null && constraints.IsReferenceType) + return new NullDefault (new NullLiteral (Location), type); + } + else + { + Constant c = New.Constantify(type); + if (c != null) + return new NullDefault (c, type); + + if (!TypeManager.IsValueType (type)) + return new NullDefault (new NullLiteral (Location), type); + } eclass = ExprClass.Variable; return this; } public override void Emit (EmitContext ec) { - if (type.IsGenericParameter || TypeManager.IsValueType (type)) { - LocalTemporary temp_storage = new LocalTemporary (type); + LocalTemporary temp_storage = new LocalTemporary(type); - temp_storage.AddressOf (ec, AddressOp.LoadStore); - ec.ig.Emit (OpCodes.Initobj, type); - temp_storage.Emit (ec); - } else - ec.ig.Emit (OpCodes.Ldnull); + temp_storage.AddressOf(ec, AddressOp.LoadStore); + ec.ig.Emit(OpCodes.Initobj, type); + temp_storage.Emit(ec); } } @@ -1942,34 +2033,25 @@ namespace Mono.CSharp { // A list of core types that the compiler requires or uses // static public Type activator_type; + static public Type generic_ilist_type; + static public Type generic_icollection_type; static public Type generic_ienumerator_type; static public Type generic_ienumerable_type; static public Type generic_nullable_type; - // - // Tracks the generic parameters. - // - static PtrHashtable builder_to_type_param; - // // These methods are called by code generated by the compiler // static public MethodInfo activator_create_instance; - static void InitGenerics () - { - builder_to_type_param = new PtrHashtable (); - } - - static void CleanUpGenerics () - { - builder_to_type_param = null; - } - static void InitGenericCoreTypes () { activator_type = CoreLookupType ("System", "Activator"); + generic_ilist_type = CoreLookupType ( + "System.Collections.Generic", "IList", 1); + generic_icollection_type = CoreLookupType ( + "System.Collections.Generic", "ICollection", 1); generic_ienumerator_type = CoreLookupType ( "System.Collections.Generic", "IEnumerator", 1); generic_ienumerable_type = CoreLookupType ( @@ -1991,23 +2073,12 @@ namespace Mono.CSharp { return CoreLookupType (ns, MemberName.MakeName (name, arity)); } - public static void AddTypeParameter (Type t, TypeParameter tparam) - { - if (!builder_to_type_param.Contains (t)) - builder_to_type_param.Add (t, tparam); - } - public static TypeContainer LookupGenericTypeContainer (Type t) { t = DropGenericTypeArguments (t); return LookupTypeContainer (t); } - public static TypeParameter LookupTypeParameter (Type t) - { - return (TypeParameter) builder_to_type_param [t]; - } - public static GenericConstraints GetTypeParameterConstraints (Type t) { if (!t.IsGenericParameter) @@ -2020,177 +2091,12 @@ namespace Mono.CSharp { return ReflectionConstraints.GetConstraints (t); } - public static bool HasGenericArguments (Type t) - { - return GetNumberOfTypeArguments (t) > 0; - } - - public static int GetNumberOfTypeArguments (Type t) - { - if (t.IsGenericParameter) - return 0; - DeclSpace tc = LookupDeclSpace (t); - if (tc != null) - return tc.IsGeneric ? tc.CountTypeParameters : 0; - else - return t.IsGenericType ? t.GetGenericArguments ().Length : 0; - } - - public static Type[] GetTypeArguments (Type t) - { - DeclSpace tc = LookupDeclSpace (t); - if (tc != null) { - if (!tc.IsGeneric) - return Type.EmptyTypes; - - TypeParameter[] tparam = tc.TypeParameters; - Type[] ret = new Type [tparam.Length]; - for (int i = 0; i < tparam.Length; i++) { - ret [i] = tparam [i].Type; - if (ret [i] == null) - throw new InternalErrorException (); - } - - return ret; - } else - return t.GetGenericArguments (); - } - - public static Type DropGenericTypeArguments (Type t) - { - if (!t.IsGenericType) - return t; - // Micro-optimization: a generic typebuilder is always a generic type definition - if (t is TypeBuilder) - return t; - return t.GetGenericTypeDefinition (); - } - - public static MethodBase DropGenericMethodArguments (MethodBase m) - { - if (m.IsGenericMethodDefinition) - return m; - if (m.IsGenericMethod) - return ((MethodInfo) m).GetGenericMethodDefinition (); - if (!m.DeclaringType.IsGenericType) - return m; - - Type t = m.DeclaringType.GetGenericTypeDefinition (); - BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; - - if (m is ConstructorInfo) { - foreach (ConstructorInfo c in t.GetConstructors (bf)) - if (c.MetadataToken == m.MetadataToken) - return c; - } else { - foreach (MethodBase mb in t.GetMethods (bf)) - if (mb.MetadataToken == m.MetadataToken) - return mb; - } - - return m; - } - - public static FieldInfo GetGenericFieldDefinition (FieldInfo fi) - { - if (fi.DeclaringType.IsGenericTypeDefinition || - !fi.DeclaringType.IsGenericType) - return fi; - - Type t = fi.DeclaringType.GetGenericTypeDefinition (); - BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; - - foreach (FieldInfo f in t.GetFields (bf)) - if (f.MetadataToken == fi.MetadataToken) - return f; - - return fi; - } - - // - // Whether `array' is an array of T and `enumerator' is `IEnumerable'. - // For instance "string[]" -> "IEnumerable". - // - public static bool IsIEnumerable (Type array, Type enumerator) - { - if (!array.IsArray || !enumerator.IsGenericType) - return false; - - if (enumerator.GetGenericTypeDefinition () != generic_ienumerable_type) - return false; - - Type[] args = GetTypeArguments (enumerator); - return args [0] == GetElementType (array); - } - - public static bool IsEqual (Type a, Type b) - { - if (a.Equals (b)) - return true; - - if (a.IsGenericParameter && b.IsGenericParameter) { - if (a.DeclaringMethod != b.DeclaringMethod && - (a.DeclaringMethod == null || b.DeclaringMethod == null)) - return false; - return a.GenericParameterPosition == b.GenericParameterPosition; - } - - if (a.IsArray && b.IsArray) { - if (a.GetArrayRank () != b.GetArrayRank ()) - return false; - return IsEqual (a.GetElementType (), b.GetElementType ()); - } - - if (a.IsByRef && b.IsByRef) - return IsEqual (a.GetElementType (), b.GetElementType ()); - - if (a.IsGenericType && b.IsGenericType) { - if (a.GetGenericTypeDefinition () != b.GetGenericTypeDefinition ()) - return false; - - Type[] aargs = a.GetGenericArguments (); - Type[] bargs = b.GetGenericArguments (); - - if (aargs.Length != bargs.Length) - return false; - - for (int i = 0; i < aargs.Length; i++) { - if (!IsEqual (aargs [i], bargs [i])) - return false; - } - - return true; - } - - // - // This is to build with the broken circular dependencies between - // System and System.Configuration in the 2.x profile where we - // end up with a situation where: - // - // System on the second build is referencing the System.Configuration - // that has references to the first System build. - // - // Point in case: NameValueCollection built on the first pass, vs - // NameValueCollection build on the second one. The problem is that - // we need to override some methods sometimes, or we need to - // - if (RootContext.BrokenCircularDeps){ - if (a.Name == b.Name && a.Namespace == b.Namespace){ - Console.WriteLine ("GonziMatch: {0}.{1}", a.Namespace, a.Name); - return true; - } - } - return false; - } - /// /// Check whether `a' and `b' may become equal generic types. /// The algorithm to do that is a little bit complicated. /// - public static bool MayBecomeEqualGenericTypes (Type a, Type b, Type[] class_infered, - Type[] method_infered) + public static bool MayBecomeEqualGenericTypes (Type a, Type b, Type[] class_inferred, + Type[] method_inferred) { if (a.IsGenericParameter) { // @@ -2212,7 +2118,7 @@ namespace Mono.CSharp { // if (b.IsGenericParameter || !b.IsGenericType) { int pos = a.GenericParameterPosition; - Type[] args = a.DeclaringMethod != null ? method_infered : class_infered; + Type[] args = a.DeclaringMethod != null ? method_inferred : class_inferred; if (args [pos] == null) { args [pos] = b; return true; @@ -2244,7 +2150,7 @@ namespace Mono.CSharp { } if (b.IsGenericParameter) - return MayBecomeEqualGenericTypes (b, a, class_infered, method_infered); + return MayBecomeEqualGenericTypes (b, a, class_inferred, method_inferred); // // At this point, neither a nor b are a type parameter. @@ -2256,7 +2162,7 @@ namespace Mono.CSharp { // if (a.IsGenericType || b.IsGenericType) - return MayBecomeEqualGenericInstances (a, b, class_infered, method_infered); + return MayBecomeEqualGenericInstances (a, b, class_inferred, method_inferred); // // If both of them are arrays. @@ -2269,7 +2175,7 @@ namespace Mono.CSharp { a = a.GetElementType (); b = b.GetElementType (); - return MayBecomeEqualGenericTypes (a, b, class_infered, method_infered); + return MayBecomeEqualGenericTypes (a, b, class_inferred, method_inferred); } // @@ -2284,8 +2190,8 @@ namespace Mono.CSharp { // particular instantiation (26.3.1). // public static bool MayBecomeEqualGenericInstances (Type a, Type b, - Type[] class_infered, - Type[] method_infered) + Type[] class_inferred, + Type[] method_inferred) { if (!a.IsGenericType || !b.IsGenericType) return false; @@ -2293,79 +2199,25 @@ namespace Mono.CSharp { return false; return MayBecomeEqualGenericInstances ( - GetTypeArguments (a), GetTypeArguments (b), class_infered, method_infered); + GetTypeArguments (a), GetTypeArguments (b), class_inferred, method_inferred); } public static bool MayBecomeEqualGenericInstances (Type[] aargs, Type[] bargs, - Type[] class_infered, - Type[] method_infered) + Type[] class_inferred, + Type[] method_inferred) { if (aargs.Length != bargs.Length) return false; for (int i = 0; i < aargs.Length; i++) { - if (!MayBecomeEqualGenericTypes (aargs [i], bargs [i], class_infered, method_infered)) + if (!MayBecomeEqualGenericTypes (aargs [i], bargs [i], class_inferred, method_inferred)) return false; } return true; } - /// - /// Check whether `type' and `parent' are both instantiations of the same - /// generic type. Note that we do not check the type parameters here. - /// - public static bool IsInstantiationOfSameGenericType (Type type, Type parent) - { - int tcount = GetNumberOfTypeArguments (type); - int pcount = GetNumberOfTypeArguments (parent); - - if (tcount != pcount) - return false; - - type = DropGenericTypeArguments (type); - parent = DropGenericTypeArguments (parent); - - return type.Equals (parent); - } - - /// - /// Whether `mb' is a generic method definition. - /// - public static bool IsGenericMethodDefinition (MethodBase mb) - { - if (mb.DeclaringType is TypeBuilder) { - IMethodData method = (IMethodData) builder_to_method [mb]; - if (method == null) - return false; - - return method.GenericMethod != null; - } - - return mb.IsGenericMethodDefinition; - } - - /// - /// Whether `mb' is a generic method definition. - /// - public static bool IsGenericMethod (MethodBase mb) - { - if (mb.DeclaringType is TypeBuilder) { - IMethodData method = (IMethodData) builder_to_method [mb]; - if (method == null) - return false; - - return method.GenericMethod != null; - } - - return mb.IsGenericMethod; - } - - // - // Type inference. - // - - static bool InferType (Type pt, Type at, Type[] infered) + static bool UnifyType (Type pt, Type at, Type[] inferred) { if (pt.IsGenericParameter) { if (pt.DeclaringMethod == null) @@ -2373,20 +2225,15 @@ namespace Mono.CSharp { int pos = pt.GenericParameterPosition; - if (infered [pos] == null) { - infered [pos] = at; - return true; - } - - if (infered [pos] != at) - return false; + if (inferred [pos] == null) + inferred [pos] = at; - return true; + return inferred [pos] == at; } if (!pt.ContainsGenericParameters) { if (at.ContainsGenericParameters) - return InferType (at, pt, infered); + return UnifyType (at, pt, inferred); else return true; } @@ -2396,15 +2243,19 @@ namespace Mono.CSharp { if (at.GetArrayRank () != pt.GetArrayRank ()) return false; - return InferType (pt.GetElementType (), at.GetElementType (), infered); + return UnifyType (pt.GetElementType (), at.GetElementType (), inferred); } - if (!pt.IsGenericType || - (pt.GetGenericTypeDefinition () != generic_ienumerable_type)) - return false; + if (!pt.IsGenericType) + return false; + + Type gt = pt.GetGenericTypeDefinition (); + if ((gt != generic_ilist_type) && (gt != generic_icollection_type) && + (gt != generic_ienumerable_type)) + return false; Type[] args = GetTypeArguments (pt); - return InferType (args [0], at.GetElementType (), infered); + return UnifyType (args [0], at.GetElementType (), inferred); } if (pt.IsArray) { @@ -2412,11 +2263,11 @@ namespace Mono.CSharp { (pt.GetArrayRank () != at.GetArrayRank ())) return false; - return InferType (pt.GetElementType (), at.GetElementType (), infered); + return UnifyType (pt.GetElementType (), at.GetElementType (), inferred); } if (pt.IsByRef && at.IsByRef) - return InferType (pt.GetElementType (), at.GetElementType (), infered); + return UnifyType (pt.GetElementType (), at.GetElementType (), inferred); ArrayList list = new ArrayList (); if (at.IsGenericType) list.Add (at); @@ -2425,51 +2276,26 @@ namespace Mono.CSharp { list.AddRange (TypeManager.GetInterfaces (at)); - bool found_one = false; - foreach (Type type in list) { if (!type.IsGenericType) continue; - Type[] infered_types = new Type [infered.Length]; - - if (!InferGenericInstance (pt, type, infered_types)) + if (DropGenericTypeArguments (pt) != DropGenericTypeArguments (type)) continue; - for (int i = 0; i < infered_types.Length; i++) { - if (infered [i] == null) { - infered [i] = infered_types [i]; - continue; - } - - if (infered [i] != infered_types [i]) - return false; - } - - found_one = true; + if (!UnifyTypes (pt.GetGenericArguments (), type.GetGenericArguments (), inferred)) + return false; } - return found_one; + return true; } - static bool InferGenericInstance (Type pt, Type at, Type[] infered_types) + static bool UnifyTypes (Type[] pts, Type [] ats, Type [] inferred) { - Type[] at_args = at.GetGenericArguments (); - Type[] pt_args = pt.GetGenericArguments (); - - if (at_args.Length != pt_args.Length) - return false; - - for (int i = 0; i < at_args.Length; i++) { - if (!InferType (pt_args [i], at_args [i], infered_types)) - return false; - } - - for (int i = 0; i < infered_types.Length; i++) { - if (infered_types [i] == null) + for (int i = 0; i < ats.Length; i++) { + if (!UnifyType (pts [i], ats [i], inferred)) return false; } - return true; } @@ -2482,34 +2308,28 @@ namespace Mono.CSharp { public static bool InferParamsTypeArguments (EmitContext ec, ArrayList arguments, ref MethodBase method) { - if ((arguments == null) || !TypeManager.IsGenericMethod (method)) + if (!TypeManager.IsGenericMethod (method)) return true; - int arg_count; - - if (arguments == null) - arg_count = 0; - else - arg_count = arguments.Count; - - ParameterData pd = TypeManager.GetParameterData (method); + // if there are no arguments, there's no way to infer the type-arguments + if (arguments == null || arguments.Count == 0) + return false; + ParameterData pd = TypeManager.GetParameterData (method); int pd_count = pd.Count; + int arg_count = arguments.Count; if (pd_count == 0) return false; - + if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) return false; - + if (pd_count - 1 > arg_count) return false; - - if (pd_count == 1 && arg_count == 0) - return true; Type[] method_args = method.GetGenericArguments (); - Type[] infered_types = new Type [method_args.Length]; + Type[] inferred_types = new Type [method_args.Length]; // // If we have come this far, the case which @@ -2525,7 +2345,7 @@ namespace Mono.CSharp { Type pt = pd.ParameterType (i); Type at = a.Type; - if (!InferType (pt, at, infered_types)) + if (!UnifyType (pt, at, inferred_types)) return false; } @@ -2537,34 +2357,31 @@ namespace Mono.CSharp { if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr)) continue; - if (!InferType (element_type, a.Type, infered_types)) + if (!UnifyType (element_type, a.Type, inferred_types)) return false; } - for (int i = 0; i < infered_types.Length; i++) - if (infered_types [i] == null) + for (int i = 0; i < inferred_types.Length; i++) + if (inferred_types [i] == null) return false; - method = ((MethodInfo)method).MakeGenericMethod (infered_types); + method = ((MethodInfo)method).MakeGenericMethod (inferred_types); return true; } static bool InferTypeArguments (Type[] param_types, Type[] arg_types, - Type[] infered_types) + Type[] inferred_types) { - if (infered_types == null) - return false; - for (int i = 0; i < arg_types.Length; i++) { if (arg_types [i] == null) continue; - if (!InferType (param_types [i], arg_types [i], infered_types)) + if (!UnifyType (param_types [i], arg_types [i], inferred_types)) return false; } - for (int i = 0; i < infered_types.Length; i++) - if (infered_types [i] == null) + for (int i = 0; i < inferred_types.Length; i++) + if (inferred_types [i] == null) return false; return true; @@ -2606,7 +2423,7 @@ namespace Mono.CSharp { if (!is_open) return !TypeManager.IsGenericMethodDefinition (method); - Type[] infered_types = new Type [method_args.Length]; + Type[] inferred_types = new Type [method_args.Length]; Type[] param_types = new Type [pd.Count]; Type[] arg_types = new Type [pd.Count]; @@ -2616,16 +2433,16 @@ namespace Mono.CSharp { Argument a = (Argument) arguments [i]; if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr) || - (a.Expr is AnonymousMethod)) + (a.Expr is AnonymousMethodExpression)) continue; arg_types [i] = a.Type; } - if (!InferTypeArguments (param_types, arg_types, infered_types)) + if (!InferTypeArguments (param_types, arg_types, inferred_types)) return false; - method = ((MethodInfo)method).MakeGenericMethod (infered_types); + method = ((MethodInfo)method).MakeGenericMethod (inferred_types); return true; } @@ -2643,7 +2460,7 @@ namespace Mono.CSharp { return false; Type[] method_args = method.GetGenericArguments (); - Type[] infered_types = new Type [method_args.Length]; + Type[] inferred_types = new Type [method_args.Length]; Type[] param_types = new Type [pd.Count]; Type[] arg_types = new Type [pd.Count]; @@ -2653,33 +2470,12 @@ namespace Mono.CSharp { arg_types [i] = apd.ParameterType (i); } - if (!InferTypeArguments (param_types, arg_types, infered_types)) + if (!InferTypeArguments (param_types, arg_types, inferred_types)) return false; - method = ((MethodInfo)method).MakeGenericMethod (infered_types); + method = ((MethodInfo)method).MakeGenericMethod (inferred_types); return true; } - - public static bool IsNullableType (Type t) - { - return generic_nullable_type == DropGenericTypeArguments (t); - } - - public static bool IsNullableTypeOf (Type t, Type nullable) - { - if (!IsNullableType (t)) - return false; - - return GetTypeArguments (t) [0] == nullable; - } - - public static bool IsNullableValueType (Type t) - { - if (!IsNullableType (t)) - return false; - - return GetTypeArguments (t) [0].IsValueType; - } } public abstract class Nullable @@ -2714,10 +2510,15 @@ namespace Mono.CSharp { LocalTemporary temp; bool has_temp; - public Unwrap (Expression expr, Location loc) + protected Unwrap (Expression expr) { this.expr = expr; - this.loc = loc; + this.loc = expr.Location; + } + + public static Unwrap Create (Expression expr, EmitContext ec) + { + return new Unwrap (expr).Resolve (ec) as Unwrap; } public override Expression DoResolve (EmitContext ec) @@ -2822,10 +2623,15 @@ namespace Mono.CSharp { Expression expr; NullableInfo info; - public Wrap (Expression expr, Location loc) + protected Wrap (Expression expr) { this.expr = expr; - this.loc = loc; + this.loc = expr.Location; + } + + public static Wrap Create (Expression expr, EmitContext ec) + { + return new Wrap (expr).Resolve (ec) as Wrap; } public override Expression DoResolve (EmitContext ec) @@ -2902,7 +2708,7 @@ namespace Mono.CSharp { if (expr == null) return null; - unwrap = (Unwrap) new Unwrap (expr, loc).Resolve (ec); + unwrap = Unwrap.Create (expr, ec); if (unwrap == null) return null; @@ -2910,7 +2716,7 @@ namespace Mono.CSharp { if (underlying == null) return null; - wrap = new Wrap (underlying, loc).Resolve (ec); + wrap = Wrap.Create (underlying, ec); if (wrap == null) return null; @@ -3034,15 +2840,13 @@ namespace Mono.CSharp { public override Expression DoResolve (EmitContext ec) { if (TypeManager.IsNullableType (left.Type)) { - left_unwrap = new Unwrap (left, loc); - left = left_unwrap.Resolve (ec); + left = left_unwrap = Unwrap.Create (left, ec); if (left == null) return null; } if (TypeManager.IsNullableType (right.Type)) { - right_unwrap = new Unwrap (right, loc); - right = right_unwrap.Resolve (ec); + right = right_unwrap = Unwrap.Create (right, ec); if (right == null) return null; } @@ -3059,7 +2863,7 @@ namespace Mono.CSharp { if (((Oper == Binary.Operator.BitwiseAnd) || (Oper == Binary.Operator.BitwiseOr)) && ((left.Type == TypeManager.bool_type) && (right.Type == TypeManager.bool_type))) { Expression empty = new EmptyExpression (TypeManager.bool_type); - bool_wrap = new Wrap (empty, loc).Resolve (ec); + bool_wrap = Wrap.Create (empty, ec); null_value = new NullableLiteral (bool_wrap.Type, loc).Resolve (ec); type = bool_wrap.Type; @@ -3088,7 +2892,7 @@ namespace Mono.CSharp { if (underlying == null) return null; - underlying = new Wrap (underlying, loc).Resolve (ec); + underlying = Wrap.Create (underlying, ec); if (underlying == null) return null; @@ -3321,9 +3125,8 @@ namespace Mono.CSharp { public override Expression DoResolve (EmitContext ec) { - unwrap = new Unwrap (expr, loc); - expr = unwrap.Resolve (ec); - if (expr == null) + unwrap = Unwrap.Create (expr, ec); + if (unwrap == null) return null; if (unwrap.Type != TypeManager.bool_type) @@ -3396,7 +3199,7 @@ namespace Mono.CSharp { if (TypeManager.IsNullableType (ltype)) { NullableInfo info = new NullableInfo (ltype); - unwrap = (Unwrap) new Unwrap (left, loc).Resolve (ec); + unwrap = Unwrap.Create (left, ec); if (unwrap == null) return null; @@ -3414,14 +3217,13 @@ namespace Mono.CSharp { return this; } - if (unwrap != null) { - expr = Convert.ImplicitConversion (ec, unwrap, rtype, loc); - if (expr != null) { - left = expr; - expr = right; - type = expr.Type; - return this; - } + Expression left_null = unwrap != null ? unwrap : left; + expr = Convert.ImplicitConversion (ec, left_null, rtype, loc); + if (expr != null) { + left = expr; + expr = right; + type = rtype; + return this; } Binary.Error_OperatorCannotBeApplied (loc, "??", ltype, rtype); @@ -3483,7 +3285,7 @@ namespace Mono.CSharp { if (expr == null) return null; - unwrap = (Unwrap) new Unwrap (expr, loc).Resolve (ec); + unwrap = Unwrap.Create (expr, ec); if (unwrap == null) return null;