Repository: dotnet/roslyn
File: src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_StringConcat.cs (C#)

Code before:
        }

        /// <summary>
        /// Given a visited argument to a string concatenation, attempts to simplify it for inclusion in the final argument list to <code>string.Concat</code>. This includes:
        /// <list type="bullet">
        /// <item>Removing null or empty string constants</item>
        /// <item>Merging consecutive string or char constants into a single string constant</item>
        /// <item>Deconstructing nested string.Concat calls into their arguments</item>
        /// <item>Converting char.ToString() calls into the underlying char expression</item>
        /// <item>Converting `strValue ?? ""` into just `strValue`</item>
        /// </list>
        /// If the argument is simplified into a single argument, it is returned as <code>singleConcatArgument</code>. If it is deconstructed into multiple arguments (as in the case of
        /// nested string.Concat calls), those arguments are returned as <code>nestedConcatArguments</code>. If the argument is optimized away entirely (as in the case of null or empty string constants),
        /// then both return values will be null/default. If the argument is merged into the preceding argument, then <paramref name="precedingArgument"/> will be updated to reflect that, and both return values will be null/default.
        /// </summary>
        private (BoundExpression? singleConcatArgument, ImmutableArray<BoundExpression> nestedConcatArguments) SimplifyConcatArgument(BoundExpression argument, [NotNullIfNotNull(nameof(precedingArgument))] ref BoundExpression? precedingArgument, ref WellKnownConcatRelatedMethods wellKnownConcatOptimizationMethods)
        {
            if (argument is BoundConversion { ConversionKind: ConversionKind.Boxing, Type.SpecialType: SpecialType.System_Object, Operand: { Type.SpecialType: SpecialType.System_Char } operand })
            {
                argument = operand;
            }
            else if (argument is BoundCall call)
            {
                if (wellKnownConcatOptimizationMethods.IsWellKnownConcatMethod(call, out var concatArguments))
                {
                    return (null, concatArguments);
                }
                else if (wellKnownConcatOptimizationMethods.IsCharToString(call, out var charExpression))
                {
                    argument = charExpression;
                }
            }
            // This is `strValue ?? ""`, possibly from a nested binary addition of an interpolated string. We can just directly use the left operand
            else if (argument is BoundNullCoalescingOperator { LeftOperand: { Type.SpecialType: SpecialType.System_String } left, RightOperand: BoundLiteral { ConstantValueOpt: { IsString: true, RopeValue.IsEmpty: true } } })
            {
                argument = left;
            }

            switch (argument.ConstantValueOpt)
            {
                case { IsNull: true } or { IsString: true, RopeValue.IsEmpty: true }:
                    // If this is a null constant or an empty string, then we don't need to include it in the final arguments list
                    return (null, default);

                case { IsString: true } or { IsChar: true }:
                    // See if we can merge this argument with the previous one
                    if (precedingArgument is { ConstantValueOpt: { IsString: true } or { IsChar: true } })
                    {
                        var constantValue = precedingArgument.ConstantValueOpt!;
                        var previous = getRope(constantValue);
                        var current = getRope(argument.ConstantValueOpt!);

Review comment (suggestion):
>return (null, concatArguments); [](http://example.com/codeflow?start=20&length=31)

It looks like we are missing an opportunity to do a constant optimization (merge with next, etc.) for the last argument. I am not suggesting to change this behavior in context of this PR, simply making an observation. If you think it is worth implementing this optimization, consider opening an issue. #Closed

Code after:
        }

        /// <summary>
        /// Given a visited argument to a string concatenation, attempts to simplify it for inclusion in the final argument list to <code>string.Concat</code>. This includes:
        /// <list type="bullet">
        /// <item>Removing null or empty string constants</item>
        /// <item>Merging consecutive string or char constants into a single string constant</item>
        /// <item>Deconstructing nested string.Concat calls into their arguments</item>
        /// <item>Converting char.ToString() calls into the underlying char expression</item>
        /// <item>Converting `strValue ?? ""` into just `strValue`</item>
        /// </list>
        /// If the argument is simplified into a single argument, it is returned as <code>singleConcatArgument</code>. If it is deconstructed into multiple arguments (as in the case of
        /// nested string.Concat calls), those arguments are returned as <code>nestedConcatArguments</code>. If the argument is optimized away entirely (as in the case of null or empty string constants),
        /// then both return values will be null/default. If the argument is merged into the following argument, then <paramref name="followingArgument"/> will be updated to reflect that, and both return values will be null/default.
        /// </summary>
        private (BoundExpression? singleConcatArgument, ImmutableArray<BoundExpression> nestedConcatArguments) SimplifyConcatArgument(BoundExpression argument, [NotNullIfNotNull(nameof(followingArgument))] ref BoundExpression? followingArgument, ref WellKnownConcatRelatedMethods wellKnownConcatOptimizationMethods)
        {
            if (argument is BoundConversion { ConversionKind: ConversionKind.Boxing, Type.SpecialType: SpecialType.System_Object, Operand: { Type.SpecialType: SpecialType.System_Char } operand })
            {
                argument = operand;
            }
            else if (argument is BoundCall call)
            {
                if (wellKnownConcatOptimizationMethods.IsWellKnownConcatMethod(call, out var concatArguments))
                {
                    return (null, concatArguments);
                }
                else if (wellKnownConcatOptimizationMethods.IsCharToString(call, out var charExpression))
                {
                    argument = charExpression;
                }
            }
            // This is `strValue ?? ""`, possibly from a nested binary addition of an interpolated string. We can just directly use the left operand
            else if (argument is BoundNullCoalescingOperator { LeftOperand: { Type.SpecialType: SpecialType.System_String } left, RightOperand: BoundLiteral { ConstantValueOpt: { IsString: true, RopeValue.IsEmpty: true } } })
            {
                argument = left;
            }

            switch (argument.ConstantValueOpt)
            {
                case { IsNull: true } or { IsString: true, RopeValue.IsEmpty: true }:
                    // If this is a null constant or an empty string, then we don't need to include it in the final arguments list
                    return (null, default);

                case { IsString: true } or { IsChar: true }:
                    // See if we can merge this argument with the next one
                    if (followingArgument is { ConstantValueOpt: { IsString: true } or { IsChar: true } })
                    {
                        var constantValue = followingArgument.ConstantValueOpt;
                        var next = getRope(constantValue);
                        var current = getRope(argument.ConstantValueOpt);