| File: Emitter\Model\TypeParameterSymbolAdapter.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.Reflection.Metadata; using Microsoft.CodeAnalysis.CSharp.Emit; using Roslyn.Utilities; using System.Diagnostics; using Microsoft.CodeAnalysis.Emit; using System.Collections.Immutable; namespace Microsoft.CodeAnalysis.CSharp.Symbols { internal partial class #if DEBUG TypeParameterSymbolAdapter : SymbolAdapter, #else TypeParameterSymbol : #endif Cci.IGenericParameterReference, Cci.IGenericMethodParameterReference, Cci.IGenericTypeParameterReference, Cci.IGenericParameter, Cci.IGenericMethodParameter, Cci.IGenericTypeParameter { public bool IsEncDeleted => false; bool Cci.ITypeReference.IsEnum { get { return false; } } bool Cci.ITypeReference.IsValueType { get { return false; } } Cci.ITypeDefinition Cci.ITypeReference.GetResolvedType(EmitContext context) { return null; } Cci.PrimitiveTypeCode Cci.ITypeReference.TypeCode { get { return Cci.PrimitiveTypeCode.NotPrimitive; } } TypeDefinitionHandle Cci.ITypeReference.TypeDef { get { return default(TypeDefinitionHandle); } } Cci.IGenericMethodParameter Cci.IGenericParameter.AsGenericMethodParameter { get { CheckDefinitionInvariant(); if (AdaptedTypeParameterSymbol.ContainingSymbol.Kind == SymbolKind.Method) { return this; } return null; } } Cci.IGenericMethodParameterReference Cci.ITypeReference.AsGenericMethodParameterReference { get { Debug.Assert(AdaptedTypeParameterSymbol.IsDefinition); if (AdaptedTypeParameterSymbol.ContainingSymbol.Kind == SymbolKind.Method) { return this; } return null; } } Cci.IGenericTypeInstanceReference Cci.ITypeReference.AsGenericTypeInstanceReference { get { return null; } } Cci.IGenericTypeParameter Cci.IGenericParameter.AsGenericTypeParameter { get { CheckDefinitionInvariant(); if (AdaptedTypeParameterSymbol.ContainingSymbol.Kind == SymbolKind.NamedType) { return this; } return null; } } Cci.IGenericTypeParameterReference Cci.ITypeReference.AsGenericTypeParameterReference { get { Debug.Assert(AdaptedTypeParameterSymbol.IsDefinition); if (AdaptedTypeParameterSymbol.ContainingSymbol.Kind == SymbolKind.NamedType) { return this; } return null; } } Cci.INamespaceTypeDefinition Cci.ITypeReference.AsNamespaceTypeDefinition(EmitContext context) { return null; } Cci.INamespaceTypeReference Cci.ITypeReference.AsNamespaceTypeReference { get { return null; } } Cci.INestedTypeDefinition Cci.ITypeReference.AsNestedTypeDefinition(EmitContext context) { return null; } Cci.INestedTypeReference Cci.ITypeReference.AsNestedTypeReference { get { return null; } } Cci.ISpecializedNestedTypeReference Cci.ITypeReference.AsSpecializedNestedTypeReference { get { return null; } } Cci.ITypeDefinition Cci.ITypeReference.AsTypeDefinition(EmitContext context) { return null; } void Cci.IReference.Dispatch(Cci.MetadataVisitor visitor) { throw ExceptionUtilities.Unreachable(); //We've not yet discovered a scenario in which we need this. //If you're hitting this exception, uncomment the code below //and add a unit test. #if false Debug.Assert(this.IsDefinition); SymbolKind kind = this.ContainingSymbol.Kind; if (((Module)visitor.Context).SourceModule == this.ContainingModule) { if (kind == SymbolKind.NamedType) { visitor.Visit((IGenericTypeParameter)this); } else if (kind == SymbolKind.Method) { visitor.Visit((IGenericMethodParameter)this); } else { throw new NotSupportedException(); } } else { if (kind == SymbolKind.NamedType) { visitor.Visit((IGenericTypeParameterReference)this); } else if (kind == SymbolKind.Method) { visitor.Visit((IGenericMethodParameterReference)this); } else { throw new NotSupportedException(); } } #endif } Cci.IDefinition Cci.IReference.AsDefinition(EmitContext context) { Debug.Assert(AdaptedTypeParameterSymbol.IsDefinition); return null; } string Cci.INamedEntity.Name { get { return AdaptedTypeParameterSymbol.MetadataName; } } ushort Cci.IParameterListEntry.Index { get { return (ushort)AdaptedTypeParameterSymbol.Ordinal; } } Cci.IMethodReference Cci.IGenericMethodParameterReference.DefiningMethod { get { Debug.Assert(AdaptedTypeParameterSymbol.IsDefinition); return ((MethodSymbol)AdaptedTypeParameterSymbol.ContainingSymbol).GetCciAdapter(); } } Cci.ITypeReference Cci.IGenericTypeParameterReference.DefiningType { get { Debug.Assert(AdaptedTypeParameterSymbol.IsDefinition); return ((NamedTypeSymbol)AdaptedTypeParameterSymbol.ContainingSymbol).GetCciAdapter(); } } IEnumerable<Cci.TypeReferenceWithAttributes> Cci.IGenericParameter.GetConstraints(EmitContext context) { var moduleBeingBuilt = (PEModuleBuilder)context.Module; var seenValueType = false; if (AdaptedTypeParameterSymbol.HasUnmanagedTypeConstraint) { var typeRef = moduleBeingBuilt.GetSpecialType( SpecialType.System_ValueType, syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNode, diagnostics: context.Diagnostics); var modifier = CSharpCustomModifier.CreateRequired( moduleBeingBuilt.Compilation.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_UnmanagedType)); // emit "(class [mscorlib]System.ValueType modreq([mscorlib]System.Runtime.InteropServices.UnmanagedType" pattern as "unmanaged" yield return new Cci.TypeReferenceWithAttributes(new Cci.ModifiedTypeReference(typeRef, ImmutableArray.Create<Cci.ICustomModifier>(modifier))); // do not emit another one for Dev11 similarities seenValueType = true; } foreach (var type in AdaptedTypeParameterSymbol.ConstraintTypesNoUseSiteDiagnostics) { switch (type.SpecialType) { case SpecialType.System_Object: Debug.Assert(!type.NullableAnnotation.IsAnnotated()); break; case SpecialType.System_ValueType: seenValueType = true; break; } var typeRef = moduleBeingBuilt.Translate(type.Type, syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNode, diagnostics: context.Diagnostics); yield return type.GetTypeRefWithAttributes( moduleBeingBuilt, declaringSymbol: AdaptedTypeParameterSymbol, typeRef); } if (AdaptedTypeParameterSymbol.HasValueTypeConstraint && !seenValueType) { // Add System.ValueType constraint to comply with Dev11 output var typeRef = moduleBeingBuilt.GetSpecialType(SpecialType.System_ValueType, syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNode, diagnostics: context.Diagnostics); yield return new Cci.TypeReferenceWithAttributes(typeRef); } } bool Cci.IGenericParameter.MustBeReferenceType { get { return AdaptedTypeParameterSymbol.HasReferenceTypeConstraint; } } bool Cci.IGenericParameter.MustBeValueType { get { return AdaptedTypeParameterSymbol.HasValueTypeConstraint || AdaptedTypeParameterSymbol.HasUnmanagedTypeConstraint; } } bool Cci.IGenericParameter.AllowsRefLikeType { get { return AdaptedTypeParameterSymbol.AllowsRefLikeType; } } bool Cci.IGenericParameter.MustHaveDefaultConstructor { get { // add constructor constraint for value type constrained // type parameters to comply with Dev11 output // do this for "unmanaged" constraint too return AdaptedTypeParameterSymbol.HasConstructorConstraint || AdaptedTypeParameterSymbol.HasValueTypeConstraint || AdaptedTypeParameterSymbol.HasUnmanagedTypeConstraint; } } Cci.TypeParameterVariance Cci.IGenericParameter.Variance { get { switch (AdaptedTypeParameterSymbol.Variance) { case VarianceKind.None: return Cci.TypeParameterVariance.NonVariant; case VarianceKind.In: return Cci.TypeParameterVariance.Contravariant; case VarianceKind.Out: return Cci.TypeParameterVariance.Covariant; default: throw ExceptionUtilities.UnexpectedValue(AdaptedTypeParameterSymbol.Variance); } } } Cci.IMethodDefinition Cci.IGenericMethodParameter.DefiningMethod { get { CheckDefinitionInvariant(); return ((MethodSymbol)AdaptedTypeParameterSymbol.ContainingSymbol).GetCciAdapter(); } } Cci.ITypeDefinition Cci.IGenericTypeParameter.DefiningType { get { CheckDefinitionInvariant(); return ((NamedTypeSymbol)AdaptedTypeParameterSymbol.ContainingSymbol).GetCciAdapter(); } } } internal partial class TypeParameterSymbol { #if DEBUG private TypeParameterSymbolAdapter _lazyAdapter; protected sealed override SymbolAdapter GetCciAdapterImpl() => GetCciAdapter(); internal new TypeParameterSymbolAdapter GetCciAdapter() { if (_lazyAdapter is null) { return InterlockedOperations.Initialize(ref _lazyAdapter, new TypeParameterSymbolAdapter(this)); } return _lazyAdapter; } #else internal TypeParameterSymbol AdaptedTypeParameterSymbol => this; internal new TypeParameterSymbol GetCciAdapter() { return this; } #endif } #if DEBUG internal partial class TypeParameterSymbolAdapter { internal TypeParameterSymbolAdapter(TypeParameterSymbol underlyingTypeParameterSymbol) { AdaptedTypeParameterSymbol = underlyingTypeParameterSymbol; } internal sealed override Symbol AdaptedSymbol => AdaptedTypeParameterSymbol; internal TypeParameterSymbol AdaptedTypeParameterSymbol { get; } } #endif }