~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/generic.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// generic.cs: Generics support
 
3
//
 
4
// Authors: Martin Baulig (martin@ximian.com)
 
5
//          Miguel de Icaza (miguel@ximian.com)
 
6
//          Marek Safar (marek.safar@gmail.com)
 
7
//
 
8
// Dual licensed under the terms of the MIT X11 or GNU GPL
 
9
//
 
10
// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
 
11
// Copyright 2004-2008 Novell, Inc
 
12
// Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
 
13
//
 
14
 
 
15
using System;
 
16
using System.Collections.Generic;
 
17
using System.Text;
 
18
using System.Linq;
 
19
 
 
20
#if STATIC
 
21
using MetaType = IKVM.Reflection.Type;
 
22
using IKVM.Reflection;
 
23
using IKVM.Reflection.Emit;
 
24
#else
 
25
using MetaType = System.Type;
 
26
using System.Reflection;
 
27
using System.Reflection.Emit;
 
28
#endif
 
29
 
 
30
namespace Mono.CSharp {
 
31
        public enum Variance
 
32
        {
 
33
                //
 
34
                // Don't add or modify internal values, they are used as -/+ calculation signs
 
35
                //
 
36
                None                    = 0,
 
37
                Covariant               = 1,
 
38
                Contravariant   = -1
 
39
        }
 
40
 
 
41
        [Flags]
 
42
        public enum SpecialConstraint
 
43
        {
 
44
                None            = 0,
 
45
                Constructor = 1 << 2,
 
46
                Class           = 1 << 3,
 
47
                Struct          = 1 << 4
 
48
        }
 
49
 
 
50
        public class SpecialContraintExpr : FullNamedExpression
 
51
        {
 
52
                public SpecialContraintExpr (SpecialConstraint constraint, Location loc)
 
53
                {
 
54
                        this.loc = loc;
 
55
                        this.Constraint = constraint;
 
56
                }
 
57
 
 
58
                public SpecialConstraint Constraint { get; private set; }
 
59
 
 
60
                protected override Expression DoResolve (ResolveContext rc)
 
61
                {
 
62
                        throw new NotImplementedException ();
 
63
                }
 
64
 
 
65
                public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext ec)
 
66
                {
 
67
                        throw new NotImplementedException ();
 
68
                }
 
69
        }
 
70
 
 
71
        //
 
72
        // A set of parsed constraints for a type parameter
 
73
        //
 
74
        public class Constraints
 
75
        {
 
76
                SimpleMemberName tparam;
 
77
                List<FullNamedExpression> constraints;
 
78
                Location loc;
 
79
                bool resolved;
 
80
                bool resolving;
 
81
                
 
82
                public IEnumerable<FullNamedExpression> ConstraintExpressions {
 
83
                        get {
 
84
                                return constraints;
 
85
                        }
 
86
                }
 
87
 
 
88
                public Constraints (SimpleMemberName tparam, List<FullNamedExpression> constraints, Location loc)
 
89
                {
 
90
                        this.tparam = tparam;
 
91
                        this.constraints = constraints;
 
92
                        this.loc = loc;
 
93
                }
 
94
 
 
95
                #region Properties
 
96
 
 
97
                public List<FullNamedExpression> TypeExpressions {
 
98
                        get {
 
99
                                return constraints;
 
100
                        }
 
101
                }
 
102
 
 
103
                public Location Location {
 
104
                        get {
 
105
                                return loc;
 
106
                        }
 
107
                }
 
108
 
 
109
                public SimpleMemberName TypeParameter {
 
110
                        get {
 
111
                                return tparam;
 
112
                        }
 
113
                }
 
114
 
 
115
                #endregion
 
116
 
 
117
                public static bool CheckConflictingInheritedConstraint (TypeParameterSpec spec, TypeSpec bb, IMemberContext context, Location loc)
 
118
                {
 
119
                        if (spec.HasSpecialClass && bb.IsStruct) {
 
120
                                context.Module.Compiler.Report.Error (455, loc,
 
121
                                        "Type parameter `{0}' inherits conflicting constraints `{1}' and `{2}'",
 
122
                                        spec.Name, "class", bb.GetSignatureForError ());
 
123
 
 
124
                                return false;
 
125
                        }
 
126
 
 
127
                        return CheckConflictingInheritedConstraint (spec, spec.BaseType, bb, context, loc);
 
128
                }
 
129
 
 
130
                static bool CheckConflictingInheritedConstraint (TypeParameterSpec spec, TypeSpec ba, TypeSpec bb, IMemberContext context, Location loc)
 
131
                {
 
132
                        if (ba == bb)
 
133
                                return true;
 
134
 
 
135
                        if (TypeSpec.IsBaseClass (ba, bb, false) || TypeSpec.IsBaseClass (bb, ba, false))
 
136
                                return true;
 
137
 
 
138
                        Error_ConflictingConstraints (context, spec, ba, bb, loc);
 
139
                        return false;
 
140
                }
 
141
 
 
142
                public static void Error_ConflictingConstraints (IMemberContext context, TypeParameterSpec tp, TypeSpec ba, TypeSpec bb, Location loc)
 
143
                {
 
144
                        context.Module.Compiler.Report.Error (455, loc,
 
145
                                "Type parameter `{0}' inherits conflicting constraints `{1}' and `{2}'",
 
146
                                tp.Name, ba.GetSignatureForError (), bb.GetSignatureForError ());
 
147
                }
 
148
 
 
149
                public void CheckGenericConstraints (IMemberContext context, bool obsoleteCheck)
 
150
                {
 
151
                        foreach (var c in constraints) {
 
152
                                if (c == null)
 
153
                                        continue;
 
154
 
 
155
                                var t = c.Type;
 
156
                                if (t == null)
 
157
                                        continue;
 
158
 
 
159
                                if (obsoleteCheck) {
 
160
                                        ObsoleteAttribute obsolete_attr = t.GetAttributeObsolete ();
 
161
                                        if (obsolete_attr != null)
 
162
                                                AttributeTester.Report_ObsoleteMessage (obsolete_attr, t.GetSignatureForError (), c.Location, context.Module.Compiler.Report);
 
163
                                }
 
164
 
 
165
                                ConstraintChecker.Check (context, t, c.Location);
 
166
                        }
 
167
                }
 
168
 
 
169
                //
 
170
                // Resolve the constraints types with only possible early checks, return
 
171
                // value `false' is reserved for recursive failure
 
172
                //
 
173
                public bool Resolve (IMemberContext context, TypeParameter tp)
 
174
                {
 
175
                        if (resolved)
 
176
                                return true;
 
177
 
 
178
                        if (resolving)
 
179
                                return false;
 
180
 
 
181
                        resolving = true;
 
182
                        var spec = tp.Type;
 
183
                        List<TypeParameterSpec> tparam_types = null;
 
184
                        bool iface_found = false;
 
185
 
 
186
                        spec.BaseType = context.Module.Compiler.BuiltinTypes.Object;
 
187
 
 
188
                        for (int i = 0; i < constraints.Count; ++i) {
 
189
                                var constraint = constraints[i];
 
190
 
 
191
                                if (constraint is SpecialContraintExpr) {
 
192
                                        spec.SpecialConstraint |= ((SpecialContraintExpr) constraint).Constraint;
 
193
                                        if (spec.HasSpecialStruct)
 
194
                                                spec.BaseType = context.Module.Compiler.BuiltinTypes.ValueType;
 
195
 
 
196
                                        // Set to null as it does not have a type
 
197
                                        constraints[i] = null;
 
198
                                        continue;
 
199
                                }
 
200
 
 
201
                                var type = constraint.ResolveAsType (context);
 
202
                                if (type == null)
 
203
                                        continue;
 
204
 
 
205
                                if (type.Arity > 0 && ((InflatedTypeSpec) type).HasDynamicArgument ()) {
 
206
                                        context.Module.Compiler.Report.Error (1968, constraint.Location,
 
207
                                                "A constraint cannot be the dynamic type `{0}'", type.GetSignatureForError ());
 
208
                                        continue;
 
209
                                }
 
210
 
 
211
                                if (!context.CurrentMemberDefinition.IsAccessibleAs (type)) {
 
212
                                        context.Module.Compiler.Report.SymbolRelatedToPreviousError (type);
 
213
                                        context.Module.Compiler.Report.Error (703, loc,
 
214
                                                "Inconsistent accessibility: constraint type `{0}' is less accessible than `{1}'",
 
215
                                                type.GetSignatureForError (), context.GetSignatureForError ());
 
216
                                }
 
217
 
 
218
                                if (type.IsInterface) {
 
219
                                        if (!spec.AddInterface (type)) {
 
220
                                                context.Module.Compiler.Report.Error (405, constraint.Location,
 
221
                                                        "Duplicate constraint `{0}' for type parameter `{1}'", type.GetSignatureForError (), tparam.Value);
 
222
                                        }
 
223
 
 
224
                                        iface_found = true;
 
225
                                        continue;
 
226
                                }
 
227
 
 
228
 
 
229
                                var constraint_tp = type as TypeParameterSpec;
 
230
                                if (constraint_tp != null) {
 
231
                                        if (tparam_types == null) {
 
232
                                                tparam_types = new List<TypeParameterSpec> (2);
 
233
                                        } else if (tparam_types.Contains (constraint_tp)) {
 
234
                                                context.Module.Compiler.Report.Error (405, constraint.Location,
 
235
                                                        "Duplicate constraint `{0}' for type parameter `{1}'", type.GetSignatureForError (), tparam.Value);
 
236
                                                continue;
 
237
                                        }
 
238
 
 
239
                                        //
 
240
                                        // Checks whether each generic method parameter constraint type
 
241
                                        // is valid with respect to T
 
242
                                        //
 
243
                                        if (tp.IsMethodTypeParameter) {
 
244
                                                TypeManager.CheckTypeVariance (type, Variance.Contravariant, context);
 
245
                                        }
 
246
 
 
247
                                        var tp_def = constraint_tp.MemberDefinition as TypeParameter;
 
248
                                        if (tp_def != null && !tp_def.ResolveConstraints (context)) {
 
249
                                                context.Module.Compiler.Report.Error (454, constraint.Location,
 
250
                                                        "Circular constraint dependency involving `{0}' and `{1}'",
 
251
                                                        constraint_tp.GetSignatureForError (), tp.GetSignatureForError ());
 
252
                                                continue;
 
253
                                        }
 
254
 
 
255
                                        //
 
256
                                        // Checks whether there are no conflicts between type parameter constraints
 
257
                                        //
 
258
                                        // class Foo<T, U>
 
259
                                        //      where T : A
 
260
                                        //      where U : B, T
 
261
                                        //
 
262
                                        // A and B are not convertible and only 1 class constraint is allowed
 
263
                                        //
 
264
                                        if (constraint_tp.HasTypeConstraint) {
 
265
                                                if (spec.HasTypeConstraint || spec.HasSpecialStruct) {
 
266
                                                        if (!CheckConflictingInheritedConstraint (spec, constraint_tp.BaseType, context, constraint.Location))
 
267
                                                                continue;
 
268
                                                } else {
 
269
                                                        for (int ii = 0; ii < tparam_types.Count; ++ii) {
 
270
                                                                if (!tparam_types[ii].HasTypeConstraint)
 
271
                                                                        continue;
 
272
 
 
273
                                                                if (!CheckConflictingInheritedConstraint (spec, tparam_types[ii].BaseType, constraint_tp.BaseType, context, constraint.Location))
 
274
                                                                        break;
 
275
                                                        }
 
276
                                                }
 
277
                                        }
 
278
 
 
279
                                        if (constraint_tp.HasSpecialStruct) {
 
280
                                                context.Module.Compiler.Report.Error (456, constraint.Location,
 
281
                                                        "Type parameter `{0}' has the `struct' constraint, so it cannot be used as a constraint for `{1}'",
 
282
                                                        constraint_tp.GetSignatureForError (), tp.GetSignatureForError ());
 
283
                                                continue;
 
284
                                        }
 
285
 
 
286
                                        tparam_types.Add (constraint_tp);
 
287
                                        continue;
 
288
                                }
 
289
 
 
290
                                if (iface_found || spec.HasTypeConstraint) {
 
291
                                        context.Module.Compiler.Report.Error (406, constraint.Location,
 
292
                                                "The class type constraint `{0}' must be listed before any other constraints. Consider moving type constraint to the beginning of the constraint list",
 
293
                                                type.GetSignatureForError ());
 
294
                                }
 
295
 
 
296
                                if (spec.HasSpecialStruct || spec.HasSpecialClass) {
 
297
                                        context.Module.Compiler.Report.Error (450, constraint.Location,
 
298
                                                "`{0}': cannot specify both a constraint class and the `class' or `struct' constraint",
 
299
                                                type.GetSignatureForError ());
 
300
                                }
 
301
 
 
302
                                switch (type.BuiltinType) {
 
303
                                case BuiltinTypeSpec.Type.Array:
 
304
                                case BuiltinTypeSpec.Type.Delegate:
 
305
                                case BuiltinTypeSpec.Type.MulticastDelegate:
 
306
                                case BuiltinTypeSpec.Type.Enum:
 
307
                                case BuiltinTypeSpec.Type.ValueType:
 
308
                                case BuiltinTypeSpec.Type.Object:
 
309
                                        context.Module.Compiler.Report.Error (702, constraint.Location,
 
310
                                                "A constraint cannot be special class `{0}'", type.GetSignatureForError ());
 
311
                                        continue;
 
312
                                case BuiltinTypeSpec.Type.Dynamic:
 
313
                                        context.Module.Compiler.Report.Error (1967, constraint.Location,
 
314
                                                "A constraint cannot be the dynamic type");
 
315
                                        continue;
 
316
                                }
 
317
 
 
318
                                if (type.IsSealed || !type.IsClass) {
 
319
                                        context.Module.Compiler.Report.Error (701, loc,
 
320
                                                "`{0}' is not a valid constraint. A constraint must be an interface, a non-sealed class or a type parameter",
 
321
                                                TypeManager.CSharpName (type));
 
322
                                        continue;
 
323
                                }
 
324
 
 
325
                                if (type.IsStatic) {
 
326
                                        context.Module.Compiler.Report.Error (717, constraint.Location,
 
327
                                                "`{0}' is not a valid constraint. Static classes cannot be used as constraints",
 
328
                                                type.GetSignatureForError ());
 
329
                                }
 
330
 
 
331
                                spec.BaseType = type;
 
332
                        }
 
333
 
 
334
                        if (tparam_types != null)
 
335
                                spec.TypeArguments = tparam_types.ToArray ();
 
336
 
 
337
                        resolving = false;
 
338
                        resolved = true;
 
339
                        return true;
 
340
                }
 
341
 
 
342
                public void VerifyClsCompliance (Report report)
 
343
                {
 
344
                        foreach (var c in constraints)
 
345
                        {
 
346
                                if (c == null)
 
347
                                        continue;
 
348
 
 
349
                                if (!c.Type.IsCLSCompliant ()) {
 
350
                                        report.SymbolRelatedToPreviousError (c.Type);
 
351
                                        report.Warning (3024, 1, loc, "Constraint type `{0}' is not CLS-compliant",
 
352
                                                c.Type.GetSignatureForError ());
 
353
                                }
 
354
                        }
 
355
                }
 
356
        }
 
357
 
 
358
        //
 
359
        // A type parameter for a generic type or generic method definition
 
360
        //
 
361
        public class TypeParameter : MemberCore, ITypeDefinition
 
362
        {
 
363
                static readonly string[] attribute_target = new string [] { "type parameter" };
 
364
                
 
365
                Constraints constraints;
 
366
                GenericTypeParameterBuilder builder;
 
367
                readonly TypeParameterSpec spec;
 
368
 
 
369
                public TypeParameter (int index, MemberName name, Constraints constraints, Attributes attrs, Variance variance)
 
370
                        : base (null, name, attrs)
 
371
                {
 
372
                        this.constraints = constraints;
 
373
                        this.spec = new TypeParameterSpec (null, index, this, SpecialConstraint.None, variance, null);
 
374
                }
 
375
 
 
376
                //
 
377
                // Used by parser
 
378
                //
 
379
                public TypeParameter (MemberName name, Attributes attrs, Variance variance)
 
380
                        : base (null, name, attrs)
 
381
                {
 
382
                        this.spec = new TypeParameterSpec (null, -1, this, SpecialConstraint.None, variance, null);
 
383
                }
 
384
                
 
385
                public TypeParameter (TypeParameterSpec spec, TypeSpec parentSpec, MemberName name, Attributes attrs)
 
386
                        : base (null, name, attrs)
 
387
                {
 
388
                        this.spec = new TypeParameterSpec (parentSpec, spec.DeclaredPosition, spec.MemberDefinition, spec.SpecialConstraint, spec.Variance, null) {
 
389
                                BaseType = spec.BaseType,
 
390
                                InterfacesDefined = spec.InterfacesDefined,
 
391
                                TypeArguments = spec.TypeArguments
 
392
                        };
 
393
                }
 
394
                
 
395
                #region Properties
 
396
 
 
397
                public override AttributeTargets AttributeTargets {
 
398
                        get {
 
399
                                return AttributeTargets.GenericParameter;
 
400
                        }
 
401
                }
 
402
 
 
403
                public Constraints Constraints {
 
404
                        get {
 
405
                                return constraints;
 
406
                        }
 
407
                        set {
 
408
                                constraints = value;
 
409
                        }
 
410
                }
 
411
 
 
412
                public IAssemblyDefinition DeclaringAssembly {
 
413
                        get     {
 
414
                                return Module.DeclaringAssembly;
 
415
                        }
 
416
                }
 
417
 
 
418
                public override string DocCommentHeader {
 
419
                        get {
 
420
                                throw new InvalidOperationException (
 
421
                                        "Unexpected attempt to get doc comment from " + this.GetType ());
 
422
                        }
 
423
                }
 
424
 
 
425
                bool ITypeDefinition.IsComImport {
 
426
                        get {
 
427
                                return false;
 
428
                        }
 
429
                }
 
430
 
 
431
                bool ITypeDefinition.IsPartial {
 
432
                        get {
 
433
                                return false;
 
434
                        }
 
435
                }
 
436
 
 
437
                public bool IsMethodTypeParameter {
 
438
                        get {
 
439
                                return spec.IsMethodOwned;
 
440
                        }
 
441
                }
 
442
 
 
443
                bool ITypeDefinition.IsTypeForwarder {
 
444
                        get {
 
445
                                return false;
 
446
                        }
 
447
                }
 
448
 
 
449
                public string Name {
 
450
                        get {
 
451
                                return MemberName.Name;
 
452
                        }
 
453
                }
 
454
 
 
455
                public string Namespace {
 
456
                        get {
 
457
                                return null;
 
458
                        }
 
459
                }
 
460
 
 
461
                public TypeParameterSpec Type {
 
462
                        get {
 
463
                                return spec;
 
464
                        }
 
465
                }
 
466
 
 
467
                public int TypeParametersCount {
 
468
                        get {
 
469
                                return 0;
 
470
                        }
 
471
                }
 
472
 
 
473
                public TypeParameterSpec[] TypeParameters {
 
474
                        get {
 
475
                                return null;
 
476
                        }
 
477
                }
 
478
 
 
479
                public override string[] ValidAttributeTargets {
 
480
                        get {
 
481
                                return attribute_target;
 
482
                        }
 
483
                }
 
484
 
 
485
                public Variance Variance {
 
486
                        get {
 
487
                                return spec.Variance;
 
488
                        }
 
489
                }
 
490
 
 
491
                #endregion
 
492
 
 
493
                //
 
494
                // This is called for each part of a partial generic type definition.
 
495
                //
 
496
                // If partial type parameters constraints are not null and we don't
 
497
                // already have constraints they become our constraints. If we already
 
498
                // have constraints, we must check that they're the same.
 
499
                //
 
500
                public bool AddPartialConstraints (TypeDefinition part, TypeParameter tp)
 
501
                {
 
502
                        if (builder == null)
 
503
                                throw new InvalidOperationException ();
 
504
 
 
505
                        var new_constraints = tp.constraints;
 
506
                        if (new_constraints == null)
 
507
                                return true;
 
508
 
 
509
                        // TODO: could create spec only
 
510
                        //tp.Define (null, -1, part.Definition);
 
511
                        tp.spec.DeclaringType = part.Definition;
 
512
                        if (!tp.ResolveConstraints (part))
 
513
                                return false;
 
514
 
 
515
                        if (constraints != null)
 
516
                                return spec.HasSameConstraintsDefinition (tp.Type);
 
517
 
 
518
                        // Copy constraint from resolved part to partial container
 
519
                        spec.SpecialConstraint = tp.spec.SpecialConstraint;
 
520
                        spec.Interfaces = tp.spec.Interfaces;
 
521
                        spec.TypeArguments = tp.spec.TypeArguments;
 
522
                        spec.BaseType = tp.spec.BaseType;
 
523
                        
 
524
                        return true;
 
525
                }
 
526
 
 
527
                public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
 
528
                {
 
529
                        builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
 
530
                }
 
531
 
 
532
                public void CheckGenericConstraints (bool obsoleteCheck)
 
533
                {
 
534
                        if (constraints != null)
 
535
                                constraints.CheckGenericConstraints (this, obsoleteCheck);
 
536
                }
 
537
 
 
538
                public TypeParameter CreateHoistedCopy (TypeSpec declaringSpec)
 
539
                {
 
540
                        return new TypeParameter (spec, declaringSpec, MemberName, null);
 
541
                }
 
542
 
 
543
                public override bool Define ()
 
544
                {
 
545
                        return true;
 
546
                }
 
547
 
 
548
                //
 
549
                // This is the first method which is called during the resolving
 
550
                // process; we're called immediately after creating the type parameters
 
551
                // with SRE (by calling `DefineGenericParameters()' on the TypeBuilder /
 
552
                // MethodBuilder).
 
553
                //
 
554
                public void Define (GenericTypeParameterBuilder type, TypeSpec declaringType, TypeContainer parent)
 
555
                {
 
556
                        if (builder != null)
 
557
                                throw new InternalErrorException ();
 
558
 
 
559
                        // Needed to get compiler reference
 
560
                        this.Parent = parent;
 
561
                        this.builder = type;
 
562
                        spec.DeclaringType = declaringType;
 
563
                        spec.SetMetaInfo (type);
 
564
                }
 
565
 
 
566
                public void EmitConstraints (GenericTypeParameterBuilder builder)
 
567
                {
 
568
                        var attr = GenericParameterAttributes.None;
 
569
                        if (spec.Variance == Variance.Contravariant)
 
570
                                attr |= GenericParameterAttributes.Contravariant;
 
571
                        else if (spec.Variance == Variance.Covariant)
 
572
                                attr |= GenericParameterAttributes.Covariant;
 
573
 
 
574
                        if (spec.HasSpecialClass)
 
575
                                attr |= GenericParameterAttributes.ReferenceTypeConstraint;
 
576
                        else if (spec.HasSpecialStruct)
 
577
                                attr |= GenericParameterAttributes.NotNullableValueTypeConstraint | GenericParameterAttributes.DefaultConstructorConstraint;
 
578
 
 
579
                        if (spec.HasSpecialConstructor)
 
580
                                attr |= GenericParameterAttributes.DefaultConstructorConstraint;
 
581
 
 
582
                        if (spec.BaseType.BuiltinType != BuiltinTypeSpec.Type.Object)
 
583
                                builder.SetBaseTypeConstraint (spec.BaseType.GetMetaInfo ());
 
584
 
 
585
                        if (spec.InterfacesDefined != null)
 
586
                                builder.SetInterfaceConstraints (spec.InterfacesDefined.Select (l => l.GetMetaInfo ()).ToArray ());
 
587
 
 
588
                        if (spec.TypeArguments != null)
 
589
                                builder.SetInterfaceConstraints (spec.TypeArguments.Select (l => l.GetMetaInfo ()).ToArray ());
 
590
 
 
591
                        builder.SetGenericParameterAttributes (attr);
 
592
                }
 
593
 
 
594
                public override void Emit ()
 
595
                {
 
596
                        EmitConstraints (builder);
 
597
 
 
598
                        if (OptAttributes != null)
 
599
                                OptAttributes.Emit ();
 
600
 
 
601
                        base.Emit ();
 
602
                }
 
603
 
 
604
                public void ErrorInvalidVariance (IMemberContext mc, Variance expected)
 
605
                {
 
606
                        Report.SymbolRelatedToPreviousError (mc.CurrentMemberDefinition);
 
607
                        string input_variance = Variance == Variance.Contravariant ? "contravariant" : "covariant";
 
608
                        string gtype_variance;
 
609
                        switch (expected) {
 
610
                        case Variance.Contravariant: gtype_variance = "contravariantly"; break;
 
611
                        case Variance.Covariant: gtype_variance = "covariantly"; break;
 
612
                        default: gtype_variance = "invariantly"; break;
 
613
                        }
 
614
 
 
615
                        Delegate d = mc as Delegate;
 
616
                        string parameters = d != null ? d.Parameters.GetSignatureForError () : "";
 
617
 
 
618
                        Report.Error (1961, Location,
 
619
                                "The {2} type parameter `{0}' must be {3} valid on `{1}{4}'",
 
620
                                        GetSignatureForError (), mc.GetSignatureForError (), input_variance, gtype_variance, parameters);
 
621
                }
 
622
 
 
623
                public TypeSpec GetAttributeCoClass ()
 
624
                {
 
625
                        return null;
 
626
                }
 
627
 
 
628
                public string GetAttributeDefaultMember ()
 
629
                {
 
630
                        throw new NotSupportedException ();
 
631
                }
 
632
 
 
633
                public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
 
634
                {
 
635
                        throw new NotSupportedException ();
 
636
                }
 
637
 
 
638
                public override string GetSignatureForDocumentation ()
 
639
                {
 
640
                        throw new NotImplementedException ();
 
641
                }
 
642
 
 
643
                public override string GetSignatureForError ()
 
644
                {
 
645
                        return MemberName.Name;
 
646
                }
 
647
 
 
648
                bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
 
649
                {
 
650
                        return spec.MemberDefinition.DeclaringAssembly == assembly;
 
651
                }
 
652
 
 
653
                public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
 
654
                {
 
655
                        throw new NotSupportedException ("Not supported for compiled definition");
 
656
                }
 
657
 
 
658
                //
 
659
                // Resolves all type parameter constraints
 
660
                //
 
661
                public bool ResolveConstraints (IMemberContext context)
 
662
                {
 
663
                        if (constraints != null)
 
664
                                return constraints.Resolve (context, this);
 
665
 
 
666
                        if (spec.BaseType == null)
 
667
                                spec.BaseType = context.Module.Compiler.BuiltinTypes.Object;
 
668
 
 
669
                        return true;
 
670
                }
 
671
 
 
672
                public override bool IsClsComplianceRequired ()
 
673
                {
 
674
                        return false;
 
675
                }
 
676
 
 
677
                public new void VerifyClsCompliance ()
 
678
                {
 
679
                        if (constraints != null)
 
680
                                constraints.VerifyClsCompliance (Report);
 
681
                }
 
682
 
 
683
                public void WarningParentNameConflict (TypeParameter conflict)
 
684
                {
 
685
                        conflict.Report.SymbolRelatedToPreviousError (conflict.Location, null);
 
686
                        conflict.Report.Warning (693, 3, Location,
 
687
                                "Type parameter `{0}' has the same name as the type parameter from outer type `{1}'",
 
688
                                GetSignatureForError (), conflict.CurrentType.GetSignatureForError ());
 
689
                }
 
690
        }
 
691
 
 
692
        [System.Diagnostics.DebuggerDisplay ("{DisplayDebugInfo()}")]
 
693
        public class TypeParameterSpec : TypeSpec
 
694
        {
 
695
                public static readonly new TypeParameterSpec[] EmptyTypes = new TypeParameterSpec[0];
 
696
 
 
697
                Variance variance;
 
698
                SpecialConstraint spec;
 
699
                int tp_pos;
 
700
                TypeSpec[] targs;
 
701
                TypeSpec[] ifaces_defined;
 
702
 
 
703
                //
 
704
                // Creates type owned type parameter
 
705
                //
 
706
                public TypeParameterSpec (TypeSpec declaringType, int index, ITypeDefinition definition, SpecialConstraint spec, Variance variance, MetaType info)
 
707
                        : base (MemberKind.TypeParameter, declaringType, definition, info, Modifiers.PUBLIC)
 
708
                {
 
709
                        this.variance = variance;
 
710
                        this.spec = spec;
 
711
                        state &= ~StateFlags.Obsolete_Undetected;
 
712
                        tp_pos = index;
 
713
                }
 
714
 
 
715
                //
 
716
                // Creates method owned type parameter
 
717
                //
 
718
                public TypeParameterSpec (int index, ITypeDefinition definition, SpecialConstraint spec, Variance variance, MetaType info)
 
719
                        : this (null, index, definition, spec, variance, info)
 
720
                {
 
721
                }
 
722
 
 
723
                #region Properties
 
724
 
 
725
                public int DeclaredPosition {
 
726
                        get {
 
727
                                return tp_pos;
 
728
                        }
 
729
                        set {
 
730
                                tp_pos = value;
 
731
                        }
 
732
                }
 
733
 
 
734
                public bool HasSpecialConstructor {
 
735
                        get {
 
736
                                return (spec & SpecialConstraint.Constructor) != 0;
 
737
                        }
 
738
                }
 
739
 
 
740
                public bool HasSpecialClass {
 
741
                        get {
 
742
                                return (spec & SpecialConstraint.Class) != 0;
 
743
                        }
 
744
                }
 
745
 
 
746
                public bool HasSpecialStruct {
 
747
                        get {
 
748
                                return (spec & SpecialConstraint.Struct) != 0;
 
749
                        }
 
750
                }
 
751
 
 
752
                public bool HasAnyTypeConstraint {
 
753
                        get {
 
754
                                return (spec & (SpecialConstraint.Class | SpecialConstraint.Struct)) != 0 || ifaces != null || targs != null || HasTypeConstraint;
 
755
                        }
 
756
                }
 
757
 
 
758
                public bool HasTypeConstraint {
 
759
                        get {
 
760
                                var bt = BaseType.BuiltinType;
 
761
                                return bt != BuiltinTypeSpec.Type.Object && bt != BuiltinTypeSpec.Type.ValueType;
 
762
                        }
 
763
                }
 
764
 
 
765
                public override IList<TypeSpec> Interfaces {
 
766
                        get {
 
767
                                if ((state & StateFlags.InterfacesExpanded) == 0) {
 
768
                                        if (ifaces != null) {
 
769
                                                if (ifaces_defined == null)
 
770
                                                        ifaces_defined = ifaces.ToArray ();
 
771
 
 
772
                                                for (int i = 0; i < ifaces_defined.Length; ++i ) {
 
773
                                                        var iface_type = ifaces_defined[i];
 
774
                                                        var td = iface_type.MemberDefinition as TypeDefinition;
 
775
                                                        if (td != null)
 
776
                                                                td.DoExpandBaseInterfaces ();
 
777
 
 
778
                                                        if (iface_type.Interfaces != null) {
 
779
                                                                for (int ii = 0; ii < iface_type.Interfaces.Count; ++ii) {
 
780
                                                                        var ii_iface_type = iface_type.Interfaces [ii];
 
781
                                                                        AddInterface (ii_iface_type);
 
782
                                                                }
 
783
                                                        }
 
784
                                                }
 
785
                                        } else if (ifaces_defined == null) {
 
786
                                                ifaces_defined = ifaces == null ? TypeSpec.EmptyTypes : ifaces.ToArray ();
 
787
                                        }
 
788
 
 
789
                                        //
 
790
                                        // Include all base type interfaces too, see ImportTypeBase for details
 
791
                                        //
 
792
                                        if (BaseType != null) {
 
793
                                                var td = BaseType.MemberDefinition as TypeDefinition;
 
794
                                                if (td != null)
 
795
                                                        td.DoExpandBaseInterfaces ();
 
796
 
 
797
                                                if (BaseType.Interfaces != null) {
 
798
                                                        foreach (var iface in BaseType.Interfaces) {
 
799
                                                                AddInterface (iface);
 
800
                                                        }
 
801
                                                }
 
802
                                        }
 
803
 
 
804
                                        state |= StateFlags.InterfacesExpanded;
 
805
                                }
 
806
 
 
807
                                return ifaces;
 
808
                        }
 
809
                }
 
810
 
 
811
                //
 
812
                // Unexpanded interfaces list
 
813
                //
 
814
                public TypeSpec[] InterfacesDefined {
 
815
                        get {
 
816
                                if (ifaces_defined == null) {
 
817
                                        if (ifaces == null)
 
818
                                                return null;
 
819
 
 
820
                                        ifaces_defined = ifaces.ToArray ();
 
821
                                }
 
822
 
 
823
                                return ifaces_defined.Length == 0 ? null : ifaces_defined;
 
824
                        }
 
825
                        set {
 
826
                                ifaces_defined = value;
 
827
                                if (value != null && value.Length != 0)
 
828
                                        ifaces = new List<TypeSpec> (value);
 
829
                        }
 
830
                }
 
831
 
 
832
                public bool IsConstrained {
 
833
                        get {
 
834
                                return spec != SpecialConstraint.None || ifaces != null || targs != null || HasTypeConstraint;
 
835
                        }
 
836
                }
 
837
 
 
838
                //
 
839
                // Returns whether the type parameter is known to be a reference type
 
840
                //
 
841
                public new bool IsReferenceType {
 
842
                        get {
 
843
                                if ((spec & (SpecialConstraint.Class | SpecialConstraint.Struct)) != 0)
 
844
                                        return (spec & SpecialConstraint.Class) != 0;
 
845
 
 
846
                                //
 
847
                                // Full check is needed (see IsValueType for details)
 
848
                                //
 
849
                                if (HasTypeConstraint && TypeSpec.IsReferenceType (BaseType))
 
850
                                        return true;
 
851
 
 
852
                                if (targs != null) {
 
853
                                        foreach (var ta in targs) {
 
854
                                                //
 
855
                                                // Secondary special constraints are ignored (I am not sure why)
 
856
                                                //
 
857
                                                var tp = ta as TypeParameterSpec;
 
858
                                                if (tp != null && (tp.spec & (SpecialConstraint.Class | SpecialConstraint.Struct)) != 0)
 
859
                                                        continue;
 
860
 
 
861
                                                if (TypeSpec.IsReferenceType (ta))
 
862
                                                        return true;
 
863
                                        }
 
864
                                }
 
865
 
 
866
                                return false;
 
867
                        }
 
868
                }
 
869
 
 
870
                //
 
871
                // Returns whether the type parameter is known to be a value type
 
872
                //
 
873
                public new bool IsValueType {
 
874
                        get {
 
875
                                //
 
876
                                // Even if structs/enums cannot be used directly as constraints
 
877
                                // they can apear as constraint type when inheriting base constraint
 
878
                                // which has dependant type parameter constraint which has been
 
879
                                // inflated using value type
 
880
                                //
 
881
                                // class A : B<int> { override void Foo<U> () {} }
 
882
                                // class B<T> { virtual void Foo<U> () where U : T {} }
 
883
                                //
 
884
                                if (HasSpecialStruct)
 
885
                                        return true;
 
886
 
 
887
                                if (targs != null) {
 
888
                                        foreach (var ta in targs) {
 
889
                                                if (TypeSpec.IsValueType (ta))
 
890
                                                        return true;
 
891
                                        }
 
892
                                }
 
893
 
 
894
                                return false;
 
895
                        }
 
896
                }
 
897
 
 
898
                public override string Name {
 
899
                        get {
 
900
                                return definition.Name;
 
901
                        }
 
902
                }
 
903
 
 
904
                public bool IsMethodOwned {
 
905
                        get {
 
906
                                return DeclaringType == null;
 
907
                        }
 
908
                }
 
909
 
 
910
                public SpecialConstraint SpecialConstraint {
 
911
                        get {
 
912
                                return spec;
 
913
                        }
 
914
                        set {
 
915
                                spec = value;
 
916
                        }
 
917
                }
 
918
 
 
919
                //
 
920
                // Types used to inflate the generic type
 
921
                //
 
922
                public new TypeSpec[] TypeArguments {
 
923
                        get {
 
924
                                return targs;
 
925
                        }
 
926
                        set {
 
927
                                targs = value;
 
928
                        }
 
929
                }
 
930
 
 
931
                public Variance Variance {
 
932
                        get {
 
933
                                return variance;
 
934
                        }
 
935
                }
 
936
 
 
937
                #endregion
 
938
 
 
939
                public string DisplayDebugInfo ()
 
940
                {
 
941
                        var s = GetSignatureForError ();
 
942
                        return IsMethodOwned ? s + "!!" : s + "!";
 
943
                }
 
944
 
 
945
                //
 
946
                // Finds effective base class. The effective base class is always a class-type
 
947
                //
 
948
                public TypeSpec GetEffectiveBase ()
 
949
                {
 
950
                        if (HasSpecialStruct)
 
951
                                return BaseType;
 
952
 
 
953
                        //
 
954
                        // If T has a class-type constraint C but no type-parameter constraints, its effective base class is C
 
955
                        //
 
956
                        if (BaseType != null && targs == null) {
 
957
                                //
 
958
                                // If T has a constraint V that is a value-type, use instead the most specific base type of V that is a class-type.
 
959
                                // 
 
960
                                // LAMESPEC: Is System.ValueType always the most specific base type in this case?
 
961
                                //
 
962
                                // Note: This can never happen in an explicitly given constraint, but may occur when the constraints of a generic method
 
963
                                // are implicitly inherited by an overriding method declaration or an explicit implementation of an interface method.
 
964
                                //
 
965
                                return BaseType.IsStruct ? BaseType.BaseType : BaseType;
 
966
                        }
 
967
 
 
968
                        var types = targs;
 
969
                        if (HasTypeConstraint) {
 
970
                                Array.Resize (ref types, types.Length + 1);
 
971
 
 
972
                                for (int i = 0; i < types.Length - 1; ++i) {
 
973
                                        types[i] = types[i].BaseType;
 
974
                                }
 
975
 
 
976
                                types[types.Length - 1] = BaseType;
 
977
                        } else {
 
978
                                types = types.Select (l => l.BaseType).ToArray ();
 
979
                        }
 
980
 
 
981
                        if (types != null)
 
982
                                return Convert.FindMostEncompassedType (types);
 
983
 
 
984
                        return BaseType;
 
985
                }
 
986
 
 
987
                public override string GetSignatureForDocumentation ()
 
988
                {
 
989
                        var prefix = IsMethodOwned ? "``" : "`";
 
990
                        return prefix + DeclaredPosition;
 
991
                }
 
992
 
 
993
                public override string GetSignatureForError ()
 
994
                {
 
995
                        return Name;
 
996
                }
 
997
 
 
998
                //
 
999
                // Constraints have to match by definition but not position, used by
 
1000
                // partial classes or methods
 
1001
                //
 
1002
                public bool HasSameConstraintsDefinition (TypeParameterSpec other)
 
1003
                {
 
1004
                        if (spec != other.spec)
 
1005
                                return false;
 
1006
 
 
1007
                        if (BaseType != other.BaseType)
 
1008
                                return false;
 
1009
 
 
1010
                        if (!TypeSpecComparer.Override.IsSame (InterfacesDefined, other.InterfacesDefined))
 
1011
                                return false;
 
1012
 
 
1013
                        if (!TypeSpecComparer.Override.IsSame (targs, other.targs))
 
1014
                                return false;
 
1015
 
 
1016
                        return true;
 
1017
                }
 
1018
 
 
1019
                //
 
1020
                // Constraints have to match by using same set of types, used by
 
1021
                // implicit interface implementation
 
1022
                //
 
1023
                public bool HasSameConstraintsImplementation (TypeParameterSpec other)
 
1024
                {
 
1025
                        if (spec != other.spec)
 
1026
                                return false;
 
1027
 
 
1028
                        //
 
1029
                        // It can be same base type or inflated type parameter
 
1030
                        //
 
1031
                        // interface I<T> { void Foo<U> where U : T; }
 
1032
                        // class A : I<int> { void Foo<X> where X : int {} }
 
1033
                        //
 
1034
                        bool found;
 
1035
                        if (!TypeSpecComparer.Override.IsEqual (BaseType, other.BaseType)) {
 
1036
                                if (other.targs == null)
 
1037
                                        return false;
 
1038
 
 
1039
                                found = false;
 
1040
                                foreach (var otarg in other.targs) {
 
1041
                                        if (TypeSpecComparer.Override.IsEqual (BaseType, otarg)) {
 
1042
                                                found = true;
 
1043
                                                break;
 
1044
                                        }
 
1045
                                }
 
1046
 
 
1047
                                if (!found)
 
1048
                                        return false;
 
1049
                        }
 
1050
 
 
1051
                        // Check interfaces implementation -> definition
 
1052
                        if (InterfacesDefined != null) {
 
1053
                                //
 
1054
                                // Iterate over inflated interfaces
 
1055
                                //
 
1056
                                foreach (var iface in Interfaces) {
 
1057
                                        found = false;
 
1058
                                        if (other.InterfacesDefined != null) {
 
1059
                                                foreach (var oiface in other.Interfaces) {
 
1060
                                                        if (TypeSpecComparer.Override.IsEqual (iface, oiface)) {
 
1061
                                                                found = true;
 
1062
                                                                break;
 
1063
                                                        }
 
1064
                                                }
 
1065
                                        }
 
1066
 
 
1067
                                        if (found)
 
1068
                                                continue;
 
1069
 
 
1070
                                        if (other.targs != null) {
 
1071
                                                foreach (var otarg in other.targs) {
 
1072
                                                        if (TypeSpecComparer.Override.IsEqual (BaseType, otarg)) {
 
1073
                                                                found = true;
 
1074
                                                                break;
 
1075
                                                        }
 
1076
                                                }
 
1077
                                        }
 
1078
 
 
1079
                                        if (!found)
 
1080
                                                return false;
 
1081
                                }
 
1082
                        }
 
1083
 
 
1084
                        // Check interfaces implementation <- definition
 
1085
                        if (other.InterfacesDefined != null) {
 
1086
                                if (InterfacesDefined == null)
 
1087
                                        return false;
 
1088
 
 
1089
                                //
 
1090
                                // Iterate over inflated interfaces
 
1091
                                //
 
1092
                                foreach (var oiface in other.Interfaces) {
 
1093
                                        found = false;
 
1094
                                        foreach (var iface in Interfaces) {
 
1095
                                                if (TypeSpecComparer.Override.IsEqual (iface, oiface)) {
 
1096
                                                        found = true;
 
1097
                                                        break;
 
1098
                                                }
 
1099
                                        }
 
1100
 
 
1101
                                        if (!found)
 
1102
                                                return false;
 
1103
                                }
 
1104
                        }
 
1105
 
 
1106
                        // Check type parameters implementation -> definition
 
1107
                        if (targs != null) {
 
1108
                                if (other.targs == null)
 
1109
                                        return false;
 
1110
 
 
1111
                                foreach (var targ in targs) {
 
1112
                                        found = false;
 
1113
                                        foreach (var otarg in other.targs) {
 
1114
                                                if (TypeSpecComparer.Override.IsEqual (targ, otarg)) {
 
1115
                                                        found = true;
 
1116
                                                        break;
 
1117
                                                }
 
1118
                                        }
 
1119
 
 
1120
                                        if (!found)
 
1121
                                                return false;
 
1122
                                }
 
1123
                        }
 
1124
 
 
1125
                        // Check type parameters implementation <- definition
 
1126
                        if (other.targs != null) {
 
1127
                                foreach (var otarg in other.targs) {
 
1128
                                        // Ignore inflated type arguments, were checked above
 
1129
                                        if (!otarg.IsGenericParameter)
 
1130
                                                continue;
 
1131
 
 
1132
                                        if (targs == null)
 
1133
                                                return false;
 
1134
 
 
1135
                                        found = false;
 
1136
                                        foreach (var targ in targs) {
 
1137
                                                if (TypeSpecComparer.Override.IsEqual (targ, otarg)) {
 
1138
                                                        found = true;
 
1139
                                                        break;
 
1140
                                                }
 
1141
                                        }
 
1142
 
 
1143
                                        if (!found)
 
1144
                                                return false;
 
1145
                                }                               
 
1146
                        }
 
1147
 
 
1148
                        return true;
 
1149
                }
 
1150
 
 
1151
                public static TypeParameterSpec[] InflateConstraints (TypeParameterInflator inflator, TypeParameterSpec[] tparams)
 
1152
                {
 
1153
                        return InflateConstraints (tparams, l => l, inflator);
 
1154
                }
 
1155
 
 
1156
                public static TypeParameterSpec[] InflateConstraints<T> (TypeParameterSpec[] tparams, Func<T, TypeParameterInflator> inflatorFactory, T arg)
 
1157
                {
 
1158
                        TypeParameterSpec[] constraints = null;
 
1159
                        TypeParameterInflator? inflator = null;
 
1160
 
 
1161
                        for (int i = 0; i < tparams.Length; ++i) {
 
1162
                                var tp = tparams[i];
 
1163
                                if (tp.HasTypeConstraint || tp.InterfacesDefined != null || tp.TypeArguments != null) {
 
1164
                                        if (constraints == null) {
 
1165
                                                constraints = new TypeParameterSpec[tparams.Length];
 
1166
                                                Array.Copy (tparams, constraints, constraints.Length);
 
1167
                                        }
 
1168
 
 
1169
                                        //
 
1170
                                        // Using a factory to avoid possibly expensive inflator build up
 
1171
                                        //
 
1172
                                        if (inflator == null)
 
1173
                                                inflator = inflatorFactory (arg);
 
1174
 
 
1175
                                        constraints[i] = (TypeParameterSpec) constraints[i].InflateMember (inflator.Value);
 
1176
                                }
 
1177
                        }
 
1178
 
 
1179
                        if (constraints == null)
 
1180
                                constraints = tparams;
 
1181
 
 
1182
                        return constraints;
 
1183
                }
 
1184
 
 
1185
                public void InflateConstraints (TypeParameterInflator inflator, TypeParameterSpec tps)
 
1186
                {
 
1187
                        tps.BaseType = inflator.Inflate (BaseType);
 
1188
 
 
1189
                        var defined = InterfacesDefined;
 
1190
                        if (defined != null) {
 
1191
                                tps.ifaces_defined = new TypeSpec[defined.Length];
 
1192
                                for (int i = 0; i < defined.Length; ++i)
 
1193
                                        tps.ifaces_defined [i] = inflator.Inflate (defined[i]);
 
1194
                        }
 
1195
 
 
1196
                        var ifaces = Interfaces;
 
1197
                        if (ifaces != null) {
 
1198
                                tps.ifaces = new List<TypeSpec> (ifaces.Count);
 
1199
                                for (int i = 0; i < ifaces.Count; ++i)
 
1200
                                        tps.ifaces.Add (inflator.Inflate (ifaces[i]));
 
1201
                        }
 
1202
 
 
1203
                        if (targs != null) {
 
1204
                                tps.targs = new TypeSpec[targs.Length];
 
1205
                                for (int i = 0; i < targs.Length; ++i)
 
1206
                                        tps.targs[i] = inflator.Inflate (targs[i]);
 
1207
                        }
 
1208
                }
 
1209
 
 
1210
                public override MemberSpec InflateMember (TypeParameterInflator inflator)
 
1211
                {
 
1212
                        var tps = (TypeParameterSpec) MemberwiseClone ();
 
1213
                        InflateConstraints (inflator, tps);
 
1214
                        return tps;
 
1215
                }
 
1216
 
 
1217
                //
 
1218
                // Populates type parameter members using type parameter constraints
 
1219
                // The trick here is to be called late enough but not too late to
 
1220
                // populate member cache with all members from other types
 
1221
                //
 
1222
                protected override void InitializeMemberCache (bool onlyTypes)
 
1223
                {
 
1224
                        cache = new MemberCache ();
 
1225
 
 
1226
                        //
 
1227
                        // For a type parameter the membercache is the union of the sets of members of the types
 
1228
                        // specified as a primary constraint or secondary constraint
 
1229
                        //
 
1230
                        if (BaseType.BuiltinType != BuiltinTypeSpec.Type.Object && BaseType.BuiltinType != BuiltinTypeSpec.Type.ValueType)
 
1231
                                cache.AddBaseType (BaseType);
 
1232
 
 
1233
                        if (InterfacesDefined != null) {
 
1234
                                foreach (var iface_type in InterfacesDefined) {
 
1235
                                        cache.AddInterface (iface_type);
 
1236
                                }
 
1237
                        }
 
1238
 
 
1239
                        if (targs != null) {
 
1240
                                foreach (var ta in targs) {
 
1241
                                        var b_type = ta.BaseType;
 
1242
                                        if (b_type.BuiltinType != BuiltinTypeSpec.Type.Object && b_type.BuiltinType != BuiltinTypeSpec.Type.ValueType)
 
1243
                                                cache.AddBaseType (b_type);
 
1244
 
 
1245
                                        var tps = ta as TypeParameterSpec;
 
1246
                                        var ifaces = tps != null ? tps.InterfacesDefined : ta.Interfaces;
 
1247
 
 
1248
                                        if (ifaces != null) {
 
1249
                                                foreach (var iface_type in ifaces) {
 
1250
                                                        cache.AddInterface (iface_type);
 
1251
                                                }
 
1252
                                        }
 
1253
                                }
 
1254
                        }
 
1255
                }
 
1256
 
 
1257
                public bool IsConvertibleToInterface (TypeSpec iface)
 
1258
                {
 
1259
                        if (Interfaces != null) {
 
1260
                                foreach (var t in Interfaces) {
 
1261
                                        if (t == iface)
 
1262
                                                return true;
 
1263
                                }
 
1264
                        }
 
1265
 
 
1266
                        if (TypeArguments != null) {
 
1267
                                foreach (var t in TypeArguments) {
 
1268
                                        if (((TypeParameterSpec) t).IsConvertibleToInterface (iface))
 
1269
                                                return true;
 
1270
                                }
 
1271
                        }
 
1272
 
 
1273
                        return false;
 
1274
                }
 
1275
 
 
1276
                public static bool HasAnyTypeParameterTypeConstrained (IGenericMethodDefinition md)
 
1277
                {
 
1278
                        var tps = md.TypeParameters;
 
1279
                        for (int i = 0; i < md.TypeParametersCount; ++i) {
 
1280
                                if (tps[i].HasAnyTypeConstraint) {
 
1281
                                        return true;
 
1282
                                }
 
1283
                        }
 
1284
 
 
1285
                        return false;
 
1286
                }
 
1287
 
 
1288
                public static bool HasAnyTypeParameterConstrained (IGenericMethodDefinition md)
 
1289
                {
 
1290
                        var tps = md.TypeParameters;
 
1291
                        for (int i = 0; i < md.TypeParametersCount; ++i) {
 
1292
                                if (tps[i].IsConstrained) {
 
1293
                                        return true;
 
1294
                                }
 
1295
                        }
 
1296
 
 
1297
                        return false;
 
1298
                }
 
1299
 
 
1300
                public bool HasDependencyOn (TypeSpec type)
 
1301
                {
 
1302
                        if (TypeArguments != null) {
 
1303
                                foreach (var targ in TypeArguments) {
 
1304
                                        if (TypeSpecComparer.Override.IsEqual (targ, type))
 
1305
                                                return true;
 
1306
 
 
1307
                                        var tps = targ as TypeParameterSpec;
 
1308
                                        if (tps != null && tps.HasDependencyOn (type))
 
1309
                                                return true;
 
1310
                                }
 
1311
                        }
 
1312
 
 
1313
                        return false;
 
1314
                }
 
1315
 
 
1316
                public override TypeSpec Mutate (TypeParameterMutator mutator)
 
1317
                {
 
1318
                        return mutator.Mutate (this);
 
1319
                }
 
1320
        }
 
1321
 
 
1322
        public struct TypeParameterInflator
 
1323
        {
 
1324
                readonly TypeSpec type;
 
1325
                readonly TypeParameterSpec[] tparams;
 
1326
                readonly TypeSpec[] targs;
 
1327
                readonly IModuleContext context;
 
1328
 
 
1329
                public TypeParameterInflator (TypeParameterInflator nested, TypeSpec type)
 
1330
                        : this (nested.context, type, nested.tparams, nested.targs)
 
1331
                {
 
1332
                }
 
1333
 
 
1334
                public TypeParameterInflator (IModuleContext context, TypeSpec type, TypeParameterSpec[] tparams, TypeSpec[] targs)
 
1335
                {
 
1336
                        if (tparams.Length != targs.Length)
 
1337
                                throw new ArgumentException ("Invalid arguments");
 
1338
 
 
1339
                        this.context = context;
 
1340
                        this.tparams = tparams;
 
1341
                        this.targs = targs;
 
1342
                        this.type = type;
 
1343
                }
 
1344
 
 
1345
                #region Properties
 
1346
 
 
1347
                public IModuleContext Context {
 
1348
                        get {
 
1349
                                return context;
 
1350
                        }
 
1351
                }
 
1352
 
 
1353
                public TypeSpec TypeInstance {
 
1354
                        get {
 
1355
                                return type;
 
1356
                        }
 
1357
                }
 
1358
 
 
1359
                //
 
1360
                // Type parameters to inflate
 
1361
                //
 
1362
                public TypeParameterSpec[] TypeParameters {
 
1363
                        get {
 
1364
                                return tparams;
 
1365
                        }
 
1366
                }
 
1367
 
 
1368
                #endregion
 
1369
 
 
1370
                public TypeSpec Inflate (TypeSpec type)
 
1371
                {
 
1372
                        var tp = type as TypeParameterSpec;
 
1373
                        if (tp != null)
 
1374
                                return Inflate (tp);
 
1375
 
 
1376
                        var ac = type as ArrayContainer;
 
1377
                        if (ac != null) {
 
1378
                                var et = Inflate (ac.Element);
 
1379
                                if (et != ac.Element)
 
1380
                                        return ArrayContainer.MakeType (context.Module, et, ac.Rank);
 
1381
 
 
1382
                                return ac;
 
1383
                        }
 
1384
 
 
1385
                        //
 
1386
                        // When inflating a nested type, inflate its parent first
 
1387
                        // in case it's using same type parameters (was inflated within the type)
 
1388
                        //
 
1389
                        TypeSpec[] targs;
 
1390
                        int i = 0;
 
1391
                        if (type.IsNested) {
 
1392
                                var parent = Inflate (type.DeclaringType);
 
1393
 
 
1394
                                //
 
1395
                                // Keep the inflated type arguments
 
1396
                                // 
 
1397
                                targs = type.TypeArguments;
 
1398
 
 
1399
                                //
 
1400
                                // When inflating imported nested type used inside same declaring type, we get TypeSpec
 
1401
                                // because the import cache helps us to catch it. However, that means we have to look at
 
1402
                                // type definition to get type argument (they are in fact type parameter in this case)
 
1403
                                //
 
1404
                                if (targs.Length == 0 && type.Arity > 0)
 
1405
                                        targs = type.MemberDefinition.TypeParameters;
 
1406
 
 
1407
                                //
 
1408
                                // Parent was inflated, find the same type on inflated type
 
1409
                                // to use same cache for nested types on same generic parent
 
1410
                                //
 
1411
                                type = MemberCache.FindNestedType (parent, type.Name, type.Arity);
 
1412
 
 
1413
                                //
 
1414
                                // Handle the tricky case where parent shares local type arguments
 
1415
                                // which means inflating inflated type
 
1416
                                //
 
1417
                                // class Test<T> {
 
1418
                                //              public static Nested<T> Foo () { return null; }
 
1419
                                //
 
1420
                                //              public class Nested<U> {}
 
1421
                                //      }
 
1422
                                //
 
1423
                                //  return type of Test<string>.Foo() has to be Test<string>.Nested<string> 
 
1424
                                //
 
1425
                                if (targs.Length > 0) {
 
1426
                                        var inflated_targs = new TypeSpec[targs.Length];
 
1427
                                        for (; i < targs.Length; ++i)
 
1428
                                                inflated_targs[i] = Inflate (targs[i]);
 
1429
 
 
1430
                                        type = type.MakeGenericType (context, inflated_targs);
 
1431
                                }
 
1432
 
 
1433
                                return type;
 
1434
                        }
 
1435
 
 
1436
                        // Nothing to do for non-generic type
 
1437
                        if (type.Arity == 0)
 
1438
                                return type;
 
1439
 
 
1440
                        targs = new TypeSpec[type.Arity];
 
1441
 
 
1442
                        //
 
1443
                        // Inflating using outside type arguments, var v = new Foo<int> (), class Foo<T> {}
 
1444
                        //
 
1445
                        if (type is InflatedTypeSpec) {
 
1446
                                for (; i < targs.Length; ++i)
 
1447
                                        targs[i] = Inflate (type.TypeArguments[i]);
 
1448
 
 
1449
                                type = type.GetDefinition ();
 
1450
                        } else {
 
1451
                                //
 
1452
                                // Inflating parent using inside type arguments, class Foo<T> { ITest<T> foo; }
 
1453
                                //
 
1454
                                var args = type.MemberDefinition.TypeParameters;
 
1455
                                foreach (var ds_tp in args)
 
1456
                                        targs[i++] = Inflate (ds_tp);
 
1457
                        }
 
1458
 
 
1459
                        return type.MakeGenericType (context, targs);
 
1460
                }
 
1461
 
 
1462
                public TypeSpec Inflate (TypeParameterSpec tp)
 
1463
                {
 
1464
                        for (int i = 0; i < tparams.Length; ++i)
 
1465
                                if (tparams [i] == tp)
 
1466
                                        return targs[i];
 
1467
 
 
1468
                        // This can happen when inflating nested types
 
1469
                        // without type arguments specified
 
1470
                        return tp;
 
1471
                }
 
1472
        }
 
1473
 
 
1474
        //
 
1475
        // Before emitting any code we have to change all MVAR references to VAR
 
1476
        // when the method is of generic type and has hoisted variables
 
1477
        //
 
1478
        public class TypeParameterMutator
 
1479
        {
 
1480
                readonly TypeParameters mvar;
 
1481
                readonly TypeParameters var;
 
1482
                readonly TypeParameterSpec[] src;
 
1483
                Dictionary<TypeSpec, TypeSpec> mutated_typespec;
 
1484
 
 
1485
                public TypeParameterMutator (TypeParameters mvar, TypeParameters var)
 
1486
                {
 
1487
                        if (mvar.Count != var.Count)
 
1488
                                throw new ArgumentException ();
 
1489
 
 
1490
                        this.mvar = mvar;
 
1491
                        this.var = var;
 
1492
                }
 
1493
 
 
1494
                public TypeParameterMutator (TypeParameterSpec[] srcVar, TypeParameters destVar)
 
1495
                {
 
1496
                        if (srcVar.Length != destVar.Count)
 
1497
                                throw new ArgumentException ();
 
1498
 
 
1499
                        this.src = srcVar;
 
1500
                        this.var = destVar;
 
1501
                }
 
1502
 
 
1503
                #region Properties
 
1504
 
 
1505
                public TypeParameters MethodTypeParameters {
 
1506
                        get {
 
1507
                                return mvar;
 
1508
                        }
 
1509
                }
 
1510
 
 
1511
                #endregion
 
1512
 
 
1513
                public static TypeSpec GetMemberDeclaringType (TypeSpec type)
 
1514
                {
 
1515
                        if (type is InflatedTypeSpec) {
 
1516
                                if (type.DeclaringType == null)
 
1517
                                        return type.GetDefinition ();
 
1518
 
 
1519
                                var parent = GetMemberDeclaringType (type.DeclaringType);
 
1520
                                type = MemberCache.GetMember<TypeSpec> (parent, type);
 
1521
                        }
 
1522
 
 
1523
                        return type;
 
1524
                }
 
1525
 
 
1526
                public TypeSpec Mutate (TypeSpec ts)
 
1527
                {
 
1528
                        TypeSpec value;
 
1529
                        if (mutated_typespec != null && mutated_typespec.TryGetValue (ts, out value))
 
1530
                                return value;
 
1531
 
 
1532
                        value = ts.Mutate (this);
 
1533
                        if (mutated_typespec == null)
 
1534
                                mutated_typespec = new Dictionary<TypeSpec, TypeSpec> ();
 
1535
 
 
1536
                        mutated_typespec.Add (ts, value);
 
1537
                        return value;
 
1538
                }
 
1539
 
 
1540
                public TypeParameterSpec Mutate (TypeParameterSpec tp)
 
1541
                {
 
1542
                        if (mvar != null) {
 
1543
                                for (int i = 0; i < mvar.Count; ++i) {
 
1544
                                        if (mvar[i].Type == tp)
 
1545
                                                return var[i].Type;
 
1546
                                }
 
1547
                        } else {
 
1548
                                for (int i = 0; i < src.Length; ++i) {
 
1549
                                        if (src[i] == tp)
 
1550
                                                return var[i].Type;
 
1551
                                }
 
1552
                        }
 
1553
 
 
1554
                        return tp;
 
1555
                }
 
1556
 
 
1557
                public TypeSpec[] Mutate (TypeSpec[] targs)
 
1558
                {
 
1559
                        TypeSpec[] mutated = new TypeSpec[targs.Length];
 
1560
                        bool changed = false;
 
1561
                        for (int i = 0; i < targs.Length; ++i) {
 
1562
                                mutated[i] = Mutate (targs[i]);
 
1563
                                changed |= targs[i] != mutated[i];
 
1564
                        }
 
1565
 
 
1566
                        return changed ? mutated : targs;
 
1567
                }
 
1568
        }
 
1569
 
 
1570
        /// <summary>
 
1571
        ///   A TypeExpr which already resolved to a type parameter.
 
1572
        /// </summary>
 
1573
        public class TypeParameterExpr : TypeExpression
 
1574
        {
 
1575
                public TypeParameterExpr (TypeParameter type_parameter, Location loc)
 
1576
                        : base (type_parameter.Type, loc)
 
1577
                {
 
1578
                        this.eclass = ExprClass.TypeParameter;
 
1579
                }
 
1580
        }
 
1581
 
 
1582
        public class InflatedTypeSpec : TypeSpec
 
1583
        {
 
1584
                TypeSpec[] targs;
 
1585
                TypeParameterSpec[] constraints;
 
1586
                readonly TypeSpec open_type;
 
1587
                readonly IModuleContext context;
 
1588
 
 
1589
                public InflatedTypeSpec (IModuleContext context, TypeSpec openType, TypeSpec declaringType, TypeSpec[] targs)
 
1590
                        : base (openType.Kind, declaringType, openType.MemberDefinition, null, openType.Modifiers)
 
1591
                {
 
1592
                        if (targs == null)
 
1593
                                throw new ArgumentNullException ("targs");
 
1594
 
 
1595
                        this.state &= ~SharedStateFlags;
 
1596
                        this.state |= (openType.state & SharedStateFlags);
 
1597
 
 
1598
                        this.context = context;
 
1599
                        this.open_type = openType;
 
1600
                        this.targs = targs;
 
1601
 
 
1602
                        foreach (var arg in targs) {
 
1603
                                if (arg.HasDynamicElement || arg.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
1604
                                        state |= StateFlags.HasDynamicElement;
 
1605
                                        break;
 
1606
                                }
 
1607
                        }
 
1608
 
 
1609
                        if (open_type.Kind == MemberKind.MissingType)
 
1610
                                MemberCache = MemberCache.Empty;
 
1611
 
 
1612
                        if ((open_type.Modifiers & Modifiers.COMPILER_GENERATED) != 0)
 
1613
                                state |= StateFlags.ConstraintsChecked;
 
1614
                }
 
1615
 
 
1616
                #region Properties
 
1617
 
 
1618
                public override TypeSpec BaseType {
 
1619
                        get {
 
1620
                                if (cache == null || (state & StateFlags.PendingBaseTypeInflate) != 0)
 
1621
                                        InitializeMemberCache (true);
 
1622
 
 
1623
                                return base.BaseType;
 
1624
                        }
 
1625
                }
 
1626
 
 
1627
                //
 
1628
                // Inflated type parameters with constraints array, mapping with type arguments is based on index
 
1629
                //
 
1630
                public TypeParameterSpec[] Constraints {
 
1631
                        get {
 
1632
                                if (constraints == null) {
 
1633
                                        constraints = TypeParameterSpec.InflateConstraints (MemberDefinition.TypeParameters, l => l.CreateLocalInflator (context), this);
 
1634
                                }
 
1635
 
 
1636
                                return constraints;
 
1637
                        }
 
1638
                }
 
1639
 
 
1640
                //
 
1641
                // Used to cache expensive constraints validation on constructed types
 
1642
                //
 
1643
                public bool HasConstraintsChecked {
 
1644
                        get {
 
1645
                                return (state & StateFlags.ConstraintsChecked) != 0;
 
1646
                        }
 
1647
                        set {
 
1648
                                state = value ? state | StateFlags.ConstraintsChecked : state & ~StateFlags.ConstraintsChecked;
 
1649
                        }
 
1650
                }
 
1651
 
 
1652
                public override IList<TypeSpec> Interfaces {
 
1653
                        get {
 
1654
                                if (cache == null)
 
1655
                                        InitializeMemberCache (true);
 
1656
 
 
1657
                                return base.Interfaces;
 
1658
                        }
 
1659
                }
 
1660
 
 
1661
                public override bool IsExpressionTreeType {
 
1662
                        get {
 
1663
                                return (open_type.state & StateFlags.InflatedExpressionType) != 0;
 
1664
                        }
 
1665
                }
 
1666
 
 
1667
                public override bool IsGenericIterateInterface {
 
1668
                        get {
 
1669
                                return (open_type.state & StateFlags.GenericIterateInterface) != 0;
 
1670
                        }
 
1671
                }
 
1672
 
 
1673
                public override bool IsGenericTask {
 
1674
                        get {
 
1675
                                return (open_type.state & StateFlags.GenericTask) != 0;
 
1676
                        }
 
1677
                }
 
1678
 
 
1679
                public override bool IsNullableType {
 
1680
                        get {
 
1681
                                return (open_type.state & StateFlags.InflatedNullableType) != 0;
 
1682
                        }
 
1683
                }
 
1684
 
 
1685
                //
 
1686
                // Types used to inflate the generic  type
 
1687
                //
 
1688
                public override TypeSpec[] TypeArguments {
 
1689
                        get {
 
1690
                                return targs;
 
1691
                        }
 
1692
                }
 
1693
 
 
1694
                #endregion
 
1695
 
 
1696
                public override bool AddInterface (TypeSpec iface)
 
1697
                {
 
1698
                        var inflator = CreateLocalInflator (context);
 
1699
                        iface = inflator.Inflate (iface);
 
1700
                        if (iface == null)
 
1701
                                return false;
 
1702
 
 
1703
                        return base.AddInterface (iface);
 
1704
                }
 
1705
 
 
1706
                public static bool ContainsTypeParameter (TypeSpec type)
 
1707
                {
 
1708
                        if (type.Kind == MemberKind.TypeParameter)
 
1709
                                return true;
 
1710
 
 
1711
                        var element_container = type as ElementTypeSpec;
 
1712
                        if (element_container != null)
 
1713
                                return ContainsTypeParameter (element_container.Element);
 
1714
 
 
1715
                        foreach (var t in type.TypeArguments) {
 
1716
                                if (ContainsTypeParameter (t)) {
 
1717
                                        return true;
 
1718
                                }
 
1719
                        }
 
1720
 
 
1721
                        return false;
 
1722
                }
 
1723
 
 
1724
                TypeParameterInflator CreateLocalInflator (IModuleContext context)
 
1725
                {
 
1726
                        TypeParameterSpec[] tparams_full;
 
1727
                        TypeSpec[] targs_full = targs;
 
1728
                        if (IsNested) {
 
1729
                                //
 
1730
                                // Special case is needed when we are inflating an open type (nested type definition)
 
1731
                                // on inflated parent. Consider following case
 
1732
                                //
 
1733
                                // Foo<T>.Bar<U> => Foo<string>.Bar<U>
 
1734
                                //
 
1735
                                // Any later inflation of Foo<string>.Bar<U> has to also inflate T if used inside Bar<U>
 
1736
                                //
 
1737
                                List<TypeSpec> merged_targs = null;
 
1738
                                List<TypeParameterSpec> merged_tparams = null;
 
1739
 
 
1740
                                var type = DeclaringType;
 
1741
 
 
1742
                                do {
 
1743
                                        if (type.TypeArguments.Length > 0) {
 
1744
                                                if (merged_targs == null) {
 
1745
                                                        merged_targs = new List<TypeSpec> ();
 
1746
                                                        merged_tparams = new List<TypeParameterSpec> ();
 
1747
                                                        if (targs.Length > 0) {
 
1748
                                                                merged_targs.AddRange (targs);
 
1749
                                                                merged_tparams.AddRange (open_type.MemberDefinition.TypeParameters);
 
1750
                                                        }
 
1751
                                                }
 
1752
                                                merged_tparams.AddRange (type.MemberDefinition.TypeParameters);
 
1753
                                                merged_targs.AddRange (type.TypeArguments);
 
1754
                                        }
 
1755
                                        type = type.DeclaringType;
 
1756
                                } while (type != null);
 
1757
 
 
1758
                                if (merged_targs != null) {
 
1759
                                        // Type arguments are not in the right order but it should not matter in this case
 
1760
                                        targs_full = merged_targs.ToArray ();
 
1761
                                        tparams_full = merged_tparams.ToArray ();
 
1762
                                } else if (targs.Length == 0) {
 
1763
                                        tparams_full = TypeParameterSpec.EmptyTypes;
 
1764
                                } else {
 
1765
                                        tparams_full = open_type.MemberDefinition.TypeParameters;
 
1766
                                }
 
1767
                        } else if (targs.Length == 0) {
 
1768
                                tparams_full = TypeParameterSpec.EmptyTypes;
 
1769
                        } else {
 
1770
                                tparams_full = open_type.MemberDefinition.TypeParameters;
 
1771
                        }
 
1772
 
 
1773
                        return new TypeParameterInflator (context, this, tparams_full, targs_full);
 
1774
                }
 
1775
 
 
1776
                MetaType CreateMetaInfo (TypeParameterMutator mutator)
 
1777
                {
 
1778
                        //
 
1779
                        // Converts nested type arguments into right order
 
1780
                        // Foo<string, bool>.Bar<int> => string, bool, int
 
1781
                        //
 
1782
                        var all = new List<MetaType> ();
 
1783
                        TypeSpec type = this;
 
1784
                        TypeSpec definition = type;
 
1785
                        do {
 
1786
                                if (type.GetDefinition().IsGeneric) {
 
1787
                                        all.InsertRange (0,
 
1788
                                                type.TypeArguments != TypeSpec.EmptyTypes ?
 
1789
                                                type.TypeArguments.Select (l => l.GetMetaInfo ()) :
 
1790
                                                type.MemberDefinition.TypeParameters.Select (l => l.GetMetaInfo ()));
 
1791
                                }
 
1792
 
 
1793
                                definition = definition.GetDefinition ();
 
1794
                                type = type.DeclaringType;
 
1795
                        } while (type != null);
 
1796
 
 
1797
                        return definition.GetMetaInfo ().MakeGenericType (all.ToArray ());
 
1798
                }
 
1799
 
 
1800
                public override ObsoleteAttribute GetAttributeObsolete ()
 
1801
                {
 
1802
                        return open_type.GetAttributeObsolete ();
 
1803
                }
 
1804
 
 
1805
                protected override bool IsNotCLSCompliant (out bool attrValue)
 
1806
                {
 
1807
                        if (base.IsNotCLSCompliant (out attrValue))
 
1808
                                return true;
 
1809
 
 
1810
                        foreach (var ta in TypeArguments) {
 
1811
                                if (ta.MemberDefinition.CLSAttributeValue == false)
 
1812
                                        return true;
 
1813
                        }
 
1814
 
 
1815
                        return false;
 
1816
                }
 
1817
 
 
1818
                public override TypeSpec GetDefinition ()
 
1819
                {
 
1820
                        return open_type;
 
1821
                }
 
1822
 
 
1823
                public override MetaType GetMetaInfo ()
 
1824
                {
 
1825
                        if (info == null)
 
1826
                                info = CreateMetaInfo (null);
 
1827
 
 
1828
                        return info;
 
1829
                }
 
1830
 
 
1831
                public override string GetSignatureForError ()
 
1832
                {
 
1833
                        if (IsNullableType)
 
1834
                                return targs[0].GetSignatureForError () + "?";
 
1835
 
 
1836
                        return base.GetSignatureForError ();
 
1837
                }
 
1838
 
 
1839
                protected override string GetTypeNameSignature ()
 
1840
                {
 
1841
                        if (targs.Length == 0 || MemberDefinition is AnonymousTypeClass)
 
1842
                                return null;
 
1843
 
 
1844
                        return "<" + TypeManager.CSharpName (targs) + ">";
 
1845
                }
 
1846
 
 
1847
                public bool HasDynamicArgument ()
 
1848
                {
 
1849
                        for (int i = 0; i < targs.Length; ++i) {
 
1850
                                var item = targs[i];
 
1851
 
 
1852
                                if (item.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
 
1853
                                        return true;
 
1854
 
 
1855
                                if (item is InflatedTypeSpec) {
 
1856
                                        if (((InflatedTypeSpec) item).HasDynamicArgument ())
 
1857
                                                return true;
 
1858
 
 
1859
                                        continue;
 
1860
                                }
 
1861
 
 
1862
                                if (item.IsArray) {
 
1863
                                        while (item.IsArray) {
 
1864
                                                item = ((ArrayContainer) item).Element;
 
1865
                                        }
 
1866
 
 
1867
                                        if (item.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
 
1868
                                                return true;
 
1869
                                }
 
1870
                        }
 
1871
 
 
1872
                        return false;
 
1873
                }
 
1874
 
 
1875
                protected override void InitializeMemberCache (bool onlyTypes)
 
1876
                {
 
1877
                        if (cache == null) {
 
1878
                                var open_cache = onlyTypes ? open_type.MemberCacheTypes : open_type.MemberCache;
 
1879
 
 
1880
                                // Surprisingly, calling MemberCache on open type could meantime create cache on this type
 
1881
                                // for imported type parameter constraints referencing nested type of this declaration
 
1882
                                if (cache == null)
 
1883
                                        cache = new MemberCache (open_cache);
 
1884
                        }
 
1885
 
 
1886
                        var inflator = CreateLocalInflator (context);
 
1887
 
 
1888
                        //
 
1889
                        // Two stage inflate due to possible nested types recursive
 
1890
                        // references
 
1891
                        //
 
1892
                        // class A<T> {
 
1893
                        //    B b;
 
1894
                        //    class B {
 
1895
                        //      T Value;
 
1896
                        //    }
 
1897
                        // }
 
1898
                        //
 
1899
                        // When resolving type of `b' members of `B' cannot be 
 
1900
                        // inflated because are not yet available in membercache
 
1901
                        //
 
1902
                        if ((state & StateFlags.PendingMemberCacheMembers) == 0) {
 
1903
                                open_type.MemberCacheTypes.InflateTypes (cache, inflator);
 
1904
 
 
1905
                                //
 
1906
                                // Inflate any implemented interfaces
 
1907
                                //
 
1908
                                if (open_type.Interfaces != null) {
 
1909
                                        ifaces = new List<TypeSpec> (open_type.Interfaces.Count);
 
1910
                                        foreach (var iface in open_type.Interfaces) {
 
1911
                                                var iface_inflated = inflator.Inflate (iface);
 
1912
                                                if (iface_inflated == null)
 
1913
                                                        continue;
 
1914
 
 
1915
                                                base.AddInterface (iface_inflated);
 
1916
                                        }
 
1917
                                }
 
1918
 
 
1919
                                //
 
1920
                                // Handles the tricky case of recursive nested base generic type
 
1921
                                //
 
1922
                                // class A<T> : Base<A<T>.Nested> {
 
1923
                                //    class Nested {}
 
1924
                                // }
 
1925
                                //
 
1926
                                // When inflating A<T>. base type is not yet known, secondary
 
1927
                                // inflation is required (not common case) once base scope
 
1928
                                // is known
 
1929
                                //
 
1930
                                if (open_type.BaseType == null) {
 
1931
                                        if (IsClass)
 
1932
                                                state |= StateFlags.PendingBaseTypeInflate;
 
1933
                                } else {
 
1934
                                        BaseType = inflator.Inflate (open_type.BaseType);
 
1935
                                }
 
1936
                        } else if ((state & StateFlags.PendingBaseTypeInflate) != 0) {
 
1937
                                //
 
1938
                                // It can happen when resolving base type without being defined
 
1939
                                // which is not allowed to happen and will always lead to an error
 
1940
                                //
 
1941
                                // class B { class N {} }
 
1942
                                // class A<T> : A<B.N> {}
 
1943
                                //
 
1944
                                if (open_type.BaseType == null)
 
1945
                                        return;
 
1946
 
 
1947
                                BaseType = inflator.Inflate (open_type.BaseType);
 
1948
                                state &= ~StateFlags.PendingBaseTypeInflate;
 
1949
                        }
 
1950
 
 
1951
                        if (onlyTypes) {
 
1952
                                state |= StateFlags.PendingMemberCacheMembers;
 
1953
                                return;
 
1954
                        }
 
1955
 
 
1956
                        var tc = open_type.MemberDefinition as TypeDefinition;
 
1957
                        if (tc != null && !tc.HasMembersDefined) {
 
1958
                                //
 
1959
                                // Inflating MemberCache with undefined members
 
1960
                                //
 
1961
                                return;
 
1962
                        }
 
1963
 
 
1964
                        if ((state & StateFlags.PendingBaseTypeInflate) != 0) {
 
1965
                                BaseType = inflator.Inflate (open_type.BaseType);
 
1966
                                state &= ~StateFlags.PendingBaseTypeInflate;
 
1967
                        }
 
1968
 
 
1969
                        state &= ~StateFlags.PendingMemberCacheMembers;
 
1970
                        open_type.MemberCache.InflateMembers (cache, open_type, inflator);
 
1971
                }
 
1972
 
 
1973
                public override TypeSpec Mutate (TypeParameterMutator mutator)
 
1974
                {
 
1975
                        var targs = TypeArguments;
 
1976
                        if (targs != null)
 
1977
                                targs = mutator.Mutate (targs);
 
1978
 
 
1979
                        var decl = DeclaringType;
 
1980
                        if (IsNested && DeclaringType.IsGenericOrParentIsGeneric)
 
1981
                                decl = mutator.Mutate (decl);
 
1982
 
 
1983
                        if (targs == TypeArguments && decl == DeclaringType)
 
1984
                                return this;
 
1985
 
 
1986
                        var mutated = (InflatedTypeSpec) MemberwiseClone ();
 
1987
                        if (decl != DeclaringType) {
 
1988
                                // Gets back MethodInfo in case of metaInfo was inflated
 
1989
                                //mutated.info = MemberCache.GetMember<TypeSpec> (DeclaringType.GetDefinition (), this).info;
 
1990
 
 
1991
                                mutated.declaringType = decl;
 
1992
                                mutated.state |= StateFlags.PendingMetaInflate;
 
1993
                        }
 
1994
 
 
1995
                        if (targs != null) {
 
1996
                                mutated.targs = targs;
 
1997
                                mutated.info = null;
 
1998
                        }
 
1999
 
 
2000
                        return mutated;
 
2001
                }
 
2002
        }
 
2003
 
 
2004
 
 
2005
        //
 
2006
        // Tracks the type arguments when instantiating a generic type. It's used
 
2007
        // by both type arguments and type parameters
 
2008
        //
 
2009
        public class TypeArguments
 
2010
        {
 
2011
                List<FullNamedExpression> args;
 
2012
                TypeSpec[] atypes;
 
2013
 
 
2014
                public List<FullNamedExpression> Args {
 
2015
                        get { return this.args; }
 
2016
                }
 
2017
 
 
2018
                public TypeArguments (params FullNamedExpression[] types)
 
2019
                {
 
2020
                        this.args = new List<FullNamedExpression> (types);
 
2021
                }
 
2022
 
 
2023
                public void Add (FullNamedExpression type)
 
2024
                {
 
2025
                        args.Add (type);
 
2026
                }
 
2027
 
 
2028
                /// <summary>
 
2029
                ///   We may only be used after Resolve() is called and return the fully
 
2030
                ///   resolved types.
 
2031
                /// </summary>
 
2032
                // TODO: Not needed, just return type from resolve
 
2033
                public TypeSpec[] Arguments {
 
2034
                        get {
 
2035
                                return atypes;
 
2036
                        }
 
2037
                        set {
 
2038
                                atypes = value;
 
2039
                        }
 
2040
                }
 
2041
 
 
2042
                public int Count {
 
2043
                        get {
 
2044
                                return args.Count;
 
2045
                        }
 
2046
                }
 
2047
 
 
2048
                public virtual bool IsEmpty {
 
2049
                        get {
 
2050
                                return false;
 
2051
                        }
 
2052
                }
 
2053
 
 
2054
                public List<FullNamedExpression> TypeExpressions {
 
2055
                        get {
 
2056
                                return this.args;
 
2057
                        }
 
2058
                }
 
2059
 
 
2060
                public string GetSignatureForError()
 
2061
                {
 
2062
                        StringBuilder sb = new StringBuilder ();
 
2063
                        for (int i = 0; i < Count; ++i) {
 
2064
                                var expr = args[i];
 
2065
                                if (expr != null)
 
2066
                                        sb.Append (expr.GetSignatureForError ());
 
2067
 
 
2068
                                if (i + 1 < Count)
 
2069
                                        sb.Append (',');
 
2070
                        }
 
2071
 
 
2072
                        return sb.ToString ();
 
2073
                }
 
2074
 
 
2075
                /// <summary>
 
2076
                ///   Resolve the type arguments.
 
2077
                /// </summary>
 
2078
                public virtual bool Resolve (IMemberContext ec)
 
2079
                {
 
2080
                        if (atypes != null)
 
2081
                            return atypes.Length != 0;
 
2082
 
 
2083
                        int count = args.Count;
 
2084
                        bool ok = true;
 
2085
 
 
2086
                        atypes = new TypeSpec [count];
 
2087
 
 
2088
                        for (int i = 0; i < count; i++){
 
2089
                                var te = args[i].ResolveAsType (ec);
 
2090
                                if (te == null) {
 
2091
                                        ok = false;
 
2092
                                        continue;
 
2093
                                }
 
2094
 
 
2095
                                atypes[i] = te;
 
2096
 
 
2097
                                if (te.IsStatic) {
 
2098
                                        ec.Module.Compiler.Report.Error (718, args[i].Location, "`{0}': static classes cannot be used as generic arguments",
 
2099
                                                te.GetSignatureForError ());
 
2100
                                        ok = false;
 
2101
                                }
 
2102
 
 
2103
                                if (te.IsPointer || te.IsSpecialRuntimeType) {
 
2104
                                        ec.Module.Compiler.Report.Error (306, args[i].Location,
 
2105
                                                "The type `{0}' may not be used as a type argument",
 
2106
                                                te.GetSignatureForError ());
 
2107
                                        ok = false;
 
2108
                                }
 
2109
                        }
 
2110
 
 
2111
                        if (!ok)
 
2112
                                atypes = TypeSpec.EmptyTypes;
 
2113
 
 
2114
                        return ok;
 
2115
                }
 
2116
 
 
2117
                public TypeArguments Clone ()
 
2118
                {
 
2119
                        TypeArguments copy = new TypeArguments ();
 
2120
                        foreach (var ta in args)
 
2121
                                copy.args.Add (ta);
 
2122
 
 
2123
                        return copy;
 
2124
                }
 
2125
        }
 
2126
 
 
2127
        public class UnboundTypeArguments : TypeArguments
 
2128
        {
 
2129
                public UnboundTypeArguments (int arity)
 
2130
                        : base (new FullNamedExpression[arity])
 
2131
                {
 
2132
                }
 
2133
 
 
2134
                public override bool IsEmpty {
 
2135
                        get {
 
2136
                                return true;
 
2137
                        }
 
2138
                }
 
2139
 
 
2140
                public override bool Resolve (IMemberContext ec)
 
2141
                {
 
2142
                        // Nothing to be resolved
 
2143
                        return true;
 
2144
                }
 
2145
        }
 
2146
 
 
2147
        public class TypeParameters
 
2148
        {
 
2149
                List<TypeParameter> names;
 
2150
                TypeParameterSpec[] types;
 
2151
 
 
2152
                public TypeParameters ()
 
2153
                {
 
2154
                        names = new List<TypeParameter> ();
 
2155
                }
 
2156
 
 
2157
                public TypeParameters (int count)
 
2158
                {
 
2159
                        names = new List<TypeParameter> (count);
 
2160
                }
 
2161
 
 
2162
                #region Properties
 
2163
 
 
2164
                public int Count {
 
2165
                        get {
 
2166
                                return names.Count;
 
2167
                        }
 
2168
                }
 
2169
 
 
2170
                public TypeParameterSpec[] Types {
 
2171
                        get {
 
2172
                                return types;
 
2173
                        }
 
2174
                }
 
2175
 
 
2176
                #endregion
 
2177
 
 
2178
                public void Add (TypeParameter tparam)
 
2179
                {
 
2180
                        names.Add (tparam);
 
2181
                }
 
2182
 
 
2183
                public void Add (TypeParameters tparams)
 
2184
                {
 
2185
                        names.AddRange (tparams.names);
 
2186
                }
 
2187
 
 
2188
                public void Define (GenericTypeParameterBuilder[] buiders, TypeSpec declaringType, int parentOffset, TypeContainer parent)
 
2189
                {
 
2190
                        types = new TypeParameterSpec[Count];
 
2191
                        for (int i = 0; i < types.Length; ++i) {
 
2192
                                var tp = names[i];
 
2193
 
 
2194
                                tp.Define (buiders[i + parentOffset], declaringType, parent);
 
2195
                                types[i] = tp.Type;
 
2196
                                types[i].DeclaredPosition = i + parentOffset;
 
2197
 
 
2198
                                if (tp.Variance != Variance.None && !(declaringType != null && (declaringType.Kind == MemberKind.Interface || declaringType.Kind == MemberKind.Delegate))) {
 
2199
                                        parent.Compiler.Report.Error (1960, tp.Location, "Variant type parameters can only be used with interfaces and delegates");
 
2200
                                }
 
2201
                        }
 
2202
                }
 
2203
 
 
2204
                public TypeParameter this[int index] {
 
2205
                        get {
 
2206
                                return names [index];
 
2207
                        }
 
2208
                        set {
 
2209
                                names[index] = value;
 
2210
                        }
 
2211
                }
 
2212
 
 
2213
                public TypeParameter Find (string name)
 
2214
                {
 
2215
                        foreach (var tp in names) {
 
2216
                                if (tp.Name == name)
 
2217
                                        return tp;
 
2218
                        }
 
2219
 
 
2220
                        return null;
 
2221
                }
 
2222
 
 
2223
                public string[] GetAllNames ()
 
2224
                {
 
2225
                        return names.Select (l => l.Name).ToArray ();
 
2226
                }
 
2227
 
 
2228
                public string GetSignatureForError ()
 
2229
                {
 
2230
                        StringBuilder sb = new StringBuilder ();
 
2231
                        for (int i = 0; i < Count; ++i) {
 
2232
                                if (i > 0)
 
2233
                                        sb.Append (',');
 
2234
 
 
2235
                                var name = names[i];
 
2236
                                if (name != null)
 
2237
                                        sb.Append (name.GetSignatureForError ());
 
2238
                        }
 
2239
 
 
2240
                        return sb.ToString ();
 
2241
                }
 
2242
 
 
2243
                public void VerifyClsCompliance ()
 
2244
                {
 
2245
                        foreach (var tp in names) {
 
2246
                                tp.VerifyClsCompliance ();
 
2247
                        }
 
2248
                }
 
2249
        }
 
2250
 
 
2251
        //
 
2252
        // A type expression of generic type with type arguments
 
2253
        //
 
2254
        class GenericTypeExpr : TypeExpr
 
2255
        {
 
2256
                TypeArguments args;
 
2257
                TypeSpec open_type;
 
2258
 
 
2259
                /// <summary>
 
2260
                ///   Instantiate the generic type `t' with the type arguments `args'.
 
2261
                ///   Use this constructor if you already know the fully resolved
 
2262
                ///   generic type.
 
2263
                /// </summary>          
 
2264
                public GenericTypeExpr (TypeSpec open_type, TypeArguments args, Location l)
 
2265
                {
 
2266
                        this.open_type = open_type;
 
2267
                        loc = l;
 
2268
                        this.args = args;
 
2269
                }
 
2270
 
 
2271
                public override string GetSignatureForError ()
 
2272
                {
 
2273
                        return TypeManager.CSharpName (type);
 
2274
                }
 
2275
 
 
2276
                public override TypeSpec ResolveAsType (IMemberContext mc)
 
2277
                {
 
2278
                        if (eclass != ExprClass.Unresolved)
 
2279
                                return type;
 
2280
 
 
2281
                        if (!args.Resolve (mc))
 
2282
                                return null;
 
2283
 
 
2284
                        TypeSpec[] atypes = args.Arguments;
 
2285
 
 
2286
                        //
 
2287
                        // Now bind the parameters
 
2288
                        //
 
2289
                        var inflated = open_type.MakeGenericType (mc, atypes);
 
2290
                        type = inflated;
 
2291
                        eclass = ExprClass.Type;
 
2292
 
 
2293
                        //
 
2294
                        // The constraints can be checked only when full type hierarchy is known
 
2295
                        //
 
2296
                        if (!inflated.HasConstraintsChecked && mc.Module.HasTypesFullyDefined) {
 
2297
                                var constraints = inflated.Constraints;
 
2298
                                if (constraints != null) {
 
2299
                                        var cc = new ConstraintChecker (mc);
 
2300
                                        if (cc.CheckAll (open_type, atypes, constraints, loc)) {
 
2301
                                                inflated.HasConstraintsChecked = true;
 
2302
                                        }
 
2303
                                }
 
2304
                        }
 
2305
 
 
2306
                        return type;
 
2307
                }
 
2308
 
 
2309
                public override bool Equals (object obj)
 
2310
                {
 
2311
                        GenericTypeExpr cobj = obj as GenericTypeExpr;
 
2312
                        if (cobj == null)
 
2313
                                return false;
 
2314
 
 
2315
                        if ((type == null) || (cobj.type == null))
 
2316
                                return false;
 
2317
 
 
2318
                        return type == cobj.type;
 
2319
                }
 
2320
 
 
2321
                public override int GetHashCode ()
 
2322
                {
 
2323
                        return base.GetHashCode ();
 
2324
                }
 
2325
        }
 
2326
 
 
2327
        //
 
2328
        // Generic type with unbound type arguments, used for typeof (G<,,>)
 
2329
        //
 
2330
        class GenericOpenTypeExpr : TypeExpression
 
2331
        {
 
2332
                public GenericOpenTypeExpr (TypeSpec type, /*UnboundTypeArguments args,*/ Location loc)
 
2333
                        : base (type.GetDefinition (), loc)
 
2334
                {
 
2335
                }
 
2336
        }
 
2337
 
 
2338
        struct ConstraintChecker
 
2339
        {
 
2340
                IMemberContext mc;
 
2341
                bool recursive_checks;
 
2342
 
 
2343
                public ConstraintChecker (IMemberContext ctx)
 
2344
                {
 
2345
                        this.mc = ctx;
 
2346
                        recursive_checks = false;
 
2347
                }
 
2348
 
 
2349
                //
 
2350
                // Checks the constraints of open generic type against type
 
2351
                // arguments. This version is used for types which could not be
 
2352
                // checked immediatelly during construction because the type
 
2353
                // hierarchy was not yet fully setup (before Emit phase)
 
2354
                //
 
2355
                public static bool Check (IMemberContext mc, TypeSpec type, Location loc)
 
2356
                {
 
2357
                        //
 
2358
                        // Check declaring type first if there is any
 
2359
                        //
 
2360
                        if (type.DeclaringType != null && !Check (mc, type.DeclaringType, loc))
 
2361
                                return false;
 
2362
 
 
2363
                        while (type is ElementTypeSpec)
 
2364
                                type = ((ElementTypeSpec) type).Element;
 
2365
 
 
2366
                        if (type.Arity == 0)
 
2367
                                return true;
 
2368
 
 
2369
                        var gtype = type as InflatedTypeSpec;
 
2370
                        if (gtype == null)
 
2371
                                return true;
 
2372
 
 
2373
                        var constraints = gtype.Constraints;
 
2374
                        if (constraints == null)
 
2375
                                return true;
 
2376
 
 
2377
                        if (gtype.HasConstraintsChecked)
 
2378
                                return true;
 
2379
 
 
2380
                        var cc = new ConstraintChecker (mc);
 
2381
                        cc.recursive_checks = true;
 
2382
 
 
2383
                        if (cc.CheckAll (gtype.GetDefinition (), type.TypeArguments, constraints, loc)) {
 
2384
                                gtype.HasConstraintsChecked = true;
 
2385
                                return true;
 
2386
                        }
 
2387
 
 
2388
                        return false;
 
2389
                }
 
2390
 
 
2391
                //
 
2392
                // Checks all type arguments againts type parameters constraints
 
2393
                // NOTE: It can run in probing mode when `this.mc' is null
 
2394
                //
 
2395
                public bool CheckAll (MemberSpec context, TypeSpec[] targs, TypeParameterSpec[] tparams, Location loc)
 
2396
                {
 
2397
                        for (int i = 0; i < tparams.Length; i++) {
 
2398
                                var targ = targs[i];
 
2399
                                if (!CheckConstraint (context, targ, tparams [i], loc))
 
2400
                                        return false;
 
2401
 
 
2402
                                if (!recursive_checks)
 
2403
                                        continue;
 
2404
 
 
2405
                                if (!Check (mc, targ, loc))
 
2406
                                        return false;
 
2407
                        }
 
2408
 
 
2409
                        return true;
 
2410
                }
 
2411
 
 
2412
                bool CheckConstraint (MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, Location loc)
 
2413
                {
 
2414
                        //
 
2415
                        // First, check the `class' and `struct' constraints.
 
2416
                        //
 
2417
                        if (tparam.HasSpecialClass && !TypeSpec.IsReferenceType (atype)) {
 
2418
                                if (mc != null) {
 
2419
                                        mc.Module.Compiler.Report.Error (452, loc,
 
2420
                                                "The type `{0}' must be a reference type in order to use it as type parameter `{1}' in the generic type or method `{2}'",
 
2421
                                                TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ());
 
2422
                                }
 
2423
 
 
2424
                                return false;
 
2425
                        }
 
2426
 
 
2427
                        if (tparam.HasSpecialStruct && (!TypeSpec.IsValueType (atype) || atype.IsNullableType)) {
 
2428
                                if (mc != null) {
 
2429
                                        mc.Module.Compiler.Report.Error (453, loc,
 
2430
                                                "The type `{0}' must be a non-nullable value type in order to use it as type parameter `{1}' in the generic type or method `{2}'",
 
2431
                                                TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ());
 
2432
                                }
 
2433
 
 
2434
                                return false;
 
2435
                        }
 
2436
 
 
2437
                        bool ok = true;
 
2438
 
 
2439
                        //
 
2440
                        // Check the class constraint
 
2441
                        //
 
2442
                        if (tparam.HasTypeConstraint) {
 
2443
                                if (!CheckConversion (mc, context, atype, tparam, tparam.BaseType, loc)) {
 
2444
                                        if (mc == null)
 
2445
                                                return false;
 
2446
 
 
2447
                                        ok = false;
 
2448
                                }
 
2449
                        }
 
2450
 
 
2451
                        //
 
2452
                        // Check the interfaces constraints
 
2453
                        //
 
2454
                        if (tparam.Interfaces != null) {
 
2455
                                foreach (TypeSpec iface in tparam.Interfaces) {
 
2456
                                        if (!CheckConversion (mc, context, atype, tparam, iface, loc)) {
 
2457
                                                if (mc == null)
 
2458
                                                        return false;
 
2459
 
 
2460
                                                ok = false;
 
2461
                                                break;
 
2462
                                        }
 
2463
                                }
 
2464
                        }
 
2465
 
 
2466
                        //
 
2467
                        // Check the type parameter constraint
 
2468
                        //
 
2469
                        if (tparam.TypeArguments != null) {
 
2470
                                foreach (var ta in tparam.TypeArguments) {
 
2471
                                        if (!CheckConversion (mc, context, atype, tparam, ta, loc)) {
 
2472
                                                if (mc == null)
 
2473
                                                        return false;
 
2474
 
 
2475
                                                ok = false;
 
2476
                                                break;
 
2477
                                        }
 
2478
                                }
 
2479
                        }
 
2480
 
 
2481
                        //
 
2482
                        // Finally, check the constructor constraint.
 
2483
                        //
 
2484
                        if (!tparam.HasSpecialConstructor)
 
2485
                                return ok;
 
2486
 
 
2487
                        if (!HasDefaultConstructor (atype)) {
 
2488
                                if (mc != null) {
 
2489
                                        mc.Module.Compiler.Report.SymbolRelatedToPreviousError (atype);
 
2490
                                        mc.Module.Compiler.Report.Error (310, loc,
 
2491
                                                "The type `{0}' must have a public parameterless constructor in order to use it as parameter `{1}' in the generic type or method `{2}'",
 
2492
                                                TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ());
 
2493
                                }
 
2494
                                return false;
 
2495
                        }
 
2496
 
 
2497
                        return ok;
 
2498
                }
 
2499
 
 
2500
                static bool HasDynamicTypeArgument (TypeSpec[] targs)
 
2501
                {
 
2502
                        for (int i = 0; i < targs.Length; ++i) {
 
2503
                                var targ = targs [i];
 
2504
                                if (targ.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
 
2505
                                        return true;
 
2506
 
 
2507
                                if (HasDynamicTypeArgument (targ.TypeArguments))
 
2508
                                        return true;
 
2509
                        }
 
2510
 
 
2511
                        return false;
 
2512
                }
 
2513
 
 
2514
                bool CheckConversion (IMemberContext mc, MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, TypeSpec ttype, Location loc)
 
2515
                {
 
2516
                        if (atype == ttype)
 
2517
                                return true;
 
2518
 
 
2519
                        if (atype.IsGenericParameter) {
 
2520
                                var tps = (TypeParameterSpec) atype;
 
2521
                                if (tps.HasDependencyOn (ttype))
 
2522
                                        return true;
 
2523
 
 
2524
                                if (Convert.ImplicitTypeParameterConversion (null, tps, ttype) != null)
 
2525
                                        return true;
 
2526
 
 
2527
                        } else if (TypeSpec.IsValueType (atype)) {
 
2528
                                if (atype.IsNullableType) {
 
2529
                                        //
 
2530
                                        // LAMESPEC: Only identity or base type ValueType or Object satisfy nullable type
 
2531
                                        //
 
2532
                                        if (TypeSpec.IsBaseClass (atype, ttype, false))
 
2533
                                                return true;
 
2534
                                } else {
 
2535
                                        if (Convert.ImplicitBoxingConversion (null, atype, ttype) != null)
 
2536
                                                return true;
 
2537
                                }
 
2538
                        } else {
 
2539
                                if (Convert.ImplicitReferenceConversionExists (atype, ttype) || Convert.ImplicitBoxingConversion (null, atype, ttype) != null)
 
2540
                                        return true;
 
2541
                        }
 
2542
 
 
2543
                        if (mc != null) {
 
2544
                                mc.Module.Compiler.Report.SymbolRelatedToPreviousError (tparam);
 
2545
                                if (atype.IsGenericParameter) {
 
2546
                                        mc.Module.Compiler.Report.Error (314, loc,
 
2547
                                                "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing or type parameter conversion from `{0}' to `{3}'",
 
2548
                                                atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ());
 
2549
                                } else if (TypeSpec.IsValueType (atype)) {
 
2550
                                        if (atype.IsNullableType) {
 
2551
                                                if (ttype.IsInterface) {
 
2552
                                                        mc.Module.Compiler.Report.Error (313, loc,
 
2553
                                                                "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. The nullable type `{0}' never satisfies interface constraint `{3}'",
 
2554
                                                                atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ());
 
2555
                                                } else {
 
2556
                                                        mc.Module.Compiler.Report.Error (312, loc,
 
2557
                                                                "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. The nullable type `{0}' does not satisfy constraint `{3}'",
 
2558
                                                                atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ());
 
2559
                                                }
 
2560
                                        } else {
 
2561
                                                mc.Module.Compiler.Report.Error (315, loc,
 
2562
                                                        "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing conversion from `{0}' to `{3}'",
 
2563
                                                        atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ());
 
2564
                                        }
 
2565
                                } else {
 
2566
                                        mc.Module.Compiler.Report.Error (311, loc,
 
2567
                                                "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no implicit reference conversion from `{0}' to `{3}'",
 
2568
                                                atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ());
 
2569
                                }
 
2570
                        }
 
2571
 
 
2572
                        return false;
 
2573
                }
 
2574
 
 
2575
                static bool HasDefaultConstructor (TypeSpec atype)
 
2576
                {
 
2577
                        var tp = atype as TypeParameterSpec;
 
2578
                        if (tp != null) {
 
2579
                                return tp.HasSpecialConstructor || tp.HasSpecialStruct;
 
2580
                        }
 
2581
 
 
2582
                        if (atype.IsStruct || atype.IsEnum)
 
2583
                                return true;
 
2584
 
 
2585
                        if (atype.IsAbstract)
 
2586
                                return false;
 
2587
 
 
2588
                        var tdef = atype.GetDefinition ();
 
2589
 
 
2590
                        var found = MemberCache.FindMember (tdef,
 
2591
                                MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters),
 
2592
                                BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly);
 
2593
 
 
2594
                        return found != null && (found.Modifiers & Modifiers.PUBLIC) != 0;
 
2595
                }
 
2596
        }
 
2597
 
 
2598
        public partial class TypeManager
 
2599
        {
 
2600
                public static Variance CheckTypeVariance (TypeSpec t, Variance expected, IMemberContext member)
 
2601
                {
 
2602
                        var tp = t as TypeParameterSpec;
 
2603
                        if (tp != null) {
 
2604
                                Variance v = tp.Variance;
 
2605
                                if (expected == Variance.None && v != expected ||
 
2606
                                        expected == Variance.Covariant && v == Variance.Contravariant ||
 
2607
                                        expected == Variance.Contravariant && v == Variance.Covariant) {
 
2608
                                        ((TypeParameter)tp.MemberDefinition).ErrorInvalidVariance (member, expected);
 
2609
                                }
 
2610
 
 
2611
                                return expected;
 
2612
                        }
 
2613
 
 
2614
                        if (t.TypeArguments.Length > 0) {
 
2615
                                var targs_definition = t.MemberDefinition.TypeParameters;
 
2616
                                TypeSpec[] targs = GetTypeArguments (t);
 
2617
                                for (int i = 0; i < targs.Length; ++i) {
 
2618
                                        Variance v = targs_definition[i].Variance;
 
2619
                                        CheckTypeVariance (targs[i], (Variance) ((int)v * (int)expected), member);
 
2620
                                }
 
2621
 
 
2622
                                return expected;
 
2623
                        }
 
2624
 
 
2625
                        if (t.IsArray)
 
2626
                                return CheckTypeVariance (GetElementType (t), expected, member);
 
2627
 
 
2628
                        return Variance.None;
 
2629
                }
 
2630
        }
 
2631
 
 
2632
        //
 
2633
        // Implements C# type inference
 
2634
        //
 
2635
        class TypeInference
 
2636
        {
 
2637
                //
 
2638
                // Tracks successful rate of type inference
 
2639
                //
 
2640
                int score = int.MaxValue;
 
2641
                readonly Arguments arguments;
 
2642
                readonly int arg_count;
 
2643
 
 
2644
                public TypeInference (Arguments arguments)
 
2645
                {
 
2646
                        this.arguments = arguments;
 
2647
                        if (arguments != null)
 
2648
                                arg_count = arguments.Count;
 
2649
                }
 
2650
 
 
2651
                public int InferenceScore {
 
2652
                        get {
 
2653
                                return score;
 
2654
                        }
 
2655
                }
 
2656
 
 
2657
                public TypeSpec[] InferMethodArguments (ResolveContext ec, MethodSpec method)
 
2658
                {
 
2659
                        var method_generic_args = method.GenericDefinition.TypeParameters;
 
2660
                        TypeInferenceContext context = new TypeInferenceContext (method_generic_args);
 
2661
                        if (!context.UnfixedVariableExists)
 
2662
                                return TypeSpec.EmptyTypes;
 
2663
 
 
2664
                        AParametersCollection pd = method.Parameters;
 
2665
                        if (!InferInPhases (ec, context, pd))
 
2666
                                return null;
 
2667
 
 
2668
                        return context.InferredTypeArguments;
 
2669
                }
 
2670
 
 
2671
                //
 
2672
                // Implements method type arguments inference
 
2673
                //
 
2674
                bool InferInPhases (ResolveContext ec, TypeInferenceContext tic, AParametersCollection methodParameters)
 
2675
                {
 
2676
                        int params_arguments_start;
 
2677
                        if (methodParameters.HasParams) {
 
2678
                                params_arguments_start = methodParameters.Count - 1;
 
2679
                        } else {
 
2680
                                params_arguments_start = arg_count;
 
2681
                        }
 
2682
 
 
2683
                        TypeSpec [] ptypes = methodParameters.Types;
 
2684
                        
 
2685
                        //
 
2686
                        // The first inference phase
 
2687
                        //
 
2688
                        TypeSpec method_parameter = null;
 
2689
                        for (int i = 0; i < arg_count; i++) {
 
2690
                                Argument a = arguments [i];
 
2691
                                if (a == null)
 
2692
                                        continue;
 
2693
                                
 
2694
                                if (i < params_arguments_start) {
 
2695
                                        method_parameter = methodParameters.Types [i];
 
2696
                                } else if (i == params_arguments_start) {
 
2697
                                        if (arg_count == params_arguments_start + 1 && TypeManager.HasElementType (a.Type))
 
2698
                                                method_parameter = methodParameters.Types [params_arguments_start];
 
2699
                                        else
 
2700
                                                method_parameter = TypeManager.GetElementType (methodParameters.Types [params_arguments_start]);
 
2701
 
 
2702
                                        ptypes = (TypeSpec[]) ptypes.Clone ();
 
2703
                                        ptypes [i] = method_parameter;
 
2704
                                }
 
2705
 
 
2706
                                //
 
2707
                                // When a lambda expression, an anonymous method
 
2708
                                // is used an explicit argument type inference takes a place
 
2709
                                //
 
2710
                                AnonymousMethodExpression am = a.Expr as AnonymousMethodExpression;
 
2711
                                if (am != null) {
 
2712
                                        if (am.ExplicitTypeInference (ec, tic, method_parameter))
 
2713
                                                --score; 
 
2714
                                        continue;
 
2715
                                }
 
2716
 
 
2717
                                if (a.IsByRef) {
 
2718
                                        score -= tic.ExactInference (a.Type, method_parameter);
 
2719
                                        continue;
 
2720
                                }
 
2721
 
 
2722
                                if (a.Expr.Type == InternalType.NullLiteral)
 
2723
                                        continue;
 
2724
 
 
2725
                                if (TypeSpec.IsValueType (method_parameter)) {
 
2726
                                        score -= tic.LowerBoundInference (a.Type, method_parameter);
 
2727
                                        continue;
 
2728
                                }
 
2729
 
 
2730
                                //
 
2731
                                // Otherwise an output type inference is made
 
2732
                                //
 
2733
                                score -= tic.OutputTypeInference (ec, a.Expr, method_parameter);
 
2734
                        }
 
2735
 
 
2736
                        //
 
2737
                        // Part of the second phase but because it happens only once
 
2738
                        // we don't need to call it in cycle
 
2739
                        //
 
2740
                        bool fixed_any = false;
 
2741
                        if (!tic.FixIndependentTypeArguments (ec, ptypes, ref fixed_any))
 
2742
                                return false;
 
2743
 
 
2744
                        return DoSecondPhase (ec, tic, ptypes, !fixed_any);
 
2745
                }
 
2746
 
 
2747
                bool DoSecondPhase (ResolveContext ec, TypeInferenceContext tic, TypeSpec[] methodParameters, bool fixDependent)
 
2748
                {
 
2749
                        bool fixed_any = false;
 
2750
                        if (fixDependent && !tic.FixDependentTypes (ec, ref fixed_any))
 
2751
                                return false;
 
2752
 
 
2753
                        // If no further unfixed type variables exist, type inference succeeds
 
2754
                        if (!tic.UnfixedVariableExists)
 
2755
                                return true;
 
2756
 
 
2757
                        if (!fixed_any && fixDependent)
 
2758
                                return false;
 
2759
                        
 
2760
                        // For all arguments where the corresponding argument output types
 
2761
                        // contain unfixed type variables but the input types do not,
 
2762
                        // an output type inference is made
 
2763
                        for (int i = 0; i < arg_count; i++) {
 
2764
                                
 
2765
                                // Align params arguments
 
2766
                                TypeSpec t_i = methodParameters [i >= methodParameters.Length ? methodParameters.Length - 1: i];
 
2767
                                
 
2768
                                if (!t_i.IsDelegate) {
 
2769
                                        if (!t_i.IsExpressionTreeType)
 
2770
                                                continue;
 
2771
 
 
2772
                                        t_i = TypeManager.GetTypeArguments (t_i) [0];
 
2773
                                }
 
2774
 
 
2775
                                var mi = Delegate.GetInvokeMethod (t_i);
 
2776
                                TypeSpec rtype = mi.ReturnType;
 
2777
 
 
2778
                                if (tic.IsReturnTypeNonDependent (ec, mi, rtype)) {
 
2779
                                        // It can be null for default arguments
 
2780
                                        if (arguments[i] == null)
 
2781
                                                continue;
 
2782
 
 
2783
                                        score -= tic.OutputTypeInference (ec, arguments[i].Expr, t_i);
 
2784
                                }
 
2785
                        }
 
2786
 
 
2787
 
 
2788
                        return DoSecondPhase (ec, tic, methodParameters, true);
 
2789
                }
 
2790
        }
 
2791
 
 
2792
        public class TypeInferenceContext
 
2793
        {
 
2794
                protected enum BoundKind
 
2795
                {
 
2796
                        Exact   = 0,
 
2797
                        Lower   = 1,
 
2798
                        Upper   = 2
 
2799
                }
 
2800
 
 
2801
                struct BoundInfo : IEquatable<BoundInfo>
 
2802
                {
 
2803
                        public readonly TypeSpec Type;
 
2804
                        public readonly BoundKind Kind;
 
2805
 
 
2806
                        public BoundInfo (TypeSpec type, BoundKind kind)
 
2807
                        {
 
2808
                                this.Type = type;
 
2809
                                this.Kind = kind;
 
2810
                        }
 
2811
                        
 
2812
                        public override int GetHashCode ()
 
2813
                        {
 
2814
                                return Type.GetHashCode ();
 
2815
                        }
 
2816
 
 
2817
                        public Expression GetTypeExpression ()
 
2818
                        {
 
2819
                                return new TypeExpression (Type, Location.Null);
 
2820
                        }
 
2821
 
 
2822
                        #region IEquatable<BoundInfo> Members
 
2823
 
 
2824
                        public bool Equals (BoundInfo other)
 
2825
                        {
 
2826
                                return Type == other.Type && Kind == other.Kind;
 
2827
                        }
 
2828
 
 
2829
                        #endregion
 
2830
                }
 
2831
 
 
2832
                readonly TypeSpec[] tp_args;
 
2833
                readonly TypeSpec[] fixed_types;
 
2834
                readonly List<BoundInfo>[] bounds;
 
2835
                bool failed;
 
2836
 
 
2837
                // TODO MemberCache: Could it be TypeParameterSpec[] ??
 
2838
                public TypeInferenceContext (TypeSpec[] typeArguments)
 
2839
                {
 
2840
                        if (typeArguments.Length == 0)
 
2841
                                throw new ArgumentException ("Empty generic arguments");
 
2842
 
 
2843
                        fixed_types = new TypeSpec [typeArguments.Length];
 
2844
                        for (int i = 0; i < typeArguments.Length; ++i) {
 
2845
                                if (typeArguments [i].IsGenericParameter) {
 
2846
                                        if (bounds == null) {
 
2847
                                                bounds = new List<BoundInfo> [typeArguments.Length];
 
2848
                                                tp_args = new TypeSpec [typeArguments.Length];
 
2849
                                        }
 
2850
                                        tp_args [i] = typeArguments [i];
 
2851
                                } else {
 
2852
                                        fixed_types [i] = typeArguments [i];
 
2853
                                }
 
2854
                        }
 
2855
                }
 
2856
 
 
2857
                // 
 
2858
                // Used together with AddCommonTypeBound fo implement
 
2859
                // 7.4.2.13 Finding the best common type of a set of expressions
 
2860
                //
 
2861
                public TypeInferenceContext ()
 
2862
                {
 
2863
                        fixed_types = new TypeSpec [1];
 
2864
                        tp_args = new TypeSpec [1];
 
2865
                        tp_args[0] = InternalType.Arglist; // it can be any internal type
 
2866
                        bounds = new List<BoundInfo> [1];
 
2867
                }
 
2868
 
 
2869
                public TypeSpec[] InferredTypeArguments {
 
2870
                        get {
 
2871
                                return fixed_types;
 
2872
                        }
 
2873
                }
 
2874
 
 
2875
                public void AddCommonTypeBound (TypeSpec type)
 
2876
                {
 
2877
                        AddToBounds (new BoundInfo (type, BoundKind.Lower), 0);
 
2878
                }
 
2879
 
 
2880
                void AddToBounds (BoundInfo bound, int index)
 
2881
                {
 
2882
                        //
 
2883
                        // Some types cannot be used as type arguments
 
2884
                        //
 
2885
                        if (bound.Type.Kind == MemberKind.Void || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType ||
 
2886
                                bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod)
 
2887
                                return;
 
2888
 
 
2889
                        var a = bounds [index];
 
2890
                        if (a == null) {
 
2891
                                a = new List<BoundInfo> (2);
 
2892
                                a.Add (bound);
 
2893
                                bounds [index] = a;
 
2894
                                return;
 
2895
                        }
 
2896
 
 
2897
                        if (a.Contains (bound))
 
2898
                                return;
 
2899
 
 
2900
                        a.Add (bound);
 
2901
                }
 
2902
                
 
2903
                bool AllTypesAreFixed (TypeSpec[] types)
 
2904
                {
 
2905
                        foreach (TypeSpec t in types) {
 
2906
                                if (t.IsGenericParameter) {
 
2907
                                        if (!IsFixed (t))
 
2908
                                                return false;
 
2909
                                        continue;
 
2910
                                }
 
2911
 
 
2912
                                if (TypeManager.IsGenericType (t))
 
2913
                                        return AllTypesAreFixed (TypeManager.GetTypeArguments (t));
 
2914
                        }
 
2915
                        
 
2916
                        return true;
 
2917
                }               
 
2918
 
 
2919
                //
 
2920
                // 26.3.3.8 Exact Inference
 
2921
                //
 
2922
                public int ExactInference (TypeSpec u, TypeSpec v)
 
2923
                {
 
2924
                        // If V is an array type
 
2925
                        if (v.IsArray) {
 
2926
                                if (!u.IsArray)
 
2927
                                        return 0;
 
2928
 
 
2929
                                var ac_u = (ArrayContainer) u;
 
2930
                                var ac_v = (ArrayContainer) v;
 
2931
                                if (ac_u.Rank != ac_v.Rank)
 
2932
                                        return 0;
 
2933
 
 
2934
                                return ExactInference (ac_u.Element, ac_v.Element);
 
2935
                        }
 
2936
 
 
2937
                        // If V is constructed type and U is constructed type
 
2938
                        if (TypeManager.IsGenericType (v)) {
 
2939
                                if (!TypeManager.IsGenericType (u) || v.MemberDefinition != u.MemberDefinition)
 
2940
                                        return 0;
 
2941
 
 
2942
                                TypeSpec [] ga_u = TypeManager.GetTypeArguments (u);
 
2943
                                TypeSpec [] ga_v = TypeManager.GetTypeArguments (v);
 
2944
                                if (ga_u.Length != ga_v.Length)
 
2945
                                        return 0;
 
2946
 
 
2947
                                int score = 0;
 
2948
                                for (int i = 0; i < ga_u.Length; ++i)
 
2949
                                        score += ExactInference (ga_u [i], ga_v [i]);
 
2950
 
 
2951
                                return System.Math.Min (1, score);
 
2952
                        }
 
2953
 
 
2954
                        // If V is one of the unfixed type arguments
 
2955
                        int pos = IsUnfixed (v);
 
2956
                        if (pos == -1)
 
2957
                                return 0;
 
2958
 
 
2959
                        AddToBounds (new BoundInfo (u, BoundKind.Exact), pos);
 
2960
                        return 1;
 
2961
                }
 
2962
 
 
2963
                public bool FixAllTypes (ResolveContext ec)
 
2964
                {
 
2965
                        for (int i = 0; i < tp_args.Length; ++i) {
 
2966
                                if (!FixType (ec, i))
 
2967
                                        return false;
 
2968
                        }
 
2969
                        return true;
 
2970
                }
 
2971
 
 
2972
                //
 
2973
                // All unfixed type variables Xi are fixed for which all of the following hold:
 
2974
                // a, There is at least one type variable Xj that depends on Xi
 
2975
                // b, Xi has a non-empty set of bounds
 
2976
                // 
 
2977
                public bool FixDependentTypes (ResolveContext ec, ref bool fixed_any)
 
2978
                {
 
2979
                        for (int i = 0; i < tp_args.Length; ++i) {
 
2980
                                if (fixed_types[i] != null)
 
2981
                                        continue;
 
2982
 
 
2983
                                if (bounds[i] == null)
 
2984
                                        continue;
 
2985
 
 
2986
                                if (!FixType (ec, i))
 
2987
                                        return false;
 
2988
                                
 
2989
                                fixed_any = true;
 
2990
                        }
 
2991
 
 
2992
                        return true;
 
2993
                }
 
2994
 
 
2995
                //
 
2996
                // All unfixed type variables Xi which depend on no Xj are fixed
 
2997
                //
 
2998
                public bool FixIndependentTypeArguments (ResolveContext ec, TypeSpec[] methodParameters, ref bool fixed_any)
 
2999
                {
 
3000
                        var types_to_fix = new List<TypeSpec> (tp_args);
 
3001
                        for (int i = 0; i < methodParameters.Length; ++i) {
 
3002
                                TypeSpec t = methodParameters[i];
 
3003
 
 
3004
                                if (!t.IsDelegate) {
 
3005
                                        if (!t.IsExpressionTreeType)
 
3006
                                                continue;
 
3007
 
 
3008
                                        t =  TypeManager.GetTypeArguments (t) [0];
 
3009
                                }
 
3010
 
 
3011
                                if (t.IsGenericParameter)
 
3012
                                        continue;
 
3013
 
 
3014
                                var invoke = Delegate.GetInvokeMethod (t);
 
3015
                                TypeSpec rtype = invoke.ReturnType;
 
3016
                                while (rtype.IsArray)
 
3017
                                        rtype = ((ArrayContainer) rtype).Element;
 
3018
 
 
3019
                                if (!rtype.IsGenericParameter && !TypeManager.IsGenericType (rtype))
 
3020
                                        continue;
 
3021
 
 
3022
                                // Remove dependent types, they cannot be fixed yet
 
3023
                                RemoveDependentTypes (types_to_fix, rtype);
 
3024
                        }
 
3025
 
 
3026
                        foreach (TypeSpec t in types_to_fix) {
 
3027
                                if (t == null)
 
3028
                                        continue;
 
3029
 
 
3030
                                int idx = IsUnfixed (t);
 
3031
                                if (idx >= 0 && !FixType (ec, idx)) {
 
3032
                                        return false;
 
3033
                                }
 
3034
                        }
 
3035
 
 
3036
                        fixed_any = types_to_fix.Count > 0;
 
3037
                        return true;
 
3038
                }
 
3039
 
 
3040
                //
 
3041
                // 26.3.3.10 Fixing
 
3042
                //
 
3043
                public bool FixType (ResolveContext ec, int i)
 
3044
                {
 
3045
                        // It's already fixed
 
3046
                        if (fixed_types[i] != null)
 
3047
                                throw new InternalErrorException ("Type argument has been already fixed");
 
3048
 
 
3049
                        if (failed)
 
3050
                                return false;
 
3051
 
 
3052
                        var candidates = bounds [i];
 
3053
                        if (candidates == null)
 
3054
                                return false;
 
3055
 
 
3056
                        if (candidates.Count == 1) {
 
3057
                                TypeSpec t = candidates[0].Type;
 
3058
                                if (t == InternalType.NullLiteral)
 
3059
                                        return false;
 
3060
 
 
3061
                                fixed_types [i] = t;
 
3062
                                return true;
 
3063
                        }
 
3064
 
 
3065
                        //
 
3066
                        // Determines a unique type from which there is
 
3067
                        // a standard implicit conversion to all the other
 
3068
                        // candidate types.
 
3069
                        //
 
3070
                        TypeSpec best_candidate = null;
 
3071
                        int cii;
 
3072
                        int candidates_count = candidates.Count;
 
3073
                        for (int ci = 0; ci < candidates_count; ++ci) {
 
3074
                                BoundInfo bound = candidates [ci];
 
3075
                                for (cii = 0; cii < candidates_count; ++cii) {
 
3076
                                        if (cii == ci)
 
3077
                                                continue;
 
3078
 
 
3079
                                        BoundInfo cbound = candidates[cii];
 
3080
                                        
 
3081
                                        // Same type parameters with different bounds
 
3082
                                        if (cbound.Type == bound.Type) {
 
3083
                                                if (bound.Kind != BoundKind.Exact)
 
3084
                                                        bound = cbound;
 
3085
 
 
3086
                                                continue;
 
3087
                                        }
 
3088
 
 
3089
                                        if (bound.Kind == BoundKind.Exact || cbound.Kind == BoundKind.Exact) {
 
3090
                                                if (cbound.Kind == BoundKind.Lower) {
 
3091
                                                        if (!Convert.ImplicitConversionExists (ec, cbound.GetTypeExpression (), bound.Type)) {
 
3092
                                                                break;
 
3093
                                                        }
 
3094
 
 
3095
                                                        continue;
 
3096
                                                }
 
3097
                                                if (cbound.Kind == BoundKind.Upper) {
 
3098
                                                        if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
 
3099
                                                                break;
 
3100
                                                        }
 
3101
 
 
3102
                                                        continue;
 
3103
                                                }
 
3104
                                                
 
3105
                                                if (bound.Kind != BoundKind.Exact) {
 
3106
                                                        if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
 
3107
                                                                break;
 
3108
                                                        }
 
3109
 
 
3110
                                                        bound = cbound;
 
3111
                                                        continue;
 
3112
                                                }
 
3113
                                                
 
3114
                                                break;
 
3115
                                        }
 
3116
 
 
3117
                                        if (bound.Kind == BoundKind.Lower) {
 
3118
                                                if (cbound.Kind == BoundKind.Lower) {
 
3119
                                                        if (!Convert.ImplicitConversionExists (ec, cbound.GetTypeExpression (), bound.Type)) {
 
3120
                                                                break;
 
3121
                                                        }
 
3122
                                                } else {
 
3123
                                                        if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
 
3124
                                                                break;
 
3125
                                                        }
 
3126
 
 
3127
                                                        bound = cbound;
 
3128
                                                }
 
3129
 
 
3130
                                                continue;
 
3131
                                        }
 
3132
 
 
3133
                                        if (bound.Kind == BoundKind.Upper) {
 
3134
                                                if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) {
 
3135
                                                        break;
 
3136
                                                }
 
3137
                                        } else {
 
3138
                                                throw new NotImplementedException ("variance conversion");
 
3139
                                        }
 
3140
                                }
 
3141
 
 
3142
                                if (cii != candidates_count)
 
3143
                                        continue;
 
3144
 
 
3145
                                //
 
3146
                                // We already have the best candidate, break if thet are different
 
3147
                                //
 
3148
                                // Dynamic is never ambiguous as we prefer dynamic over other best candidate types
 
3149
                                //
 
3150
                                if (best_candidate != null) {
 
3151
 
 
3152
                                        if (best_candidate.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
 
3153
                                                continue;
 
3154
 
 
3155
                                        if (bound.Type.BuiltinType != BuiltinTypeSpec.Type.Dynamic && best_candidate != bound.Type)
 
3156
                                                return false;
 
3157
                                }
 
3158
 
 
3159
                                best_candidate = bound.Type;
 
3160
                        }
 
3161
 
 
3162
                        if (best_candidate == null)
 
3163
                                return false;
 
3164
 
 
3165
                        fixed_types[i] = best_candidate;
 
3166
                        return true;
 
3167
                }
 
3168
 
 
3169
                public bool HasBounds (int pos)
 
3170
                {
 
3171
                        return bounds[pos] != null;
 
3172
                }
 
3173
                
 
3174
                //
 
3175
                // Uses inferred or partially infered types to inflate delegate type argument. Returns
 
3176
                // null when type parameter has not been fixed
 
3177
                //
 
3178
                public TypeSpec InflateGenericArgument (IModuleContext context, TypeSpec parameter)
 
3179
                {
 
3180
                        var tp = parameter as TypeParameterSpec;
 
3181
                        if (tp != null) {
 
3182
                                //
 
3183
                                // Type inference works on generic arguments (MVAR) only
 
3184
                                //
 
3185
                                if (!tp.IsMethodOwned)
 
3186
                                        return parameter;
 
3187
 
 
3188
                                //
 
3189
                                // Ensure the type parameter belongs to same container
 
3190
                                //
 
3191
                                if (tp.DeclaredPosition < tp_args.Length && tp_args[tp.DeclaredPosition] == parameter)
 
3192
                                        return fixed_types[tp.DeclaredPosition] ?? parameter;
 
3193
 
 
3194
                                return parameter;
 
3195
                        }
 
3196
 
 
3197
                        var gt = parameter as InflatedTypeSpec;
 
3198
                        if (gt != null) {
 
3199
                                var inflated_targs = new TypeSpec [gt.TypeArguments.Length];
 
3200
                                for (int ii = 0; ii < inflated_targs.Length; ++ii) {
 
3201
                                        var inflated = InflateGenericArgument (context, gt.TypeArguments [ii]);
 
3202
                                        if (inflated == null)
 
3203
                                                return null;
 
3204
 
 
3205
                                        inflated_targs[ii] = inflated;
 
3206
                                }
 
3207
 
 
3208
                                return gt.GetDefinition ().MakeGenericType (context, inflated_targs);
 
3209
                        }
 
3210
 
 
3211
                        var ac = parameter as ArrayContainer;
 
3212
                        if (ac != null) {
 
3213
                                var inflated = InflateGenericArgument (context, ac.Element);
 
3214
                                if (inflated != ac.Element)
 
3215
                                        return ArrayContainer.MakeType (context.Module, inflated);
 
3216
                        }
 
3217
 
 
3218
                        return parameter;
 
3219
                }
 
3220
                
 
3221
                //
 
3222
                // Tests whether all delegate input arguments are fixed and generic output type
 
3223
                // requires output type inference 
 
3224
                //
 
3225
                public bool IsReturnTypeNonDependent (ResolveContext ec, MethodSpec invoke, TypeSpec returnType)
 
3226
                {
 
3227
                        while (returnType.IsArray)
 
3228
                                returnType = ((ArrayContainer) returnType).Element;
 
3229
 
 
3230
                        if (returnType.IsGenericParameter) {
 
3231
                                if (IsFixed (returnType))
 
3232
                                    return false;
 
3233
                        } else if (TypeManager.IsGenericType (returnType)) {
 
3234
                                if (returnType.IsDelegate) {
 
3235
                                        invoke = Delegate.GetInvokeMethod (returnType);
 
3236
                                        return IsReturnTypeNonDependent (ec, invoke, invoke.ReturnType);
 
3237
                                }
 
3238
                                        
 
3239
                                TypeSpec[] g_args = TypeManager.GetTypeArguments (returnType);
 
3240
                                
 
3241
                                // At least one unfixed return type has to exist 
 
3242
                                if (AllTypesAreFixed (g_args))
 
3243
                                        return false;
 
3244
                        } else {
 
3245
                                return false;
 
3246
                        }
 
3247
 
 
3248
                        // All generic input arguments have to be fixed
 
3249
                        AParametersCollection d_parameters = invoke.Parameters;
 
3250
                        return AllTypesAreFixed (d_parameters.Types);
 
3251
                }
 
3252
 
 
3253
                bool IsFixed (TypeSpec type)
 
3254
                {
 
3255
                        return IsUnfixed (type) == -1;
 
3256
                }               
 
3257
 
 
3258
                int IsUnfixed (TypeSpec type)
 
3259
                {
 
3260
                        if (!type.IsGenericParameter)
 
3261
                                return -1;
 
3262
 
 
3263
                        for (int i = 0; i < tp_args.Length; ++i) {
 
3264
                                if (tp_args[i] == type) {
 
3265
                                        if (fixed_types[i] != null)
 
3266
                                                break;
 
3267
 
 
3268
                                        return i;
 
3269
                                }
 
3270
                        }
 
3271
 
 
3272
                        return -1;
 
3273
                }
 
3274
 
 
3275
                //
 
3276
                // 26.3.3.9 Lower-bound Inference
 
3277
                //
 
3278
                public int LowerBoundInference (TypeSpec u, TypeSpec v)
 
3279
                {
 
3280
                        return LowerBoundInference (u, v, false);
 
3281
                }
 
3282
 
 
3283
                //
 
3284
                // Lower-bound (false) or Upper-bound (true) inference based on inversed argument
 
3285
                //
 
3286
                int LowerBoundInference (TypeSpec u, TypeSpec v, bool inversed)
 
3287
                {
 
3288
                        // If V is one of the unfixed type arguments
 
3289
                        int pos = IsUnfixed (v);
 
3290
                        if (pos != -1) {
 
3291
                                AddToBounds (new BoundInfo (u, inversed ? BoundKind.Upper : BoundKind.Lower), pos);
 
3292
                                return 1;
 
3293
                        }                       
 
3294
 
 
3295
                        // If U is an array type
 
3296
                        var u_ac = u as ArrayContainer;
 
3297
                        if (u_ac != null) {
 
3298
                                var v_ac = v as ArrayContainer;
 
3299
                                if (v_ac != null) {
 
3300
                                        if (u_ac.Rank != v_ac.Rank)
 
3301
                                                return 0;
 
3302
 
 
3303
                                        if (TypeSpec.IsValueType (u_ac.Element))
 
3304
                                                return ExactInference (u_ac.Element, v_ac.Element);
 
3305
 
 
3306
                                        return LowerBoundInference (u_ac.Element, v_ac.Element, inversed);
 
3307
                                }
 
3308
 
 
3309
                                if (u_ac.Rank != 1 || !v.IsGenericIterateInterface)
 
3310
                                        return 0;
 
3311
 
 
3312
                                var v_i = TypeManager.GetTypeArguments (v) [0];
 
3313
                                if (TypeSpec.IsValueType (u_ac.Element))
 
3314
                                        return ExactInference (u_ac.Element, v_i);
 
3315
 
 
3316
                                return LowerBoundInference (u_ac.Element, v_i);
 
3317
                        }
 
3318
                        
 
3319
                        if (v.IsGenericOrParentIsGeneric) {
 
3320
                                //
 
3321
                                // if V is a constructed type C<V1..Vk> and there is a unique type C<U1..Uk>
 
3322
                                // such that U is identical to, inherits from (directly or indirectly),
 
3323
                                // or implements (directly or indirectly) C<U1..Uk>
 
3324
                                //
 
3325
                                var u_candidates = new List<TypeSpec> ();
 
3326
                                var open_v = v.MemberDefinition;
 
3327
 
 
3328
                                for (TypeSpec t = u; t != null; t = t.BaseType) {
 
3329
                                        if (open_v == t.MemberDefinition)
 
3330
                                                u_candidates.Add (t);
 
3331
 
 
3332
                                        //
 
3333
                                        // Using this trick for dynamic type inference, the spec says the type arguments are "unknown" but
 
3334
                                        // that would complicate the process a lot, instead I treat them as dynamic
 
3335
                                        //
 
3336
                                        if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
 
3337
                                                u_candidates.Add (t);
 
3338
                                }
 
3339
 
 
3340
                                if (u.Interfaces != null) {
 
3341
                                        foreach (var iface in u.Interfaces) {
 
3342
                                                if (open_v == iface.MemberDefinition)
 
3343
                                                        u_candidates.Add (iface);
 
3344
                                        }
 
3345
                                }
 
3346
 
 
3347
                                TypeSpec[] unique_candidate_targs = null;
 
3348
                                var ga_v = TypeSpec.GetAllTypeArguments (v);
 
3349
                                foreach (TypeSpec u_candidate in u_candidates) {
 
3350
                                        //
 
3351
                                        // The unique set of types U1..Uk means that if we have an interface I<T>,
 
3352
                                        // class U : I<int>, I<long> then no type inference is made when inferring
 
3353
                                        // type I<T> by applying type U because T could be int or long
 
3354
                                        //
 
3355
                                        if (unique_candidate_targs != null) {
 
3356
                                                TypeSpec[] second_unique_candidate_targs = TypeSpec.GetAllTypeArguments (u_candidate);
 
3357
                                                if (TypeSpecComparer.Equals (unique_candidate_targs, second_unique_candidate_targs)) {
 
3358
                                                        unique_candidate_targs = second_unique_candidate_targs;
 
3359
                                                        continue;
 
3360
                                                }
 
3361
 
 
3362
                                                //
 
3363
                                                // This should always cause type inference failure
 
3364
                                                //
 
3365
                                                failed = true;
 
3366
                                                return 1;
 
3367
                                        }
 
3368
 
 
3369
                                        //
 
3370
                                        // A candidate is dynamic type expression, to simplify things use dynamic
 
3371
                                        // for all type parameter of this type. For methods like this one
 
3372
                                        // 
 
3373
                                        // void M<T, U> (IList<T>, IList<U[]>)
 
3374
                                        //
 
3375
                                        // dynamic becomes both T and U when the arguments are of dynamic type
 
3376
                                        //
 
3377
                                        if (u_candidate.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
3378
                                                unique_candidate_targs = new TypeSpec[ga_v.Length];
 
3379
                                                for (int i = 0; i < unique_candidate_targs.Length; ++i)
 
3380
                                                        unique_candidate_targs[i] = u_candidate;
 
3381
                                        } else {
 
3382
                                                unique_candidate_targs = TypeSpec.GetAllTypeArguments (u_candidate);
 
3383
                                        }
 
3384
                                }
 
3385
 
 
3386
                                if (unique_candidate_targs != null) {
 
3387
                                        int score = 0;
 
3388
                                        int tp_index = -1;
 
3389
                                        TypeParameterSpec[] tps = null;
 
3390
 
 
3391
                                        for (int i = 0; i < unique_candidate_targs.Length; ++i) {
 
3392
                                                if (tp_index < 0) {
 
3393
                                                        while (v.Arity == 0)
 
3394
                                                                v = v.DeclaringType;
 
3395
 
 
3396
                                                        tps = v.MemberDefinition.TypeParameters;
 
3397
                                                        tp_index = tps.Length - 1;
 
3398
                                                }
 
3399
 
 
3400
                                                Variance variance = tps [tp_index--].Variance;
 
3401
 
 
3402
                                                TypeSpec u_i = unique_candidate_targs [i];
 
3403
                                                if (variance == Variance.None || TypeSpec.IsValueType (u_i)) {
 
3404
                                                        if (ExactInference (u_i, ga_v [i]) == 0)
 
3405
                                                                ++score;
 
3406
                                                } else {
 
3407
                                                        bool upper_bound = (variance == Variance.Contravariant && !inversed) ||
 
3408
                                                                (variance == Variance.Covariant && inversed);
 
3409
 
 
3410
                                                        if (LowerBoundInference (u_i, ga_v [i], upper_bound) == 0)
 
3411
                                                                ++score;
 
3412
                                                }
 
3413
                                        }
 
3414
 
 
3415
                                        return score;
 
3416
                                }
 
3417
                        }
 
3418
 
 
3419
                        return 0;
 
3420
                }
 
3421
 
 
3422
                //
 
3423
                // 26.3.3.6 Output Type Inference
 
3424
                //
 
3425
                public int OutputTypeInference (ResolveContext ec, Expression e, TypeSpec t)
 
3426
                {
 
3427
                        // If e is a lambda or anonymous method with inferred return type
 
3428
                        AnonymousMethodExpression ame = e as AnonymousMethodExpression;
 
3429
                        if (ame != null) {
 
3430
                                TypeSpec rt = ame.InferReturnType (ec, this, t);
 
3431
                                var invoke = Delegate.GetInvokeMethod (t);
 
3432
 
 
3433
                                if (rt == null) {
 
3434
                                        AParametersCollection pd = invoke.Parameters;
 
3435
                                        return ame.Parameters.Count == pd.Count ? 1 : 0;
 
3436
                                }
 
3437
 
 
3438
                                TypeSpec rtype = invoke.ReturnType;
 
3439
                                return LowerBoundInference (rt, rtype) + 1;
 
3440
                        }
 
3441
 
 
3442
                        //
 
3443
                        // if E is a method group and T is a delegate type or expression tree type
 
3444
                        // return type Tb with parameter types T1..Tk and return type Tb, and overload
 
3445
                        // resolution of E with the types T1..Tk yields a single method with return type U,
 
3446
                        // then a lower-bound inference is made from U for Tb.
 
3447
                        //
 
3448
                        if (e is MethodGroupExpr) {
 
3449
                                if (!t.IsDelegate) {
 
3450
                                        if (!t.IsExpressionTreeType)
 
3451
                                                return 0;
 
3452
 
 
3453
                                        t = TypeManager.GetTypeArguments (t)[0];
 
3454
                                }
 
3455
 
 
3456
                                var invoke = Delegate.GetInvokeMethod (t);
 
3457
                                TypeSpec rtype = invoke.ReturnType;
 
3458
 
 
3459
                                if (!IsReturnTypeNonDependent (ec, invoke, rtype))
 
3460
                                        return 0;
 
3461
 
 
3462
                                // LAMESPEC: Standard does not specify that all methodgroup arguments
 
3463
                                // has to be fixed but it does not specify how to do recursive type inference
 
3464
                                // either. We choose the simple option and infer return type only
 
3465
                                // if all delegate generic arguments are fixed.
 
3466
                                TypeSpec[] param_types = new TypeSpec [invoke.Parameters.Count];
 
3467
                                for (int i = 0; i < param_types.Length; ++i) {
 
3468
                                        var inflated = InflateGenericArgument (ec, invoke.Parameters.Types[i]);
 
3469
                                        if (inflated == null)
 
3470
                                                return 0;
 
3471
 
 
3472
                                        param_types[i] = inflated;
 
3473
                                }
 
3474
 
 
3475
                                MethodGroupExpr mg = (MethodGroupExpr) e;
 
3476
                                Arguments args = DelegateCreation.CreateDelegateMethodArguments (ec, invoke.Parameters, param_types, e.Location);
 
3477
                                mg = mg.OverloadResolve (ec, ref args, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly);
 
3478
                                if (mg == null)
 
3479
                                        return 0;
 
3480
 
 
3481
                                return LowerBoundInference (mg.BestCandidateReturnType, rtype) + 1;
 
3482
                        }
 
3483
 
 
3484
                        //
 
3485
                        // if e is an expression with type U, then
 
3486
                        // a lower-bound inference is made from U for T
 
3487
                        //
 
3488
                        return LowerBoundInference (e.Type, t) * 2;
 
3489
                }
 
3490
 
 
3491
                void RemoveDependentTypes (List<TypeSpec> types, TypeSpec returnType)
 
3492
                {
 
3493
                        int idx = IsUnfixed (returnType);
 
3494
                        if (idx >= 0) {
 
3495
                                types [idx] = null;
 
3496
                                return;
 
3497
                        }
 
3498
 
 
3499
                        if (TypeManager.IsGenericType (returnType)) {
 
3500
                                foreach (TypeSpec t in TypeManager.GetTypeArguments (returnType)) {
 
3501
                                        RemoveDependentTypes (types, t);
 
3502
                                }
 
3503
                        }
 
3504
                }
 
3505
 
 
3506
                public bool UnfixedVariableExists {
 
3507
                        get {
 
3508
                                foreach (TypeSpec ut in fixed_types) {
 
3509
                                        if (ut == null)
 
3510
                                                return true;
 
3511
                                }
 
3512
 
 
3513
                                return false;
 
3514
                        }
 
3515
                }
 
3516
        }
 
3517
}