2010-03-12 Jb Evain <jbevain@novell.com>
[mono.git] / mcs / mcs / delegate.cs
1 //
2 // delegate.cs: Delegate Handler
3 //
4 // Authors:
5 //     Ravi Pratap (ravi@ximian.com)
6 //     Miguel de Icaza (miguel@ximian.com)
7 //     Marek Safar (marek.safar@gmail.com)
8 //
9 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 //
11 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
12 // Copyright 2003-2009 Novell, Inc (http://www.novell.com)
13 //
14
15 using System;
16 using System.Reflection;
17 using System.Reflection.Emit;
18
19 namespace Mono.CSharp {
20
21         //
22         // Delegate container implementation
23         //
24         public class Delegate : TypeContainer
25         {
26                 FullNamedExpression ReturnType;
27                 public readonly AParametersCollection Parameters;
28
29                 // TODO: Maybe I can keep member cache only and not the builders
30                 Constructor Constructor;
31                 Method InvokeBuilder;
32                 Method BeginInvokeBuilder;
33                 Method EndInvokeBuilder;
34
35                 static readonly string[] attribute_targets = new string [] { "type", "return" };
36
37                 public static readonly string InvokeMethodName = "Invoke";
38                 
39                 Expression instance_expr;
40                 ReturnParameter return_attributes;
41
42                 const Modifiers MethodModifiers = Modifiers.PUBLIC | Modifiers.VIRTUAL;
43
44                 const Modifiers AllowedModifiers =
45                         Modifiers.NEW |
46                         Modifiers.PUBLIC |
47                         Modifiers.PROTECTED |
48                         Modifiers.INTERNAL |
49                         Modifiers.UNSAFE |
50                         Modifiers.PRIVATE;
51
52                 public Delegate (NamespaceEntry ns, DeclSpace parent, FullNamedExpression type,
53                                  Modifiers mod_flags, MemberName name, ParametersCompiled param_list,
54                                  Attributes attrs)
55                         : base (ns, parent, name, attrs, MemberKind.Delegate)
56
57                 {
58                         this.ReturnType = type;
59                         ModFlags        = ModifiersExtensions.Check (AllowedModifiers, mod_flags,
60                                                            IsTopLevel ? Modifiers.INTERNAL :
61                                                            Modifiers.PRIVATE, name.Location, Report);
62                         Parameters      = param_list;
63                 }
64
65                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
66                 {
67                         if (a.Target == AttributeTargets.ReturnValue) {
68                                 if (return_attributes == null)
69                                         return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
70
71                                 return_attributes.ApplyAttributeBuilder (a, cb, pa);
72                                 return;
73                         }
74
75                         base.ApplyAttributeBuilder (a, cb, pa);
76                 }
77
78                 public override AttributeTargets AttributeTargets {
79                         get {
80                                 return AttributeTargets.Delegate;
81                         }
82                 }
83
84                 protected override Type BaseType {
85                         get {
86                                 return TypeManager.multicast_delegate_type;
87                         }
88                 }
89
90                 protected override bool DoDefineMembers ()
91                 {
92                         if (IsGeneric) {
93                                 foreach (TypeParameter type_param in TypeParameters) {
94                                         if (!type_param.Resolve (this))
95                                                 return false;
96                                 }
97
98                                 foreach (TypeParameter type_param in TypeParameters) {
99                                         if (!type_param.DefineType (this))
100                                                 return false;
101                                 }
102                         }
103
104                         member_cache = new MemberCache (BaseType, this);
105
106                         var ctor_parameters = ParametersCompiled.CreateFullyResolved (
107                                 new [] {
108                                         new Parameter (new TypeExpression (TypeManager.object_type, Location), "object", Parameter.Modifier.NONE, null, Location),
109                                         new Parameter (new TypeExpression (TypeManager.intptr_type, Location), "method", Parameter.Modifier.NONE, null, Location)
110                                 },
111                                 new [] {
112                                         TypeManager.object_type,
113                                         TypeManager.intptr_type
114                                 }
115                         );
116
117                         Constructor = new Constructor (this, System.Reflection.ConstructorInfo.ConstructorName,
118                                 Modifiers.PUBLIC, null, ctor_parameters, null, Location);
119                         Constructor.Define ();
120
121                         //
122                         // Here the various methods like Invoke, BeginInvoke etc are defined
123                         //
124                         // First, call the `out of band' special method for
125                         // defining recursively any types we need:
126                         //
127                         var p = Parameters.AsCompiled;
128
129                         if (!p.Resolve (this))
130                                 return false;
131
132                         //
133                         // Invoke method
134                         //
135
136                         // Check accessibility
137                         foreach (var partype in p.Types) {
138                                 if (!IsAccessibleAs (partype)) {
139                                         Report.SymbolRelatedToPreviousError (partype);
140                                         Report.Error (59, Location,
141                                                 "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'",
142                                                 TypeManager.CSharpName (partype), GetSignatureForError ());
143                                 }
144                         }
145
146                         ReturnType = ReturnType.ResolveAsTypeTerminal (this, false);
147                         if (ReturnType == null)
148                                 return false;
149
150                         var ret_type = ReturnType.Type;
151
152                         //
153                         // We don't have to check any others because they are all
154                         // guaranteed to be accessible - they are standard types.
155                         //
156                         if (!IsAccessibleAs (ret_type)) {
157                                 Report.SymbolRelatedToPreviousError (ret_type);
158                                 Report.Error (58, Location,
159                                                   "Inconsistent accessibility: return type `" +
160                                                   TypeManager.CSharpName (ret_type) + "' is less " +
161                                                   "accessible than delegate `" + GetSignatureForError () + "'");
162                                 return false;
163                         }
164
165                         CheckProtectedModifier ();
166
167                         if (RootContext.StdLib && TypeManager.IsSpecialType (ret_type)) {
168                                 Method.Error1599 (Location, ret_type, Report);
169                                 return false;
170                         }
171
172                         TypeManager.CheckTypeVariance (ret_type, Variance.Covariant, this);
173
174                         InvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName (InvokeMethodName), p, null);
175                         InvokeBuilder.Define ();
176
177                         //
178                         // Don't emit async method for compiler generated delegates (e.g. dynamic site containers)
179                         //
180                         if (TypeManager.iasyncresult_type != null && TypeManager.asynccallback_type != null && !IsCompilerGenerated) {
181                                 DefineAsyncMethods (Parameters.CallingConvention);
182                         }
183
184                         return true;
185                 }
186
187                 void DefineAsyncMethods (CallingConventions cc)
188                 {
189                         //
190                         // BeginInvoke
191                         //
192                         Parameter[] compiled = new Parameter[Parameters.Count];
193                         for (int i = 0; i < compiled.Length; ++i)
194                                 compiled[i] = new Parameter (new TypeExpression (Parameters.Types[i], Location),
195                                         Parameters.FixedParameters[i].Name,
196                                         Parameters.FixedParameters[i].ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT),
197                                         null, Location);
198
199                         ParametersCompiled async_parameters = new ParametersCompiled (Compiler, compiled);
200
201                         async_parameters = ParametersCompiled.MergeGenerated (Compiler, async_parameters, false,
202                                 new Parameter[] {
203                                         new Parameter (new TypeExpression (TypeManager.asynccallback_type, Location), "callback", Parameter.Modifier.NONE, null, Location),
204                                         new Parameter (new TypeExpression (TypeManager.object_type, Location), "object", Parameter.Modifier.NONE, null, Location)
205                                 },
206                                 new [] {
207                                         TypeManager.asynccallback_type,
208                                         TypeManager.object_type
209                                 }
210                         );
211
212                         BeginInvokeBuilder = new Method (this, null,
213                                 new TypeExpression (TypeManager.iasyncresult_type, Location), MethodModifiers,
214                                 new MemberName ("BeginInvoke"), async_parameters, null);
215                         BeginInvokeBuilder.Define ();
216
217                         //
218                         // EndInvoke is a bit more interesting, all the parameters labeled as
219                         // out or ref have to be duplicated here.
220                         //
221
222                         //
223                         // Define parameters, and count out/ref parameters
224                         //
225                         ParametersCompiled end_parameters;
226                         int out_params = 0;
227
228                         foreach (Parameter p in Parameters.FixedParameters) {
229                                 if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)
230                                         ++out_params;
231                         }
232
233                         if (out_params > 0) {
234                                 var end_param_types = new Type [out_params];
235                                 Parameter[] end_params = new Parameter[out_params];
236
237                                 int param = 0;
238                                 for (int i = 0; i < Parameters.FixedParameters.Length; ++i) {
239                                         Parameter p = Parameters.AsCompiled [i];
240                                         if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)
241                                                 continue;
242
243                                         end_param_types[param] = Parameters.Types[i];
244                                         end_params[param] = p;
245                                         ++param;
246                                 }
247                                 end_parameters = ParametersCompiled.CreateFullyResolved (end_params, end_param_types);
248                         } else {
249                                 end_parameters = ParametersCompiled.EmptyReadOnlyParameters;
250                         }
251
252                         end_parameters = ParametersCompiled.MergeGenerated (Compiler, end_parameters, false,
253                                 new Parameter (
254                                         new TypeExpression (TypeManager.iasyncresult_type, Location),
255                                         "result", Parameter.Modifier.NONE, null, Location),
256                                 TypeManager.iasyncresult_type);
257
258                         //
259                         // Create method, define parameters, register parameters with type system
260                         //
261                         EndInvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName ("EndInvoke"), end_parameters, null);
262                         EndInvokeBuilder.Define ();
263                 }
264
265                 public override void Emit ()
266                 {
267                         if (TypeManager.IsDynamicType (ReturnType.Type)) {
268                                 return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
269                                 PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder);
270                         } else {
271                                 var trans_flags = TypeManager.HasDynamicTypeUsed (ReturnType.Type);
272                                 if (trans_flags != null) {
273                                         var pa = PredefinedAttributes.Get.DynamicTransform;
274                                         if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.bool_type.MakeArrayType ())) {
275                                                 return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location);
276                                                 return_attributes.Builder.SetCustomAttribute (
277                                                         new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
278                                         }
279                                 }
280                         }
281
282                         Parameters.AsCompiled.ApplyAttributes (InvokeBuilder.MethodBuilder);
283                         
284                         Constructor.ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
285                         InvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
286
287                         if (BeginInvokeBuilder != null) {
288                                 BeginInvokeBuilder.Parameters.ApplyAttributes (BeginInvokeBuilder.MethodBuilder);
289
290                                 BeginInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
291                                 EndInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
292                         }
293
294                         if (OptAttributes != null) {
295                                 OptAttributes.Emit ();
296                         }
297
298                         base.Emit ();
299                 }
300
301                 protected override TypeAttributes TypeAttr {
302                         get {
303                                 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) |
304                                         TypeAttributes.Class | TypeAttributes.Sealed |
305                                         base.TypeAttr;
306                         }
307                 }
308
309                 public override string[] ValidAttributeTargets {
310                         get {
311                                 return attribute_targets;
312                         }
313                 }
314
315                 //TODO: duplicate
316                 protected override bool VerifyClsCompliance ()
317                 {
318                         if (!base.VerifyClsCompliance ()) {
319                                 return false;
320                         }
321
322                         Parameters.AsCompiled.VerifyClsCompliance (this);
323
324                         if (!AttributeTester.IsClsCompliant (ReturnType.Type)) {
325                                 Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
326                                         GetSignatureForError ());
327                         }
328                         return true;
329                 }
330
331
332                 public static MethodSpec GetConstructor (CompilerContext ctx, Type container_type, Type delegate_type)
333                 {
334                         Type dt = delegate_type;
335                         Type[] g_args = null;
336                         if (TypeManager.IsGenericType (delegate_type)) {
337                                 g_args = TypeManager.GetTypeArguments (delegate_type);
338                                 delegate_type = TypeManager.DropGenericTypeArguments (delegate_type);
339                         }
340
341                         Delegate d = TypeManager.LookupDelegate (delegate_type);
342                         if (d != null) {
343                                 if (g_args != null)
344                                         return Import.CreateMethod (TypeBuilder.GetConstructor (dt, d.Constructor.ConstructorBuilder));
345
346                                 return d.Constructor.Spec;
347                         }
348
349                         Expression ml = Expression.MemberLookup (ctx, container_type,
350                                 null, dt, ConstructorInfo.ConstructorName, MemberTypes.Constructor,
351                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, Location.Null);
352
353                         MethodGroupExpr mg = ml as MethodGroupExpr;
354                         if (mg == null) {
355                                 ctx.Report.Error (-100, Location.Null, "Internal error: could not find delegate constructor!");
356                                 // FIXME: null will cause a crash later
357                                 return null;
358                         }
359
360                         return mg.Methods[0];
361                 }
362
363                 //
364                 // Returns the MethodBase for "Invoke" from a delegate type, this is used
365                 // to extract the signature of a delegate.
366                 //
367                 public static MethodSpec GetInvokeMethod (CompilerContext ctx, Type container_type, Type delegate_type)
368                 {
369                         Type dt = delegate_type;
370
371                         Type[] g_args = null;
372                         if (TypeManager.IsGenericType (delegate_type)) {
373                                 g_args = TypeManager.GetTypeArguments (delegate_type);
374                                 delegate_type = TypeManager.DropGenericTypeArguments (delegate_type);
375                         }
376
377                         Delegate d = TypeManager.LookupDelegate (delegate_type);
378                         MethodSpec invoke;
379                         if (d != null) {
380                                 if (g_args != null) {
381                                         invoke = Import.CreateMethod (TypeBuilder.GetMethod (dt, d.InvokeBuilder.MethodBuilder));
382 #if MS_COMPATIBLE
383 //                                      ParametersCompiled p = (ParametersCompiled) d.Parameters.InflateTypes (g_args, g_args);
384 //                                      TypeManager.RegisterMethod (invoke, p);
385 #endif
386                                         return invoke;
387                                 }
388                                 return d.InvokeBuilder.Spec;
389                         }
390
391                         Expression ml = Expression.MemberLookup (ctx, container_type, null, dt,
392                                 "Invoke", Location.Null);
393
394                         MethodGroupExpr mg = ml as MethodGroupExpr;
395                         if (mg == null) {
396                                 ctx.Report.Error (-100, Location.Null, "Internal error: could not find Invoke method!");
397                                 // FIXME: null will cause a crash later
398                                 return null;
399                         }
400
401                         invoke = mg.Methods[0];
402 #if MS_COMPATIBLE
403 //                      if (g_args != null) {
404 //                              AParametersCollection p = TypeManager.GetParameterData (invoke);
405 //                              p = p.InflateTypes (g_args, g_args);
406 //                              TypeManager.RegisterMethod (invoke, p);
407 //                              return invoke;
408 //                      }
409 #endif
410
411                         return invoke;
412                 }
413
414                 //
415                 // 15.2 Delegate compatibility
416                 //
417                 public static bool IsTypeCovariant (Expression a, Type b)
418                 {
419                         //
420                         // For each value parameter (a parameter with no ref or out modifier), an 
421                         // identity conversion or implicit reference conversion exists from the
422                         // parameter type in D to the corresponding parameter type in M
423                         //
424                         if (a.Type == b)
425                                 return true;
426
427                         if (RootContext.Version == LanguageVersion.ISO_1)
428                                 return false;
429
430                         return Convert.ImplicitReferenceConversionExists (a, b);
431                 }
432
433                 public static string FullDelegateDesc (MethodSpec invoke_method)
434                 {
435                         return TypeManager.GetFullNameSignature (invoke_method.MetaInfo).Replace (".Invoke", "");
436                 }
437                 
438                 public Expression InstanceExpression {
439                         get {
440                                 return instance_expr;
441                         }
442                         set {
443                                 instance_expr = value;
444                         }
445                 }
446         }
447
448         //
449         // Base class for `NewDelegate' and `ImplicitDelegateCreation'
450         //
451         public abstract class DelegateCreation : Expression, MethodGroupExpr.IErrorHandler
452         {
453                 protected MethodSpec constructor_method;
454                 protected MethodSpec delegate_method;
455                 // We keep this to handle IsBase only
456                 protected MethodGroupExpr method_group;
457                 protected Expression delegate_instance_expression;
458
459                 // TODO: Should either cache it or use interface to abstract it
460                 public static Arguments CreateDelegateMethodArguments (AParametersCollection pd, Location loc)
461                 {
462                         Arguments delegate_arguments = new Arguments (pd.Count);
463                         for (int i = 0; i < pd.Count; ++i) {
464                                 Argument.AType atype_modifier;
465                                 Type atype = pd.Types [i];
466                                 switch (pd.FixedParameters [i].ModFlags) {
467                                 case Parameter.Modifier.REF:
468                                         atype_modifier = Argument.AType.Ref;
469                                         //atype = atype.GetElementType ();
470                                         break;
471                                 case Parameter.Modifier.OUT:
472                                         atype_modifier = Argument.AType.Out;
473                                         //atype = atype.GetElementType ();
474                                         break;
475                                 default:
476                                         atype_modifier = 0;
477                                         break;
478                                 }
479                                 delegate_arguments.Add (new Argument (new TypeExpression (atype, loc), atype_modifier));
480                         }
481                         return delegate_arguments;
482                 }
483
484                 public override Expression CreateExpressionTree (ResolveContext ec)
485                 {
486                         MemberAccess ma = new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Delegate", loc), "CreateDelegate", loc);
487
488                         Arguments args = new Arguments (3);
489                         args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
490                         args.Add (new Argument (new NullLiteral (loc)));
491                         args.Add (new Argument (new TypeOfMethod (delegate_method, loc)));
492                         Expression e = new Invocation (ma, args).Resolve (ec);
493                         if (e == null)
494                                 return null;
495
496                         e = Convert.ExplicitConversion (ec, e, type, loc);
497                         if (e == null)
498                                 return null;
499
500                         return e.CreateExpressionTree (ec);
501                 }
502
503                 protected override Expression DoResolve (ResolveContext ec)
504                 {
505                         constructor_method = Delegate.GetConstructor (ec.Compiler, ec.CurrentType, type);
506
507                         var invoke_method = Delegate.GetInvokeMethod (ec.Compiler, ec.CurrentType, type);
508                         method_group.DelegateType = type;
509                         method_group.CustomErrorHandler = this;
510
511                         Arguments arguments = CreateDelegateMethodArguments (invoke_method.Parameters, loc);
512                         method_group = method_group.OverloadResolve (ec, ref arguments, false, loc);
513                         if (method_group == null)
514                                 return null;
515
516                         delegate_method = (MethodSpec) method_group;
517                         
518                         if (TypeManager.IsNullableType (delegate_method.DeclaringType)) {
519                                 ec.Report.Error (1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type",
520                                         TypeManager.GetFullNameSignature (delegate_method.MetaInfo));
521                                 return null;
522                         }               
523                         
524                         Invocation.IsSpecialMethodInvocation (ec, delegate_method, loc);
525
526                         ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr;
527                         if (emg != null) {
528                                 delegate_instance_expression = emg.ExtensionExpression;
529                                 Type e_type = delegate_instance_expression.Type;
530                                 if (TypeManager.IsValueType (e_type)) {
531                                         ec.Report.Error (1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates",
532                                                 TypeManager.CSharpSignature (delegate_method.MetaInfo), TypeManager.CSharpName (e_type));
533                                 }
534                         }
535
536                         Type rt = TypeManager.TypeToCoreType (delegate_method.ReturnType);
537                         Expression ret_expr = new TypeExpression (rt, loc);
538                         if (!Delegate.IsTypeCovariant (ret_expr, (TypeManager.TypeToCoreType (invoke_method.ReturnType)))) {
539                                 Error_ConversionFailed (ec, delegate_method, ret_expr);
540                         }
541
542                         if (Invocation.IsMethodExcluded (delegate_method, loc)) {
543                                 ec.Report.SymbolRelatedToPreviousError (delegate_method.MetaInfo);
544                                 MethodOrOperator m = TypeManager.GetMethod (delegate_method.MetaInfo) as MethodOrOperator;
545                                 if (m != null && m.IsPartialDefinition) {
546                                         ec.Report.Error (762, loc, "Cannot create delegate from partial method declaration `{0}'",
547                                                 TypeManager.CSharpSignature (delegate_method.MetaInfo));
548                                 } else {
549                                         ec.Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute",
550                                                 TypeManager.CSharpSignature (delegate_method.MetaInfo));
551                                 }
552                         }
553
554                         DoResolveInstanceExpression (ec);
555                         eclass = ExprClass.Value;
556                         return this;
557                 }
558
559                 void DoResolveInstanceExpression (ResolveContext ec)
560                 {
561                         //
562                         // Argument is another delegate
563                         //
564                         if (delegate_instance_expression != null)
565                                 return;
566
567                         if (method_group.IsStatic) {
568                                 delegate_instance_expression = null;
569                                 return;
570                         }
571
572                         Expression instance = method_group.InstanceExpression;
573                         if (instance != null && instance != EmptyExpression.Null) {
574                                 delegate_instance_expression = instance;
575                                 Type instance_type = delegate_instance_expression.Type;
576                                 if (TypeManager.IsValueType (instance_type) || TypeManager.IsGenericParameter (instance_type)) {
577                                         delegate_instance_expression = new BoxedCast (
578                                                 delegate_instance_expression, TypeManager.object_type);
579                                 }
580                         } else {
581                                 delegate_instance_expression = ec.GetThis (loc);
582                         }
583                 }
584                 
585                 public override void Emit (EmitContext ec)
586                 {
587                         if (delegate_instance_expression == null)
588                                 ec.ig.Emit (OpCodes.Ldnull);
589                         else
590                                 delegate_instance_expression.Emit (ec);
591
592                         if (!delegate_method.DeclaringType.IsSealed && delegate_method.IsVirtual && !method_group.IsBase) {
593                                 ec.ig.Emit (OpCodes.Dup);
594                                 ec.ig.Emit (OpCodes.Ldvirtftn, (MethodInfo) delegate_method.MetaInfo);
595                         } else {
596                                 ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method.MetaInfo);
597                         }
598
599                         ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) constructor_method.MetaInfo);
600                 }
601
602                 void Error_ConversionFailed (ResolveContext ec, MethodSpec method, Expression return_type)
603                 {
604                         var invoke_method = Delegate.GetInvokeMethod (ec.Compiler, ec.CurrentType, type);
605                         string member_name = delegate_instance_expression != null ?
606                                 Delegate.FullDelegateDesc (method) :
607                                 TypeManager.GetFullNameSignature (method.MetaInfo);
608
609                         ec.Report.SymbolRelatedToPreviousError (type);
610                         ec.Report.SymbolRelatedToPreviousError (method.MetaInfo);
611                         if (RootContext.Version == LanguageVersion.ISO_1) {
612                                 ec.Report.Error (410, loc, "A method or delegate `{0} {1}' parameters and return type must be same as delegate `{2} {3}' parameters and return type",
613                                         TypeManager.CSharpName (method.ReturnType), member_name,
614                                         TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method));
615                                 return;
616                         }
617                         if (return_type == null) {
618                                 ec.Report.Error (123, loc, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters",
619                                         member_name, Delegate.FullDelegateDesc (invoke_method));
620                                 return;
621                         }
622
623                         ec.Report.Error (407, loc, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type",
624                                 return_type.GetSignatureForError (), member_name,
625                                 TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method));
626                 }
627
628                 public static bool ImplicitStandardConversionExists (ResolveContext ec, MethodGroupExpr mg, Type target_type)
629                 {
630                         if (target_type == TypeManager.delegate_type || target_type == TypeManager.multicast_delegate_type)
631                                 return false;
632
633                         mg.DelegateType = target_type;
634                         var invoke = Delegate.GetInvokeMethod (ec.Compiler, null, target_type);
635
636                         Arguments arguments = CreateDelegateMethodArguments (invoke.Parameters, mg.Location);
637                         return mg.OverloadResolve (ec, ref arguments, true, mg.Location) != null;
638                 }
639
640                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
641                 {
642                         if (delegate_instance_expression != null)
643                                 delegate_instance_expression.MutateHoistedGenericType (storey);
644
645                         storey.MutateGenericMethod (delegate_method);
646                         storey.MutateConstructor (constructor_method);
647                 }
648
649                 #region IErrorHandler Members
650
651                 public bool NoExactMatch (ResolveContext ec, MethodSpec method)
652                 {
653                         if (method.IsGenericMethod)
654                                 return false;
655
656                         Error_ConversionFailed (ec, method, null);
657                         return true;
658                 }
659
660                 public bool AmbiguousCall (ResolveContext ec, MethodSpec ambiguous)
661                 {
662                         return false;
663                 }
664
665                 #endregion
666         }
667
668         //
669         // Created from the conversion code
670         //
671         public class ImplicitDelegateCreation : DelegateCreation
672         {
673                 ImplicitDelegateCreation (Type t, MethodGroupExpr mg, Location l)
674                 {
675                         type = t;
676                         this.method_group = mg;
677                         loc = l;
678                 }
679
680                 static public Expression Create (ResolveContext ec, MethodGroupExpr mge,
681                                                  Type target_type, Location loc)
682                 {
683                         ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, mge, loc);
684                         return d.DoResolve (ec);
685                 }
686         }
687         
688         //
689         // A delegate-creation-expression, invoked from the `New' class 
690         //
691         public class NewDelegate : DelegateCreation
692         {
693                 public Arguments Arguments;
694
695                 //
696                 // This constructor is invoked from the `New' expression
697                 //
698                 public NewDelegate (Type type, Arguments Arguments, Location loc)
699                 {
700                         this.type = type;
701                         this.Arguments = Arguments;
702                         this.loc  = loc; 
703                 }
704
705                 protected override Expression DoResolve (ResolveContext ec)
706                 {
707                         if (Arguments == null || Arguments.Count != 1) {
708                                 ec.Report.Error (149, loc, "Method name expected");
709                                 return null;
710                         }
711
712                         Argument a = Arguments [0];
713                         if (!a.ResolveMethodGroup (ec))
714                                 return null;
715
716                         Expression e = a.Expr;
717
718                         AnonymousMethodExpression ame = e as AnonymousMethodExpression;
719                         if (ame != null && RootContext.Version != LanguageVersion.ISO_1) {
720                                 e = ame.Compatible (ec, type);
721                                 if (e == null)
722                                         return null;
723
724                                 return e.Resolve (ec);
725                         }
726
727                         method_group = e as MethodGroupExpr;
728                         if (method_group == null) {
729                                 if (TypeManager.IsDynamicType (e.Type)) {
730                                         e = Convert.ImplicitConversionRequired (ec, e, type, loc);
731                                 } else if (!TypeManager.IsDelegateType (e.Type)) {
732                                         e.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup | ResolveFlags.Type, loc);
733                                         return null;
734                                 }
735
736                                 //
737                                 // An argument is not a method but another delegate
738                                 //
739                                 delegate_instance_expression = e;
740                                 method_group = new MethodGroupExpr (new [] { 
741                                         Delegate.GetInvokeMethod (ec.Compiler, ec.CurrentType, e.Type) }, e.Type, loc);
742                         }
743
744                         return base.DoResolve (ec);
745                 }
746         }
747
748         //
749         // Invocation converted to delegate Invoke call
750         //
751         class DelegateInvocation : ExpressionStatement
752         {
753                 readonly Expression InstanceExpr;
754                 Arguments arguments;
755                 MethodSpec method;
756                 
757                 public DelegateInvocation (Expression instance_expr, Arguments args, Location loc)
758                 {
759                         this.InstanceExpr = instance_expr;
760                         this.arguments = args;
761                         this.loc = loc;
762                 }
763                 
764                 public override Expression CreateExpressionTree (ResolveContext ec)
765                 {
766                         Arguments args = Arguments.CreateForExpressionTree (ec, this.arguments,
767                                 InstanceExpr.CreateExpressionTree (ec));
768
769                         return CreateExpressionFactoryCall (ec, "Invoke", args);
770                 }
771
772                 protected override Expression DoResolve (ResolveContext ec)
773                 {
774                         if (InstanceExpr is EventExpr) {
775                                 ((EventExpr) InstanceExpr).Error_CannotAssign (ec);
776                                 return null;
777                         }
778                         
779                         Type del_type = InstanceExpr.Type;
780                         if (del_type == null)
781                                 return null;
782                         
783                         method = Delegate.GetInvokeMethod (ec.Compiler, ec.CurrentType, del_type);
784                         var mb = method;
785                         var me = new MethodGroupExpr (new [] { mb }, del_type, loc);
786                         me.InstanceExpression = InstanceExpr;
787
788                         AParametersCollection pd = mb.Parameters;
789                         int pd_count = pd.Count;
790
791                         int arg_count = arguments == null ? 0 : arguments.Count;
792
793                         bool params_method = pd.HasParams;
794                         bool is_params_applicable = false;
795                         bool is_applicable = me.IsApplicable (ec, ref arguments, arg_count, ref mb, ref is_params_applicable) == 0;
796                         if (arguments != null)
797                                 arg_count = arguments.Count;
798
799                         if (!is_applicable && !params_method && arg_count != pd_count) {
800                                 ec.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
801                                         TypeManager.CSharpName (del_type), arg_count.ToString ());
802                         } else if (arguments == null || !arguments.HasDynamic) {
803                                 me.VerifyArgumentsCompat (ec, ref arguments, arg_count, mb,
804                                         is_params_applicable || (!is_applicable && params_method), false, loc);
805                         }
806
807                         type = TypeManager.TypeToCoreType (method.ReturnType);
808                         eclass = ExprClass.Value;
809                         return this;
810                 }
811
812                 public override void Emit (EmitContext ec)
813                 {
814                         //
815                         // Invocation on delegates call the virtual Invoke member
816                         // so we are always `instance' calls
817                         //
818                         Invocation.EmitCall (ec, false, InstanceExpr, method, arguments, loc);
819                 }
820
821                 public override void EmitStatement (EmitContext ec)
822                 {
823                         Emit (ec);
824                         // 
825                         // Pop the return value if there is one
826                         //
827                         if (type != TypeManager.void_type)
828                                 ec.ig.Emit (OpCodes.Pop);
829                 }
830
831                 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
832                 {
833                         return Invocation.MakeExpression (ctx, InstanceExpr, method, arguments);
834                 }
835
836                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
837                 {
838                         storey.MutateGenericMethod (method);
839                         type = storey.MutateType (type);
840
841                         if (arguments != null)
842                                 arguments.MutateHoistedGenericType (storey);
843
844                         InstanceExpr.MutateHoistedGenericType (storey);
845                 }
846         }
847 }