PageRenderTime 537ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/mcs/generic.cs

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