- static public Type activator_type;
-
- public static TypeContainer LookupGenericTypeContainer (Type t)
- {
- t = DropGenericTypeArguments (t);
- return LookupTypeContainer (t);
- }
-
- public static Variance GetTypeParameterVariance (Type type)
- {
- TypeParameter tparam = LookupTypeParameter (type);
- if (tparam != null)
- return tparam.Variance;
-
- switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) {
- case GenericParameterAttributes.Covariant:
- return Variance.Covariant;
- case GenericParameterAttributes.Contravariant:
- return Variance.Contravariant;
- default:
- return Variance.None;
- }
- }
-
- /// <summary>
- /// Check whether `a' and `b' may become equal generic types.
- /// The algorithm to do that is a little bit complicated.
- /// </summary>
- public static bool MayBecomeEqualGenericTypes (Type a, Type b, Type[] class_inferred,
- Type[] method_inferred)
- {
- if (a.IsGenericParameter) {
- //
- // If a is an array of a's type, they may never
- // become equal.
- //
- while (b.IsArray) {
- b = GetElementType (b);
- if (a.Equals (b))
- return false;
- }
-
- //
- // If b is a generic parameter or an actual type,
- // they may become equal:
- //
- // class X<T,U> : I<T>, I<U>
- // class X<T> : I<T>, I<float>
- //
- if (b.IsGenericParameter || !b.IsGenericType) {
- int pos = a.GenericParameterPosition;
- Type[] args = a.DeclaringMethod != null ? method_inferred : class_inferred;
- if (args [pos] == null) {
- args [pos] = b;
- return true;
- }
-
- return args [pos] == a;
- }
-
- //
- // We're now comparing a type parameter with a
- // generic instance. They may become equal unless
- // the type parameter appears anywhere in the
- // generic instance:
- //
- // class X<T,U> : I<T>, I<X<U>>
- // -> error because you could instanciate it as
- // X<X<int>,int>
- //
- // class X<T> : I<T>, I<X<T>> -> ok
- //
-
- Type[] bargs = GetTypeArguments (b);
- for (int i = 0; i < bargs.Length; i++) {
- if (a.Equals (bargs [i]))
- return false;
+ public static Variance CheckTypeVariance (TypeSpec t, Variance expected, IMemberContext member)
+ {
+ var tp = t as TypeParameterSpec;
+ if (tp != null) {
+ Variance v = tp.Variance;
+ if (expected == Variance.None && v != expected ||
+ expected == Variance.Covariant && v == Variance.Contravariant ||
+ expected == Variance.Contravariant && v == Variance.Covariant) {
+ ((TypeParameter)tp.MemberDefinition).ErrorInvalidVariance (member, expected);