return false;
if (ClassConstraint != null) {
- if (!ClassConstraint.IsValueType)
+ if (!TypeManager.IsValueType (ClassConstraint))
return false;
if (ClassConstraint != TypeManager.value_type)
}
}
+ public class ReflectionConstraints : GenericConstraints
+ {
+ GenericParameterAttributes attrs;
+ Type base_type;
+ Type class_constraint;
+ Type[] iface_constraints;
+ string name;
+
+ public static GenericConstraints GetConstraints (Type t)
+ {
+ Type[] constraints = t.GetGenericParameterConstraints ();
+ GenericParameterAttributes attrs = t.GenericParameterAttributes;
+ if (constraints.Length == 0 && attrs == GenericParameterAttributes.None)
+ return null;
+ return new ReflectionConstraints (t.Name, constraints, attrs);
+ }
+
+ private ReflectionConstraints (string name, Type[] constraints, GenericParameterAttributes attrs)
+ {
+ this.name = name;
+ this.attrs = attrs;
+
+ if ((constraints.Length > 0) && !constraints[0].IsInterface) {
+ class_constraint = constraints[0];
+ iface_constraints = new Type[constraints.Length - 1];
+ Array.Copy (constraints, 1, iface_constraints, 0, constraints.Length - 1);
+ } else
+ iface_constraints = constraints;
+
+ if (HasValueTypeConstraint)
+ base_type = TypeManager.value_type;
+ else if (class_constraint != null)
+ base_type = class_constraint;
+ else
+ base_type = TypeManager.object_type;
+ }
+
+ public override string TypeParameter
+ {
+ get { return name; }
+ }
+
+ public override GenericParameterAttributes Attributes
+ {
+ get { return attrs; }
+ }
+
+ public override Type ClassConstraint
+ {
+ get { return class_constraint; }
+ }
+
+ public override Type EffectiveBaseClass
+ {
+ get { return base_type; }
+ }
+
+ public override Type[] InterfaceConstraints
+ {
+ get { return iface_constraints; }
+ }
+ }
+
+ public enum Variance
+ {
+ None,
+ Covariant,
+ Contravariant
+ }
+
public enum SpecialConstraint
{
Constructor,
}
TypeExpr expr;
- ConstructedType cexpr = fn as ConstructedType;
+ GenericTypeExpr cexpr = fn as GenericTypeExpr;
if (cexpr != null) {
- if (!cexpr.ResolveConstructedType (ec))
- return false;
-
- expr = cexpr;
+ expr = cexpr.ResolveAsBaseTerminal (ec, false);
} else
expr = ((Expression) obj).ResolveAsTypeTerminal (ec, false);
else
effective_base_type = TypeManager.object_type;
+ if ((attrs & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)
+ attrs |= GenericParameterAttributes.DefaultConstructorConstraint;
+
resolved = true;
return true;
}
resolved_types = true;
foreach (object obj in constraints) {
- ConstructedType cexpr = obj as ConstructedType;
+ GenericTypeExpr cexpr = obj as GenericTypeExpr;
if (cexpr == null)
continue;
{
static readonly string[] attribute_target = new string [] { "type parameter" };
- string name;
DeclSpace decl;
GenericConstraints gc;
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.name = name;
this.decl = decl;
this.constraints = constraints;
+ this.variance = variance;
}
public GenericConstraints GenericConstraints {
get { return decl; }
}
+ public Variance Variance {
+ get { return variance; }
+ }
+
public Type Type {
get { return type; }
}
TypeManager.AddTypeParameter (type, this);
}
+ public void ErrorInvalidVariance (MemberCore mc, Variance expected)
+ {
+ Report.SymbolRelatedToPreviousError (mc);
+ string input_variance = Variance == Variance.Contravariant ? "contravariant" : "covariant";
+ string gtype_variance;
+ switch (expected) {
+ case Variance.Contravariant: gtype_variance = "contravariantly"; break;
+ case Variance.Covariant: gtype_variance = "covariantly"; break;
+ default: gtype_variance = "invariantly"; break;
+ }
+
+ Report.Error (1961, Location,
+ "The {2} type parameter `{0}' must be {3} valid on `{1}'",
+ GetSignatureForError (), mc.GetSignatureForError (), input_variance, gtype_variance);
+ }
+
/// <summary>
/// This is the second method which is called during the resolving
/// process - in case of class type parameters, we're called from
gc = (GenericConstraints) constraints;
}
- if (gc == null)
- return true;
+ SetConstraints (type);
+ return true;
+ }
- if (gc.HasClassConstraint)
- type.SetBaseTypeConstraint (gc.ClassConstraint);
+ 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 true;
}
- public override void ApplyAttributeBuilder (Attribute a,
- CustomAttributeBuilder cb)
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
{
type.SetCustomAttribute (cb);
}
return false;
}
- public override string ToString ()
- {
- return "TypeParameter[" + name + "]";
- }
-
- 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);
}
args.AddRange (new_args.args);
}
- /// <summary>
- /// We're used during the parsing process: the parser can't distinguish
- /// between type parameters and type arguments. Because of that, the
- /// parser creates a `MemberName' with `TypeArguments' for both cases and
- /// in case of a generic type definition, we call GetDeclarations().
- /// </summary>
+ // TODO: Should be deleted
public TypeParameterName[] GetDeclarations ()
{
- TypeParameterName[] ret = new TypeParameterName [args.Count];
- for (int i = 0; i < args.Count; i++) {
- TypeParameterName name = args [i] as TypeParameterName;
- if (name != null) {
- ret [i] = name;
- continue;
- }
- SimpleName sn = args [i] as SimpleName;
- if (sn != null && !sn.HasTypeArguments) {
- ret [i] = new TypeParameterName (sn.Name, null, sn.Location);
- continue;
- }
-
- Expression expr = (Expression) args [i];
- // TODO: Wrong location
- Report.Error (81, Location, "Type parameter declaration must be an identifier not a type");
- ret [i] = new TypeParameterName (expr.GetSignatureForError (), null, expr.Location);
- }
- return ret;
+ return (TypeParameterName[]) args.ToArray (typeof (TypeParameterName));
}
/// <summary>
}
}
- 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;
- }
- }
-
- public override string ToString ()
- {
- StringBuilder s = new StringBuilder ();
-
- int count = Count;
- for (int i = 0; i < count; i++){
- //
- // FIXME: Use TypeManager.CSharpname once we have the type
- //
- if (args != null)
- s.Append (args [i].ToString ());
- if (i+1 < count)
- s.Append (",");
+ return args.Count;
}
- return s.ToString ();
}
public string GetSignatureForError()
/// </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>
- /// An instantiation of a generic type.
+ /// A reference expression to generic type
/// </summary>
- public class ConstructedType : TypeExpr {
- FullNamedExpression name;
+ class GenericTypeExpr : TypeExpr
+ {
TypeArguments args;
- Type[] gen_params, atypes;
- Type gt;
+ Type[] gen_params; // TODO: Waiting for constrains check cleanup
+ Type open_type;
- /// <summary>
- /// Instantiate the generic type `fname' with the type arguments `args'.
- /// </summary>
- public ConstructedType (FullNamedExpression fname, TypeArguments args, Location l)
- {
- loc = l;
- this.name = fname;
- this.args = args;
-
- eclass = ExprClass.Type;
- }
-
- /// <summary>
- /// This is used to construct the `this' type inside a generic type definition.
- /// </summary>
- public ConstructedType (Type t, TypeParameter[] type_params, Location l)
+ //
+ // Should be carefully used only with defined generic containers. Type parameters
+ // can be used as type arguments in this case.
+ //
+ // TODO: This could be GenericTypeExpr specialization
+ //
+ public GenericTypeExpr (DeclSpace gType, Location l)
{
- gt = t.GetGenericTypeDefinition ();
+ open_type = gType.TypeBuilder.GetGenericTypeDefinition ();
- args = new TypeArguments (l);
- foreach (TypeParameter type_param in type_params)
+ args = new TypeArguments ();
+ foreach (TypeParameter type_param in gType.TypeParameters)
args.Add (new TypeParameterExpr (type_param, l));
this.loc = l;
- this.name = new TypeExpression (gt, l);
- eclass = ExprClass.Type;
}
/// <summary>
/// Use this constructor if you already know the fully resolved
/// generic type.
/// </summary>
- public ConstructedType (Type t, TypeArguments args, Location l)
- : this ((FullNamedExpression)null, args, l)
+ public GenericTypeExpr (Type t, TypeArguments args, Location l)
{
- gt = t.GetGenericTypeDefinition ();
- this.name = new TypeExpression (gt, l);
+ open_type = t.GetGenericTypeDefinition ();
+
+ loc = l;
+ this.args = args;
}
public TypeArguments TypeArguments {
protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
{
- if (!ResolveConstructedType (ec))
+ if (eclass != ExprClass.Invalid)
+ return this;
+
+ eclass = ExprClass.Type;
+
+ if (!args.Resolve (ec))
return null;
+ gen_params = open_type.GetGenericArguments ();
+ Type[] atypes = args.Arguments;
+
+ if (atypes.Length != gen_params.Length) {
+ Namespace.Error_InvalidNumberOfTypeArguments (open_type, loc);
+ return null;
+ }
+
+ //
+ // Now bind the parameters
+ //
+ type = open_type.MakeGenericType (atypes);
return this;
}
/// </summary>
public bool CheckConstraints (IResolveContext ec)
{
- return ConstraintChecker.CheckConstraints (ec, gt, gen_params, atypes, loc);
+ return ConstraintChecker.CheckConstraints (ec, open_type, gen_params, args.Arguments, loc);
}
-
- /// <summary>
- /// Resolve the constructed type, but don't check the constraints.
- /// </summary>
- public bool ResolveConstructedType (IResolveContext ec)
- {
- if (type != null)
- return true;
- // If we already know the fully resolved generic type.
- if (gt != null)
- return DoResolveType (ec);
-
- int num_args;
- Type t = name.Type;
-
- if (t == null) {
- Report.Error (246, loc, "Cannot find type `{0}'<...>", GetSignatureForError ());
- return false;
- }
-
- num_args = TypeManager.GetNumberOfTypeArguments (t);
- if (num_args == 0) {
- Report.Error (308, loc,
- "The non-generic type `{0}' cannot " +
- "be used with type arguments.",
- TypeManager.CSharpName (t));
- return false;
- }
-
- gt = t.GetGenericTypeDefinition ();
- return DoResolveType (ec);
- }
-
- bool DoResolveType (IResolveContext ec)
+
+ public bool VerifyVariantTypeParameters (IResolveContext rc)
{
- //
- // Resolve the arguments.
- //
- if (args.Resolve (ec) == false)
- return false;
+ for (int i = 0; i < args.Count; i++) {
+ var argument = args.Arguments [i];
+ TypeParameter tparam = TypeManager.LookupTypeParameter (argument);
+ if (tparam == null)
+ continue;
- gen_params = gt.GetGenericArguments ();
- atypes = args.Arguments;
+ if (tparam.Variance == Variance.None)
+ continue;
- if (atypes.Length != gen_params.Length) {
- Report.Error (305, loc,
- "Using the generic type `{0}' " +
- "requires {1} type arguments",
- TypeManager.CSharpName (gt),
- gen_params.Length.ToString ());
- return false;
+ if (tparam.Variance != TypeManager.GetTypeParameterVariance (gen_params [i])) {
+ var mc = (MemberCore) rc;
+ tparam.ErrorInvalidVariance (mc, TypeManager.GetTypeParameterVariance (gen_params[i]));
+ }
}
-
- //
- // Now bind the parameters.
- //
- type = gt.MakeGenericType (atypes);
return true;
}
- public Expression GetSimpleName (EmitContext ec)
- {
- return this;
- }
-
+
public override bool CheckAccessLevel (DeclSpace ds)
{
- return ds.CheckAccessLevel (gt);
- }
-
- public override bool AsAccessible (DeclSpace ds)
- {
- foreach (Type t in atypes) {
- if (!ds.IsAccessibleAs (t))
- return false;
- }
-
- return ds.IsAccessibleAs (gt);
+ return ds.CheckAccessLevel (open_type);
}
public override bool IsClass {
- get { return gt.IsClass; }
+ get { return open_type.IsClass; }
}
public override bool IsValueType {
- get { return gt.IsValueType; }
+ get { return TypeManager.IsStruct (open_type); }
}
public override bool IsInterface {
- get { return gt.IsInterface; }
+ get { return open_type.IsInterface; }
}
public override bool IsSealed {
- get { return gt.IsSealed; }
+ get { return open_type.IsSealed; }
}
public override bool Equals (object obj)
{
- ConstructedType cobj = obj as ConstructedType;
+ GenericTypeExpr cobj = obj as GenericTypeExpr;
if (cobj == null)
return false;
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];
new_args.Add (new TypeExpression (t, loc));
}
- TypeExpr ct = new ConstructedType (ctype, new_args, loc);
+ TypeExpr ct = new GenericTypeExpr (ctype, new_args, loc);
if (ct.ResolveAsTypeStep (ec, false) == null)
return false;
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>
ec, mb, implementing, is_override))
return false;
- bool ok = true;
- foreach (Parameter p in parameters.FixedParameters){
- if (p.Resolve (ec) == null)
- ok = false;
- }
+ bool ok = parameters.Resolve (ec);
+
if ((return_type != null) && (return_type.ResolveAsTypeTerminal (ec, false) == null))
ok = false;
OptAttributes.Emit ();
}
- public override bool DefineMembers ()
- {
- return true;
- }
-
public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
MemberFilter filter, object criteria)
{
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.
// 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);
}
public static ATypeInference CreateInstance (ArrayList arguments)
{
- if (RootContext.Version == LanguageVersion.ISO_2)
- return new TypeInferenceV2 (arguments);
-
return new TypeInferenceV3 (arguments);
}
public abstract Type[] InferDelegateArguments (MethodBase method);
}
- //
- // Implements C# 2.0 type inference
- //
- class TypeInferenceV2 : ATypeInference
- {
- public TypeInferenceV2 (ArrayList arguments)
- : base (arguments)
- {
- }
-
- public override Type[] InferDelegateArguments (MethodBase method)
- {
- AParametersCollection pd = TypeManager.GetParameterData (method);
- if (arg_count != pd.Count)
- return null;
-
- Type[] method_args = method.GetGenericArguments ();
- Type[] inferred_types = new Type[method_args.Length];
-
- Type[] param_types = new Type[pd.Count];
- Type[] arg_types = (Type[])arguments.ToArray (typeof (Type));
-
- for (int i = 0; i < arg_count; i++) {
- param_types[i] = pd.Types [i];
- }
-
- if (!InferTypeArguments (param_types, arg_types, inferred_types))
- return null;
-
- return inferred_types;
- }
-
- public override Type[] InferMethodArguments (EmitContext ec, MethodBase method)
- {
- AParametersCollection pd = TypeManager.GetParameterData (method);
- Type[] method_generic_args = method.GetGenericArguments ();
- Type [] inferred_types = new Type [method_generic_args.Length];
- Type[] arg_types = new Type [pd.Count];
-
- int a_count = arg_types.Length;
- if (pd.HasParams)
- --a_count;
-
- for (int i = 0; i < a_count; i++) {
- Argument a = (Argument) arguments[i];
- if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr || a.Expr is AnonymousMethodExpression)
- continue;
-
- if (!TypeInferenceV2.UnifyType (pd.Types [i], a.Type, inferred_types))
- return null;
- }
-
- if (pd.HasParams) {
- Type element_type = TypeManager.GetElementType (pd.Types [a_count]);
- for (int i = a_count; i < arg_count; i++) {
- Argument a = (Argument) arguments [i];
- if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr || a.Expr is AnonymousMethodExpression)
- continue;
-
- if (!TypeInferenceV2.UnifyType (element_type, a.Type, inferred_types))
- return null;
- }
- }
-
- for (int i = 0; i < inferred_types.Length; i++)
- if (inferred_types [i] == null)
- return null;
-
- return inferred_types;
- }
-
- static bool InferTypeArguments (Type[] param_types, Type[] arg_types,
- Type[] inferred_types)
- {
- for (int i = 0; i < arg_types.Length; i++) {
- if (arg_types[i] == null)
- continue;
-
- if (!UnifyType (param_types[i], arg_types[i], inferred_types))
- return false;
- }
-
- for (int i = 0; i < inferred_types.Length; ++i)
- if (inferred_types[i] == null)
- return false;
-
- return true;
- }
-
- public static bool UnifyType (Type pt, Type at, Type[] inferred)
- {
- if (pt.IsGenericParameter) {
- if (pt.DeclaringMethod == null)
- return pt == at;
-
- int pos = pt.GenericParameterPosition;
-
- if (inferred [pos] == null)
- inferred [pos] = at;
-
- return inferred [pos] == at;
- }
-
- if (!pt.ContainsGenericParameters) {
- if (at.ContainsGenericParameters)
- return UnifyType (at, pt, inferred);
- else
- return true;
- }
-
- if (at.IsArray) {
- if (pt.IsArray) {
- if (at.GetArrayRank () != pt.GetArrayRank ())
- return false;
-
- return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
- }
-
- if (!pt.IsGenericType)
- return false;
-
- Type gt = pt.GetGenericTypeDefinition ();
- if ((gt != TypeManager.generic_ilist_type) && (gt != TypeManager.generic_icollection_type) &&
- (gt != TypeManager.generic_ienumerable_type))
- return false;
-
- Type[] args = TypeManager.GetTypeArguments (pt);
- return UnifyType (args[0], at.GetElementType (), inferred);
- }
-
- if (pt.IsArray) {
- if (!at.IsArray ||
- (pt.GetArrayRank () != at.GetArrayRank ()))
- return false;
-
- return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
- }
-
- if (pt.IsByRef && at.IsByRef)
- return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
- ArrayList list = new ArrayList ();
- if (at.IsGenericType)
- list.Add (at);
- for (Type bt = at.BaseType; bt != null; bt = bt.BaseType)
- list.Add (bt);
-
- list.AddRange (TypeManager.GetInterfaces (at));
-
- foreach (Type type in list) {
- if (!type.IsGenericType)
- continue;
-
- if (TypeManager.DropGenericTypeArguments (pt) != TypeManager.DropGenericTypeArguments (type))
- continue;
-
- if (!UnifyTypes (pt.GetGenericArguments (), type.GetGenericArguments (), inferred))
- return false;
- }
-
- return true;
- }
-
- static bool UnifyTypes (Type[] pts, Type[] ats, Type[] inferred)
- {
- for (int i = 0; i < ats.Length; i++) {
- if (!UnifyType (pts [i], ats [i], inferred))
- return false;
- }
- return true;
- }
- }
-
//
// Implements C# 3.0 type inference
//
} else {
params_arguments_start = arg_count;
}
+
+ Type [] ptypes = methodParameters.Types;
//
// The first inference phase
method_parameter = methodParameters.Types [params_arguments_start];
else
method_parameter = TypeManager.GetElementType (methodParameters.Types [params_arguments_start]);
+
+ ptypes = (Type[]) ptypes.Clone ();
+ ptypes [i] = method_parameter;
}
//
continue;
}
- if (a.Expr is NullLiteral)
+ if (a.Expr.Type == TypeManager.null_type)
continue;
//
// we don't need to call it in cycle
//
bool fixed_any = false;
- if (!tic.FixIndependentTypeArguments (methodParameters, ref fixed_any))
+ if (!tic.FixIndependentTypeArguments (ptypes, ref fixed_any))
return false;
- return DoSecondPhase (ec, tic, methodParameters, !fixed_any);
+ return DoSecondPhase (ec, tic, ptypes, !fixed_any);
}
- bool DoSecondPhase (EmitContext ec, TypeInferenceContext tic, AParametersCollection methodParameters, bool fixDependent)
+ bool DoSecondPhase (EmitContext ec, TypeInferenceContext tic, Type[] methodParameters, bool fixDependent)
{
bool fixed_any = false;
- if (fixDependent && !tic.FixDependentTypes (methodParameters, ref fixed_any))
+ if (fixDependent && !tic.FixDependentTypes (ref fixed_any))
return false;
// If no further unfixed type variables exist, type inference succeeds
// contain unfixed type variables but the input types do not,
// an output type inference is made
for (int i = 0; i < arg_count; i++) {
- Type t_i = methodParameters.Types [i];
+
+ // Align params arguments
+ Type t_i = methodParameters [i >= methodParameters.Length ? methodParameters.Length - 1: i];
+
if (!TypeManager.IsDelegateType (t_i)) {
if (TypeManager.DropGenericTypeArguments (t_i) != TypeManager.expression_type)
continue;
// a, There is at least one type variable Xj that depends on Xi
// b, Xi has a non-empty set of bounds
//
- public bool FixDependentTypes (AParametersCollection methodParameters, ref bool fixed_any)
+ public bool FixDependentTypes (ref bool fixed_any)
{
for (int i = 0; i < unfixed_types.Length; ++i) {
if (unfixed_types[i] == null)
//
// All unfixed type variables Xi which depend on no Xj are fixed
//
- public bool FixIndependentTypeArguments (AParametersCollection methodParameters, ref bool fixed_any)
+ public bool FixIndependentTypeArguments (Type[] methodParameters, ref bool fixed_any)
{
ArrayList types_to_fix = new ArrayList (unfixed_types);
- for (int i = 0; i < methodParameters.Types.Length; ++i) {
- Type t = methodParameters.Types [i];
- if (t.IsGenericParameter)
- continue;
+ for (int i = 0; i < methodParameters.Length; ++i) {
+ Type t = methodParameters[i];
if (!TypeManager.IsDelegateType (t)) {
if (TypeManager.DropGenericTypeArguments (t) != TypeManager.expression_type)
t = t.GetGenericArguments () [0];
}
+ if (t.IsGenericParameter)
+ continue;
+
MethodInfo invoke = Delegate.GetInvokeMethod (t, t);
Type rtype = invoke.ReturnType;
if (!rtype.IsGenericParameter && !rtype.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;
}