}
}
+ public enum Variance
+ {
+ None,
+ Covariant,
+ Contravariant
+ }
+
public enum SpecialConstraint
{
Constructor,
Constraints constraints;
GenericTypeParameterBuilder type;
MemberCache member_cache;
+ Variance variance;
public TypeParameter (DeclSpace parent, DeclSpace decl, string name,
- Constraints constraints, Attributes attrs, Location loc)
+ Constraints constraints, Attributes attrs, Variance variance, Location loc)
: base (parent, new MemberName (name, loc), attrs)
{
this.decl = decl;
this.constraints = constraints;
+ this.variance = variance;
+ if (variance != Variance.None && !(decl is Interface) && !(decl is Delegate)) {
+ Report.Error (-36, loc, "Generic variance can only be used with interfaces and delegates");
+ }
}
public GenericConstraints GenericConstraints {
get { return decl; }
}
+ public Variance Variance {
+ get { return variance; }
+ }
+
public Type Type {
get { return type; }
}
gc = (GenericConstraints) constraints;
}
- if (gc == null)
- return true;
+ SetConstraints (type);
+ return true;
+ }
- if (gc.HasClassConstraint || gc.HasValueTypeConstraint)
- type.SetBaseTypeConstraint (gc.EffectiveBaseClass);
+ public void SetConstraints (GenericTypeParameterBuilder type)
+ {
+ GenericParameterAttributes attr = GenericParameterAttributes.None;
+ if (variance == Variance.Contravariant)
+ attr |= GenericParameterAttributes.Contravariant;
+ else if (variance == Variance.Covariant)
+ attr |= GenericParameterAttributes.Covariant;
- type.SetInterfaceConstraints (gc.InterfaceConstraints);
- type.SetGenericParameterAttributes (gc.Attributes);
- TypeManager.RegisterBuilder (type, gc.InterfaceConstraints);
+ if (gc != null) {
+ if (gc.HasClassConstraint || gc.HasValueTypeConstraint)
+ type.SetBaseTypeConstraint (gc.EffectiveBaseClass);
- return true;
+ attr |= gc.Attributes;
+ type.SetInterfaceConstraints (gc.InterfaceConstraints);
+ TypeManager.RegisterBuilder (type, gc.InterfaceConstraints);
+ }
+
+ type.SetGenericParameterAttributes (attr);
}
/// <summary>
public class TypeParameterName : SimpleName
{
Attributes attributes;
+ Variance variance;
public TypeParameterName (string name, Attributes attrs, Location loc)
+ : this (name, attrs, Variance.None, loc)
+ {
+ }
+
+ public TypeParameterName (string name, Attributes attrs, Variance variance, Location loc)
: base (name, loc)
{
attributes = attrs;
+ this.variance = variance;
}
public Attributes OptAttributes {
return attributes;
}
}
+
+ public Variance Variance {
+ get {
+ return variance;
+ }
+ }
}
/// <summary>
return ConstraintChecker.CheckConstraints (ec, open_type, gen_params, args.Arguments, loc);
}
+ static bool IsVariant (Type type)
+ {
+ return (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) != 0;
+ }
+
+ static bool IsCovariant (Type type)
+ {
+ return (type.GenericParameterAttributes & GenericParameterAttributes.Covariant) != 0;
+ }
+
+ static bool IsContravariant (Type type)
+ {
+ return (type.GenericParameterAttributes & GenericParameterAttributes.Contravariant) != 0;
+ }
+
+ public bool VerifyVariantTypeParameters ()
+ {
+ for (int i = 0; i < args.Count; i++) {
+ Type argument = args.Arguments[i];
+ if (argument.IsGenericParameter && IsVariant (argument)) {
+ if (IsContravariant (argument) && !IsContravariant (gen_params[i])) {
+ Report.Error (-34, loc, "Contravariant type parameters can only be used " +
+ "as type arguments in contravariant positions");
+ return false;
+ }
+ else if (IsCovariant (argument) && !IsCovariant (gen_params[i])) {
+ Report.Error (-35, loc, "Covariant type parameters can only be used " +
+ "as type arguments in covariant positions");
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+
public override bool CheckAccessLevel (DeclSpace ds)
{
return ds.CheckAccessLevel (open_type);
}
public override bool IsValueType {
- get { return open_type.IsValueType; }
+ get { return TypeManager.IsStruct (open_type); }
}
public override bool IsInterface {
if (!atype.IsGenericType)
#endif
is_class = atype.IsClass || atype.IsInterface;
- is_struct = atype.IsValueType && !TypeManager.IsNullableType (atype);
+ is_struct = TypeManager.IsValueType (atype) && !TypeManager.IsNullableType (atype);
}
//
if (!gc.HasConstructorConstraint)
return true;
- if (TypeManager.IsBuiltinType (atype) || atype.IsValueType)
+ if (TypeManager.IsBuiltinType (atype) || TypeManager.IsValueType (atype))
return true;
if (HasDefaultConstructor (atype))
public class GenericMethod : DeclSpace
{
FullNamedExpression return_type;
- Parameters parameters;
+ ParametersCompiled parameters;
public GenericMethod (NamespaceEntry ns, DeclSpace parent, MemberName name,
- FullNamedExpression return_type, Parameters parameters)
+ FullNamedExpression return_type, ParametersCompiled parameters)
: base (ns, parent, name, null)
{
this.return_type = return_type;
// become equal.
//
while (b.IsArray) {
- b = b.GetElementType ();
+ b = GetElementType (b);
if (a.Equals (b))
return false;
}
if (a.GetArrayRank () != b.GetArrayRank ())
return false;
- a = a.GetElementType ();
- b = b.GetElementType ();
+ a = GetElementType (a);
+ b = GetElementType (b);
return MayBecomeEqualGenericTypes (a, b, class_inferred, method_inferred);
}
if (at.GetArrayRank () != pt.GetArrayRank ())
return false;
- return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
+ return UnifyType (TypeManager.GetElementType (pt), TypeManager.GetElementType (at), inferred);
}
if (!pt.IsGenericType)