private BoundExpression MakeTupleCreationExpression(SyntaxNode syntax, NamedTypeSymbol type, ImmutableArray <BoundExpression> rewrittenArguments)
        {
            NamedTypeSymbol underlyingTupleType = type.TupleUnderlyingType ?? type;

            Debug.Assert(underlyingTupleType.IsTupleCompatible());

            ArrayBuilder <NamedTypeSymbol> underlyingTupleTypeChain = ArrayBuilder <NamedTypeSymbol> .GetInstance();

            TupleTypeSymbol.GetUnderlyingTypeChain(underlyingTupleType, underlyingTupleTypeChain);

            try
            {
                // make a creation expression for the smallest type
                NamedTypeSymbol smallestType = underlyingTupleTypeChain.Pop();
                ImmutableArray <BoundExpression> smallestCtorArguments = ImmutableArray.Create(rewrittenArguments,
                                                                                               underlyingTupleTypeChain.Count * (TupleTypeSymbol.RestPosition - 1),
                                                                                               smallestType.Arity);
                var smallestCtor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(smallestType.OriginalDefinition,
                                                                                          TupleTypeSymbol.GetTupleCtor(smallestType.Arity),
                                                                                          _diagnostics,
                                                                                          syntax);
                if ((object)smallestCtor == null)
                {
                    return(_factory.BadExpression(type));
                }

                MethodSymbol smallestConstructor = smallestCtor.AsMember(smallestType);
                BoundObjectCreationExpression currentCreation = new BoundObjectCreationExpression(syntax, smallestConstructor, null, smallestCtorArguments);

                if (underlyingTupleTypeChain.Count > 0)
                {
                    NamedTypeSymbol tuple8Type = underlyingTupleTypeChain.Peek();
                    var             tuple8Ctor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(tuple8Type.OriginalDefinition,
                                                                                                        TupleTypeSymbol.GetTupleCtor(TupleTypeSymbol.RestPosition),
                                                                                                        _diagnostics,
                                                                                                        syntax);
                    if ((object)tuple8Ctor == null)
                    {
                        return(_factory.BadExpression(type));
                    }

                    // make successively larger creation expressions containing the previous one
                    do
                    {
                        ImmutableArray <BoundExpression> ctorArguments = ImmutableArray.Create(rewrittenArguments,
                                                                                               (underlyingTupleTypeChain.Count - 1) * (TupleTypeSymbol.RestPosition - 1),
                                                                                               TupleTypeSymbol.RestPosition - 1)
                                                                         .Add(currentCreation);

                        MethodSymbol constructor = tuple8Ctor.AsMember(underlyingTupleTypeChain.Pop());
                        currentCreation = new BoundObjectCreationExpression(syntax, constructor, null, ctorArguments);
                    }while (underlyingTupleTypeChain.Count > 0);
                }

                currentCreation = currentCreation.Update(
                    currentCreation.Constructor,
                    currentCreation.Arguments,
                    currentCreation.ArgumentNamesOpt,
                    currentCreation.ArgumentRefKindsOpt,
                    currentCreation.Expanded,
                    currentCreation.ArgsToParamsOpt,
                    currentCreation.ConstantValue,
                    currentCreation.InitializerExpressionOpt,
                    currentCreation.BinderOpt,
                    type);

                return(currentCreation);
            }
            finally
            {
                underlyingTupleTypeChain.Free();
            }
        }
        /// <summary>
        /// Converts the expression for creating a tuple instance into an expression creating a ValueTuple (if short) or nested ValueTuples (if longer).
        ///
        /// For instance, for a long tuple we'll generate:
        /// creationExpression(ctor=largestCtor, args=firstArgs+(nested creationExpression for remainder, with smaller ctor and next few args))
        /// </summary>
        private BoundNode RewriteTupleCreationExpression(BoundTupleExpression node, ImmutableArray <BoundExpression> rewrittenArguments)
        {
            NamedTypeSymbol underlyingTupleType = node.Type.TupleUnderlyingType;

            ArrayBuilder <NamedTypeSymbol> underlyingTupleTypeChain = ArrayBuilder <NamedTypeSymbol> .GetInstance();

            TupleTypeSymbol.GetUnderlyingTypeChain(underlyingTupleType, underlyingTupleTypeChain);

            try
            {
                // make a creation expression for the smallest type
                NamedTypeSymbol smallestType = underlyingTupleTypeChain.Pop();
                ImmutableArray <BoundExpression> smallestCtorArguments = ImmutableArray.Create(rewrittenArguments,
                                                                                               underlyingTupleTypeChain.Count * (TupleTypeSymbol.RestPosition - 1),
                                                                                               smallestType.Arity);
                var smallestCtor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(smallestType.OriginalDefinition,
                                                                                          TupleTypeSymbol.GetTupleCtor(smallestType.Arity),
                                                                                          _diagnostics,
                                                                                          node.Syntax);
                if ((object)smallestCtor == null)
                {
                    return(node);
                }

                MethodSymbol smallestConstructor = smallestCtor.AsMember(smallestType);
                BoundObjectCreationExpression currentCreation = new BoundObjectCreationExpression(node.Syntax, smallestConstructor, smallestCtorArguments);

                if (underlyingTupleTypeChain.Count > 0)
                {
                    NamedTypeSymbol tuple8Type = underlyingTupleTypeChain.Peek();
                    var             tuple8Ctor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(tuple8Type.OriginalDefinition,
                                                                                                        TupleTypeSymbol.GetTupleCtor(TupleTypeSymbol.RestPosition),
                                                                                                        _diagnostics,
                                                                                                        node.Syntax);
                    if ((object)tuple8Ctor == null)
                    {
                        return(node);
                    }

                    // make successively larger creation expressions containing the previous one
                    do
                    {
                        ImmutableArray <BoundExpression> ctorArguments = ImmutableArray.Create(rewrittenArguments,
                                                                                               (underlyingTupleTypeChain.Count - 1) * (TupleTypeSymbol.RestPosition - 1),
                                                                                               TupleTypeSymbol.RestPosition - 1)
                                                                         .Add(currentCreation);

                        MethodSymbol constructor = tuple8Ctor.AsMember(underlyingTupleTypeChain.Pop());
                        currentCreation = new BoundObjectCreationExpression(node.Syntax, constructor, ctorArguments);
                    }while (underlyingTupleTypeChain.Count > 0);
                }

                return(currentCreation);
            }
            finally
            {
                underlyingTupleTypeChain.Free();
            }
        }