File: Semantics\InterpolatedStringTests.vb
Web Access
Project: src\src\Compilers\VisualBasic\Test\Semantic\Microsoft.CodeAnalysis.VisualBasic.Semantic.UnitTests.vbproj (Microsoft.CodeAnalysis.VisualBasic.Semantic.UnitTests)
' 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 Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.VisualBasic.SyntaxFacts
Imports Roslyn.Test.Utilities
 
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
 
    Public Class InterpolatedStringTests
        Inherits BasicTestBase
 
        Private ReadOnly _formattableStringSource As Xml.Linq.XElement =
<file name="FormattableString.vb">
Namespace System
 
    Public MustInherit Class FormattableString
        Implements IFormattable
 
        Public NotOverridable Overrides Function ToString() As String
            Return ToString(Globalization.CultureInfo.CurrentCulture)
        End Function
 
        Public MustOverride Overloads Function ToString(formatProvider As IFormatProvider) As String
 
        Public Overloads Function ToString(format As String, formatProvider As IFormatProvider) As String Implements IFormattable.ToString
            Return ToString(formatProvider)
        End Function
 
        Public Shared Function Invariant(formattable As FormattableString) As String
            Return formattable.ToString(Globalization.CultureInfo.InvariantCulture)
        End Function
    End Class
 
End Namespace
 
Namespace System.Runtime.CompilerServices
 
    Public Module FormattableStringFactory
 
        Public Function Create(formatString As String, ParamArray args As Object()) As FormattableString
            Return New ConcreteFormattableString(formatString, args)
        End Function
 
        Private NotInheritable Class ConcreteFormattableString
            Inherits FormattableString
 
            Private ReadOnly FormatString As String
            Private ReadOnly Arguments As Object()
 
            Public Sub New(formatString As String, arguments As Object())
                Me.FormatString = formatString
                Me.Arguments = arguments
            End Sub
 
            Public Overrides Function ToString(provider As IFormatProvider) As String
                Return String.Format(provider, FormatString, Arguments)
            End Function
 
        End Class
 
    End Module
 
End Namespace
</file>
 
        <Fact>
        Public Sub SimpleInterpolation()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <file name="a.vb">
Imports System.Console
 
Module Program
    Sub Main()
        Dim number = 8675309
        Write($"Jenny: {number}")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="Jenny: 8675309")
 
        End Sub
 
        <Fact>
        Public Sub InterpolationWithAlignment()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <file name="a.vb">
Imports System.Console
 
Module Program
    Sub Main()
        Dim number = 8675309
        Write($"Jenny: {number,12}")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="Jenny:      8675309")
 
        End Sub
 
        <Fact>
        Public Sub InterpolationWithAlignmentWithNonDecimalBaseAndOrTypeSuffix()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <file name="a.vb">
Imports System.Console
 
Module Program
    Sub Main()
        Dim number = 8675309
        Write($"Jenny: {number,&amp;H1A} {1,1UL}")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="Jenny: " & "8675309".PadLeft(&H1A) & " 1")
 
        End Sub
 
        <Fact>
        Public Sub InterpolationWithFormat()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <file name="a.vb">
Imports System.Console
 
Module Program
    Sub Main()
        Dim number = 8675309
        Write($"Jenny: {number:###-####}")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="Jenny: 867-5309")
 
        End Sub
 
        <Fact>
        Public Sub InterpolationWithFormatAndAlignment()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <file name="a.vb">
Imports System.Console
 
Module Program
    Sub Main()
        Dim number = 8675309
        Write($"Jenny: {number,12:###-####}")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="Jenny:     867-5309")
 
        End Sub
 
        <Fact>
        Public Sub TwoInterpolations()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <file name="a.vb">
Imports System.Console
 
Module Program
    Sub Main()
        Dim Hello = "Goodbye", World = "No one"
        Write($"This is a ""{NameOf(Hello)}, {NameOf(World)}!"" program.")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="This is a ""Hello, World!"" program.")
 
        End Sub
 
        <Fact>
        Public Sub EscapeSequences()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <file name="a.vb">
Imports System.Console
 
Module Program
    Sub Main()
        Dim arr As Object() = {}
        Write($"Solution: {{ { If(arr.Length > 0, String.Join("", "", arr), "Ø") } }}")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="Solution: { Ø }")
 
        End Sub
 
        <Fact>
        Public Sub EscapeSequencesWitNoInterpolations()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <file name="a.vb">
Imports System.Console
 
Module Program
    Sub Main()
        Write($"{{Ø}}")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="{Ø}")
 
        End Sub
 
        <Fact, WorkItem(1102783, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1102783")>
        Public Sub SmartQuotes()
 
            CompileAndVerify(
<compilation>
    <file name="a.vb">
Module Program
    Sub Main()
 
        Dim arr = {
            $<%= LEFT_DOUBLE_QUOTATION_MARK %>1<%= RIGHT_DOUBLE_QUOTATION_MARK %>,
            $<%= RIGHT_DOUBLE_QUOTATION_MARK %>2<%= LEFT_DOUBLE_QUOTATION_MARK %>,
            $<%= LEFT_DOUBLE_QUOTATION_MARK %>3",
            $"4<%= LEFT_DOUBLE_QUOTATION_MARK %>,
            $"5<%= RIGHT_DOUBLE_QUOTATION_MARK %>,
            $<%= RIGHT_DOUBLE_QUOTATION_MARK %>6",
            $" <%= RIGHT_DOUBLE_QUOTATION_MARK %><%= LEFT_DOUBLE_QUOTATION_MARK %> ",
            $<%= RIGHT_DOUBLE_QUOTATION_MARK %> {1:x<%= RIGHT_DOUBLE_QUOTATION_MARK %><%= LEFT_DOUBLE_QUOTATION_MARK %>y} <%= LEFT_DOUBLE_QUOTATION_MARK %>
        }
 
        System.Console.WriteLine(String.Join("", arr))
 
    End Sub
End Module    </file>
</compilation>, expectedOutput:="123456 ""  xy")
 
        End Sub
 
        <Fact, WorkItem(1102800, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1102800")>
        Public Sub FullwidthDelimiters()
 
            ' Any combination of fullwidth and ASCII curly braces of the same direction is an escaping sequence for the corresponding ASCII curly brace.
            ' We insert that curly brace doubled and because this is the escaping sequence understood by String.Format, that will be replaced by a single brace.
            ' This is deliberate design and it aligns with existing rules for double quote escaping in strings.
            CompileAndVerify(
<compilation>
    <file name="a.vb">
Imports System.Console
Module Program
    Sub Main()
        WriteLine($"{0<%= FULLWIDTH_RIGHT_CURLY_BRACKET %>" = "0")
        WriteLine($"<%= FULLWIDTH_LEFT_CURLY_BRACKET %>10<%= FULLWIDTH_COLON %>X}" = "A")
 
        WriteLine($"}}" = "}")
        WriteLine($"}<%= FULLWIDTH_RIGHT_CURLY_BRACKET %>" = "}")
        WriteLine($"<%= FULLWIDTH_RIGHT_CURLY_BRACKET %>}" = "}")
        WriteLine($"<%= FULLWIDTH_RIGHT_CURLY_BRACKET %><%= FULLWIDTH_RIGHT_CURLY_BRACKET %>" = "}")
 
        WriteLine($"{{" = "{")
        WriteLine($"{<%= FULLWIDTH_LEFT_CURLY_BRACKET %>" = "{")
        WriteLine($"<%= FULLWIDTH_LEFT_CURLY_BRACKET %>{" = "{")
        WriteLine($"<%= FULLWIDTH_LEFT_CURLY_BRACKET %><%= FULLWIDTH_LEFT_CURLY_BRACKET %>" = "{")
 
        WriteLine(<%= FULLWIDTH_DOLLAR_SIGN %><%= FULLWIDTH_QUOTATION_MARK %><%= LEFT_DOUBLE_QUOTATION_MARK %><%= LEFT_DOUBLE_QUOTATION_MARK %>" = """")
    End Sub
End Module</file>
</compilation>, expectedOutput:="True
True
True
True
True
True
True
True
True
True
True")
 
        End Sub
 
        <Fact>
        Public Sub NestedInterpolations()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <file name="a.vb">
Imports System.Console
 
Module Program
    Sub Main()
        Write($"The date/time is {$"{#2014-12-18 09:00:00#:yyyy-MM-dd HH:mm:ss}"}.")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="The date/time is 2014-12-18 09:00:00.")
 
        End Sub
 
        <Fact>
        Public Sub StringToCharArrayConversion()
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim s As Char() = $"{1} + {1} = {2}"
        Write(s.Length)
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="9")
 
        End Sub
 
        <Fact>
        Public Sub UserDefinedConversions()
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim s As C = "{1} + {1} = {2}"
    End Sub
End Module
 
Class C
    Shared Widening Operator CType(obj As String) As C
        Write("CType")
        Return New C()
    End Operator
End Class
    </file>
</compilation>, expectedOutput:="CType")
 
        End Sub
 
        <Fact>
        Public Sub TargetTyping()
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim s As IFormattable = $"{1} + {1} = {2}"
        Write(CObj(s).ToString())
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="1 + 1 = 2")
 
            Dim compilation = verifier.Compilation
            Dim mainTree = Aggregate t In compilation.SyntaxTrees Where t.FilePath = "a.vb" Into [Single]()
            Dim root = mainTree.GetRoot()
            Dim sm = compilation.GetSemanticModel(mainTree)
 
            Dim stringType = compilation.GetSpecialType(SpecialType.System_String)
            Dim iFormattableType = compilation.GetTypeByMetadataName("System.IFormattable")
 
            For Each e In root.DescendantNodes().OfType(Of InterpolatedStringExpressionSyntax)
                Assert.True(sm.GetSymbolInfo(e).IsEmpty, "Interpolated String expressions shouldn't bind to symbols.")
 
                Dim info = sm.GetTypeInfo(e)
                Assert.Equal(stringType, info.Type)
                Assert.Equal(iFormattableType, info.ConvertedType)
            Next
 
        End Sub
 
        <Fact>
        Public Sub TargetTypingThroughArrayLiteralsAndLambdas()
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        M(Of IFormattable)({$"", Nothing})
 
        N(Of IFormattable)(Function()
                               If True Then
                                   Return $""
                               Else
                                   Return Nothing
                               End If
                           End Function)
    End Sub
 
    Sub M(Of T)(obj As T())
        Write(obj(0).GetType().Name)
    End Sub
 
    Sub N(Of T)(f As Func(Of T))
        Write(f().GetType().Name)
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="ConcreteFormattableStringConcreteFormattableString")
 
            Dim compilation = verifier.Compilation
            Dim mainTree = Aggregate t In compilation.SyntaxTrees Where t.FilePath = "a.vb" Into [Single]()
            Dim root = mainTree.GetRoot()
            Dim sm = compilation.GetSemanticModel(mainTree)
 
            Dim stringType = compilation.GetSpecialType(SpecialType.System_String)
            Dim iFormattableType = compilation.GetTypeByMetadataName("System.IFormattable")
 
            For Each e In root.DescendantNodes().OfType(Of InterpolatedStringExpressionSyntax)
                Assert.True(sm.GetSymbolInfo(e).IsEmpty, "Interpolated String expressions shouldn't bind to symbols.")
 
                Dim info = sm.GetTypeInfo(e)
                Assert.Equal(stringType, info.Type)
                Assert.Equal(iFormattableType, info.ConvertedType)
            Next
 
        End Sub
 
        <Fact>
        Public Sub TargetTypingExplicitConversions()
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim ctf = CType($"{1} + {1} = {2}", IFormattable)
        Dim ctfs = CType($"{1} + {1} = {2}", FormattableString)
        Dim dcf = DirectCast($"{1} + {1} = {2}", IFormattable)
        Dim dcfs = DirectCast($"{1} + {1} = {2}", FormattableString)
        Dim tcf = TryCast($"{1} + {1} = {2}", IFormattable)
        Dim tcfs = TryCast($"{1} + {1} = {2}", FormattableString)
        Write(CObj(ctf).ToString())
        Write(CObj(ctfs).ToString())
        Write(CObj(dcf).ToString())
        Write(CObj(dcfs).ToString())
        Write(CObj(tcf).ToString())
        Write(CObj(tcfs).ToString())
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="1 + 1 = 21 + 1 = 21 + 1 = 21 + 1 = 21 + 1 = 21 + 1 = 2")
 
        End Sub
 
        <Fact>
        Public Sub TargetTypingThroughArrayLiteralsAndLambdasWithNarrowingConversionFromString()
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        M(Of Integer)({$"1", Nothing})
 
        N(Of Integer)(Function()
                               If True Then
                                   Return $"1"
                               Else
                                   Return Nothing
                               End If
                           End Function)
    End Sub
 
    Sub M(Of T)(obj As T())
        Write(obj(0).GetType().Name)
        Write(obj(0))
    End Sub
 
    Sub N(Of T)(f As Func(Of T))
        Write(f().GetType().Name)
        Write(f())
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="Int321Int321")
 
        End Sub
 
        <Fact>
        Public Sub InterpolatedStringConversionIsWidening()
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Option Strict On
 
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim s As IFormattable = $"{1} + {1} = {2}"
        Write(CObj(s).ToString())
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="1 + 1 = 2")
 
        End Sub
 
        <Fact>
        Public Sub ParenthesizationPreventsTargetTyping()
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntime(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim s As IFormattable = ($"{1} + {1} = {2}")
    End Sub
End Module
    </file>
</compilation>)
 
            AssertTheseCompileDiagnostics(compilation,
<expected>
BC42322: Runtime errors might occur when converting 'String' to 'IFormattable'.
        Dim s As IFormattable = ($"{1} + {1} = {2}")
                                ~~~~~~~~~~~~~~~~~~~~
</expected>)
 
        End Sub
 
        <Fact>
        Public Sub InvariantCulture()
 
            Dim previousCulture = Threading.Thread.CurrentThread.CurrentCulture
 
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
Imports System.Threading
Imports System.Globalization
Imports System.FormattableString
 
Module Program
    Sub Main()
        Dim previousCulture = Thread.CurrentThread.CurrentCulture
        Try
            Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("de-DE")
            Write($"{1.5}")
            Write(CObj(CType($"{1.5}", IFormattable)).ToString())
            Write(CObj(CType($"{1.5}", FormattableString)).ToString())
            Write(Invariant($"{1.5}"))
        Finally
            Thread.CurrentThread.CurrentCulture = previousCulture
        End Try
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="1,51,51,51.5")
 
            Assert.Equal(previousCulture, Threading.Thread.CurrentThread.CurrentCulture)
        End Sub
 
        <Fact>
        Public Sub OverloadResolutionWithStringAndIFormattablePrefersString()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main(args As String())
        M($"")
    End Sub
 
    Sub M(s As String)
        Write("String")
    End Sub
 
    Sub M(s As IFormattable)
        Write("IFormattable")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="String")
 
        End Sub
 
        <Fact>
        Public Sub OverloadResolutionWithStringAndFormattableStringPrefersString()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main(args As String())
        M($"")
    End Sub
 
    Sub M(s As String)
        Write("String")
    End Sub
 
    Sub M(s As FormattableString)
        Write("FormattableString")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="String")
 
        End Sub
 
        <Fact>
        Public Sub OverloadResolutionWithIFormattableAndFormattableStringPrefersFormattableString()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main(args As String())
        M($"")
    End Sub
 
    Sub M(s As IFormattable)
        Write("IFormattable")
    End Sub
 
    Sub M(s As FormattableString)
        Write("FormattableString")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="FormattableString")
 
        End Sub
 
        <Fact>
        Public Sub OverloadResolutionWithStringIFormattableAndFormattableStringPrefersString()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main(args As String())
        M($"")
    End Sub
 
    Sub M(s As String)
        Write("String")
    End Sub
 
    Sub M(s As IFormattable)
        Write("IFormattable")
    End Sub
 
    Sub M(s As FormattableString)
        Write("FormattableString")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="String")
 
        End Sub
 
        <Fact>
        Public Sub OverloadResolutionWithFuncOfStringAndFuncOfFormattableStringPrefersFuncOfString()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main(args As String())
        M(Function() $"")
    End Sub
 
    Sub M(f As Func(Of String))
        Write("String")
    End Sub
 
    Sub M(f As Func(Of FormattableString))
        Write("FormattableString")
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="String")
 
        End Sub
 
        <Fact>
        Public Sub TypeInferredAsString()
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim s = $"{1} + {1} = {2}"
        M(s)
 
        Dim arr1 = {$""}
        M(arr1)
 
        Dim arr2 = {$"", $""}
        M(arr2)
 
        M($"")
    End Sub
 
    Sub M(Of T)(obj As T)
        Write(GetType(T).Name)
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="StringString[]String[]String")
 
            Dim compilation = verifier.Compilation
            Dim mainTree = Aggregate t In compilation.SyntaxTrees Where t.FilePath = "a.vb" Into [Single]()
            Dim root = mainTree.GetRoot()
            Dim sm = compilation.GetSemanticModel(mainTree)
 
            Dim stringType = compilation.GetSpecialType(SpecialType.System_String)
 
            For Each e In root.DescendantNodes().OfType(Of InterpolatedStringExpressionSyntax)
                Assert.True(sm.GetSymbolInfo(e).IsEmpty, "Interpolated String expressions shouldn't bind to symbols.")
 
                Dim info = sm.GetTypeInfo(e)
                Assert.Equal(stringType, info.Type)
                Assert.Equal(stringType, info.ConvertedType)
            Next
        End Sub
 
        <Fact>
        Public Sub DominantTypeWithNothingLiteralInferredAsString()
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        M({$"", Nothing})
 
        M(If(True, Nothing, $""))
 
        N(Function()
              If True Then
                  Return $""
              Else
                  Return Nothing
              End If
          End Function)
    End Sub
 
    Sub M(Of T)(obj As T)
        Write(GetType(T).Name)
    End Sub
 
    Sub N(Of T)(f As Func(Of T))
        Write(GetType(T).Name)
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="String[]StringString")
 
            Dim compilation = verifier.Compilation
            Dim mainTree = Aggregate t In compilation.SyntaxTrees Where t.FilePath = "a.vb" Into [Single]()
            Dim root = mainTree.GetRoot()
            Dim sm = compilation.GetSemanticModel(mainTree)
 
            Dim stringType = compilation.GetSpecialType(SpecialType.System_String)
 
            For Each e In root.DescendantNodes().OfType(Of InterpolatedStringExpressionSyntax)
                Assert.True(sm.GetSymbolInfo(e).IsEmpty, "Interpolated String expressions shouldn't bind to symbols.")
 
                Dim info = sm.GetTypeInfo(e)
                Assert.Equal(stringType, info.Type)
                Assert.Equal(stringType, info.ConvertedType)
            Next
 
        End Sub
 
        <Fact>
        Public Sub DominantTypeWithIFormattableCannotBeInferred()
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim iFormattableInstance As IFormattable = $""
 
        M({$"", Nothing, iFormattableInstance})
 
        M(If(True, iFormattableInstance, $""))
 
        N(Function()
              If True Then
                  Return $""
              ElseIf True Then
                  Return iFormattableInstance
              Else
                  Return Nothing
              End If
          End Function)
    End Sub
 
    Sub M(Of T)(obj As T)
        Write(GetType(T).Name)
    End Sub
 
    Sub N(Of T)(f As Func(Of T))
        Write(GetType(T).Name)
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="Object[]ObjectObject")
 
            Dim compilation = verifier.Compilation
            Dim mainTree = Aggregate t In compilation.SyntaxTrees Where t.FilePath = "a.vb" Into [Single]()
            Dim root = mainTree.GetRoot()
            Dim sm = compilation.GetSemanticModel(mainTree)
 
            Dim stringType = compilation.GetSpecialType(SpecialType.System_String)
            Dim objectType = compilation.GetSpecialType(SpecialType.System_Object)
 
            For Each e In root.DescendantNodes().OfType(Of InterpolatedStringExpressionSyntax).Skip(1)
                Assert.True(sm.GetSymbolInfo(e).IsEmpty, "Interpolated String expressions shouldn't bind to symbols.")
 
                Dim info = sm.GetTypeInfo(e)
                Assert.Equal(stringType, info.Type)
                Assert.Equal(objectType, info.ConvertedType)
            Next
 
        End Sub
 
        <Fact>
        Public Sub DominantTypeWithFormattableStringCannotBeInferred()
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim formattableStringInstance As FormattableString = $""
 
        M({$"", Nothing, formattableStringInstance})
 
        M(If(True, formattableStringInstance, $""))
 
        N(Function()
              If True Then
                  Return $""
              ElseIf True Then
                  Return formattableStringInstance
              Else
                  Return Nothing
              End If
          End Function)
    End Sub
 
    Sub M(Of T)(obj As T)
        Write(GetType(T).Name)
    End Sub
 
    Sub N(Of T)(f As Func(Of T))
        Write(GetType(T).Name)
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="Object[]ObjectObject")
 
            Dim compilation = verifier.Compilation
            Dim mainTree = Aggregate t In compilation.SyntaxTrees Where t.FilePath = "a.vb" Into [Single]()
            Dim root = mainTree.GetRoot()
            Dim sm = compilation.GetSemanticModel(mainTree)
 
            Dim stringType = compilation.GetSpecialType(SpecialType.System_String)
            Dim objectType = compilation.GetSpecialType(SpecialType.System_Object)
 
            For Each e In root.DescendantNodes().OfType(Of InterpolatedStringExpressionSyntax).Skip(1)
                Assert.True(sm.GetSymbolInfo(e).IsEmpty, "Interpolated String expressions shouldn't bind to symbols.")
 
                Dim info = sm.GetTypeInfo(e)
                Assert.Equal(stringType, info.Type)
                Assert.Equal(objectType, info.ConvertedType)
            Next
 
        End Sub
 
        <Fact>
        Public Sub DominantTypeWithIFormattableAndFormattableStringCannotBeInferred()
            Dim verifier = CompileAndVerify(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim formattableStringInstance As FormattableString = $""
        Dim iFormattableInstance As IFormattable = $""
 
        M({$"", Nothing, formattableStringInstance, iFormattableInstance})
 
        N(Function()
              If True Then
                  Return $""
              ElseIf True Then
                  Return formattableStringInstance
              ElseIf True Then
                  Return iFormattableInstance
              Else
                  Return Nothing
              End If
          End Function)
    End Sub
 
    Sub M(Of T)(obj As T)
        Write(GetType(T).Name)
    End Sub
 
    Sub N(Of T)(f As Func(Of T))
        Write(GetType(T).Name)
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="IFormattable[]IFormattable")
 
            Dim compilation = verifier.Compilation
            Dim mainTree = Aggregate t In compilation.SyntaxTrees Where t.FilePath = "a.vb" Into [Single]()
            Dim root = mainTree.GetRoot()
            Dim sm = compilation.GetSemanticModel(mainTree)
 
            Dim stringType = compilation.GetSpecialType(SpecialType.System_String)
            Dim iFormattableType = compilation.GetTypeByMetadataName("System.IFormattable")
 
            Dim interpolatedStrings = root.DescendantNodes().OfType(Of InterpolatedStringExpressionSyntax).ToArray()
            Dim formattableStringType = compilation.GetTypeByMetadataName("System.FormattableString")
 
            Assert.True(sm.GetSymbolInfo(interpolatedStrings(0)).IsEmpty, "Interpolated String expressions shouldn't bind to symbols.")
 
            Dim info = sm.GetTypeInfo(interpolatedStrings(0))
            Assert.Equal(stringType, info.Type)
            Assert.Equal(formattableStringType, info.ConvertedType)
 
            For Each e In interpolatedStrings.Skip(1)
                Assert.True(sm.GetSymbolInfo(e).IsEmpty, "Interpolated String expressions shouldn't bind to symbols.")
 
                info = sm.GetTypeInfo(e)
                Assert.Equal(stringType, info.Type)
                Assert.Equal(iFormattableType, info.ConvertedType)
            Next
 
        End Sub
 
        <Fact>
        Public Sub ERR_InterpolationAlignmentOutOfRange()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Write($"This alignment is just small enough {New Object,32767}.") ' Short.MaxValue
        Write($"This alignment is too big {New Object,32768}.") ' Short.MaxValue + 1
        Write($"This alignment is too small {New Object,-32768}.") ' -Short.MaxValue - 1
        Write($"This alignment is just big enough {New Object,-32767}.") ' -Short.MaxValue
        Write($"This alignment is way too big {New Object,9223372036854775808}.") ' Long.MaxValue + 1
    End Sub
End Module
    </file>
</compilation>)
 
            AssertTheseCompileDiagnostics(compilation,
<expected>
BC37250: Alignment value is outside of the supported range.
        Write($"This alignment is too big {New Object,32768}.") ' Short.MaxValue + 1
                                                      ~~~~~
BC37250: Alignment value is outside of the supported range.
        Write($"This alignment is too small {New Object,-32768}.") ' -Short.MaxValue - 1
                                                        ~~~~~~
BC30036: Overflow.
        Write($"This alignment is way too big {New Object,9223372036854775808}.") ' Long.MaxValue + 1
                                                          ~~~~~~~~~~~~~~~~~~~
</expected>)
 
        End Sub
 
        <Fact>
        Public Sub Error_AmbiguousTypeArgumentInferenceWithIFormattable()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim iFormattableInstance As IFormattable = $""
 
        M($"", iFormattableInstance)
    End Sub
 
    Sub M(Of T)(a As T, b As T)
        Write(GetType(T).Name)
    End Sub
End Module
    </file>
</compilation>)
 
            AssertTheseCompileDiagnostics(compilation,
<expected>
BC36651: Data type(s) of the type parameter(s) in method 'Public Sub M(Of T)(a As T, b As T)' cannot be inferred from these arguments because more than one type is possible. Specifying the data type(s) explicitly might correct this error.
        M($"", iFormattableInstance)
        ~
</expected>)
 
        End Sub
 
        <Fact>
        Public Sub Error_AmbiguousTypeArgumentInferenceWithFormattableString()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim formattableStringInstance As FormattableString = $""
 
        M($"", formattableStringInstance)
    End Sub
 
    Sub M(Of T)(a As T, b As T)
        Write(GetType(T).Name)
    End Sub
End Module
    </file>
</compilation>)
 
            AssertTheseCompileDiagnostics(compilation,
<expected>
BC36657: Data type(s) of the type parameter(s) in method 'Public Sub M(Of T)(a As T, b As T)' cannot be inferred from these arguments because they do not convert to the same type. Specifying the data type(s) explicitly might correct this error.
        M($"", formattableStringInstance)
        ~
</expected>)
 
        End Sub
 
        <Fact>
        Public Sub Error_InterpolationExpressionNotAValue()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Write($"Expression {AddressOf Main} is not a value.")
    End Sub
End Module
    </file>
</compilation>)
 
            AssertTheseCompileDiagnostics(compilation,
<expected>
BC30491: Expression does not produce a value.
        Write($"Expression {AddressOf Main} is not a value.")
                            ~~~~~~~~~~~~~~
</expected>)
 
        End Sub
 
        <Fact>
        Public Sub FlowAnalysis_Warning_InterpolatedVariableUsedBeforeBeingAssigned()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim v As Object
 
        Write($"{v}")
    End Sub
End Module
    </file>
</compilation>)
 
            AssertTheseCompileDiagnostics(compilation,
<expected>
BC42104: Variable 'v' is used before it has been assigned a value. A null reference exception could result at runtime.
        Write($"{v}")
                 ~
</expected>)
 
        End Sub
 
        <Fact>
        Public Sub FlowAnalysis_InterpolatedLocalConstNotConsideredUnused()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Const v As Object = Nothing
 
        Write($"{v}")
    End Sub
End Module
    </file>
</compilation>)
 
            AssertNoDiagnostics(compilation)
 
        End Sub
 
        <Fact>
        Public Sub FlowAnalysis_AnalyzeDataFlowReportsCorrectResultsForVariablesUsedInInterpolations()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim v As Object = Nothing
 
        WriteLine($"{v}")
 
        WriteLine(v)
    End Sub
End Module
    </file>
</compilation>)
 
            AssertNoDiagnostics(compilation)
 
            Dim mainTree = Aggregate t In compilation.SyntaxTrees Where t.FilePath = "a.vb" Into [Single]()
            Dim root = mainTree.GetRoot()
            Dim sm = compilation.GetSemanticModel(mainTree)
 
            Dim vSymbol = CType(sm.GetDeclaredSymbol(root.DescendantNodes().OfType(Of ModifiedIdentifierSyntax).Single()), ILocalSymbol)
 
            Dim writeLineCall = root.DescendantNodes().OfType(Of ExpressionStatementSyntax).First()
            Assert.Equal("WriteLine($""{v}"")", writeLineCall.ToString())
 
            Dim analysis = sm.AnalyzeDataFlow(writeLineCall)
 
            Assert.True(analysis.Succeeded)
            Assert.DoesNotContain(vSymbol, analysis.AlwaysAssigned)
            Assert.DoesNotContain(vSymbol, analysis.Captured)
            Assert.Contains(vSymbol, analysis.DataFlowsIn)
            Assert.DoesNotContain(vSymbol, analysis.DataFlowsOut)
            Assert.Contains(vSymbol, analysis.ReadInside)
            Assert.Contains(vSymbol, analysis.ReadOutside)
            Assert.DoesNotContain(vSymbol, analysis.UnsafeAddressTaken)
            Assert.DoesNotContain(vSymbol, analysis.VariablesDeclared)
            Assert.DoesNotContain(vSymbol, analysis.WrittenInside)
            Assert.Contains(vSymbol, analysis.WrittenOutside)
 
        End Sub
 
        <Fact>
        Public Sub FlowAnalysis_AnalyzeDataFlowReportsCorrectResultsForVariablesCapturedInInterpolations()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <%= _formattableStringSource %>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim v As Object = Nothing
 
        WriteLine($"{(Function() v)()}")
 
        WriteLine(v)
    End Sub
End Module
    </file>
</compilation>)
 
            AssertNoDiagnostics(compilation)
 
            Dim mainTree = Aggregate t In compilation.SyntaxTrees Where t.FilePath = "a.vb" Into [Single]()
            Dim root = mainTree.GetRoot()
            Dim sm = compilation.GetSemanticModel(mainTree)
 
            Dim vSymbol = CType(sm.GetDeclaredSymbol(root.DescendantNodes().OfType(Of ModifiedIdentifierSyntax).Single()), ILocalSymbol)
 
            Dim writeLineCall = root.DescendantNodes().OfType(Of ExpressionStatementSyntax).First()
            Assert.Equal("WriteLine($""{(Function() v)()}"")", writeLineCall.ToString())
 
            Dim analysis = sm.AnalyzeDataFlow(writeLineCall)
 
            Assert.True(analysis.Succeeded)
            Assert.DoesNotContain(vSymbol, analysis.AlwaysAssigned)
            Assert.Contains(vSymbol, analysis.Captured)
            Assert.Contains(vSymbol, analysis.DataFlowsIn)
            Assert.DoesNotContain(vSymbol, analysis.DataFlowsOut)
            Assert.Contains(vSymbol, analysis.ReadInside)
            Assert.Contains(vSymbol, analysis.ReadOutside)
            Assert.DoesNotContain(vSymbol, analysis.UnsafeAddressTaken)
            Assert.DoesNotContain(vSymbol, analysis.VariablesDeclared)
            Assert.DoesNotContain(vSymbol, analysis.WrittenInside)
            Assert.Contains(vSymbol, analysis.WrittenOutside)
 
        End Sub
 
        <Fact>
        Public Sub Lowering_MissingFormattableStringDoesntProduceErrorIfFactoryMethodReturnsTypeConvertableToIFormattable()
 
            Dim verifier = CompileAndVerify(
<compilation>
    <file name="FormattableString.vb">
Namespace System.Runtime.CompilerServices
 
    Public Module FormattableStringFactory
 
        Public Function Create(formatString As String, ParamArray args As Object()) As IFormattable
            Return Nothing
        End Function
 
    End Module
 
End Namespace
    </file>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Write(CObj(CType($"{Nothing}.", IFormattable)))
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="")
 
        End Sub
 
        <Fact>
        Public Sub Lowering_CallsMostOptimalStringFormatOverload()
            Dim verifier = CompileAndVerify(
<compilation>
    <file name="FormattableString.vb">
Namespace System
 
    Public MustInherit Class FormattableString
        Implements IFormattable
 
        Public Overloads Function ToString(format As String, formatProvider As IFormatProvider) As String Implements IFormattable.ToString
            Throw New NotImplementedException()
        End Function
    End Class
 
End Namespace
 
Namespace System.Runtime.CompilerServices
 
    Public Module FormattableStringFactory
 
        Public Function Create(formatString As String, arg As Object) As FormattableString
            Console.Write("1 arg")
            Return Nothing
        End Function
 
        Public Function Create(formatString As String, arg1 As Object, arg2 as Object) As FormattableString
            Console.Write("2 arg")
            Return Nothing
        End Function
 
        Public Function Create(formatString As String, arg1 As Object, arg2 as Object, arg3 As Object) As FormattableString
            Console.Write("3 arg")
            Return Nothing
        End Function
 
        Public Function Create(formatString As String, ParamArray args As Object()) As FormattableString
            Console.Write("ParamArray")
            Return Nothing
        End Function
 
    End Module
 
End Namespace
    </file>
    <file name="a.vb">
Imports System
Imports System.Collections.Generic
Imports System.Linq
 
Module Program
    Sub Main(args As String())
        Dim empty As IFormattable = $""
        Dim literal As IFormattable = $"Text"
        Dim one As IFormattable = $"One interpolation {Date.Now.Hour}"
        Dim two As IFormattable = $"Two interpolations {Date.Now.Hour}:{Date.Now.Minute}"
        Dim three As IFormattable = $"Three interpolations {Date.Now.Hour}:{Date.Now.Minute}:{Date.Now.Second}"
        Dim four As IFormattable = $"Four interpolations {Date.Now.Hour}:{Date.Now.Minute}:{Date.Now.Second}.{Date.Now.Millisecond}"
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="ParamArrayParamArray1 arg2 arg3 argParamArray")
 
        End Sub
 
        <Fact>
        Public Sub Lowering_DoesNotCallFactoryMethodWithParamArrayInNormalForm()
            Dim verifier = CompileAndVerify(
<compilation>
    <file name="FormattableString.vb">
Namespace System
 
    Public MustInherit Class FormattableString
        Implements IFormattable
 
        Public Overloads Function ToString(format As String, formatProvider As IFormatProvider) As String Implements IFormattable.ToString
            Throw New NotImplementedException()
        End Function
    End Class
 
End Namespace
 
Namespace System.Runtime.CompilerServices
 
    Public Module FormattableStringFactory
 
        Public Function Create(formatString As String, ParamArray args As Object()) As FormattableString
            Console.Write(If(args Is Nothing, "Null", args.Length))
            Return Nothing
        End Function
 
    End Module
 
End Namespace
    </file>
    <file name="a.vb">
Imports System
Imports System.Collections.Generic
Imports System.Linq
 
Module Program
    Sub Main(args As String())
        Dim one As IFormattable = $"One interpolation {Nothing}"
    End Sub
End Module
    </file>
</compilation>, expectedOutput:="1")
 
        End Sub
 
        <Fact>
        Public Sub Lowering_ERR_InterpolatedStringFactoryError_CreateIsMissing()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <file name="FormattableString.vb">
Namespace System
 
    Public MustInherit Class FormattableString
        Implements IFormattable
 
        Public NotOverridable Overrides Function ToString() As String
            Return ToString(Globalization.CultureInfo.CurrentCulture)
        End Function
 
        Public MustOverride Overloads Function ToString(formatProvider As IFormatProvider) As String
 
        Public Overloads Function ToString(format As String, formatProvider As IFormatProvider) As String Implements IFormattable.ToString
            Return ToString(formatProvider)
        End Function
 
        Public Shared Function Invariant(formattable As FormattableString) As String
            Return formattable.ToString(Globalization.CultureInfo.InvariantCulture)
        End Function
    End Class
 
End Namespace
 
Namespace System.Runtime.CompilerServices
 
    Public Module FormattableStringFactory
 
        Private NotInheritable Class ConcreteFormattableString
            Inherits FormattableString
 
            Private ReadOnly FormatString As String
            Private ReadOnly Arguments As Object()
 
            Public Sub New(formatString As String, arguments As Object())
                Me.FormatString = formatString
                Me.Arguments = arguments
            End Sub
 
            Public Overrides Function ToString(provider As IFormatProvider) As String
                Return String.Format(provider, FormatString, Arguments)
            End Function
 
        End Class
 
    End Module
 
End Namespace
    </file>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Write(CType($"{1}.", IFormattable))
    End Sub
End Module
    </file>
</compilation>)
 
            AssertTheseEmitDiagnostics(compilation,
<expected>
BC37251: There were one or more errors emitting a call to FormattableStringFactory.Create. Method or its return type may be missing or malformed.
        Write(CType($"{1}.", IFormattable))
                    ~~~~~~~
</expected>)
 
        End Sub
 
        <Fact>
        Public Sub Lowering_ERR_InterpolatedStringFactoryError_CreateIsSub()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <file name="FormattableString.vb">
Namespace System
 
    Public MustInherit Class FormattableString
        Implements IFormattable
 
        Public NotOverridable Overrides Function ToString() As String
            Return ToString(Globalization.CultureInfo.CurrentCulture)
        End Function
 
        Public MustOverride Overloads Function ToString(formatProvider As IFormatProvider) As String
 
        Public Overloads Function ToString(format As String, formatProvider As IFormatProvider) As String Implements IFormattable.ToString
            Return ToString(formatProvider)
        End Function
 
        Public Shared Function Invariant(formattable As FormattableString) As String
            Return formattable.ToString(Globalization.CultureInfo.InvariantCulture)
        End Function
    End Class
 
End Namespace
 
Namespace System.Runtime.CompilerServices
 
    Public Module FormattableStringFactory
 
        Public Sub Create(formatString As String, ParamArray args As Object())
        End Sub
 
        Private NotInheritable Class ConcreteFormattableString
            Inherits FormattableString
 
            Private ReadOnly FormatString As String
            Private ReadOnly Arguments As Object()
 
            Public Sub New(formatString As String, arguments As Object())
                Me.FormatString = formatString
                Me.Arguments = arguments
            End Sub
 
            Public Overrides Function ToString(provider As IFormatProvider) As String
                Return String.Format(provider, FormatString, Arguments)
            End Function
 
        End Class
 
    End Module
 
End Namespace
    </file>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim obj As Object = Nothing
        Write(CType($"{obj}.", IFormattable))
    End Sub
End Module
    </file>
</compilation>)
 
            AssertTheseEmitDiagnostics(compilation,
<expected>
BC30491: Expression does not produce a value.
        Write(CType($"{obj}.", IFormattable))
                    ~~~~~~~~~
BC37251: There were one or more errors emitting a call to FormattableStringFactory.Create. Method or its return type may be missing or malformed.
        Write(CType($"{obj}.", IFormattable))
                    ~~~~~~~~~
</expected>)
 
        End Sub
 
        <Fact>
        Public Sub Lowering_ERR_InterpolatedStringFactoryError_CreateIsNotAMethod()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <file name="FormattableString.vb">
Namespace System
 
    Public MustInherit Class FormattableString
        Implements IFormattable
 
        Public NotOverridable Overrides Function ToString() As String
            Return ToString(Globalization.CultureInfo.CurrentCulture)
        End Function
 
        Public MustOverride Overloads Function ToString(formatProvider As IFormatProvider) As String
 
        Public Overloads Function ToString(format As String, formatProvider As IFormatProvider) As String Implements IFormattable.ToString
            Return ToString(formatProvider)
        End Function
 
        Public Shared Function Invariant(formattable As FormattableString) As String
            Return formattable.ToString(Globalization.CultureInfo.InvariantCulture)
        End Function
    End Class
 
End Namespace
 
Namespace System.Runtime.CompilerServices
 
    Public Module FormattableStringFactory
 
        Public ReadOnly Property Create(formatString As String, ParamArray args As Object()) As FormattableString
            Get
                Return New ConcreteFormattableString(formatString, args)
            End Get
        End Property
        
        Private NotInheritable Class ConcreteFormattableString
            Inherits FormattableString
 
            Private ReadOnly FormatString As String
            Private ReadOnly Arguments As Object()
 
            Public Sub New(formatString As String, arguments As Object())
                Me.FormatString = formatString
                Me.Arguments = arguments
            End Sub
 
            Public Overrides Function ToString(provider As IFormatProvider) As String
                Return String.Format(provider, FormatString, Arguments)
            End Function
 
        End Class
 
    End Module
 
End Namespace
    </file>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim obj As Object = Nothing
        Write(CType($"{obj}.", IFormattable))
    End Sub
End Module
    </file>
</compilation>)
 
            AssertTheseEmitDiagnostics(compilation,
<expected>
BC37251: There were one or more errors emitting a call to FormattableStringFactory.Create. Method or its return type may be missing or malformed.
        Write(CType($"{obj}.", IFormattable))
                    ~~~~~~~~~
</expected>)
 
        End Sub
 
        <Fact>
        Public Sub Lowering_ERR_InterpolatedStringFactoryError_CreateMethodIsShadowedByField()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <file name="FormattableString.vb">
Namespace System
 
    Public MustInherit Class FormattableString
        Implements IFormattable
 
        Public NotOverridable Overrides Function ToString() As String
            Return ToString(Globalization.CultureInfo.CurrentCulture)
        End Function
 
        Public MustOverride Overloads Function ToString(formatProvider As IFormatProvider) As String
 
        Public Overloads Function ToString(format As String, formatProvider As IFormatProvider) As String Implements IFormattable.ToString
            Return ToString(formatProvider)
        End Function
 
        Public Shared Function Invariant(formattable As FormattableString) As String
            Return formattable.ToString(Globalization.CultureInfo.InvariantCulture)
        End Function
    End Class
 
End Namespace
 
Namespace System.Runtime.CompilerServices
 
    Public Class FormattableStringFactoryBase
 
        Public Shared Function Create(formatString As String, ParamArray args As Object()) As FormattableString
            Return Nothing
        End Function
        
    End Class
 
    Public Class FormattableStringFactory
        Inherits FormattableStringFactoryBase
        
        Public Shadows Shared Create As Func(Of String, Object(), FormattableString) = Function(s, args) New ConcreteFormattableString(s, args)
 
        Protected NotInheritable Class ConcreteFormattableString
            Inherits FormattableString
 
            Private ReadOnly FormatString As String
            Private ReadOnly Arguments As Object()
 
            Public Sub New(formatString As String, arguments As Object())
                Me.FormatString = formatString
                Me.Arguments = arguments
            End Sub
 
            Public Overrides Function ToString(provider As IFormatProvider) As String
                Return String.Format(provider, FormatString, Arguments)
            End Function
 
        End Class
 
    End Class
 
End Namespace
    </file>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim obj As Object = Nothing
        Write(CType($"{obj}.", IFormattable))
    End Sub
End Module
    </file>
</compilation>)
 
            AssertTheseEmitDiagnostics(compilation,
<expected>
BC37251: There were one or more errors emitting a call to FormattableStringFactory.Create. Method or its return type may be missing or malformed.
        Write(CType($"{obj}.", IFormattable))
                    ~~~~~~~~~
</expected>)
 
        End Sub
 
        <Fact>
        Public Sub Lowering_ERR_InterpolatedStringFactoryError_CreateIsInAccessible()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <file name="FormattableString.vb">
Namespace System
 
    Public MustInherit Class FormattableString
        Implements IFormattable
 
        Public NotOverridable Overrides Function ToString() As String
            Return ToString(Globalization.CultureInfo.CurrentCulture)
        End Function
 
        Public MustOverride Overloads Function ToString(formatProvider As IFormatProvider) As String
 
        Public Overloads Function ToString(format As String, formatProvider As IFormatProvider) As String Implements IFormattable.ToString
            Return ToString(formatProvider)
        End Function
 
        Public Shared Function Invariant(formattable As FormattableString) As String
            Return formattable.ToString(Globalization.CultureInfo.InvariantCulture)
        End Function
    End Class
 
End Namespace
 
Namespace System.Runtime.CompilerServices
 
    Public Module FormattableStringFactory
 
        Private Function Create(formatString As String, ParamArray args As Object()) As FormattableString
            Return New ConcreteFormattableString(formatString, args)
        End Function
        
        Private NotInheritable Class ConcreteFormattableString
            Inherits FormattableString
 
            Private ReadOnly FormatString As String
            Private ReadOnly Arguments As Object()
 
            Public Sub New(formatString As String, arguments As Object())
                Me.FormatString = formatString
                Me.Arguments = arguments
            End Sub
 
            Public Overrides Function ToString(provider As IFormatProvider) As String
                Return String.Format(provider, FormatString, Arguments)
            End Function
 
        End Class
 
    End Module
 
End Namespace
    </file>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim obj As Object = Nothing
        Write(CType($"{obj}.", IFormattable))
    End Sub
End Module
    </file>
</compilation>)
 
            AssertTheseEmitDiagnostics(compilation,
<expected>
BC30390: 'FormattableStringFactory.Private Function Create(formatString As String, ParamArray args As Object()) As FormattableString' is not accessible in this context because it is 'Private'.
        Write(CType($"{obj}.", IFormattable))
                    ~~~~~~~~~
BC37251: There were one or more errors emitting a call to FormattableStringFactory.Create. Method or its return type may be missing or malformed.
        Write(CType($"{obj}.", IFormattable))
                    ~~~~~~~~~
</expected>)
 
        End Sub
 
        <Fact>
        Public Sub Lowering_ERR_InterpolatedStringFactoryError_CreateReturnIsNotConvertible()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <file name="FormattableString.vb">
Namespace System
 
    Public MustInherit Class FormattableString
        Implements IFormattable
 
        Public NotOverridable Overrides Function ToString() As String
            Return ToString(Globalization.CultureInfo.CurrentCulture)
        End Function
 
        Public MustOverride Overloads Function ToString(formatProvider As IFormatProvider) As String
 
        Public Overloads Function ToString(format As String, formatProvider As IFormatProvider) As String Implements IFormattable.ToString
            Return ToString(formatProvider)
        End Function
 
        Public Shared Function Invariant(formattable As FormattableString) As String
            Return formattable.ToString(Globalization.CultureInfo.InvariantCulture)
        End Function
    End Class
 
End Namespace
 
Namespace System.Runtime.CompilerServices
 
    Public Module FormattableStringFactory
 
        Public Function Create(formatString As String, ParamArray args As Object()) As Object()
            Return {formatString, args}
        End Function
 
        Private NotInheritable Class ConcreteFormattableString
            Inherits FormattableString
 
            Private ReadOnly FormatString As String
            Private ReadOnly Arguments As Object()
 
            Public Sub New(formatString As String, arguments As Object())
                Me.FormatString = formatString
                Me.Arguments = arguments
            End Sub
 
            Public Overrides Function ToString(provider As IFormatProvider) As String
                Return String.Format(provider, FormatString, Arguments)
            End Function
 
        End Class
 
    End Module
 
End Namespace
    </file>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim obj As Object = Nothing
        Write(CType($"{obj}.", IFormattable))
    End Sub
End Module
    </file>
</compilation>)
 
            AssertTheseEmitDiagnostics(compilation,
<expected>
BC30311: Value of type 'Object()' cannot be converted to 'IFormattable'.
        Write(CType($"{obj}.", IFormattable))
                    ~~~~~~~~~
BC37251: There were one or more errors emitting a call to FormattableStringFactory.Create. Method or its return type may be missing or malformed.
        Write(CType($"{obj}.", IFormattable))
                    ~~~~~~~~~
</expected>)
 
        End Sub
 
        <Fact>
        Public Sub Lowering_ERR_InterpolatedStringFactoryError_ArgArrayIsNotConvertible()
 
            Dim compilation = CreateCompilationWithMscorlib40AndVBRuntimeAndReferences(
<compilation>
    <file name="FormattableString.vb">
Namespace System
 
    Public MustInherit Class FormattableString
        Implements IFormattable
 
        Public NotOverridable Overrides Function ToString() As String
            Return ToString(Globalization.CultureInfo.CurrentCulture)
        End Function
 
        Public MustOverride Overloads Function ToString(formatProvider As IFormatProvider) As String
 
        Public Overloads Function ToString(format As String, formatProvider As IFormatProvider) As String Implements IFormattable.ToString
            Return ToString(formatProvider)
        End Function
 
        Public Shared Function Invariant(formattable As FormattableString) As String
            Return formattable.ToString(Globalization.CultureInfo.InvariantCulture)
        End Function
    End Class
 
End Namespace
 
Namespace System.Runtime.CompilerServices
 
    Public Module FormattableStringFactory
 
        Public Function Create(formatString As String, ParamArray args As Integer()) As FormattableString
            Return Nothing
        End Function
 
        Private NotInheritable Class ConcreteFormattableString
            Inherits FormattableString
 
            Private ReadOnly FormatString As String
            Private ReadOnly Arguments As Object()
 
            Public Sub New(formatString As String, arguments As Object())
                Me.FormatString = formatString
                Me.Arguments = arguments
            End Sub
 
            Public Overrides Function ToString(provider As IFormatProvider) As String
                Return String.Format(provider, FormatString, Arguments)
            End Function
 
        End Class
 
    End Module
 
End Namespace
    </file>
    <file name="a.vb">
Imports System
Imports System.Console
 
Module Program
    Sub Main()
        Dim s As IFormattable = $"{New String() {}}"
    End Sub
End Module
    </file>
</compilation>)
 
            AssertTheseEmitDiagnostics(compilation,
<expected>
BC37251: There were one or more errors emitting a call to FormattableStringFactory.Create. Method or its return type may be missing or malformed.
        Dim s As IFormattable = $"{New String() {}}"
                                ~~~~~~~~~~~~~~~~~~~~
BC30311: Value of type 'String()' cannot be converted to 'Integer'.
        Dim s As IFormattable = $"{New String() {}}"
                                   ~~~~~~~~~~~~~~~
</expected>)
 
        End Sub
 
    End Class
 
End Namespace