X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fgeneric.cs;h=89010834903d4f0605be0924f31431dfea63a69f;hb=b69432e9a61f7a770f908db26eb951d4cae61fcb;hp=689988a63fb9d94302df9942d0673ca03fe5b3be;hpb=3d693eeb90339833968d66c3dc9fde2fa3ba2cef;p=mono.git diff --git a/mcs/gmcs/generic.cs b/mcs/gmcs/generic.cs index 689988a63fb..89010834903 100644 --- a/mcs/gmcs/generic.cs +++ b/mcs/gmcs/generic.cs @@ -600,6 +600,7 @@ namespace Mono.CSharp { Constraints constraints; Location loc; GenericTypeParameterBuilder type; + MemberCache member_cache; public TypeParameter (DeclSpace parent, DeclSpace decl, string name, Constraints constraints, Attributes attrs, Location loc) @@ -619,10 +620,6 @@ namespace Mono.CSharp { get { return constraints; } } - public bool HasConstructorConstraint { - get { return constraints != null && constraints.HasConstructorConstraint; } - } - public DeclSpace DeclSpace { get { return decl; } } @@ -882,11 +879,19 @@ namespace Mono.CSharp { } MemberCache IMemberContainer.BaseCache { - get { return null; } + get { + if (gc == null) + return null; + + if (gc.EffectiveBaseClass.BaseType == null) + return null; + + return TypeManager.LookupMemberCache (gc.EffectiveBaseClass.BaseType); + } } bool IMemberContainer.IsInterface { - get { return true; } + get { return false; } } MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf) @@ -894,8 +899,19 @@ namespace Mono.CSharp { return FindMembers (mt, bf, null, null); } - MemberCache IMemberContainer.MemberCache { - get { return null; } + public MemberCache MemberCache { + get { + if (member_cache != null) + return member_cache; + + if (gc == null) + return null; + + Type[] ifaces = TypeManager.ExpandInterfaces (gc.InterfaceConstraints); + member_cache = new MemberCache (this, gc.EffectiveBaseClass, ifaces); + + return member_cache; + } } public MemberList FindMembers (MemberTypes mt, BindingFlags bf, @@ -987,7 +1003,7 @@ namespace Mono.CSharp { bool has_class_constr = false; if (list.Count > 0) { Type first = (Type) list [0]; - has_class_constr = !first.IsInterface && !first.IsGenericParameter; + has_class_constr = !first.IsGenericParameter && !first.IsInterface; } if ((list.Count > 0) && has_class_constr) { @@ -1119,6 +1135,12 @@ namespace Mono.CSharp { this.Location = loc; } + public TypeArguments (Location loc, params Expression[] types) + { + this.Location = loc; + this.args = new ArrayList (types); + } + public TypeArguments (int dimension, Location loc) { this.dimension = dimension; @@ -1248,9 +1270,9 @@ namespace Mono.CSharp { } atypes[i] = te.Type; - - if (te is TypeParameterExpr) { - has_type_args = true; + if (te.Type.IsGenericParameter) { + if (te is TypeParameterExpr) + has_type_args = true; continue; } @@ -1632,7 +1654,7 @@ namespace Mono.CSharp { if (TypeManager.IsBuiltinType (atype) || atype.IsValueType) return true; - if (HasDefaultConstructor (ec.DeclContainer.TypeBuilder, atype)) + if (HasDefaultConstructor (atype)) return true; Report_SymbolRelatedToPreviousError (); @@ -1681,7 +1703,7 @@ namespace Mono.CSharp { return false; } - bool HasDefaultConstructor (Type containerType, Type atype) + bool HasDefaultConstructor (Type atype) { if (atype.IsAbstract) return false; @@ -1709,8 +1731,12 @@ namespace Mono.CSharp { } TypeParameter tparam = TypeManager.LookupTypeParameter (atype); - if (tparam != null) - return tparam.HasConstructorConstraint; + if (tparam != null) { + if (tparam.GenericConstraints == null) + return false; + else + return tparam.GenericConstraints.HasConstructorConstraint; + } MemberList list = TypeManager.FindMembers ( atype, MemberTypes.Constructor, @@ -1852,8 +1878,10 @@ namespace Mono.CSharp { Error_ParameterNameCollision (p.Location, type_argument_name, "method parameter"); return false; } + + // FIXME: This is wrong, since it only looks at the outermost set of variables if (block != null) { - LocalInfo li = (LocalInfo)block.Variables[type_argument_name]; + LocalInfo li = (LocalInfo)block.Variables [type_argument_name]; if (li != null) { Error_ParameterNameCollision (li.Location, type_argument_name, "local variable"); return false; @@ -2074,9 +2102,8 @@ namespace Mono.CSharp { static void InitGenericCodeHelpers () { // Activator - Type [] type_arg = { type_type }; activator_create_instance = GetMethod ( - activator_type, "CreateInstance", type_arg); + activator_type, "CreateInstance", Type.EmptyTypes); } static Type CoreLookupType (string ns, string name, int arity) @@ -2391,7 +2418,7 @@ namespace Mono.CSharp { return false; } - for (int i = 0; i < inferred_types.Length; i++) + for (int i = 0; i < inferred_types.Length; ++i) if (inferred_types [i] == null) return false; @@ -2399,28 +2426,46 @@ namespace Mono.CSharp { } // - // Infers the remaining inferred_types from lambda expressions contained in the - // invocation call. + // Infers the type of a single LambdaExpression in the invocation call and + // stores the infered type in the inferred_types array. // - static bool LambdaInfer (EmitContext ec, ArrayList arguments, - Type[] param_types, Type[] arg_types, Type[] inferred_types) + // The index of the arguments that contain lambdas is passed in + // + // @lambdas. Merely to avoid rescanning the list. + // + // The method being called: + // @method_generic_args: The generic type arguments for the method being called + // @method_pd: The ParameterData for the method being called. + // + // The call site: + // @arguments: Arraylist of Argument()s. The arguments being passed. + // + // Returns: + // @inferred_types: the array that is populated with our results. + // + // true if the code was able to do one inference. + // + static bool LambdaInfer (EmitContext ec, + Type [] method_generic_args, + ParameterData method_pd, + ArrayList arguments, + Type[] inferred_types, + ArrayList lambdas) { - int arg_count = arg_types.Length; - - for (int i = 0; i < arg_count; i++){ - Argument a = (Argument) arguments [i]; - + int last_count = lambdas.Count; + + for (int i = 0; i < last_count; i++){ + int argn = (int) lambdas [i]; + + Argument a = (Argument) arguments [argn]; + LambdaExpression le = a.Expr as LambdaExpression; - - if (a == null) - continue; - - // - // TODO: "The argument is a lambda expression, in - // the following called L, from which no inferences - // have yet been made." - // - + + if (le == null) + throw new Exception ( + String.Format ("Internal Compiler error: argument {0} should be a Lambda Expression", + argn)); + // // "The corresponding parameter’s type, in the // following called P, is a delegate type with a @@ -2428,27 +2473,27 @@ namespace Mono.CSharp { // parameters." // // - if (!TypeManager.IsDelegateType (param_types [i])) - continue; + if (!TypeManager.IsDelegateType (method_pd.ParameterType (argn))) + goto useless_lambda; - Type p_type = param_types [i]; + Type p_type = method_pd.ParameterType (argn); MethodGroupExpr method_group = Expression.MemberLookup ( ec.ContainerType, p_type, "Invoke", MemberTypes.Method, Expression.AllBindingFlags, Location.Null) as MethodGroupExpr; if (method_group == null){ // This we report elsewhere as -200, but here we can ignore - continue; + goto useless_lambda; } - MethodInfo delegate_method = method_group.Methods [0] as MethodInfo; - if (delegate_method == null){ + MethodInfo p_delegate_method = method_group.Methods [0] as MethodInfo; + if (p_delegate_method == null){ // This should not happen. - continue; + goto useless_lambda; } - Type return_type = delegate_method.ReturnType; - if (!return_type.IsGenericParameter) - continue; + Type p_return_type = p_delegate_method.ReturnType; + if (!p_return_type.IsGenericParameter) + goto useless_lambda; // // P and L have the same number of parameters, and @@ -2456,25 +2501,22 @@ namespace Mono.CSharp { // corresponding parameter in L, or no modifiers if // L has an implicitly typed parameter list. // - ParameterData delegate_pd = TypeManager.GetParameterData (delegate_method); - int delegate_pc = delegate_pd.Count; - if (delegate_pc != le.Parameters.Count) - continue; + ParameterData p_delegate_parameters = TypeManager.GetParameterData (p_delegate_method); + int p_delegate_parameter_count = p_delegate_parameters.Count; + if (p_delegate_parameter_count != le.Parameters.Count) + goto useless_lambda; -#if false - //FIXME if (le.HasExplicitParameters){ - for (int j = 0; j < delegate_pc; j++){ - if (delegate_pd.ParameterModifier [j] != - le.Parameters.ParameterModifier[j]) - goto do_continue; + for (int j = 0; j < p_delegate_parameter_count; j++){ + if (p_delegate_parameters.ParameterModifier (j) != + le.Parameters.ParameterModifier (j)) + goto useless_lambda; } - } else { - for (int j = 0; j < delegate_pc; j++) - if (le.Parameters.ParameterModifier [j] != Parameter.Modifier.NONE) - goto do_continue; + } else { + for (int j = 0; j < p_delegate_parameter_count; j++) + if (le.Parameters.ParameterModifier (j) != Parameter.Modifier.NONE) + goto useless_lambda; } -#endif // // TODO: P’s parameter types involve no method type @@ -2482,7 +2524,16 @@ namespace Mono.CSharp { // for which a consistent set of inferences have // already been made. // - + //Console.WriteLine ("Method: {0}", p_delegate_method); + //for (int j = 0; j < p_delegate_parameter_count; j++){ + //Console.WriteLine ("PType [{2}, {0}] = {1}", j, p_delegate_parameters.ParameterType (j), argn); + //} + + // + // At this point we know that P has method type parameters + // that involve only type parameters that have a consistent + // set of inferences made. + // if (le.HasExplicitParameters){ // // TODO: If L has an explicitly typed parameter @@ -2499,13 +2550,71 @@ namespace Mono.CSharp { // parameter types are given to the parameters of L, // the body of L is a valid expression or statement // block. + + Type [] types = new Type [p_delegate_parameter_count]; + + //bool failure = false; + for (int j = 0; j < p_delegate_parameter_count; j++){ + Type p_pt = p_delegate_parameters.ParameterType (j); + + if (!p_pt.IsGenericParameter){ + types [j] = p_pt; + continue; + } + + //bool found = false; + for (int k = 0; k < method_generic_args.Length; k++){ + if (method_generic_args [k] == p_pt){ + types [j] = inferred_types [k]; + break; + } + } + // + // If we could not infer just yet, continue + // + if (types [j] == null) + goto do_continue; + } + + // + // If it results in a valid expression or statement block + // + Type lambda_inferred_type = le.TryBuild (ec, types); + + if (lambda_inferred_type != null){ + // + // Success, set the proper inferred_type value to the new type. + // return true + // + for (int k = 0; k < method_generic_args.Length; k++){ + if (method_generic_args [k] == p_return_type){ + inferred_types [k] = lambda_inferred_type; + + lambdas.RemoveAt (i); + return true; + } + } + } } + + useless_lambda: + lambdas.RemoveAt (i); do_continue: ; } - return true; +#if false + Console.WriteLine ("Inferred types"); + foreach (Type it in inferred_types){ + Console.WriteLine (" IT: {0}", it); + if (it == null) + return false; + } +#endif + + // No inference was made in any of the elements. + return false; } /// @@ -2531,11 +2640,12 @@ namespace Mono.CSharp { if (arg_count != pd.Count) return false; - Type[] method_args = method.GetGenericArguments (); + Type[] method_generic_args = method.GetGenericArguments (); bool is_open = false; - for (int i = 0; i < method_args.Length; i++) { - if (method_args [i].IsGenericParameter) { + + for (int i = 0; i < method_generic_args.Length; i++) { + if (method_generic_args [i].IsGenericParameter) { is_open = true; break; } @@ -2545,36 +2655,69 @@ namespace Mono.CSharp { if (!is_open) return !TypeManager.IsGenericMethodDefinition (method); - Type[] inferred_types = new Type [method_args.Length]; + Type[] inferred_types = new Type [method_generic_args.Length]; Type[] param_types = new Type [pd.Count]; Type[] arg_types = new Type [pd.Count]; - - int lambdas = 0; + ArrayList lambdas = null; + for (int i = 0; i < arg_count; i++) { param_types [i] = pd.ParameterType (i); Argument a = (Argument) arguments [i]; - if (a.Expr is LambdaExpression) - lambdas++; - - if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr) || - (a.Expr is AnonymousMethodExpression)) + if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr) + continue; + + if (a.Expr is LambdaExpression){ + if (lambdas == null) + lambdas = new ArrayList (); + lambdas.Add (i); + } + else if (a.Expr is AnonymousMethodExpression) { + if (RootContext.Version != LanguageVersion.LINQ) + continue; + + Type dtype = param_types[i]; + if (!TypeManager.IsDelegateType (dtype)) + continue; + + AnonymousMethodExpression am = (AnonymousMethodExpression)a.Expr; + Expression e = am.InferTypeArguments (ec, dtype); + if (e == null) + return false; + + arg_types[i] = e.Type; continue; + } arg_types [i] = a.Type; } if (!InferTypeArguments (param_types, arg_types, inferred_types)){ - Type it; - if (lambdas == 0) - return false; - - if (!LambdaInfer (ec, arguments, param_types, arg_types, inferred_types)) + //Console.WriteLine ("InferTypeArgument found {0} lambdas ", lambdas); + if (lambdas == null) return false; - } + + // + // While the lambda expressions lead to a valid inference + // + int lambda_count; + do { + lambda_count = lambdas.Count; + if (!LambdaInfer (ec, method_generic_args, pd, arguments, inferred_types, lambdas)) + return false; + } while (lambdas.Count != 0 && lambdas.Count != lambda_count); + } method = ((MethodInfo)method).MakeGenericMethod (inferred_types); + +#if MS_COMPATIBLE + // MS implementation throws NotSupportedException for GetParameters + // on unbaked generic method + ParameterData p = TypeManager.GetParameterData (method); + p.InflateTypes (param_types, inferred_types); +#endif + return true; }