}
}
+ 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>
return false;
}
- public static string GetSignatureForError (TypeParameter[] tp)
- {
- if (tp == null || tp.Length == 0)
- return "";
-
- StringBuilder sb = new StringBuilder ("<");
- for (int i = 0; i < tp.Length; ++i) {
- if (i > 0)
- sb.Append (",");
- sb.Append (tp[i].GetSignatureForError ());
- }
- sb.Append ('>');
- return sb.ToString ();
- }
-
public void InflateConstraints (Type declaring)
{
if (constraints != null)
}
}
- /// <summary>
- /// Tracks the type arguments when instantiating a generic type. We're used in
- /// ConstructedType.
- /// </summary>
+ //
+ // Tracks the type arguments when instantiating a generic type. It's used
+ // by both type arguments and type parameters
+ //
public class TypeArguments {
- public readonly Location Location;
ArrayList args;
Type[] atypes;
- int dimension;
- bool has_type_args;
- public TypeArguments (Location loc)
+ public TypeArguments ()
{
args = new ArrayList ();
- this.Location = loc;
}
- public TypeArguments (Location loc, params Expression[] types)
+ public TypeArguments (params FullNamedExpression[] types)
{
- this.Location = loc;
this.args = new ArrayList (types);
}
-
- public TypeArguments (int dimension, Location loc)
- {
- this.dimension = dimension;
- this.Location = loc;
- }
- public void Add (Expression type)
+ public void Add (FullNamedExpression type)
{
args.Add (type);
}
}
}
- public bool HasTypeArguments {
- get {
- return has_type_args;
- }
- }
-
public int Count {
get {
- if (dimension > 0)
- return dimension;
- else
- return args.Count;
- }
- }
-
- public bool IsUnbound {
- get {
- return dimension > 0;
+ return args.Count;
}
}
/// </summary>
public bool Resolve (IResolveContext ec)
{
+ if (atypes != null)
+ return atypes.Length != 0;
+
int count = args.Count;
bool ok = true;
atypes = new Type [count];
for (int i = 0; i < count; i++){
- TypeExpr te = ((Expression) args [i]).ResolveAsTypeTerminal (ec, false);
+ TypeExpr te = ((FullNamedExpression) args[i]).ResolveAsTypeTerminal (ec, false);
if (te == null) {
ok = false;
continue;
}
atypes[i] = te.Type;
- if (te.Type.IsGenericParameter) {
- if (te is TypeParameterExpr)
- has_type_args = true;
- continue;
- }
if (te.Type.IsSealed && te.Type.IsAbstract) {
- Report.Error (718, Location, "`{0}': static classes cannot be used as generic arguments",
+ Report.Error (718, te.Location, "`{0}': static classes cannot be used as generic arguments",
te.GetSignatureForError ());
- return false;
+ ok = false;
}
if (te.Type.IsPointer || TypeManager.IsSpecialType (te.Type)) {
- Report.Error (306, Location,
+ Report.Error (306, te.Location,
"The type `{0}' may not be used as a type argument",
- TypeManager.CSharpName (te.Type));
- return false;
- }
-
- if (te.Type == TypeManager.void_type) {
- Expression.Error_VoidInvalidInTheContext (Location);
- return false;
+ te.GetSignatureForError ());
+ ok = false;
}
}
+
+ if (!ok)
+ atypes = Type.EmptyTypes;
+
return ok;
}
public TypeArguments Clone ()
{
- TypeArguments copy = new TypeArguments (Location);
+ TypeArguments copy = new TypeArguments ();
foreach (Expression ta in args)
copy.args.Add (ta);
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>
{
open_type = gType.TypeBuilder.GetGenericTypeDefinition ();
- args = new TypeArguments (l);
+ args = new TypeArguments ();
foreach (TypeParameter type_param in gType.TypeParameters)
args.Add (new TypeParameterExpr (type_param, l));
protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
{
+ if (eclass != ExprClass.Invalid)
+ return this;
+
+ eclass = ExprClass.Type;
+
if (!args.Resolve (ec))
return null;
// Now bind the parameters
//
type = open_type.MakeGenericType (atypes);
- eclass = ExprClass.Type;
return this;
}
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))
if (TypeManager.HasGenericArguments (ctype)) {
Type[] types = TypeManager.GetTypeArguments (ctype);
- TypeArguments new_args = new TypeArguments (loc);
+ TypeArguments new_args = new TypeArguments ();
for (int i = 0; i < types.Length; i++) {
Type t = types [i];
ctype = ct.Type;
} else if (ctype.IsGenericParameter) {
int pos = ctype.GenericParameterPosition;
- ctype = atypes [pos];
+ if (ctype.DeclaringMethod == null) {
+ // FIXME: Implement
+ return true;
+ } else {
+ ctype = atypes [pos];
+ }
}
if (Convert.ImplicitStandardConversionExists (expr, ctype))
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;
/// Define and resolve the type parameters.
/// We're called from Method.Define().
/// </summary>
- public bool Define (MethodBuilder mb)
+ public bool Define (MethodOrOperator m)
{
TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations ();
string[] snames = new string [names.Length];
for (int i = 0; i < names.Length; i++) {
string type_argument_name = names[i].Name;
- Parameter p = parameters.GetParameterByName (type_argument_name);
- if (p != null) {
- Error_ParameterNameCollision (p.Location, type_argument_name, "method parameter");
- return false;
+ int idx = parameters.GetParameterIndexByName (type_argument_name);
+ if (idx >= 0) {
+ Block b = m.Block;
+ if (b == null)
+ b = new Block (null);
+
+ b.Error_AlreadyDeclaredTypeParameter (parameters [i].Location,
+ type_argument_name, "method parameter");
}
snames[i] = type_argument_name;
}
- GenericTypeParameterBuilder[] gen_params = mb.DefineGenericParameters (snames);
+ GenericTypeParameterBuilder[] gen_params = m.MethodBuilder.DefineGenericParameters (snames);
for (int i = 0; i < TypeParameters.Length; i++)
TypeParameters [i].Define (gen_params [i]);
return true;
}
- internal static void Error_ParameterNameCollision (Location loc, string name, string collisionWith)
- {
- Report.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
- name, collisionWith);
- }
-
/// <summary>
/// We're called from MethodData.Define() after creating the MethodBuilder.
/// </summary>
// 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)
return LowerBoundInference (e.Type, t) * 2;
}
- static void RemoveDependentTypes (ArrayList types, Type returnType)
+ void RemoveDependentTypes (ArrayList types, Type returnType)
{
- if (returnType.IsGenericParameter) {
- types [returnType.GenericParameterPosition] = null;
+ int idx = IsUnfixed (returnType);
+ if (idx >= 0) {
+ types [idx] = null;
return;
}