PageRenderTime 63ms CodeModel.GetById 23ms 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

Large files files are truncated, but you can click here to view the full file

  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. sta

Large files files are truncated, but you can click here to view the full file