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 {
TypeSpec[] targs;
TypeSpec[] ifaces_defined;
TypeSpec effective_base;
+ MemberCache interface_cache;
//
// Creates type owned type parameter
}
}
+ public MemberCache InterfaceCache {
+ get {
+ return interface_cache;
+ }
+ }
+
//
// Unexpanded interfaces list
//
// 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);
}
}
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);
}
}
}
if (ec is PointerContainer)
return PointerContainer.MakeType (context.Module, et);
+ if (ec is ReferenceContainer)
+ return ReferenceContainer.MakeType (context.Module, et);
+
throw new NotImplementedException ();
}
foreach (var arg in targs) {
if (arg.HasDynamicElement || arg.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
state |= StateFlags.HasDynamicElement;
- break;
+ }
+
+ if (arg.HasNamedTupleElement) {
+ state |= StateFlags.HasNamedTupleElement;
}
}
}
}
+ public override bool IsTupleType {
+ get {
+ return (open_type.state & StateFlags.Tuple) != 0;
+ }
+ }
+
//
// Types used to inflate the generic type
//
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;
// 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];
var ga_u = u.TypeArguments;
var ga_v = v.TypeArguments;
- if (u.TypeArguments.Length != u.TypeArguments.Length)
+ if (u.TypeArguments.Length != v.TypeArguments.Length)
return 0;
int score = 0;