File: Symbols\InstanceTypeSymbol.vb
Web Access
Project: src\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic)
' 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.
 
Imports System.Collections.Generic
Imports System.Collections.Immutable
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
    ''' <summary>
    ''' An InstanceTypeSymbol is a NamedTypeSymbol that is a pure instance type, where the class
    ''' (and any containing classes) have no type substitutions applied.
    ''' This class provide shared implementation for types whose definition is (possibly lazily)
    ''' constructed from source or metadata. It provides the shared implementation between these two, primarily
    ''' the implementation of Construct and InternalSubstituteTypeParameters.
    ''' </summary>
    Friend MustInherit Class InstanceTypeSymbol
        Inherits NamedTypeSymbol
 
        Friend NotOverridable Overrides ReadOnly Property TypeArgumentsNoUseSiteDiagnostics As ImmutableArray(Of TypeSymbol)
            Get
                ' This is always the instance type, so the type arguments are the same as the type parameters.
                If Arity > 0 Then
                    Return StaticCast(Of TypeSymbol).From(Me.TypeParameters)
                Else
                    Return ImmutableArray(Of TypeSymbol).Empty
                End If
            End Get
        End Property
 
        Public NotOverridable Overrides Function GetTypeArgumentCustomModifiers(ordinal As Integer) As ImmutableArray(Of CustomModifier)
            ' This is always the instance type, so the type arguments do not have any modifiers.
            Return GetEmptyTypeArgumentCustomModifiers(ordinal)
        End Function
 
        Friend NotOverridable Overrides ReadOnly Property HasTypeArgumentsCustomModifiers As Boolean
            Get
                ' This is always the instance type, so the type arguments do not have any modifiers.
                Return False
            End Get
        End Property
 
        ' Instance types are always constructible if they have arity >= 1
        Friend Overrides ReadOnly Property CanConstruct As Boolean
            Get
                Return Arity > 0
            End Get
        End Property
 
        Public NotOverridable Overrides Function Construct(typeArguments As ImmutableArray(Of TypeSymbol)) As NamedTypeSymbol
            CheckCanConstructAndTypeArguments(typeArguments)
 
            Dim substitution = VisualBasic.Symbols.TypeSubstitution.Create(Me, Me.TypeParameters, typeArguments, allowAlphaRenamedTypeParametersAsArguments:=True)
 
            If substitution Is Nothing Then
                Return Me
            Else
                Debug.Assert(substitution.TargetGenericDefinition Is Me)
                Return New SubstitutedNamedType.ConstructedInstanceType(substitution)
            End If
        End Function
 
        ''' <summary>
        ''' Substitute the given type substitution within this type, returning a new type. If the
        ''' substitution had no effect, return Me. 
        ''' !!! Only code implementing construction of generic types is allowed to call this method !!!
        ''' !!! All other code should use Construct methods.                                        !!! 
        ''' </summary>
        Friend Overrides Function InternalSubstituteTypeParameters(substitution As TypeSubstitution) As TypeWithModifiers
            Return New TypeWithModifiers(SubstituteTypeParametersInNamedType(substitution))
        End Function
 
        Private Function SubstituteTypeParametersInNamedType(substitution As TypeSubstitution) As NamedTypeSymbol
 
            If substitution IsNot Nothing Then
                ' The substitution might target one of this type's children.
                substitution = substitution.GetSubstitutionForGenericDefinitionOrContainers(Me)
            End If
 
            If substitution Is Nothing Then
                Return Me
            End If
 
            ' Substitution targets either this type or one of its containers
            Dim newContainer As NamedTypeSymbol
 
            If substitution.TargetGenericDefinition Is Me Then
 
                If substitution.Parent Is Nothing Then
                    Debug.Assert(Me.Arity > 0)
                    Return New SubstitutedNamedType.ConstructedInstanceType(substitution)
                End If
 
                newContainer = DirectCast(Me.ContainingType.InternalSubstituteTypeParameters(substitution.Parent).AsTypeSymbolOnly(), NamedTypeSymbol)
            Else
                newContainer = DirectCast(Me.ContainingType.InternalSubstituteTypeParameters(substitution).AsTypeSymbolOnly(), NamedTypeSymbol)
            End If
 
            Debug.Assert(Me.ContainingType IsNot Nothing)
 
            If Me.Arity = 0 Then
                Debug.Assert(Not newContainer.IsDefinition)
                Return SubstitutedNamedType.SpecializedNonGenericType.Create(DirectCast(newContainer, NamedTypeSymbol), Me, substitution)
            End If
 
            ' First we need to create SpecializedGenericType to construct this guy from.
            Dim constructFrom = SubstitutedNamedType.SpecializedGenericType.Create(DirectCast(newContainer, NamedTypeSymbol), Me)
 
            If substitution.TargetGenericDefinition Is Me Then
                Debug.Assert(newContainer.TypeSubstitution Is substitution.Parent) ' How can it be otherwise? The contained type didn't have any substitution before.
                Return New SubstitutedNamedType.ConstructedSpecializedGenericType(constructFrom, substitution)
            End If
 
            Return constructFrom
        End Function
 
        Friend Overrides ReadOnly Property TypeSubstitution As TypeSubstitution
            Get
                Return Nothing
            End Get
        End Property
 
        Public Overrides ReadOnly Property ConstructedFrom As NamedTypeSymbol
            Get
                Return Me
            End Get
        End Property
 
        Public Overrides Function GetHashCode() As Integer
            Return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(Me)
        End Function
 
        Public Overrides Function Equals(other As TypeSymbol, comparison As TypeCompareKind) As Boolean
            If other Is Me Then
                Return True
            End If
 
            If other Is Nothing OrElse (comparison And TypeCompareKind.AllIgnoreOptionsForVB) = 0 Then
                Return False
            End If
 
            Dim otherTuple = TryCast(other, TupleTypeSymbol)
            If otherTuple IsNot Nothing Then
                Return otherTuple.Equals(Me, comparison)
            End If
 
            If other.OriginalDefinition IsNot Me Then
                Return False
            End If
 
            ' Delegate comparison to the other type to ensure symmetry
            Debug.Assert(TypeOf other Is SubstitutedNamedType)
            Return other.Equals(Me, comparison)
        End Function
 
#Region "Use-Site Diagnostics"
 
        Protected Function CalculateUseSiteInfo() As UseSiteInfo(Of AssemblySymbol)
            ' Check base type.
            Dim useSiteInfo = New UseSiteInfo(Of AssemblySymbol)(PrimaryDependency).AdjustDiagnosticInfo(DeriveUseSiteErrorInfoFromBase())
 
            If useSiteInfo.DiagnosticInfo IsNot Nothing Then
                Return useSiteInfo
            End If
 
            ' If we reach a type (Me) that is in an assembly with unified references, 
            ' we check if that type definition depends on a type from a unified reference.
            If Me.ContainingModule.HasUnifiedReferences Then
                Dim errorInfo As DiagnosticInfo = GetUnificationUseSiteDiagnosticRecursive(Me, checkedTypes:=Nothing)
                If errorInfo IsNot Nothing Then
                    Debug.Assert(errorInfo.Severity = DiagnosticSeverity.Error)
                    useSiteInfo = New UseSiteInfo(Of AssemblySymbol)(errorInfo)
                End If
            End If
 
            Return useSiteInfo
        End Function
 
        Private Function DeriveUseSiteErrorInfoFromBase() As DiagnosticInfo
 
            Dim base As NamedTypeSymbol = Me.BaseTypeNoUseSiteDiagnostics
 
            While base IsNot Nothing
 
                If base.IsErrorType() AndAlso TypeOf base Is NoPiaIllegalGenericInstantiationSymbol Then
                    Return base.GetUseSiteInfo().DiagnosticInfo
                End If
 
                base = base.BaseTypeNoUseSiteDiagnostics
            End While
 
            Return Nothing
        End Function
 
        Friend NotOverridable Overrides Function GetUnificationUseSiteDiagnosticRecursive(owner As Symbol, ByRef checkedTypes As HashSet(Of TypeSymbol)) As DiagnosticInfo
            Debug.Assert(owner.ContainingModule.HasUnifiedReferences)
 
            If Not MarkCheckedIfNecessary(checkedTypes) Then
                Return Nothing
            End If
 
            Dim info = owner.ContainingModule.GetUnificationUseSiteErrorInfo(Me)
            If info IsNot Nothing Then
                Return info
            End If
 
            ' TODO (tomat): use-site errors should be reported on each part of a qualified name,
            ' we shouldn't need to walk containing types here (see bug 15793)
            ' containing type
            Dim containing = Me.ContainingType
            If containing IsNot Nothing Then
                info = containing.GetUnificationUseSiteDiagnosticRecursive(owner, checkedTypes)
                If info IsNot Nothing Then
                    Return info
                End If
            End If
 
            ' base type
            Dim base = Me.BaseTypeNoUseSiteDiagnostics
            If base IsNot Nothing Then
                info = base.GetUnificationUseSiteDiagnosticRecursive(owner, checkedTypes)
                If info IsNot Nothing Then
                    Return info
                End If
            End If
 
            ' implemented interfaces, type parameter constraints, type arguments
            Return If(GetUnificationUseSiteDiagnosticRecursive(Me.InterfacesNoUseSiteDiagnostics, owner, checkedTypes),
                      GetUnificationUseSiteDiagnosticRecursive(Me.TypeParameters, owner, checkedTypes))
        End Function
#End Region
    End Class
 
End Namespace