/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Test/Semantic/Semantics/InterpolatedStringTests.vb
2 056 строк
60 KB
Copilot
Copilot: Fix culture-sensitive StringBuilder.Append and ToString calls across codebase and add banned symbols (#80800)
25 окт 2025, 02:42
Не верифицирован
25 окт 2025, 02:42
5ce2f56
Код
Авторство
О чём код?
' 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.Threading 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,&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 = 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, 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 <Fact, WorkItem("https://github.com/dotnet/runtime/issues/44678")> Public Sub AlignmentWithNegativeValue() ' This test verifies that negative alignment values are formatted using invariant culture. ' The issue occurs when compiling under non-US cultures (e.g., Swedish sv-SE) where the ' minus sign is formatted as '−' (U+2212) instead of '-' (U+002D), causing runtime errors. ' Test under Swedish culture (sv-SE) where minus sign is represented differently Using New CultureContext(New System.Globalization.CultureInfo("sv-SE", useUserOverride:=False)) Dim verifier = CompileAndVerify( <compilation> <file name="a.vb"> Imports System.Console Module Program Sub Main() Dim st = "1" WriteLine($"{st,100}") ' Positive alignment WriteLine($"{st,-100}") ' Negative alignment - this is the problematic case End Sub End Module </file> </compilation>, expectedOutput:= " 1 1 ") verifier.VerifyDiagnostics() ' Verify that the emitted IL contains the correct format string with a proper minus sign verifier.VerifyIL("Program.Main", " { // Code size 39 (0x27) .maxstack 2 .locals init (String V_0) //st IL_0000: ldstr ""1"" IL_0005: stloc.0 IL_0006: ldstr ""{0,100}"" IL_000b: ldloc.0 IL_000c: call ""Function String.Format(String, Object) As String"" IL_0011: call ""Sub System.Console.WriteLine(String)"" IL_0016: ldstr ""{0,-100}"" IL_001b: ldloc.0 IL_001c: call ""Function String.Format(String, Object) As String"" IL_0021: call ""Sub System.Console.WriteLine(String)"" IL_0026: ret } ") End Using End Sub End Class End Namespace