}
}
+ public bool HasDynamicElement {
+ get {
+ return (state & StateFlags.HasDynamicElement) != 0;
+ }
+ }
+
public virtual IList<TypeSpec> Interfaces {
get {
return ifaces;
}
}
- public virtual MemberCache MemberCacheTypes {
+ public MemberCache MemberCacheTypes {
get {
- return MemberCache;
+ if (cache == null)
+ InitializeMemberCache (true);
+
+ return cache;
}
}
if (IsNested) {
s = DeclaringType.GetSignatureForError ();
+ } else if (MemberDefinition is AnonymousTypeClass) {
+ return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError ();
} else {
s = MemberDefinition.Namespace;
}
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;
}
}
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<object> != G<dynamic>
+ //
+ 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<dynamic>
+ //
+ // class B : A<object> {}
+ //
+ 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)
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;
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);
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;
}
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<TypeSpec[]>, IEqualityComparer<Tuple<TypeSpec, TypeSpec[]>>
+ public class DefaultImpl : IEqualityComparer<TypeSpec[]>
{
#region IEqualityComparer<TypeSpec[]> Members
- public bool Equals (TypeSpec[] x, TypeSpec[] y)
+ bool IEqualityComparer<TypeSpec[]>.Equals (TypeSpec[] x, TypeSpec[] y)
{
if (x == y)
return true;
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<TypeSpec[]>.GetHashCode (TypeSpec[] obj)
{
int hash = 0;
for (int i = 0; i < obj.Length; ++i)
}
#endregion
-
- #region IEqualityComparer<Tuple<TypeSpec,TypeSpec[]>> Members
-
- bool IEqualityComparer<Tuple<TypeSpec, TypeSpec[]>>.Equals (Tuple<TypeSpec, TypeSpec[]> x, Tuple<TypeSpec, TypeSpec[]> y)
- {
- return Equals (x.Item2, y.Item2) && x.Item1 == y.Item1;
- }
-
- int IEqualityComparer<Tuple<TypeSpec, TypeSpec[]>>.GetHashCode (Tuple<TypeSpec, TypeSpec[]> 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);
- }
}
//
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) {
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
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 ("<fake$type>");
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
}
}
+ 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
: 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
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 {