X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Ftypespec.cs;h=99b8919ef35cf9b80dce99873fa3e795334da6e1;hb=2c810c3ed9592c43ab0734b78e49cd206641e9fe;hp=f5b8df634cf636fe1c02cda4a648ab2e64f614a8;hpb=c4e1412b7a0f540fc43015ac9988a94638a0c0f2;p=mono.git diff --git a/mcs/mcs/typespec.cs b/mcs/mcs/typespec.cs index f5b8df634cf..99b8919ef35 100644 --- a/mcs/mcs/typespec.cs +++ b/mcs/mcs/typespec.cs @@ -66,6 +66,12 @@ namespace Mono.CSharp } } + public bool HasDynamicElement { + get { + return (state & StateFlags.HasDynamicElement) != 0; + } + } + public virtual IList Interfaces { get { return ifaces; @@ -194,9 +200,12 @@ namespace Mono.CSharp } } - public virtual MemberCache MemberCacheTypes { + public MemberCache MemberCacheTypes { get { - return MemberCache; + if (cache == null) + InitializeMemberCache (true); + + return cache; } } @@ -269,6 +278,8 @@ namespace Mono.CSharp if (IsNested) { s = DeclaringType.GetSignatureForError (); + } else if (MemberDefinition is AnonymousTypeClass) { + return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError (); } else { s = MemberDefinition.Namespace; } @@ -287,13 +298,16 @@ namespace Mono.CSharp return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">"; } - public bool ImplementsInterface (TypeSpec iface) + public bool ImplementsInterface (TypeSpec iface, bool variantly) { var t = this; do { if (t.Interfaces != null) { // TODO: Try t.iface foreach (TypeSpec i in t.Interfaces) { - if (i == iface || TypeSpecComparer.Variant.IsEqual (i, iface)) + if (i == iface || TypeSpecComparer.IsEqual (i, iface)) + return true; + + if (variantly && TypeSpecComparer.Variant.IsEqual (i, iface)) return true; } } @@ -306,14 +320,43 @@ namespace Mono.CSharp protected virtual void InitializeMemberCache (bool onlyTypes) { - // - // Not interested in members of nested private types - // - if (IsPrivate) { - cache = new MemberCache (0); - } else { - cache = MemberDefinition.LoadMembers (this); + MemberDefinition.LoadMembers (this, onlyTypes, ref cache); + + if (onlyTypes) + state |= StateFlags.PendingMemberCacheMembers; + else + state &= ~StateFlags.PendingMemberCacheMembers; + } + + // + // Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower + // comparison is used to hide differences between `object' and `dynamic' for generic + // types. Should not be used for comparisons where G != G + // + public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject) + { + if (dynamicIsObject && baseClass.IsGeneric) { + // + // Returns true for a hierarchies like this when passing baseClass of A + // + // class B : A {} + // + while (type != null) { + type = type.BaseType; + if (TypeSpecComparer.IsEqual (type, baseClass)) + return true; + } + + return false; + } + + while (type != null) { + type = type.BaseType; + if (type == baseClass) + return true; } + + return false; } public override MemberSpec InflateMember (TypeParameterInflator inflator) @@ -333,7 +376,7 @@ namespace Mono.CSharp public InflatedTypeSpec MakeGenericType (TypeSpec[] targs) { if (targs.Length == 0 && !IsNested) - throw new ArgumentException ("Empty type arguments"); + throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ()); InflatedTypeSpec instance; @@ -342,7 +385,8 @@ namespace Mono.CSharp if (!inflated_instances.TryGetValue (targs, out instance)) { if (GetDefinition () != this && !IsNested) - throw new InternalErrorException ("Only type definition or nested non-inflated types can be used to call MakeGenericType"); + throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType", + GetSignatureForError ()); instance = new InflatedTypeSpec (this, declaringType, targs); inflated_instances.Add (targs, instance); @@ -378,6 +422,9 @@ namespace Mono.CSharp public PredefinedTypeSpec (MemberKind kind, string ns, string name) : base (kind, null, null, null, Modifiers.PUBLIC) { + if (kind == MemberKind.Struct) + modifiers |= Modifiers.SEALED; + this.name = name; this.ns = ns; } @@ -446,16 +493,15 @@ namespace Mono.CSharp static class TypeSpecComparer { // - // Default reference comparison, it has to be used when comparing - // two possible dynamic/internal types + // Does strict reference comparion only // public static readonly DefaultImpl Default = new DefaultImpl (); - public class DefaultImpl : IEqualityComparer, IEqualityComparer> + public class DefaultImpl : IEqualityComparer { #region IEqualityComparer Members - public bool Equals (TypeSpec[] x, TypeSpec[] y) + bool IEqualityComparer.Equals (TypeSpec[] x, TypeSpec[] y) { if (x == y) return true; @@ -464,13 +510,13 @@ namespace Mono.CSharp return false; for (int i = 0; i < x.Length; ++i) - if (!IsEqual (x[i], y[i])) + if (x[i] != y[i]) return false; return true; } - public int GetHashCode (TypeSpec[] obj) + int IEqualityComparer.GetHashCode (TypeSpec[] obj) { int hash = 0; for (int i = 0; i < obj.Length; ++i) @@ -480,45 +526,6 @@ namespace Mono.CSharp } #endregion - - #region IEqualityComparer> Members - - bool IEqualityComparer>.Equals (Tuple x, Tuple y) - { - return Equals (x.Item2, y.Item2) && x.Item1 == y.Item1; - } - - int IEqualityComparer>.GetHashCode (Tuple obj) - { - return GetHashCode (obj.Item2) ^ obj.Item1.GetHashCode (); - } - - #endregion - - // - // Identity type conversion - // - public bool IsEqual (TypeSpec a, TypeSpec b) - { - if (a == b) - return a.Kind != MemberKind.InternalCompilerType; - - // - // object and dynamic are considered equivalent there is an identity conversion - // between object and dynamic, and between constructed types that are the same - // when replacing all occurences of dynamic with object. - // - if (a == InternalType.Dynamic || b == InternalType.Dynamic) - return b == TypeManager.object_type || a == TypeManager.object_type; - - if (a == null || !a.IsGeneric || b == null || !b.IsGeneric) - return false; - - if (a.MemberDefinition != b.MemberDefinition) - return false; - - return Equals (a.TypeArguments, b.TypeArguments); - } } // @@ -652,7 +659,7 @@ namespace Mono.CSharp var targs_definition = target_type_def.TypeParameters; if (!type1.IsInterface && !type1.IsDelegate) { - return Default.Equals (t1_targs, t2_targs); + return false; } for (int i = 0; i < targs_definition.Length; ++i) { @@ -784,6 +791,71 @@ namespace Mono.CSharp return false; } } + + public static bool Equals (TypeSpec[] x, TypeSpec[] y) + { + if (x == y) + return true; + + if (x.Length != y.Length) + return false; + + for (int i = 0; i < x.Length; ++i) + if (!IsEqual (x[i], y[i])) + return false; + + return true; + } + + // + // Identity type conversion + // + // Default reference comparison, it has to be used when comparing + // two possible dynamic/internal types + // + public static bool IsEqual (TypeSpec a, TypeSpec b) + { + if (a == b) { + // This also rejects dynamic == dynamic + return a.Kind != MemberKind.InternalCompilerType || a == InternalType.Dynamic; + } + + // + // object and dynamic are considered equivalent there is an identity conversion + // between object and dynamic, and between constructed types that are the same + // when replacing all occurences of dynamic with object. + // + if (a == InternalType.Dynamic || b == InternalType.Dynamic) + return b == TypeManager.object_type || a == TypeManager.object_type; + + if (a == null) + return false; + + if (a.IsArray) { + var a_a = (ArrayContainer) a; + var b_a = b as ArrayContainer; + if (b_a == null) + return false; + + return IsEqual (a_a.Element, b_a.Element) && a_a.Rank == b_a.Rank; + } + + if (!a.IsGeneric || b == null || !b.IsGeneric) + return false; + + if (a.MemberDefinition != b.MemberDefinition) + return false; + + do { + if (!Equals (a.TypeArguments, b.TypeArguments)) + return false; + + a = a.DeclaringType; + b = b.DeclaringType; + } while (a != null); + + return true; + } } public interface ITypeDefinition : IMemberDefinition @@ -795,30 +867,31 @@ namespace Mono.CSharp TypeSpec GetAttributeCoClass (); string GetAttributeDefaultMember (); AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa); - MemberCache LoadMembers (TypeSpec declaringType); + void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache); } - class InternalType : TypeSpec + class InternalType : TypeSpec, ITypeDefinition { public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method"); public static readonly InternalType Arglist = new InternalType ("__arglist"); - public static readonly InternalType Dynamic = new InternalType ("dynamic", typeof (object)); + public static readonly InternalType Dynamic = new InternalType ("dynamic", null); public static readonly InternalType MethodGroup = new InternalType ("method group"); - public static readonly InternalType Null = new InternalType ("null", typeof (object)); + public static readonly InternalType Null = new InternalType ("null"); public static readonly InternalType FakeInternalType = new InternalType (""); readonly string name; - InternalType (string name, Type metaInfo) + InternalType (string name, MemberCache cache) : this (name) { - info = metaInfo; + this.cache = cache; } InternalType (string name) : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC) { this.name = name; + this.definition = this; cache = MemberCache.Empty; // Make all internal types CLS-compliant, non-obsolete @@ -833,18 +906,95 @@ namespace Mono.CSharp } } + System.Reflection.Assembly IMemberDefinition.Assembly { + get { + throw new NotImplementedException (); + } + } + + bool IMemberDefinition.IsImported { + get { + return false; + } + } + public override string Name { get { return name; } } + string ITypeDefinition.Namespace { + get { + return null; + } + } + + int ITypeDefinition.TypeParametersCount { + get { + return 0; + } + } + + TypeParameterSpec[] ITypeDefinition.TypeParameters { + get { + return null; + } + } + #endregion public override string GetSignatureForError () { return name; } + + #region ITypeDefinition Members + + TypeSpec ITypeDefinition.GetAttributeCoClass () + { + return null; + } + + string ITypeDefinition.GetAttributeDefaultMember () + { + return null; + } + + AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa) + { + return null; + } + + void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) + { + throw new NotImplementedException (); + } + + string[] IMemberDefinition.ConditionalConditions () + { + return null; + } + + ObsoleteAttribute IMemberDefinition.GetAttributeObsolete () + { + return null; + } + + bool IMemberDefinition.IsNotCLSCompliant () + { + return false; + } + + void IMemberDefinition.SetIsAssigned () + { + } + + void IMemberDefinition.SetIsUsed () + { + } + + #endregion } public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition @@ -853,6 +1003,8 @@ namespace Mono.CSharp : base (kind, element.DeclaringType, null, info, element.Modifiers) { this.Element = element; + if (element == InternalType.Dynamic || element.HasDynamicElement) + state |= StateFlags.HasDynamicElement; // Has to use its own type definition instead of just element definition to // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition @@ -934,9 +1086,9 @@ namespace Mono.CSharp return Element.MemberDefinition.GetAttributeDefaultMember (); } - public MemberCache LoadMembers (TypeSpec declaringType) + public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) { - return Element.MemberDefinition.LoadMembers (declaringType); + Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache); } public bool IsImported {