X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fgeneric.cs;h=8ddef4f36947b630ee655efd11adbe80fa385b5c;hb=46a0e22cc572147500058e6439082c2433990003;hp=fb7b6c79942278a404d2105f69c243ce1885d4e9;hpb=d04e09ac0c813738843da7f49e9113ac4607fa8c;p=mono.git diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs index fb7b6c79942..8ddef4f3694 100644 --- a/mcs/mcs/generic.cs +++ b/mcs/mcs/generic.cs @@ -195,9 +195,7 @@ namespace Mono.CSharp { continue; if (obsoleteCheck) { - ObsoleteAttribute obsolete_attr = t.GetAttributeObsolete (); - if (obsolete_attr != null) - AttributeTester.Report_ObsoleteMessage (obsolete_attr, t.GetSignatureForError (), c.Location, context.Module.Compiler.Report); + t.CheckObsoleteness (context, c.Location); } ConstraintChecker.Check (context, t, c.Location); @@ -430,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 { @@ -651,10 +649,10 @@ namespace Mono.CSharp { var meta_constraints = new List (spec.TypeArguments.Length); foreach (var c in spec.TypeArguments) { // - // Inflated type parameters can collide with special constraint types, don't + // Inflated type parameters can collide with base type constraint, don't // emit any such type parameter. // - if (c.BuiltinType == BuiltinTypeSpec.Type.Object || c.BuiltinType == BuiltinTypeSpec.Type.ValueType) + if (c.IsClass && spec.BaseType.BuiltinType != BuiltinTypeSpec.Type.Object) continue; meta_constraints.Add (c.GetMetaInfo ()); @@ -775,6 +773,7 @@ namespace Mono.CSharp { TypeSpec[] targs; TypeSpec[] ifaces_defined; TypeSpec effective_base; + MemberCache interface_cache; // // Creates type owned type parameter @@ -884,6 +883,12 @@ namespace Mono.CSharp { } } + public MemberCache InterfaceCache { + get { + return interface_cache; + } + } + // // Unexpanded interfaces list // @@ -1114,14 +1119,20 @@ namespace Mono.CSharp { // bool found; if (!TypeSpecComparer.Override.IsEqual (BaseType, other.BaseType)) { - if (other.targs == null) - return false; - found = false; - foreach (var otarg in other.targs) { - if (TypeSpecComparer.Override.IsEqual (BaseType, otarg)) { - found = true; - break; + if (other.targs != null) { + foreach (var otarg in other.targs) { + if (TypeSpecComparer.Override.IsEqual (BaseType, otarg)) { + found = true; + break; + } + } + } else if (targs != null) { + foreach (var targ in targs) { + if (TypeSpecComparer.Override.IsEqual (targ, other.BaseType)) { + found = true; + break; + } } } @@ -1134,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) { @@ -1164,18 +1175,25 @@ namespace Mono.CSharp { // Check interfaces implementation <- definition if (other.InterfacesDefined != null) { - if (InterfacesDefined == null) - return false; - // // Iterate over inflated interfaces // - foreach (var oiface in other.Interfaces) { + foreach (var oiface in other.InterfacesDefined) { found = false; - foreach (var iface in Interfaces) { - if (TypeSpecComparer.Override.IsEqual (iface, oiface)) { - found = true; - break; + + if (InterfacesDefined != null) { + foreach (var iface in Interfaces) { + if (TypeSpecComparer.Override.IsEqual (iface, oiface)) { + found = true; + break; + } + } + } else if (targs != null) { + foreach (var targ in targs) { + if (TypeSpecComparer.Override.IsEqual (targ, oiface)) { + found = true; + break; + } } } @@ -1186,18 +1204,30 @@ namespace Mono.CSharp { // Check type parameters implementation -> definition if (targs != null) { - if (other.targs == null) - return false; - foreach (var targ in targs) { found = false; - foreach (var otarg in other.targs) { - if (TypeSpecComparer.Override.IsEqual (targ, otarg)) { - found = true; - break; + + if (other.targs != null) { + foreach (var otarg in other.targs) { + if (TypeSpecComparer.Override.IsEqual (targ, otarg)) { + found = true; + break; + } + } + } + + if (other.InterfacesDefined != null && !found) { + foreach (var iface in other.Interfaces) { + if (TypeSpecComparer.Override.IsEqual (iface, targ)) { + found = true; + break; + } } } + if (!found) + found = TypeSpecComparer.Override.IsEqual (targ, other.BaseType); + if (!found) return false; } @@ -1311,42 +1341,64 @@ namespace Mono.CSharp { { cache = new MemberCache (); + if (targs != null) { + foreach (var ta in targs) { + var tps = ta as TypeParameterSpec; + var b_type = tps == null ? ta : tps.GetEffectiveBase (); + + // + // Find the most specific type when base type was inflated from base constraints + // + if (b_type != null && !b_type.IsStructOrEnum && TypeSpec.IsBaseClass (b_type, BaseType, false)) + BaseType = b_type; + } + } + // // 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 // - if (BaseType.BuiltinType != BuiltinTypeSpec.Type.Object && BaseType.BuiltinType != BuiltinTypeSpec.Type.ValueType) + 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); } } + // + // Import interfaces after base type to match behavior from ordinary classes + // if (targs != null) { foreach (var ta in targs) { var tps = ta as TypeParameterSpec; - IList ifaces; - TypeSpec b_type; - if (tps != null) { - b_type = tps.GetEffectiveBase (); - ifaces = tps.InterfacesDefined; - } else { - b_type = ta; - ifaces = ta.Interfaces; - } - - // - // Don't add base type which was inflated from base constraints but it's not valid - // in C# context - // - if (b_type != null && b_type.BuiltinType != BuiltinTypeSpec.Type.Object && b_type.BuiltinType != BuiltinTypeSpec.Type.ValueType && !b_type.IsStructOrEnum) - cache.AddBaseType (b_type); + 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); } } } @@ -1526,7 +1578,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 @@ -1915,6 +1967,14 @@ namespace Mono.CSharp { return definition.GetMetaInfo ().MakeGenericType (all.ToArray ()); } + public override void CheckObsoleteness (IMemberContext mc, Location loc) + { + base.CheckObsoleteness (mc, loc); + + foreach (var ta in TypeArguments) + ta.CheckObsoleteness (mc, loc); + } + public override ObsoleteAttribute GetAttributeObsolete () { return open_type.GetAttributeObsolete (); @@ -2102,6 +2162,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 (DeclaringType.GetDefinition (), this).info; @@ -3078,21 +3142,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; + + var ga_u = u.TypeArguments; + var ga_v = v.TypeArguments; + + if (u.TypeArguments.Length != v.TypeArguments.Length) + return 0; - int score = 0; - for (int i = 0; i < ga_u.Length; ++i) - score += ExactInference (ga_u [i], ga_v [i]); + 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); + return System.Math.Min (1, score); + } } // If V is one of the unfixed type arguments