| File: Symbols\Source\IndexedTypeParameterSymbol.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols { /// <summary> /// Indexed type parameters are used in place of type parameters for method signatures. There is /// a unique mapping from index to a single IndexedTypeParameterSymbol. /// /// They don't have a containing symbol or locations. /// /// They do not have constraints, variance, or attributes. /// </summary> internal sealed class IndexedTypeParameterSymbol : TypeParameterSymbol { private static TypeParameterSymbol[] s_parameterPool = Array.Empty<TypeParameterSymbol>(); private readonly int _index; private IndexedTypeParameterSymbol(int index) { _index = index; } public override TypeParameterKind TypeParameterKind { get { return TypeParameterKind.Method; } } internal static TypeParameterSymbol GetTypeParameter(int index) { if (index >= s_parameterPool.Length) { GrowPool(index + 1); } return s_parameterPool[index]; } private static void GrowPool(int count) { var initialPool = s_parameterPool; while (count > initialPool.Length) { var newPoolSize = ((count + 0x0F) & ~0xF); // grow in increments of 16 var newPool = new TypeParameterSymbol[newPoolSize]; Array.Copy(initialPool, newPool, initialPool.Length); for (int i = initialPool.Length; i < newPool.Length; i++) { newPool[i] = new IndexedTypeParameterSymbol(i); } Interlocked.CompareExchange(ref s_parameterPool, newPool, initialPool); // repeat if race condition occurred and someone else resized the pool before us // and the new pool is still too small initialPool = s_parameterPool; } } /// <summary> /// Create a vector of n dummy type parameters. Always reuses the same type parameter symbol /// for the same position. /// </summary> /// <param name="count"></param> /// <returns></returns> internal static ImmutableArray<TypeParameterSymbol> TakeSymbols(int count) { if (count > s_parameterPool.Length) { GrowPool(count); } ArrayBuilder<TypeParameterSymbol> builder = ArrayBuilder<TypeParameterSymbol>.GetInstance(); for (int i = 0; i < count; i++) { builder.Add(GetTypeParameter(i)); } return builder.ToImmutableAndFree(); } internal static ImmutableArray<TypeWithAnnotations> Take(int count) { if (count > s_parameterPool.Length) { GrowPool(count); } var builder = ArrayBuilder<TypeWithAnnotations>.GetInstance(); for (int i = 0; i < count; i++) { builder.Add(TypeWithAnnotations.Create(GetTypeParameter(i), NullableAnnotation.Ignored)); } return builder.ToImmutableAndFree(); } public override int Ordinal { get { return _index; } } // These object are unique (per index). internal override bool Equals(TypeSymbol t2, TypeCompareKind comparison) { return ReferenceEquals(this, t2); } public override int GetHashCode() { return _index; } public override VarianceKind Variance { get { return VarianceKind.None; } } public override bool HasValueTypeConstraint { get { return false; } } public override bool AllowsRefLikeType { get { return false; } } public override bool IsValueTypeFromConstraintTypes { get { return false; } } public override bool HasReferenceTypeConstraint { get { return false; } } public override bool IsReferenceTypeFromConstraintTypes { get { return false; } } internal override bool? ReferenceTypeConstraintIsNullable { get { return false; } } public override bool HasNotNullConstraint => false; internal override bool? IsNotNullable => null; public override bool HasUnmanagedTypeConstraint { get { return false; } } public override bool HasConstructorConstraint { get { return false; } } public override Symbol ContainingSymbol { get { return null; } } public override ImmutableArray<Location> Locations { get { return ImmutableArray<Location>.Empty; } } public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences { get { return ImmutableArray<SyntaxReference>.Empty; } } internal override void EnsureAllConstraintsAreResolved() { } internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress) { return ImmutableArray<TypeWithAnnotations>.Empty; } internal override ImmutableArray<NamedTypeSymbol> GetInterfaces(ConsList<TypeParameterSymbol> inProgress) { return ImmutableArray<NamedTypeSymbol>.Empty; } internal override NamedTypeSymbol GetEffectiveBaseClass(ConsList<TypeParameterSymbol> inProgress) { return null; } internal override TypeSymbol GetDeducedBaseType(ConsList<TypeParameterSymbol> inProgress) { return null; } public override bool IsImplicitlyDeclared { get { return true; } } } }