File: Symbols\Tuples\TupleTypeSymbol.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.Immutable
Imports System.Globalization
Imports System.Runtime.InteropServices
Imports System.Threading
Imports Microsoft.CodeAnalysis.Collections
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.RuntimeMembers
Imports Microsoft.CodeAnalysis.VisualBasic.Emit
Imports ReferenceEqualityComparer = Roslyn.Utilities.ReferenceEqualityComparer
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
    Friend NotInheritable Class TupleTypeSymbol
        Inherits WrappedNamedTypeSymbol
 
        Private ReadOnly _locations As ImmutableArray(Of Location)
 
        Private ReadOnly _elementLocations As ImmutableArray(Of Location)
 
        ''' <summary>
        ''' Names of the elements as provided when tuple was created
        ''' </summary>
        Private ReadOnly _providedElementNames As ImmutableArray(Of String)
 
        ''' <summary>
        ''' Which element names were inferred and therefore cannot be used.
        ''' If none of the element names were inferred, or inferred names can be used (no tracking necessary), leave as default.
        ''' This information is ignored in type equality and comparison.
        ''' </summary>
        Private ReadOnly _errorPositions As ImmutableArray(Of Boolean)
 
        ''' <summary>
        ''' Actual element names.
        ''' Could be different from _providedElementNames because of case insensitivity.
        ''' I.E. - it is not an error to provide "item1" name to the first element
        '''        however its name must be "Item1", since it already has the name "Item1"
        '''        and having both "item1" and "Item1" names would be ambiguous
        ''' </summary>
        Private _lazyActualElementNames As ImmutableArray(Of String)
 
        Private ReadOnly _elementTypes As ImmutableArray(Of TypeSymbol)
 
        Private _lazyMembers As ImmutableArray(Of Symbol)
 
        Private _lazyFields As ImmutableArray(Of FieldSymbol)
 
        Private _lazyUnderlyingDefinitionToMemberMap As SmallDictionary(Of Symbol, Symbol)
 
        Friend Const RestPosition As Integer = 8
        Friend Const RestIndex As Integer = RestPosition - 1
 
        Friend Const TupleTypeName As String = "ValueTuple"
        Friend Const RestFieldName As String = "Rest"
 
        Private Shared ReadOnly tupleTypes As WellKnownType() = New WellKnownType() {WellKnownType.System_ValueTuple_T1, WellKnownType.System_ValueTuple_T2, WellKnownType.System_ValueTuple_T3, WellKnownType.System_ValueTuple_T4, WellKnownType.System_ValueTuple_T5, WellKnownType.System_ValueTuple_T6, WellKnownType.System_ValueTuple_T7, WellKnownType.System_ValueTuple_TRest}
 
        Private Shared ReadOnly tupleCtors As WellKnownMember() = New WellKnownMember() {WellKnownMember.System_ValueTuple_T1__ctor, WellKnownMember.System_ValueTuple_T2__ctor, WellKnownMember.System_ValueTuple_T3__ctor, WellKnownMember.System_ValueTuple_T4__ctor, WellKnownMember.System_ValueTuple_T5__ctor, WellKnownMember.System_ValueTuple_T6__ctor, WellKnownMember.System_ValueTuple_T7__ctor, WellKnownMember.System_ValueTuple_TRest__ctor}
 
        Private Shared ReadOnly tupleMembers As WellKnownMember()() = New WellKnownMember()() {
            New WellKnownMember() {WellKnownMember.System_ValueTuple_T1__Item1},
            New WellKnownMember() {WellKnownMember.System_ValueTuple_T2__Item1, WellKnownMember.System_ValueTuple_T2__Item2},
            New WellKnownMember() {WellKnownMember.System_ValueTuple_T3__Item1, WellKnownMember.System_ValueTuple_T3__Item2, WellKnownMember.System_ValueTuple_T3__Item3},
            New WellKnownMember() {WellKnownMember.System_ValueTuple_T4__Item1, WellKnownMember.System_ValueTuple_T4__Item2, WellKnownMember.System_ValueTuple_T4__Item3, WellKnownMember.System_ValueTuple_T4__Item4},
            New WellKnownMember() {WellKnownMember.System_ValueTuple_T5__Item1, WellKnownMember.System_ValueTuple_T5__Item2, WellKnownMember.System_ValueTuple_T5__Item3, WellKnownMember.System_ValueTuple_T5__Item4, WellKnownMember.System_ValueTuple_T5__Item5},
            New WellKnownMember() {WellKnownMember.System_ValueTuple_T6__Item1, WellKnownMember.System_ValueTuple_T6__Item2, WellKnownMember.System_ValueTuple_T6__Item3, WellKnownMember.System_ValueTuple_T6__Item4, WellKnownMember.System_ValueTuple_T6__Item5, WellKnownMember.System_ValueTuple_T6__Item6},
            New WellKnownMember() {WellKnownMember.System_ValueTuple_T7__Item1, WellKnownMember.System_ValueTuple_T7__Item2, WellKnownMember.System_ValueTuple_T7__Item3, WellKnownMember.System_ValueTuple_T7__Item4, WellKnownMember.System_ValueTuple_T7__Item5, WellKnownMember.System_ValueTuple_T7__Item6, WellKnownMember.System_ValueTuple_T7__Item7},
            New WellKnownMember() {WellKnownMember.System_ValueTuple_TRest__Item1, WellKnownMember.System_ValueTuple_TRest__Item2, WellKnownMember.System_ValueTuple_TRest__Item3, WellKnownMember.System_ValueTuple_TRest__Item4, WellKnownMember.System_ValueTuple_TRest__Item5, WellKnownMember.System_ValueTuple_TRest__Item6, WellKnownMember.System_ValueTuple_TRest__Item7, WellKnownMember.System_ValueTuple_TRest__Rest}}
 
        Public Overrides ReadOnly Property IsTupleType As Boolean
            Get
                Return True
            End Get
        End Property
 
        Public Overrides ReadOnly Property TupleUnderlyingType As NamedTypeSymbol
            Get
                Return Me._underlyingType
            End Get
        End Property
 
        Public Overrides ReadOnly Property TupleElementTypes As ImmutableArray(Of TypeSymbol)
            Get
                Return Me._elementTypes
            End Get
        End Property
 
        Public Overrides ReadOnly Property TupleElementNames As ImmutableArray(Of String)
            Get
                If _providedElementNames.IsDefault Then
                    Return Nothing
                End If
 
                If _lazyActualElementNames.IsDefault Then
                    _lazyActualElementNames = Me.TupleElements.SelectAsArray(Function(e) If(e.IsImplicitlyDeclared, Nothing, e.Name))
                End If
 
                Return _lazyActualElementNames
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsImplicitlyDeclared As Boolean
            Get
                Return False
            End Get
        End Property
 
        ''' <summary>
        ''' Get the default fields for the tuple's elements (in order and cached).
        ''' </summary>
        Public Overrides ReadOnly Property TupleElements As ImmutableArray(Of FieldSymbol)
            Get
                Dim isDefault As Boolean = Me._lazyFields.IsDefault
                If isDefault Then
                    ImmutableInterlocked.InterlockedInitialize(Of FieldSymbol)(Me._lazyFields, Me.CollectTupleElementFields())
                End If
                Return Me._lazyFields
            End Get
        End Property
 
        Friend ReadOnly Property UnderlyingDefinitionToMemberMap As SmallDictionary(Of Symbol, Symbol)
            Get
                If Me._lazyUnderlyingDefinitionToMemberMap Is Nothing Then
                    Me._lazyUnderlyingDefinitionToMemberMap = Me.ComputeDefinitionToMemberMap()
                End If
                Return Me._lazyUnderlyingDefinitionToMemberMap
            End Get
        End Property
 
        Public Overrides ReadOnly Property EnumUnderlyingType As NamedTypeSymbol
            Get
                Return Me._underlyingType.EnumUnderlyingType
            End Get
        End Property
 
        Public Overrides ReadOnly Property Kind As SymbolKind
            Get
                Return SymbolKind.NamedType
            End Get
        End Property
 
        Public Overrides ReadOnly Property TypeKind As TypeKind
            Get
                ' From the language perspective tuple is a value type
                ' composed of its underlying elements
                Return TypeKind.Struct
            End Get
        End Property
 
        Public Overrides ReadOnly Property ContainingSymbol As Symbol
            Get
                Return Me._underlyingType.ContainingSymbol
            End Get
        End Property
 
        Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location)
            Get
                Return Me._locations
            End Get
        End Property
 
        Public Overrides ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference)
            Get
                Return Symbol.GetDeclaringSyntaxReferenceHelper(Of VisualBasicSyntaxNode)(Me._locations)
            End Get
        End Property
 
        Public Overrides ReadOnly Property DeclaredAccessibility As Accessibility
            Get
                Dim result As Accessibility
                If Me._underlyingType.IsErrorType() Then
                    result = Accessibility.[Public]
                Else
                    result = Me._underlyingType.DeclaredAccessibility
                End If
                Return result
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsMustInherit As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsNotInheritable As Boolean
            Get
                Return True
            End Get
        End Property
 
        Public Overrides ReadOnly Property Arity As Integer
            Get
                Return 0
            End Get
        End Property
 
        Public Overrides ReadOnly Property TypeParameters As ImmutableArray(Of TypeParameterSymbol)
            Get
                Return ImmutableArray(Of TypeParameterSymbol).Empty
            End Get
        End Property
 
        Public Overrides Function GetTypeArgumentCustomModifiers(ordinal As Integer) As ImmutableArray(Of CustomModifier)
            Return GetEmptyTypeArgumentCustomModifiers(ordinal)
        End Function
 
        Friend Overrides ReadOnly Property HasTypeArgumentsCustomModifiers As Boolean
            Get
                Return False
            End Get
        End Property
 
        Friend Overrides ReadOnly Property TypeArgumentsNoUseSiteDiagnostics As ImmutableArray(Of TypeSymbol)
            Get
                Return ImmutableArray(Of TypeSymbol).Empty
            End Get
        End Property
 
        Public Overrides ReadOnly Property ConstructedFrom As NamedTypeSymbol
            Get
                Return Me
            End Get
        End Property
 
        Public Overrides ReadOnly Property MightContainExtensionMethods As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property Name As String
            Get
                Return String.Empty
            End Get
        End Property
 
        Friend Overrides ReadOnly Property MangleName As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Iterator Property MemberNames As IEnumerable(Of String)
            Get
                Dim [set] = PooledHashSet(Of String).GetInstance()
                For Each member In GetMembers()
                    Dim name = member.Name
                    If [set].Add(name) Then
                        Yield name
                    End If
                Next
 
                [set].Free()
            End Get
        End Property
 
        Friend Overrides ReadOnly Property HasSpecialName As Boolean
            Get
                Return False
            End Get
        End Property
 
        Friend Overrides ReadOnly Property IsComImport As Boolean
            Get
                Return False
            End Get
        End Property
 
        Friend Overrides ReadOnly Property IsWindowsRuntimeImport As Boolean
            Get
                Return False
            End Get
        End Property
 
        Friend Overrides ReadOnly Property ShouldAddWinRTMembers As Boolean
            Get
                Return False
            End Get
        End Property
 
        Public Overrides ReadOnly Property IsSerializable As Boolean
            Get
                Return Me._underlyingType.IsSerializable
            End Get
        End Property
 
        Friend Overrides ReadOnly Property Layout As TypeLayout
            Get
                Return Me._underlyingType.Layout
            End Get
        End Property
 
        Friend Overrides ReadOnly Property MarshallingCharSet As CharSet
            Get
                Return Me._underlyingType.MarshallingCharSet
            End Get
        End Property
 
        Friend Overrides ReadOnly Property HasDeclarativeSecurity As Boolean
            Get
                Return Me._underlyingType.HasDeclarativeSecurity
            End Get
        End Property
 
        Friend Overrides ReadOnly Property IsInterface As Boolean
            Get
                Return False
            End Get
        End Property
 
        Friend Overrides ReadOnly Property IsExtensibleInterfaceNoUseSiteDiagnostics As Boolean
            Get
                Return Me._underlyingType.IsExtensibleInterfaceNoUseSiteDiagnostics
            End Get
        End Property
 
        Friend Overrides ReadOnly Property CanConstruct As Boolean
            Get
                Return False
            End Get
        End Property
 
        Friend Overrides ReadOnly Property TypeSubstitution As TypeSubstitution
            Get
                Return Nothing
            End Get
        End Property
 
        Private Sub New(locationOpt As Location, underlyingType As NamedTypeSymbol, elementLocations As ImmutableArray(Of Location),
                        elementNames As ImmutableArray(Of String), elementTypes As ImmutableArray(Of TypeSymbol),
                        errorPositions As ImmutableArray(Of Boolean))
 
            Me.New(If((locationOpt Is Nothing), ImmutableArray(Of Location).Empty, ImmutableArray.Create(Of Location)(locationOpt)),
                   underlyingType, elementLocations, elementNames, elementTypes, errorPositions)
        End Sub
 
        Private Sub New(locations As ImmutableArray(Of Location), underlyingType As NamedTypeSymbol,
                        elementLocations As ImmutableArray(Of Location), elementNames As ImmutableArray(Of String),
                        elementTypes As ImmutableArray(Of TypeSymbol), errorPositions As ImmutableArray(Of Boolean))
 
            MyBase.New(underlyingType)
            Debug.Assert(elementLocations.IsDefault OrElse elementLocations.Length = elementTypes.Length)
            Debug.Assert(elementNames.IsDefault OrElse elementNames.Length = elementTypes.Length)
            Debug.Assert(Not underlyingType.IsTupleType)
            Debug.Assert(TypeOf underlyingType Is InstanceTypeSymbol OrElse
                         TypeOf underlyingType Is InstanceErrorTypeSymbol OrElse
                         TypeOf underlyingType Is SubstitutedNamedType OrElse
                         TypeOf underlyingType Is SubstitutedErrorType) ' Required to ensure symmetrical equality
            Me._elementLocations = elementLocations
            Me._providedElementNames = elementNames
            Me._elementTypes = elementTypes
            Me._locations = locations
            Me._errorPositions = errorPositions
        End Sub
 
        Friend Shared Function Create(
                                     locationOpt As Location,
                                     elementTypes As ImmutableArray(Of TypeSymbol),
                                     elementLocations As ImmutableArray(Of Location),
                                     elementNames As ImmutableArray(Of String),
                                     compilation As VisualBasicCompilation,
                                     shouldCheckConstraints As Boolean,
                                     errorPositions As ImmutableArray(Of Boolean),
                                     Optional syntax As SyntaxNode = Nothing,
                                     Optional diagnostics As BindingDiagnosticBag = Nothing) As TupleTypeSymbol
            Debug.Assert(Not shouldCheckConstraints OrElse syntax IsNot Nothing)
            Debug.Assert(elementNames.IsDefault OrElse elementTypes.Length = elementNames.Length)
            Dim length As Integer = elementTypes.Length
 
            If length <= 1 Then
                Throw ExceptionUtilities.Unreachable
            End If
 
            Dim tupleUnderlyingType As NamedTypeSymbol = TupleTypeSymbol.GetTupleUnderlyingType(elementTypes, syntax, compilation, diagnostics)
            If diagnostics?.DiagnosticBag IsNot Nothing AndAlso DirectCast(compilation.SourceModule, SourceModuleSymbol).AnyReferencedAssembliesAreLinked Then
                ' Complain about unembeddable types from linked assemblies.
                Emit.NoPia.EmbeddedTypesManager.IsValidEmbeddableType(tupleUnderlyingType, syntax, diagnostics.DiagnosticBag)
            End If
 
            Dim constructedType = TupleTypeSymbol.Create(locationOpt, tupleUnderlyingType, elementLocations, elementNames, errorPositions)
            If shouldCheckConstraints Then
                constructedType.CheckConstraints(syntax, elementLocations, diagnostics, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, compilation.Assembly))
            End If
 
            Return constructedType
        End Function
 
        Public Shared Function Create(tupleCompatibleType As NamedTypeSymbol) As TupleTypeSymbol
            Return TupleTypeSymbol.Create(ImmutableArray(Of Location).Empty, tupleCompatibleType, Nothing, Nothing, Nothing)
        End Function
 
        Public Shared Function Create(tupleCompatibleType As NamedTypeSymbol, elementNames As ImmutableArray(Of String)) As TupleTypeSymbol
            Return TupleTypeSymbol.Create(ImmutableArray(Of Location).Empty, tupleCompatibleType, Nothing, elementNames, errorPositions:=Nothing)
        End Function
 
        Public Shared Function Create(locationOpt As Location, tupleCompatibleType As NamedTypeSymbol,
                                      elementLocations As ImmutableArray(Of Location), elementNames As ImmutableArray(Of String),
                                      errorPositions As ImmutableArray(Of Boolean)) As TupleTypeSymbol
 
            Return TupleTypeSymbol.Create(If((locationOpt Is Nothing), ImmutableArray(Of Location).Empty, ImmutableArray.Create(Of Location)(locationOpt)),
                                          tupleCompatibleType, elementLocations, elementNames, errorPositions)
        End Function
 
        Public Shared Function Create(locations As ImmutableArray(Of Location), tupleCompatibleType As NamedTypeSymbol,
                                      elementLocations As ImmutableArray(Of Location), elementNames As ImmutableArray(Of String),
                                      errorPositions As ImmutableArray(Of Boolean)) As TupleTypeSymbol
 
            Debug.Assert(tupleCompatibleType.IsTupleCompatible())
 
            Dim elementTypes As ImmutableArray(Of TypeSymbol)
            If tupleCompatibleType.Arity = TupleTypeSymbol.RestPosition Then
                tupleCompatibleType = TupleTypeSymbol.EnsureRestExtensionsAreTuples(tupleCompatibleType)
                Dim tupleElementTypes As ImmutableArray(Of TypeSymbol) = tupleCompatibleType.TypeArgumentsNoUseSiteDiagnostics(TupleTypeSymbol.RestPosition - 1).TupleElementTypes
                Dim instance As ArrayBuilder(Of TypeSymbol) = ArrayBuilder(Of TypeSymbol).GetInstance(TupleTypeSymbol.RestPosition - 1 + tupleElementTypes.Length)
                instance.AddRange(tupleCompatibleType.TypeArgumentsNoUseSiteDiagnostics, TupleTypeSymbol.RestPosition - 1)
                instance.AddRange(tupleElementTypes)
                elementTypes = instance.ToImmutableAndFree()
            Else
                elementTypes = tupleCompatibleType.TypeArgumentsNoUseSiteDiagnostics
            End If
 
            Return New TupleTypeSymbol(locations, tupleCompatibleType, elementLocations, elementNames, elementTypes, errorPositions)
        End Function
 
        Private Shared Function EnsureRestExtensionsAreTuples(tupleCompatibleType As NamedTypeSymbol) As NamedTypeSymbol
            If Not tupleCompatibleType.TypeArgumentsNoUseSiteDiagnostics(TupleTypeSymbol.RestPosition - 1).IsTupleType Then
                Dim nonTupleTypeChain As ArrayBuilder(Of NamedTypeSymbol) = ArrayBuilder(Of NamedTypeSymbol).GetInstance()
                Dim namedTypeSymbol As NamedTypeSymbol = tupleCompatibleType
 
                Do
                    nonTupleTypeChain.Add(namedTypeSymbol)
                    namedTypeSymbol = CType(namedTypeSymbol.TypeArgumentsNoUseSiteDiagnostics(TupleTypeSymbol.RestPosition - 1), NamedTypeSymbol)
                Loop While namedTypeSymbol.Arity = TupleTypeSymbol.RestPosition
 
                If Not namedTypeSymbol.IsTupleType Then
                    nonTupleTypeChain.Add(namedTypeSymbol)
                End If
 
                Debug.Assert(nonTupleTypeChain.Count > 1)
                tupleCompatibleType = nonTupleTypeChain.Pop()
 
                Dim typeArgumentsBuilder As ArrayBuilder(Of TypeWithModifiers) = ArrayBuilder(Of TypeWithModifiers).GetInstance(TupleTypeSymbol.RestPosition)
                Do
                    Dim extensionTuple As TupleTypeSymbol = TupleTypeSymbol.Create(CType(Nothing, Location), tupleCompatibleType, Nothing, Nothing, Nothing)
                    tupleCompatibleType = nonTupleTypeChain.Pop()
                    tupleCompatibleType = TupleTypeSymbol.ReplaceRestExtensionType(tupleCompatibleType, typeArgumentsBuilder, extensionTuple)
                Loop While nonTupleTypeChain.Count <> 0
 
                typeArgumentsBuilder.Free()
                nonTupleTypeChain.Free()
            End If
            Return tupleCompatibleType
        End Function
 
        Private Shared Function ReplaceRestExtensionType(tupleCompatibleType As NamedTypeSymbol, typeArgumentsBuilder As ArrayBuilder(Of TypeWithModifiers), extensionTuple As TupleTypeSymbol) As NamedTypeSymbol
            Dim hasTypeArgumentsCustomModifiers As Boolean = tupleCompatibleType.HasTypeArgumentsCustomModifiers
 
            Dim typeArgumentsNoUseSiteDiagnostics As ImmutableArray(Of TypeSymbol) = tupleCompatibleType.TypeArgumentsNoUseSiteDiagnostics
            typeArgumentsBuilder.Clear()
 
            For i As Integer = 0 To TupleTypeSymbol.RestPosition - 1 - 1
                typeArgumentsBuilder.Add(New TypeWithModifiers(typeArgumentsNoUseSiteDiagnostics(i),
                                                               If(hasTypeArgumentsCustomModifiers, tupleCompatibleType.GetTypeArgumentCustomModifiers(i), Nothing)))
            Next
 
            typeArgumentsBuilder.Add(New TypeWithModifiers(extensionTuple,
                                                           If(hasTypeArgumentsCustomModifiers, tupleCompatibleType.GetTypeArgumentCustomModifiers(TupleTypeSymbol.RestPosition - 1), Nothing)))
 
            Dim definition = tupleCompatibleType.ConstructedFrom
            Dim subst = TypeSubstitution.Create(definition, definition.TypeParameters, typeArgumentsBuilder.ToImmutable(), False)
            Return definition.Construct(subst)
        End Function
 
        Friend Function WithUnderlyingType(newUnderlyingType As NamedTypeSymbol) As TupleTypeSymbol
            Debug.Assert(Not newUnderlyingType.IsTupleType AndAlso newUnderlyingType.IsTupleOrCompatibleWithTupleOfCardinality(Me._elementTypes.Length))
            Return TupleTypeSymbol.Create(Me._locations, newUnderlyingType, Me._elementLocations, Me._providedElementNames, Me._errorPositions)
        End Function
 
        Friend Function WithElementNames(newElementNames As ImmutableArray(Of String)) As TupleTypeSymbol
 
            Debug.Assert(newElementNames.IsDefault OrElse Me._elementTypes.Length = newElementNames.Length)
 
            If Me._providedElementNames.IsDefault Then
                If newElementNames.IsDefault Then
                    Return Me
                End If
            Else
                If Not newElementNames.IsDefault AndAlso Me._providedElementNames.SequenceEqual(newElementNames) Then
                    Return Me
                End If
            End If
 
            ' Note: this method is used to preserved names during target-typing, it doesn't need to preserved error positions
            Return New TupleTypeSymbol(CType(Nothing, Location), Me._underlyingType, Nothing, newElementNames, Me._elementTypes, Nothing)
        End Function
 
        Friend Shared Sub GetUnderlyingTypeChain(underlyingTupleType As NamedTypeSymbol, underlyingTupleTypeChain As ArrayBuilder(Of NamedTypeSymbol))
            Dim namedTypeSymbol As NamedTypeSymbol = underlyingTupleType
            While True
                underlyingTupleTypeChain.Add(namedTypeSymbol)
 
                If namedTypeSymbol.Arity <> TupleTypeSymbol.RestPosition Then
                    Exit While
                End If
                namedTypeSymbol = namedTypeSymbol.TypeArgumentsNoUseSiteDiagnostics(TupleTypeSymbol.RestPosition - 1).TupleUnderlyingType
            End While
        End Sub
 
        Friend Shared Sub AddElementTypes(underlyingTupleType As NamedTypeSymbol, tupleElementTypes As ArrayBuilder(Of TypeSymbol))
            Dim namedTypeSymbol As NamedTypeSymbol = underlyingTupleType
            While True
                Dim isTupleType As Boolean = namedTypeSymbol.IsTupleType
                If isTupleType Then
                    Exit While
                End If
 
                Dim length As Integer = Math.Min(namedTypeSymbol.Arity, TupleTypeSymbol.RestPosition - 1)
                tupleElementTypes.AddRange(namedTypeSymbol.TypeArgumentsNoUseSiteDiagnostics, length)
                If namedTypeSymbol.Arity <> TupleTypeSymbol.RestPosition Then
                    Return
                End If
                namedTypeSymbol = CType(namedTypeSymbol.TypeArgumentsNoUseSiteDiagnostics(TupleTypeSymbol.RestPosition - 1), NamedTypeSymbol)
            End While
            tupleElementTypes.AddRange(namedTypeSymbol.TupleElementTypes)
        End Sub
 
        Private Shared Function GetNestedTupleUnderlyingType(topLevelUnderlyingType As NamedTypeSymbol, depth As Integer) As NamedTypeSymbol
            Dim namedTypeSymbol As NamedTypeSymbol = topLevelUnderlyingType
            For i As Integer = 0 To depth - 1
                namedTypeSymbol = namedTypeSymbol.TypeArgumentsNoUseSiteDiagnostics(TupleTypeSymbol.RestPosition - 1).TupleUnderlyingType
            Next
            Return namedTypeSymbol
        End Function
 
        Private Shared Function NumberOfValueTuples(numElements As Integer, <Out()> ByRef remainder As Integer) As Integer
            remainder = (numElements - 1) Mod (RestPosition - 1) + 1
            Return (numElements - 1) \ (RestPosition - 1) + 1
        End Function
 
        Private Shared Function GetTupleUnderlyingType(elementTypes As ImmutableArray(Of TypeSymbol), syntax As SyntaxNode, compilation As VisualBasicCompilation, diagnostics As BindingDiagnosticBag) As NamedTypeSymbol
            Dim numElements As Integer = elementTypes.Length
            Dim remainder As Integer
            Dim chainLength As Integer = TupleTypeSymbol.NumberOfValueTuples(numElements, remainder)
 
            Dim wellKnownType As NamedTypeSymbol = compilation.GetWellKnownType(TupleTypeSymbol.GetTupleType(remainder))
 
            If diagnostics IsNot Nothing AndAlso syntax IsNot Nothing Then
                Binder.ReportUseSite(diagnostics, syntax, wellKnownType)
            End If
 
            Dim namedTypeSymbol As NamedTypeSymbol = wellKnownType.Construct(ImmutableArray.Create(Of TypeSymbol)(elementTypes, (chainLength - 1) * (TupleTypeSymbol.RestPosition - 1), remainder))
            Dim [loop] As Integer = chainLength - 1
            If [loop] > 0 Then
                Dim wellKnownType2 As NamedTypeSymbol = compilation.GetWellKnownType(TupleTypeSymbol.GetTupleType(TupleTypeSymbol.RestPosition))
 
                If diagnostics IsNot Nothing AndAlso syntax IsNot Nothing Then
                    Binder.ReportUseSite(diagnostics, syntax, wellKnownType2)
                End If
                Do
                    Dim typeArguments As ImmutableArray(Of TypeSymbol) = ImmutableArray.Create(Of TypeSymbol)(elementTypes, ([loop] - 1) * (TupleTypeSymbol.RestPosition - 1), TupleTypeSymbol.RestPosition - 1).Add(namedTypeSymbol)
                    namedTypeSymbol = wellKnownType2.Construct(typeArguments)
                    [loop] -= 1
                Loop While [loop] > 0
            End If
            Return namedTypeSymbol
        End Function
 
        Friend Shared Sub VerifyTupleTypePresent(cardinality As Integer, syntax As VisualBasicSyntaxNode, compilation As VisualBasicCompilation, diagnostics As BindingDiagnosticBag)
            Debug.Assert(diagnostics IsNot Nothing AndAlso syntax IsNot Nothing)
            Dim arity As Integer
            Dim num As Integer = TupleTypeSymbol.NumberOfValueTuples(cardinality, arity)
            Dim wellKnownType As NamedTypeSymbol = compilation.GetWellKnownType(TupleTypeSymbol.GetTupleType(arity))
            Binder.ReportUseSite(diagnostics, syntax, wellKnownType)
 
            If num > 1 Then
                Dim wellKnownType2 As NamedTypeSymbol = compilation.GetWellKnownType(TupleTypeSymbol.GetTupleType(TupleTypeSymbol.RestPosition))
                Binder.ReportUseSite(diagnostics, syntax, wellKnownType2)
            End If
        End Sub
 
        Private Shared Function GetTupleType(arity As Integer) As WellKnownType
            If arity > TupleTypeSymbol.RestPosition Then
                Throw ExceptionUtilities.Unreachable
            End If
 
            Return TupleTypeSymbol.tupleTypes(arity - 1)
        End Function
 
        Friend Shared Function GetTupleCtor(arity As Integer) As WellKnownMember
            If arity > TupleTypeSymbol.RestPosition Then
                Throw ExceptionUtilities.Unreachable
            End If
 
            Return TupleTypeSymbol.tupleCtors(arity - 1)
        End Function
 
        Friend Shared Function GetTupleTypeMember(arity As Integer, position As Integer) As WellKnownMember
            Return TupleTypeSymbol.tupleMembers(arity - 1)(position - 1)
        End Function
 
        Friend Shared Function TupleMemberName(position As Integer) As String
            Return "Item" & position
        End Function
 
        Private Shared ReadOnly ForbiddenNames As HashSet(Of String) = New HashSet(Of String)(
            {"CompareTo", "Deconstruct", "Equals", "GetHashCode", "Rest", "ToString"},
            IdentifierComparison.Comparer)
 
        Private Shared Function IsElementNameForbidden(name As String) As Boolean
            Return ForbiddenNames.Contains(name)
        End Function
 
        Friend Shared Function IsElementNameReserved(name As String) As Integer
            Dim result As Integer
            If TupleTypeSymbol.IsElementNameForbidden(name) Then
                result = 0
            Else
                If IdentifierComparison.StartsWith(name, "Item") Then
                    Dim s As String = name.Substring(4)
                    Dim num As Integer
 
                    If Integer.TryParse(s, num) Then
                        If num > 0 AndAlso IdentifierComparison.Equals(name, TupleTypeSymbol.TupleMemberName(num)) Then
                            result = num
                            Return result
                        End If
                    End If
                End If
                result = -1
            End If
            Return result
        End Function
 
        Private Shared Function GetWellKnownMemberInType(type As NamedTypeSymbol, relativeMember As WellKnownMember) As Symbol
            Debug.Assert(relativeMember >= WellKnownMember.System_ValueTuple_T1__Item1 AndAlso relativeMember <= WellKnownMember.System_ValueTuple_TRest__ctor)
            Debug.Assert(type.IsDefinition)
            Dim descriptor As MemberDescriptor = WellKnownMembers.GetDescriptor(relativeMember)
            Return VisualBasicCompilation.GetRuntimeMember(type, descriptor, VisualBasicCompilation.SpecialMembersSignatureComparer.Instance, Nothing)
        End Function
 
        Friend Shared Function GetWellKnownMemberInType(type As NamedTypeSymbol, relativeMember As WellKnownMember, diagnostics As BindingDiagnosticBag, syntax As SyntaxNode) As Symbol
            Dim wellKnownMemberInType As Symbol = TupleTypeSymbol.GetWellKnownMemberInType(type, relativeMember)
 
            If wellKnownMemberInType Is Nothing Then
                Dim descriptor As MemberDescriptor = WellKnownMembers.GetDescriptor(relativeMember)
                Binder.ReportDiagnostic(diagnostics, syntax, ERRID.ERR_MissingRuntimeHelper, type.Name & "."c & descriptor.Name)
            Else
                Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = wellKnownMemberInType.GetUseSiteInfo
                diagnostics.Add(useSiteInfo, syntax.GetLocation())
            End If
            Return wellKnownMemberInType
        End Function
 
        Private Function CollectTupleElementFields() As ImmutableArray(Of FieldSymbol)
            Dim builder = ArrayBuilder(Of FieldSymbol).GetInstance(_elementTypes.Length, fillWithValue:=Nothing)
 
            For Each member In GetMembers()
                If member.Kind <> SymbolKind.Field Then
                    Continue For
                End If
 
                Dim candidate = DirectCast(member, FieldSymbol)
                Dim index = candidate.TupleElementIndex
 
                If index >= 0 Then
                    If builder(index) Is Nothing OrElse builder(index).IsDefaultTupleElement Then
                        builder(index) = candidate
                    Else
                        ' there is a better field in the slot
                        ' that can only happen if the candidate is default.
                        Debug.Assert(candidate.IsDefaultTupleElement)
                    End If
                End If
            Next
 
            Debug.Assert(builder.All(Function(s) s IsNot Nothing))
 
            Return builder.ToImmutableAndFree()
        End Function
 
        Public Overrides Function GetMembers() As ImmutableArray(Of Symbol)
            Dim isDefault As Boolean = Me._lazyMembers.IsDefault
            If isDefault Then
                ImmutableInterlocked.InterlockedInitialize(Of Symbol)(Me._lazyMembers, Me.CreateMembers())
            End If
            Return Me._lazyMembers
        End Function
 
        Private Function CreateMembers() As ImmutableArray(Of Symbol)
            Dim elementsMatchedByFields = ArrayBuilder(Of Boolean).GetInstance(_elementTypes.Length, fillWithValue:=False)
            Dim members = ArrayBuilder(Of Symbol).GetInstance(Math.Max(_elementTypes.Length, _underlyingType.OriginalDefinition.GetMembers().Length))
 
            Dim currentUnderlying As NamedTypeSymbol = _underlyingType
            Dim currentNestingLevel = 0
 
            Dim currentFieldsForElements = ArrayBuilder(Of FieldSymbol).GetInstance(currentUnderlying.Arity)
 
            ' Lookup field definitions that we are interested in
            CollectTargetTupleFields(currentUnderlying, currentFieldsForElements)
 
            Dim underlyingMembers As ImmutableArray(Of Symbol) = currentUnderlying.OriginalDefinition.GetMembers()
 
            Do
                For Each member In underlyingMembers
                    Select Case member.Kind
                        Case SymbolKind.Method
                            If currentNestingLevel = 0 Then
                                members.Add(New TupleMethodSymbol(Me, DirectCast(member, MethodSymbol).AsMember(currentUnderlying)))
                            End If
 
                        Case SymbolKind.Field
                            Dim field = DirectCast(member, FieldSymbol)
 
                            Dim tupleFieldIndex = currentFieldsForElements.IndexOf(field, ReferenceEqualityComparer.Instance)
                            If tupleFieldIndex >= 0 Then
                                ' This is a tuple backing field
 
                                ' adjust tuple index for nesting
                                If currentNestingLevel <> 0 Then
                                    tupleFieldIndex += (RestPosition - 1) * currentNestingLevel
                                End If
 
                                Dim providedName = If(_providedElementNames.IsDefault, Nothing, _providedElementNames(tupleFieldIndex))
                                Dim location = If(_elementLocations.IsDefault, Nothing, _elementLocations(tupleFieldIndex))
                                Dim defaultName = TupleMemberName(tupleFieldIndex + 1)
                                ' if provided name does not match the default one,
                                ' then default element is declared implicitly
                                Dim defaultImplicitlyDeclared = Not IdentifierComparison.Equals(providedName, defaultName)
 
                                Dim FieldSymbol = field.AsMember(currentUnderlying)
 
                                ' Add a field with default name. It should be present regardless.
                                Dim defaultTupleField As TupleElementFieldSymbol
                                If currentNestingLevel <> 0 Then
                                    ' This is a matching field, but it is in the extension tuple
                                    ' Make it virtual since we are not at the top level
                                    defaultTupleField = New TupleVirtualElementFieldSymbol(Me,
                                                                                           FieldSymbol,
                                                                                           defaultName,
                                                                                           cannotUse:=False,
                                                                                           tupleElementOrdinal:=tupleFieldIndex,
                                                                                           location:=location,
                                                                                           isImplicitlyDeclared:=defaultImplicitlyDeclared,
                                                                                           correspondingDefaultFieldOpt:=Nothing)
                                Else
                                    Debug.Assert(IdentifierComparison.Equals(FieldSymbol.Name, defaultName), "top level underlying field must match default name")
 
                                    ' Add the underlying field as an element. It should have the default name.
                                    defaultTupleField = New TupleElementFieldSymbol(Me,
                                                                                    FieldSymbol,
                                                                                    tupleFieldIndex,
                                                                                    location,
                                                                                    defaultImplicitlyDeclared,
                                                                                    correspondingDefaultFieldOpt:=Nothing)
                                End If
 
                                members.Add(defaultTupleField)
 
                                If defaultImplicitlyDeclared AndAlso Not String.IsNullOrEmpty(providedName) Then
                                    Dim isError = If(_errorPositions.IsDefault, False, _errorPositions(tupleFieldIndex))
 
                                    ' The name given doesn't match the default name Item8, etc.
                                    ' Add a virtual field with the given name
                                    members.Add(New TupleVirtualElementFieldSymbol(Me,
                                                                                   FieldSymbol,
                                                                                   providedName,
                                                                                   isError,
                                                                                   tupleFieldIndex,
                                                                                   location,
                                                                                   isImplicitlyDeclared:=False,
                                                                                   correspondingDefaultFieldOpt:=defaultTupleField))
                                End If
 
                                elementsMatchedByFields(tupleFieldIndex) = True ' mark as handled
                            ElseIf currentNestingLevel = 0 Then
                                ' field at the top level didn't match a tuple backing field, simply add.
                                members.Add(New TupleFieldSymbol(Me, field.AsMember(currentUnderlying), -members.Count - 1))
                            End If
 
                        Case SymbolKind.NamedType
                                        ' We are dropping nested types, if any. Pending real need.
 
                        Case SymbolKind.Property
                            If currentNestingLevel = 0 Then
                                members.Add(New TuplePropertySymbol(Me, DirectCast(member, PropertySymbol).AsMember(currentUnderlying)))
                            End If
 
                        Case SymbolKind.Event
                            If currentNestingLevel = 0 Then
                                members.Add(New TupleEventSymbol(Me, DirectCast(member, EventSymbol).AsMember(currentUnderlying)))
                            End If
 
                        Case Else
                            If currentNestingLevel = 0 Then
                                Throw ExceptionUtilities.UnexpectedValue(member.Kind)
                            End If
                    End Select
                Next
 
                If currentUnderlying.Arity <> RestPosition Then
                    Exit Do
                End If
 
                Dim oldUnderlying = currentUnderlying
                currentUnderlying = oldUnderlying.TypeArgumentsNoUseSiteDiagnostics(RestPosition - 1).TupleUnderlyingType
                currentNestingLevel += 1
 
                If currentUnderlying.Arity <> RestPosition Then
                    ' refresh members And target fields
                    underlyingMembers = currentUnderlying.OriginalDefinition.GetMembers()
                    currentFieldsForElements.Clear()
                    CollectTargetTupleFields(currentUnderlying, currentFieldsForElements)
                Else
                    Debug.Assert(oldUnderlying.OriginalDefinition Is currentUnderlying.OriginalDefinition)
                End If
            Loop
 
            currentFieldsForElements.Free()
 
            ' At the end, add unmatched fields as error symbols
            For i As Integer = 0 To elementsMatchedByFields.Count - 1
                If Not elementsMatchedByFields(i) Then
                    ' We couldn't find a backing field for this element. It will be an error to access it.
                    Dim fieldRemainder As Integer ' one-based
                    Dim fieldChainLength = NumberOfValueTuples(i + 1, fieldRemainder)
                    Dim container As NamedTypeSymbol = GetNestedTupleUnderlyingType(_underlyingType, fieldChainLength - 1).OriginalDefinition
 
                    Dim diagnosticInfo = If(container.IsErrorType(),
                                                          Nothing,
                                                          ErrorFactory.ErrorInfo(ERRID.ERR_MissingRuntimeHelper,
                                                                               container.Name & "." & TupleMemberName(fieldRemainder)))
 
                    Dim providedName = If(_providedElementNames.IsDefault, Nothing, _providedElementNames(i))
                    Dim location = If(_elementLocations.IsDefault, Nothing, _elementLocations(i))
                    Dim defaultName = TupleMemberName(i + 1)
                    ' if provided name does not match the default one,
                    ' then default element is declared implicitly
                    Dim defaultImplicitlyDeclared = Not IdentifierComparison.Equals(providedName, defaultName)
 
                    ' Add default element field.
                    Dim defaultTupleField As TupleErrorFieldSymbol = New TupleErrorFieldSymbol(Me,
                                                                                               defaultName,
                                                                                               i,
                                                                                               If(defaultImplicitlyDeclared, Nothing, location),
                                                                                               _elementTypes(i),
                                                                                               diagnosticInfo,
                                                                                               defaultImplicitlyDeclared,
                                                                                               correspondingDefaultFieldOpt:=Nothing)
 
                    members.Add(defaultTupleField)
 
                    If defaultImplicitlyDeclared AndAlso Not String.IsNullOrEmpty(providedName) Then
                        ' Add friendly named element field.
                        ' (i << 1) + 1, because this is not a default element
                        members.Add(New TupleErrorFieldSymbol(Me,
                                                              providedName,
                                                              i,
                                                              location,
                                                              _elementTypes(i),
                                                              diagnosticInfo,
                                                              isImplicitlyDeclared:=False,
                                                              correspondingDefaultFieldOpt:=defaultTupleField))
                    End If
                End If
            Next
 
            Return members.ToImmutableAndFree()
        End Function
 
        Private Shared Sub CollectTargetTupleFields(underlying As NamedTypeSymbol, fieldsForElements As ArrayBuilder(Of FieldSymbol))
            underlying = underlying.OriginalDefinition
            Dim num As Integer = Math.Min(underlying.Arity, TupleTypeSymbol.RestPosition - 1)
            For i As Integer = 0 To num - 1
                Dim tupleTypeMember As WellKnownMember = TupleTypeSymbol.GetTupleTypeMember(underlying.Arity, i + 1)
                fieldsForElements.Add(CType(TupleTypeSymbol.GetWellKnownMemberInType(underlying, tupleTypeMember), FieldSymbol))
            Next
        End Sub
 
        Private Function ComputeDefinitionToMemberMap() As SmallDictionary(Of Symbol, Symbol)
            Dim smallDictionary As SmallDictionary(Of Symbol, Symbol) = New SmallDictionary(Of Symbol, Symbol)(ReferenceEqualityComparer.Instance)
            Dim originalDefinition As NamedTypeSymbol = Me._underlyingType.OriginalDefinition
            Dim members As ImmutableArray(Of Symbol) = Me.GetMembers()
            Dim i As Integer = members.Length - 1
            While i >= 0
                Dim symbol As Symbol = members(i)
                Dim kind As SymbolKind = symbol.Kind
                Select Case kind
                    Case SymbolKind.[Event]
                        Dim tupleUnderlyingEvent As EventSymbol = DirectCast(symbol, EventSymbol).TupleUnderlyingEvent
                        Dim associatedField As FieldSymbol = tupleUnderlyingEvent.AssociatedField
 
                        If associatedField IsNot Nothing Then
                            Debug.Assert(associatedField.ContainingSymbol Is Me._underlyingType)
                            Debug.Assert(Me._underlyingType.GetMembers(associatedField.Name).IndexOf(associatedField) < 0)
                            smallDictionary.Add(associatedField.OriginalDefinition, New TupleFieldSymbol(Me, associatedField, -i - 1))
                        End If
 
                        smallDictionary.Add(tupleUnderlyingEvent.OriginalDefinition, symbol)
 
                    Case SymbolKind.Field
                        Dim tupleUnderlyingField As FieldSymbol = DirectCast(symbol, FieldSymbol).TupleUnderlyingField
                        If tupleUnderlyingField IsNot Nothing Then
                            smallDictionary(tupleUnderlyingField.OriginalDefinition) = symbol
                        End If
 
                    Case SymbolKind.Method
                        smallDictionary.Add(DirectCast(symbol, MethodSymbol).TupleUnderlyingMethod.OriginalDefinition, symbol)
 
                    Case SymbolKind.Property
                        smallDictionary.Add(DirectCast(symbol, PropertySymbol).TupleUnderlyingProperty.OriginalDefinition, symbol)
 
                    Case Else
                        Throw ExceptionUtilities.UnexpectedValue(symbol.Kind)
                End Select
 
                i -= 1
            End While
 
            Return smallDictionary
        End Function
 
        Public Function GetTupleMemberSymbolForUnderlyingMember(Of TMember As Symbol)(underlyingMemberOpt As TMember) As TMember
            Dim result As TMember
            If underlyingMemberOpt Is Nothing Then
                result = Nothing
            Else
                Dim originalDefinition As Symbol = underlyingMemberOpt.OriginalDefinition
                If originalDefinition.ContainingType Is Me._underlyingType.OriginalDefinition Then
                    Dim symbol As Symbol = Nothing
 
                    If Me.UnderlyingDefinitionToMemberMap.TryGetValue(originalDefinition, symbol) Then
                        result = CType(symbol, TMember)
                        Return result
                    End If
                End If
                result = Nothing
            End If
            Return result
        End Function
 
        Public Overrides Function GetMembers(name As String) As ImmutableArray(Of Symbol)
            Return Me.GetMembers().WhereAsArray(Function(member, name_) IdentifierComparison.Equals(member.Name, name_), name)
        End Function
 
        Public Overrides Function GetTypeMembers() As ImmutableArray(Of NamedTypeSymbol)
            ' do not support nested types at the moment
            Debug.Assert(Not GetMembers().Any(Function(m) m.Kind = SymbolKind.NamedType))
            Return ImmutableArray(Of NamedTypeSymbol).Empty
        End Function
 
        Public Overrides Function GetTypeMembers(name As String) As ImmutableArray(Of NamedTypeSymbol)
            ' do not support nested types at the moment
            Debug.Assert(Not GetMembers().Any(Function(m) m.Kind = SymbolKind.NamedType))
            Return ImmutableArray(Of NamedTypeSymbol).Empty
        End Function
 
        Public Overrides Function GetTypeMembers(name As String, arity As Integer) As ImmutableArray(Of NamedTypeSymbol)
            ' do not support nested types at the moment
            Debug.Assert(Not GetMembers().Any(Function(m) m.Kind = SymbolKind.NamedType))
            Return ImmutableArray(Of NamedTypeSymbol).Empty
        End Function
 
        Public Overrides Function GetAttributes() As ImmutableArray(Of VisualBasicAttributeData)
            Return Me._underlyingType.GetAttributes()
        End Function
 
        Public Overrides Function Equals(obj As TypeSymbol, comparison As TypeCompareKind) As Boolean
            If obj Is Me Then
                Return True
            End If
 
            If obj Is Nothing Then
                Return False
            End If
 
            Dim otherTuple = TryCast(obj, TupleTypeSymbol)
 
            If otherTuple Is Nothing AndAlso (comparison And TypeCompareKind.IgnoreTupleNames) = 0 Then
                Return False
            End If
 
            If Not Me.TupleUnderlyingType.Equals(obj.GetTupleUnderlyingTypeOrSelf(), comparison) Then
                Return False
            End If
 
            If (comparison And TypeCompareKind.IgnoreTupleNames) = 0 Then
                Dim myNames = Me.TupleElementNames
                Dim otherNames = otherTuple.TupleElementNames
 
                If myNames.IsDefault Then
                    Return otherNames.IsDefault
                End If
 
                If otherNames.IsDefault Then
                    Return False
                End If
 
                Debug.Assert(myNames.Length = otherNames.Length)
 
                For i As Integer = 0 To myNames.Length - 1
                    If Not IdentifierComparison.Equals(myNames(i), otherNames(i)) Then
                        Return False
                    End If
                Next
            End If
 
            Return True
        End Function
 
        Public Overrides Function GetHashCode() As Integer
            Return Me._underlyingType.GetHashCode()
        End Function
 
        Friend Overrides Function GetUseSiteInfo() As UseSiteInfo(Of AssemblySymbol)
            Return Me._underlyingType.GetUseSiteInfo()
        End Function
 
        Friend Overrides Function GetUnificationUseSiteDiagnosticRecursive(owner As Symbol, ByRef checkedTypes As HashSet(Of TypeSymbol)) As DiagnosticInfo
            Return Me._underlyingType.GetUnificationUseSiteDiagnosticRecursive(owner, checkedTypes)
        End Function
 
        Friend Overrides Function GetAttributeUsageInfo() As AttributeUsageInfo
            Return AttributeUsageInfo.Null
        End Function
 
        Friend Overrides Function GetAppliedConditionalSymbols() As ImmutableArray(Of String)
            Return ImmutableArray(Of String).Empty
        End Function
 
        Friend Overrides Function GetFieldsToEmit() As IEnumerable(Of FieldSymbol)
            Throw ExceptionUtilities.Unreachable
        End Function
 
        Friend Overrides Function GetEventsToEmit() As IEnumerable(Of EventSymbol)
            Throw ExceptionUtilities.Unreachable
        End Function
 
        Friend Overrides Function GetMethodsToEmit() As IEnumerable(Of MethodSymbol)
            Throw ExceptionUtilities.Unreachable
        End Function
 
        Friend Overrides Function GetPropertiesToEmit() As IEnumerable(Of PropertySymbol)
            Throw ExceptionUtilities.Unreachable
        End Function
 
        Friend Overrides Function GetInterfacesToEmit() As IEnumerable(Of NamedTypeSymbol)
            Throw ExceptionUtilities.Unreachable
        End Function
 
        Friend Overrides Function GetCustomAttributesToEmit(moduleBuilder As PEModuleBuilder) As IEnumerable(Of VisualBasicAttributeData)
            Throw ExceptionUtilities.Unreachable
        End Function
 
        Public Shared Function TransformToTupleIfCompatible(target As TypeSymbol) As TypeSymbol
            Dim result As TypeSymbol
            If target.IsTupleCompatible() Then
                result = TupleTypeSymbol.Create(CType(target, NamedTypeSymbol))
            Else
                result = target
            End If
            Return result
        End Function
 
        Public Overrides Function Construct(typeArguments As ImmutableArray(Of TypeSymbol)) As NamedTypeSymbol
            Throw ExceptionUtilities.Unreachable
        End Function
 
        Friend Overrides Function InternalSubstituteTypeParameters(substitution As TypeSubstitution) As TypeWithModifiers
            Dim substitutedUnderlying = DirectCast(Me.TupleUnderlyingType.InternalSubstituteTypeParameters(substitution).Type, NamedTypeSymbol)
            Dim tupleType = TupleTypeSymbol.Create(Me._locations, substitutedUnderlying, Me._elementLocations,
                                                   Me._providedElementNames, Me._errorPositions)
 
            Return New TypeWithModifiers(tupleType, Nothing)
        End Function
 
        Friend Overrides Function MakeDeclaredBase(basesBeingResolved As BasesBeingResolved, diagnostics As BindingDiagnosticBag) As NamedTypeSymbol
            Return Me._underlyingType.MakeDeclaredBase(basesBeingResolved, diagnostics)
        End Function
 
        Friend Overrides Function MakeDeclaredInterfaces(basesBeingResolved As BasesBeingResolved, diagnostics As BindingDiagnosticBag) As ImmutableArray(Of NamedTypeSymbol)
            Return Me._underlyingType.MakeDeclaredInterfaces(basesBeingResolved, diagnostics)
        End Function
 
        Friend Overrides Function MakeAcyclicBaseType(diagnostics As BindingDiagnosticBag) As NamedTypeSymbol
            Return Me._underlyingType.MakeAcyclicBaseType(diagnostics)
        End Function
 
        Friend Overrides Function MakeAcyclicInterfaces(diagnostics As BindingDiagnosticBag) As ImmutableArray(Of NamedTypeSymbol)
            Return Me._underlyingType.MakeAcyclicInterfaces(diagnostics)
        End Function
 
        Friend Overrides Sub GenerateDeclarationErrors(cancellationToken As CancellationToken)
            Me._underlyingType.GenerateDeclarationErrors(cancellationToken)
        End Sub
 
        Friend Overrides Function GetSynthesizedWithEventsOverrides() As IEnumerable(Of PropertySymbol)
            ' We might need to have a real implementation here, depending on the resolution
            ' of https://github.com/dotnet/roslyn/issues/14104
            Return SpecializedCollections.EmptyEnumerable(Of PropertySymbol)()
        End Function
 
        Friend Shared Sub ReportNamesMismatchesIfAny(destination As TypeSymbol, literal As BoundTupleLiteral, diagnostics As BindingDiagnosticBag)
            Dim sourceNames = literal.ArgumentNamesOpt
 
            If sourceNames.IsDefault Then
                Return
            End If
 
            Dim inferredNames As ImmutableArray(Of Boolean) = literal.InferredNamesOpt
            Dim noInferredNames As Boolean = inferredNames.IsDefault
            Dim destinationNames As ImmutableArray(Of String) = destination.TupleElementNames
            Dim sourceLength As Integer = sourceNames.Length
            Dim allMissing As Boolean = destinationNames.IsDefault
            Debug.Assert(allMissing OrElse destinationNames.Length = sourceLength)
 
            For i = 0 To sourceLength - 1
                Dim sourceName = sourceNames(i)
                Dim wasInferred = If(noInferredNames, False, inferredNames(i))
 
                If sourceName IsNot Nothing AndAlso Not wasInferred AndAlso (allMissing OrElse String.CompareOrdinal(destinationNames(i), sourceName) <> 0) Then
                    diagnostics.Add(ERRID.WRN_TupleLiteralNameMismatch, literal.Arguments(i).Syntax.Parent.Location, sourceName, destination)
                End If
            Next
        End Sub
 
        Friend Overrides ReadOnly Property HasAnyDeclaredRequiredMembers As Boolean
            Get
                Return _underlyingType.HasAnyDeclaredRequiredMembers
            End Get
        End Property
    End Class
End Namespace