|
' 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
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests.Emit
Imports Roslyn.Test.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests
Public Class CodeGenIfOperator
Inherits BasicTestBase
' Conditional operator as parameter
<Fact>
Public Sub ConditionalOperatorAsParameter()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer Off
Imports System
Module C
Sub Main(args As String())
Dim a0 As Boolean = False
Dim a1 As Integer = 0
Dim a2 As Long = 1
Dim b0 = a0
Dim b1 = a1
Dim b2 = a2
Console.WriteLine((If(b0, b1, b2)) <> (If(a0, a1, a2)))
End Sub
End Module
</file>
</compilation>, expectedOutput:=<![CDATA[
False
]]>).VerifyIL("C.Main", <![CDATA[
{
// Code size 70 (0x46)
.maxstack 3
.locals init (Boolean V_0, //a0
Integer V_1, //a1
Long V_2, //a2
Object V_3, //b1
Object V_4) //b2
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldc.i4.0
IL_0003: stloc.1
IL_0004: ldc.i4.1
IL_0005: conv.i8
IL_0006: stloc.2
IL_0007: ldloc.0
IL_0008: box "Boolean"
IL_000d: ldloc.1
IL_000e: box "Integer"
IL_0013: stloc.3
IL_0014: ldloc.2
IL_0015: box "Long"
IL_001a: stloc.s V_4
IL_001c: call "Function Microsoft.VisualBasic.CompilerServices.Conversions.ToBoolean(Object) As Boolean"
IL_0021: brtrue.s IL_0027
IL_0023: ldloc.s V_4
IL_0025: br.s IL_0028
IL_0027: ldloc.3
IL_0028: ldloc.0
IL_0029: brtrue.s IL_002e
IL_002b: ldloc.2
IL_002c: br.s IL_0030
IL_002e: ldloc.1
IL_002f: conv.i8
IL_0030: box "Long"
IL_0035: ldc.i4.0
IL_0036: call "Function Microsoft.VisualBasic.CompilerServices.Operators.CompareObjectNotEqual(Object, Object, Boolean) As Object"
IL_003b: call "Function System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Object) As Object"
IL_0040: call "Sub System.Console.WriteLine(Object)"
IL_0045: ret
}
]]>).Compilation
End Sub
' Function call in return expression
<WorkItem(541647, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541647")>
<Fact()>
Public Sub FunctionCallAsArgument()
CompileAndVerify(
<compilation>
<file name="a.vb">
Imports System
Module C
Sub Main(args As String())
Dim z = If(True, fun_Exception(1), fun_int(1))
Dim r = If(True, fun_long(0), fun_int(1))
Dim s = If(False, fun_long(0), fun_int(1))
End Sub
Private Function fun_int(x As Integer) As Integer
Return x
End Function
Private Function fun_long(x As Integer) As Long
Return CLng(x)
End Function
Private Function fun_Exception(x As Integer) As Exception
Return New Exception()
End Function
End Module
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("C.Main", <![CDATA[
{
// Code size 28 (0x1c)
.maxstack 1
IL_0000: ldc.i4.1
IL_0001: call "Function C.fun_Exception(Integer) As System.Exception"
IL_0006: call "Function System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Object) As Object"
IL_000b: pop
IL_000c: ldc.i4.0
IL_000d: call "Function C.fun_long(Integer) As Long"
IL_0012: pop
IL_0013: ldc.i4.1
IL_0014: call "Function C.fun_int(Integer) As Integer"
IL_0019: conv.i8
IL_001a: pop
IL_001b: ret
}]]>)
End Sub
' Lambda works in return argument
<Fact()>
Public Sub LambdaAsArgument_1()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer Off
Imports System
Module C
Sub Main(args As String())
Dim Y = 2
Dim S = If(True, _
Function(z As Integer) As Integer
System.Console.WriteLine("SUB")
Return z * z
End Function, Y + 1)
S = If(False, _
Sub(Z As Integer)
System.Console.WriteLine("SUB")
End Sub, Y + 1)
System.Console.WriteLine(S)
End Sub
End Module
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("C.Main", <![CDATA[
{
// Code size 77 (0x4d)
.maxstack 2
.locals init (Object V_0) //Y
IL_0000: ldc.i4.2
IL_0001: box "Integer"
IL_0006: stloc.0
IL_0007: ldsfld "C._Closure$__.$I0-0 As <generated method>"
IL_000c: brfalse.s IL_0015
IL_000e: ldsfld "C._Closure$__.$I0-0 As <generated method>"
IL_0013: br.s IL_002b
IL_0015: ldsfld "C._Closure$__.$I As C._Closure$__"
IL_001a: ldftn "Function C._Closure$__._Lambda$__0-0(Integer) As Integer"
IL_0020: newobj "Sub VB$AnonymousDelegate_0(Of Integer, Integer)..ctor(Object, System.IntPtr)"
IL_0025: dup
IL_0026: stsfld "C._Closure$__.$I0-0 As <generated method>"
IL_002b: call "Function System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Object) As Object"
IL_0030: pop
IL_0031: ldloc.0
IL_0032: ldc.i4.1
IL_0033: box "Integer"
IL_0038: call "Function Microsoft.VisualBasic.CompilerServices.Operators.AddObject(Object, Object) As Object"
IL_003d: call "Function System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Object) As Object"
IL_0042: call "Function System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Object) As Object"
IL_0047: call "Sub System.Console.WriteLine(Object)"
IL_004c: ret
}
]]>).Compilation
End Sub
' Conditional on expression tree
<Fact()>
Public Sub ExpressionTree()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer On
Imports System
Imports System.Linq.Expressions
Module Program
Sub Main(args As String())
Dim testExpr As Expression(Of Func(Of Boolean, Long, Integer, Long)) = Function(x, y, z) If(x, y, z)
Dim testFunc = testExpr.Compile()
Dim testResult = testFunc(False, CLng(3), 100)
Console.WriteLine(testResult)
End Sub
End Module
</file>
</compilation>, expectedOutput:=<![CDATA[
100
]]>).Compilation
End Sub
' Conditional on expression tree
<Fact()>
Public Sub ExpressionTree_2()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer on
Imports System
Imports System.Linq.Expressions
Module Program
Sub Main(args As String())
Dim testExpr As Expression(Of Func(Of TestStruct, Long?, Integer, Integer?)) = Function(x, y, z) If(x, y, z)
Dim testFunc = testExpr.Compile()
Dim testResult1 = testFunc(New TestStruct(), Nothing, 10)
Dim testResult2 = testFunc(New TestStruct(), 10, Nothing)
Console.WriteLine (testResult1)
Console.WriteLine (testResult2)
End Sub
End Module
Public Structure TestStruct
Public Shared Operator IsTrue(ts As TestStruct) As Boolean
Return False
End Operator
Public Shared Operator IsFalse(ts As TestStruct) As Boolean
Return True
End Operator
End Structure
</file>
</compilation>, expectedOutput:=<![CDATA[
10
0
]]>).Compilation
End Sub
' Multiple conditional operator in expression
<Fact>
Public Sub MultipleConditional()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer Off
Imports System
Module C
Sub Main(args As String())
Dim S = If(False, 1, If(True, 2, 3))
Console.Write(S)
End Sub
End Module
</file>
</compilation>, expectedOutput:=<![CDATA[
2
]]>).VerifyIL("C.Main", <![CDATA[
{
// Code size 17 (0x11)
.maxstack 1
IL_0000: ldc.i4.2
IL_0001: box "Integer"
IL_0006: call "Function System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Object) As Object"
IL_000b: call "Sub System.Console.Write(Object)"
IL_0010: ret
}]]>).Compilation
End Sub
' Arguments are of types: bool, constant, enum
<Fact>
Public Sub EnumAsArguments()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer Off
Imports System
Module C
Sub Main(args As String())
Dim testResult = If(False, 0, color.Blue)
Console.WriteLine(testResult)
testResult = If(False, 5, color.Blue)
Console.WriteLine(testResult)
End Sub
End Module
Enum color
Red
Green
Blue
End Enum
</file>
</compilation>, expectedOutput:=<![CDATA[
2
2
]]>).VerifyIL("C.Main", <![CDATA[
{
// Code size 33 (0x21)
.maxstack 1
IL_0000: ldc.i4.2
IL_0001: box "Integer"
IL_0006: call "Function System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Object) As Object"
IL_000b: call "Sub System.Console.WriteLine(Object)"
IL_0010: ldc.i4.2
IL_0011: box "Integer"
IL_0016: call "Function System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Object) As Object"
IL_001b: call "Sub System.Console.WriteLine(Object)"
IL_0020: ret
}]]>).Compilation
End Sub
' Implicit type conversion on conditional
<Fact>
Public Sub ImplicitConversionForConditional()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Imports System
Module C
Sub Main(args As String())
Dim valueFromDatabase As Object
Dim result As Decimal
valueFromDatabase = DBNull.Value
result = CDec(If(valueFromDatabase IsNot DBNull.Value, valueFromDatabase, 0))
Console.WriteLine(result)
result = (If(valueFromDatabase IsNot DBNull.Value, CDec(valueFromDatabase), CDec(0)))
Console.WriteLine(result)
End Sub
End Module
</file>
</compilation>, expectedOutput:=<![CDATA[
0
0
]]>).VerifyIL("C.Main", <![CDATA[
{
// Code size 60 (0x3c)
.maxstack 2
.locals init (Object V_0) //valueFromDatabase
IL_0000: ldsfld "System.DBNull.Value As System.DBNull"
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldsfld "System.DBNull.Value As System.DBNull"
IL_000c: bne.un.s IL_0016
IL_000e: ldc.i4.0
IL_000f: box "Integer"
IL_0014: br.s IL_0017
IL_0016: ldloc.0
IL_0017: call "Function Microsoft.VisualBasic.CompilerServices.Conversions.ToDecimal(Object) As Decimal"
IL_001c: call "Sub System.Console.WriteLine(Decimal)"
IL_0021: ldloc.0
IL_0022: ldsfld "System.DBNull.Value As System.DBNull"
IL_0027: bne.un.s IL_0030
IL_0029: ldsfld "Decimal.Zero As Decimal"
IL_002e: br.s IL_0036
IL_0030: ldloc.0
IL_0031: call "Function Microsoft.VisualBasic.CompilerServices.Conversions.ToDecimal(Object) As Decimal"
IL_0036: call "Sub System.Console.WriteLine(Decimal)"
IL_003b: ret
}]]>).Compilation
End Sub
' Not boolean type as conditional-argument
<WorkItem(541647, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541647")>
<Fact()>
Public Sub NotBooleanAsConditionalArgument()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Imports System
Module C
Sub Main(args As String())
Dim x = 1
Dim s = If("", x, 2)
'invalid
s = If("True", x, 2)
'valid
s = If("1", x, 2)
'valid
End Sub
End Module
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("C.Main", <![CDATA[
{
// Code size 36 (0x24)
.maxstack 1
.locals init (Integer V_0) //x
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldstr ""
IL_0007: call "Function Microsoft.VisualBasic.CompilerServices.Conversions.ToBoolean(String) As Boolean"
IL_000c: pop
IL_000d: ldstr "True"
IL_0012: call "Function Microsoft.VisualBasic.CompilerServices.Conversions.ToBoolean(String) As Boolean"
IL_0017: pop
IL_0018: ldstr "1"
IL_001d: call "Function Microsoft.VisualBasic.CompilerServices.Conversions.ToBoolean(String) As Boolean"
IL_0022: pop
IL_0023: ret
}]]>).Compilation
End Sub
' Not boolean type as conditional-argument
<WorkItem(541647, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541647")>
<Fact()>
Public Sub NotBooleanAsConditionalArgument_2()
CompileAndVerify(
<compilation>
<file name="a.vb">
Imports System
Module C
Sub Main(args As String())
Dim x = 1
Dim s = If(color.Green, x, 2)
Console.WriteLine(S)
s = If(color.Red, x, 2)
Console.WriteLine(s)
End Sub
End Module
Public Enum color
Red
Blue
Green
End Enum
</file>
</compilation>, expectedOutput:=<![CDATA[
1
2
]]>)
End Sub
<WorkItem(541647, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541647")>
<Fact>
Public Sub FunctionWithNoReturnType()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer Off
Imports System
Module C
Sub Main(args As String())
Dim x = 1
Dim s = If(fun1(), x, 2)
End Sub
Private Function fun1()
End Function
End Module
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("C.Main", <![CDATA[
{
// Code size 35 (0x23)
.maxstack 1
.locals init (Object V_0) //x
IL_0000: ldc.i4.1
IL_0001: box "Integer"
IL_0006: stloc.0
IL_0007: call "Function C.fun1() As Object"
IL_000c: call "Function Microsoft.VisualBasic.CompilerServices.Conversions.ToBoolean(Object) As Boolean"
IL_0011: brtrue.s IL_001b
IL_0013: ldc.i4.2
IL_0014: box "Integer"
IL_0019: br.s IL_001c
IL_001b: ldloc.0
IL_001c: call "Function System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Object) As Object"
IL_0021: pop
IL_0022: ret
}]]>).Compilation
End Sub
' Const as conditional- argument
<WorkItem(541452, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541452")>
<Fact()>
Public Sub ConstAsArgument()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Imports System
Module C
Sub Main(args As String())
Const con As Boolean = True
Dim s1 = If(con, 1, 2)
Console.Write(s1)
End Sub
End Module
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("C.Main", <![CDATA[
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldc.i4.1
IL_0001: call "Sub System.Console.Write(Integer)"
IL_0006: ret
}
]]>).Compilation
End Sub
' Const i As Integer = IF
<Fact>
Public Sub AssignIfToConst()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Imports System
Module Program
Sub Main(args As String())
Const s As Integer = If(1>2, 9, 92)
End Sub
End Module
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("Program.Main", <![CDATA[
{
// Code size 1 (0x1)
.maxstack 0
IL_0000: ret
}]]>).Compilation
End Sub
' IF used in Redim
<WorkItem(528563, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528563")>
<Fact>
Public Sub IfUsedInRedim()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer Off
Imports System
Module Program
Sub Main(args As String())
Dim s1 As Integer()
ReDim Preserve s1(If(True, 10, 101))
End Sub
End Module
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("Program.Main", <![CDATA[
{
// Code size 20 (0x14)
.maxstack 2
.locals init (Integer() V_0) //s1
IL_0000: ldloc.0
IL_0001: ldc.i4.s 11
IL_0003: newarr "Integer"
IL_0008: call "Function Microsoft.VisualBasic.CompilerServices.Utils.CopyArray(System.Array, System.Array) As System.Array"
IL_000d: castclass "Integer()"
IL_0012: stloc.0
IL_0013: ret
}]]>).Compilation
End Sub
' IF on attribute
<Fact>
Public Sub IFOnAttribute()
CompileAndVerify(
<compilation>
<file name="a.vb">
Imports System
<Assembly: CLSCompliant(If(True, False, True))>
Public Class base
Public Shared sub Main()
End Sub
End Class
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyDiagnostics()
End Sub
' #const val =if
<Fact>
Public Sub PredefinedConst()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Public Class Program
Public Shared Sub Main()
#Const ifconst = If(True, 1, 2)
#If ifconst = 1 Then
#End If
End Sub
End Class
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("Program.Main", <![CDATA[
{
// Code size 1 (0x1)
.maxstack 0
IL_0000: ret
}]]>).Compilation
End Sub
' IF as function name
<Fact>
Public Sub IFAsFunctionName()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer Off
Module M1
Sub Main()
End Sub
Public Function [if](ByVal arg As String) As String
Return arg
End Function
End Module
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("M1.if", <![CDATA[
{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
}]]>).Compilation
End Sub
' IF as Optional parameter
<Fact()>
Public Sub IFAsOptionalParameter()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer Off
Module M1
Sub Main()
goo()
End Sub
Public Sub goo(Optional ByVal arg As String = If(False, "6", "61"))
System.Console.WriteLine(arg)
End Sub
End Module
</file>
</compilation>, expectedOutput:="61").Compilation
End Sub
' IF used in For step
<Fact()>
Public Sub IFUsedInForStep()
CompileAndVerify(
<compilation>
<file name="a.vb">
Module M1
Sub Main()
Dim s10 As Boolean = False
For c As Integer = 1 To 10 Step If(s10, 1, 2)
Next
End Sub
End Module
</file>
</compilation>, options:=TestOptions.ReleaseExe)
End Sub
' Passing IF as byref arg
<WorkItem(541647, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541647")>
<Fact()>
Public Sub IFAsByrefArg()
CompileAndVerify(
<compilation>
<file name="a.vb">
Module M1
Sub Main()
Dim X = "123"
Dim Y = "456"
Dim Z = If(1 > 2, goo(X), goo(Y))
End Sub
Private Function goo(ByRef p1 As String)
p1 = "HELLO"
End Function
End Module
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("M1.Main", <![CDATA[
{
// Code size 26 (0x1a)
.maxstack 1
.locals init (String V_0, //X
String V_1) //Y
IL_0000: ldstr "123"
IL_0005: stloc.0
IL_0006: ldstr "456"
IL_000b: stloc.1
IL_000c: ldloca.s V_1
IL_000e: call "Function M1.goo(ByRef String) As Object"
IL_0013: call "Function System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(Object) As Object"
IL_0018: pop
IL_0019: ret
}]]>)
End Sub
<WorkItem(541674, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541674")>
<Fact>
Public Sub TypeConversionInRuntime()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Imports System.Collections.Generic
Public Class Test
Private Shared Sub Main()
Dim a As Integer() = New Integer() {}
Dim b As New List(Of Integer)()
Dim c As IEnumerable(Of Integer) = If(a.Length > 0, a, DirectCast(b, IEnumerable(Of Integer)))
End Sub
End Class
</file>
</compilation>, options:=TestOptions.ReleaseDll).VerifyIL("Test.Main", <![CDATA[
{
// Code size 25 (0x19)
.maxstack 2
.locals init (Integer() V_0, //a
System.Collections.Generic.List(Of Integer) V_1) //b
IL_0000: ldc.i4.0
IL_0001: newarr "Integer"
IL_0006: stloc.0
IL_0007: newobj "Sub System.Collections.Generic.List(Of Integer)..ctor()"
IL_000c: stloc.1
IL_000d: ldloc.0
IL_000e: ldlen
IL_000f: conv.i4
IL_0010: ldc.i4.0
IL_0011: bgt.s IL_0016
IL_0013: ldloc.1
IL_0014: pop
IL_0015: ret
IL_0016: ldloc.0
IL_0017: pop
IL_0018: ret
}
]]>).Compilation
End Sub
<WorkItem(541673, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541673")>
<Fact>
Public Sub TypeConversionInRuntime_1()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer Off
Public Interface IB
Function f() As Integer
End Interface
Public Class AB1
Implements IB
Public Function f() As Integer Implements IB.f
Return 42
End Function
End Class
Public Class AB2
Implements IB
Public Function f() As Integer Implements IB.f
Return 1
End Function
End Class
Class MainClass
Public Shared Sub g(p As Boolean)
Dim x = (If(p, DirectCast(New AB1(), IB), DirectCast(New AB2(), IB))).f()
End Sub
Public Shared Sub Main()
End Sub
End Class
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("MainClass.g", <![CDATA[
{
// Code size 29 (0x1d)
.maxstack 1
.locals init (IB V_0)
IL_0000: ldarg.0
IL_0001: brtrue.s IL_000a
IL_0003: newobj "Sub AB2..ctor()"
IL_0008: br.s IL_0011
IL_000a: newobj "Sub AB1..ctor()"
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: callvirt "Function IB.f() As Integer"
IL_0016: box "Integer"
IL_001b: pop
IL_001c: ret
}]]>).Compilation
End Sub
<Fact>
Public Sub TypeConversionInRuntime_2()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer Off
Public Interface IB
Function f() As Integer
End Interface
Public Class AB1
Implements IB
Public Function f() As Integer Implements IB.f
Return 42
End Function
End Class
Class MainClass
Public Shared Sub g(p As Boolean)
Dim x = (If(p, DirectCast(New AB1(), IB), DirectCast(New AB1(), IB))).f()
End Sub
Public Shared Sub Main()
End Sub
End Class
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("MainClass.g", <![CDATA[
{
// Code size 29 (0x1d)
.maxstack 1
.locals init (IB V_0)
IL_0000: ldarg.0
IL_0001: brtrue.s IL_000a
IL_0003: newobj "Sub AB1..ctor()"
IL_0008: br.s IL_0011
IL_000a: newobj "Sub AB1..ctor()"
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: callvirt "Function IB.f() As Integer"
IL_0016: box "Integer"
IL_001b: pop
IL_001c: ret
}]]>).Compilation
End Sub
<Fact>
Public Sub TypeConversionInRuntime_3()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer Off
Public Interface IB
Function f() As Integer
End Interface
Public Class AB1
Implements IB
Public Function f() As Integer Implements IB.f
Return 42
End Function
End Class
Class MainClass
Public Shared Sub g(p As Boolean)
Dim x = (If(DirectCast(New AB1(), IB), DirectCast(New AB1(), IB))).f()
End Sub
Public Shared Sub Main()
End Sub
End Class
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("MainClass.g", <![CDATA[
{
// Code size 28 (0x1c)
.maxstack 2
.locals init (IB V_0)
IL_0000: newobj "Sub AB1..ctor()"
IL_0005: dup
IL_0006: brtrue.s IL_0010
IL_0008: pop
IL_0009: newobj "Sub AB1..ctor()"
IL_000e: stloc.0
IL_000f: ldloc.0
IL_0010: callvirt "Function IB.f() As Integer"
IL_0015: box "Integer"
IL_001a: pop
IL_001b: ret
}]]>).Compilation
End Sub
<Fact>
Public Sub TypeConversionInterface()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Interface IBase
Function m1() As IBase
End Interface
Class Derived
Public Shared mask As Integer = 1
End Class
Class Test1
Implements IBase
Private y As IBase
Private x As IBase
Private cnt As Integer = 0
Public Sub New(link As IBase)
x = Me
y = link
If y Is Nothing Then
y = Me
End If
End Sub
Public Shared Sub Main()
End Sub
Public Function m1() As IBase Implements IBase.m1
Return If(Derived.mask = 0, x, y)
End Function
'version1 (explicit impl in original repro)
Public Function m2() As IBase
Return If(Derived.mask = 0, Me, y)
End Function
'version2
End Class
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("Test1.m1", <![CDATA[
{
// Code size 21 (0x15)
.maxstack 1
IL_0000: ldsfld "Derived.mask As Integer"
IL_0005: brfalse.s IL_000e
IL_0007: ldarg.0
IL_0008: ldfld "Test1.y As IBase"
IL_000d: ret
IL_000e: ldarg.0
IL_000f: ldfld "Test1.x As IBase"
IL_0014: ret
}]]>).VerifyIL("Test1.m2", <![CDATA[
{
// Code size 16 (0x10)
.maxstack 1
IL_0000: ldsfld "Derived.mask As Integer"
IL_0005: brfalse.s IL_000e
IL_0007: ldarg.0
IL_0008: ldfld "Test1.y As IBase"
IL_000d: ret
IL_000e: ldarg.0
IL_000f: ret
}]]>).Compilation
End Sub
<Fact>
Public Sub TypeConversionInterface_1()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Interface IBase
Function m1() As IBase
End Interface
Class Derived
Public Shared mask As Integer = 1
End Class
Class Test1
Implements IBase
Private y As IBase
Private x As IBase
Private cnt As Integer = 0
Public Sub New(link As IBase)
x = Me
y = link
If y Is Nothing Then
y = Me
End If
End Sub
Public Shared Sub Main()
End Sub
Public Function m1() As IBase Implements IBase.m1
Return If(x, y)
End Function
'version1 (explicit impl in original repro)
Public Function m2() As IBase
Return If(Me, y)
End Function
'version2
End Class
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("Test1.m1", <![CDATA[
{
// Code size 17 (0x11)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldfld "Test1.x As IBase"
IL_0006: dup
IL_0007: brtrue.s IL_0010
IL_0009: pop
IL_000a: ldarg.0
IL_000b: ldfld "Test1.y As IBase"
IL_0010: ret
}]]>).VerifyIL("Test1.m2", <![CDATA[
{
// Code size 12 (0xc)
.maxstack 2
IL_0000: ldarg.0
IL_0001: dup
IL_0002: brtrue.s IL_000b
IL_0004: pop
IL_0005: ldarg.0
IL_0006: ldfld "Test1.y As IBase"
IL_000b: ret
}]]>).Compilation
End Sub
<Fact>
Public Sub TypeConversionInterface_2()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Interface IBase
Function m1() As IBase
End Interface
Class Derived
Public Shared mask As Integer = 1
End Class
Class Test1
Implements IBase
Private y As IBase
Private x As IBase
Private cnt As Integer = 0
Public Sub New(link As IBase)
x = Me
y = link
If y Is Nothing Then
y = Me
End If
End Sub
Public Shared Sub Main()
End Sub
Public Function m1() As IBase Implements IBase.m1
Return If (x, DirectCast(y, IBase))
End Function
'version1 (explicit impl in original repro)
Public Function m2() As IBase
Return If (DirectCast(Me, IBase), y)
End Function
'version2
End Class
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("Test1.m1", <![CDATA[
{
// Code size 17 (0x11)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldfld "Test1.x As IBase"
IL_0006: dup
IL_0007: brtrue.s IL_0010
IL_0009: pop
IL_000a: ldarg.0
IL_000b: ldfld "Test1.y As IBase"
IL_0010: ret
}]]>).VerifyIL("Test1.m2", <![CDATA[
{
// Code size 12 (0xc)
.maxstack 2
IL_0000: ldarg.0
IL_0001: dup
IL_0002: brtrue.s IL_000b
IL_0004: pop
IL_0005: ldarg.0
IL_0006: ldfld "Test1.y As IBase"
IL_000b: ret
}]]>).Compilation
End Sub
<Fact>
Public Sub TypeConversionInterface_3()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Imports System.Collections
Imports System.Collections.Generic
Class Test1
Implements IEnumerable
Dim x As IEnumerator
Dim y As IEnumerator
Public Shared Sub Main()
End Sub
Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return If(Me IsNot Nothing, DirectCast(x, IEnumerator), DirectCast(y, IEnumerator))
End Function
End Class
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("Test1.GetEnumerator", <![CDATA[
{
// Code size 17 (0x11)
.maxstack 1
IL_0000: ldarg.0
IL_0001: brtrue.s IL_000a
IL_0003: ldarg.0
IL_0004: ldfld "Test1.y As System.Collections.IEnumerator"
IL_0009: ret
IL_000a: ldarg.0
IL_000b: ldfld "Test1.x As System.Collections.IEnumerator"
IL_0010: ret
}]]>).Compilation
End Sub
<Fact>
Public Sub TypeConversionInterface_4()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Interface IBase
Function GetEnumerator() As IBase
End Interface
Interface IDerived
Inherits IBase
End Interface
Structure struct
Implements IBase
Public Shared Sub Main()
End Sub
Function GetEnumerator() As IBase Implements IBase.GetEnumerator
Dim x As IDerived
Dim y As IDerived
Return If(x IsNot Nothing, DirectCast(x, IBase), DirectCast(y, IBase))
End Function
End Structure
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("struct.GetEnumerator", <![CDATA[
{
// Code size 9 (0x9)
.maxstack 1
.locals init (IDerived V_0, //x
IDerived V_1, //y
IBase V_2)
IL_0000: ldloc.0
IL_0001: brtrue.s IL_0005
IL_0003: ldloc.1
IL_0004: ret
IL_0005: ldloc.0
IL_0006: stloc.2
IL_0007: ldloc.2
IL_0008: ret
}
]]>).Compilation
End Sub
<Fact>
Public Sub TypeConversionInterface_5()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Interface IBase
Function GetEnumerator() As IBase
End Interface
Interface IDerived
Inherits IBase
End Interface
Structure struct
Implements IDerived
Public Shared Sub Main()
End Sub
Function GetEnumerator() As IBase Implements IBase.GetEnumerator
Dim x As IDerived
Dim y As IDerived
Return If(x IsNot Nothing, DirectCast(x, IDerived), DirectCast(y, IDerived))
End Function
End Structure
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("struct.GetEnumerator", <![CDATA[
{
// Code size 7 (0x7)
.maxstack 1
.locals init (IDerived V_0, //x
IDerived V_1) //y
IL_0000: ldloc.0
IL_0001: brtrue.s IL_0005
IL_0003: ldloc.1
IL_0004: ret
IL_0005: ldloc.0
IL_0006: ret
}]]>).Compilation
End Sub
<Fact>
Public Sub TypeConversionInterface_6()
Dim compilation1 = CompileAndVerify(
<compilation>
<file name="a.vb">
Option Infer Off
Interface IBase
Function GetEnumerator() As IBase
End Interface
Interface IDerived
Inherits IBase
End Interface
Structure struct
Implements IDerived
Public Shared Sub Main()
End Sub
Function GetEnumerator() As IBase Implements IBase.GetEnumerator
Dim x = GetInterface()
Dim y = GetInterface()
Dim z = If(x IsNot Nothing, DirectCast(x, IBase), DirectCast(y, IBase))
End Function
Function GetInterface() As IBase
Return Nothing
End Function
End Structure
</file>
</compilation>, options:=TestOptions.ReleaseExe).VerifyIL("struct.GetEnumerator", <![CDATA[
{
// Code size 34 (0x22)
.maxstack 1
.locals init (IBase V_0, //GetEnumerator
Object V_1, //x
Object V_2) //y
IL_0000: ldarg.0
IL_0001: call "Function struct.GetInterface() As IBase"
IL_0006: stloc.1
IL_0007: ldarg.0
IL_0008: call "Function struct.GetInterface() As IBase"
IL_000d: stloc.2
IL_000e: ldloc.1
IL_000f: brtrue.s IL_0019
IL_0011: ldloc.2
IL_0012: castclass "IBase"
IL_0017: br.s IL_001f
IL_0019: ldloc.1
IL_001a: castclass "IBase"
IL_001f: pop
IL_0020: ldloc.0
IL_0021: ret
}]]>).Compilation
End Sub
<Fact, WorkItem(545065, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545065")>
Public Sub IfOnConstrainedMethodTypeParameter()
CompileAndVerify(
<compilation>
<file name="a.vb">
Friend Module BIFOpResult0011mod
Public Sub scen7(Of T As Class)(ByVal arg As T)
Dim s7_a As T = arg
Dim s7_b As T = Nothing
Dim s7_c = If(s7_a, s7_b)
System.Console.Write(s7_c)
End Sub
Sub Main()
scen7(Of String)("Q")
End Sub
End Module
</file>
</compilation>, expectedOutput:="Q").VerifyIL("BIFOpResult0011mod.scen7", <![CDATA[
{
// Code size 30 (0x1e)
.maxstack 2
.locals init (T V_0) //s7_b
IL_0000: ldarg.0
IL_0001: ldloca.s V_0
IL_0003: initobj "T"
IL_0009: dup
IL_000a: box "T"
IL_000f: brtrue.s IL_0013
IL_0011: pop
IL_0012: ldloc.0
IL_0013: box "T"
IL_0018: call "Sub System.Console.Write(Object)"
IL_001d: ret
}]]>)
End Sub
<Fact>
Public Sub IfOnUnconstrainedMethodTypeParameter()
CompileAndVerify(
<compilation>
<file name="a.vb">
Friend Module Mod1
Sub M1(Of T)(arg1 As T, arg2 As T)
System.Console.WriteLine(If(arg1, arg2))
End Sub
Sub M2(Of T1, T2 As T1)(arg1 as T1, arg2 As T2)
System.Console.WriteLine(If(arg2, arg1))
End Sub
Sub Main()
M1(Nothing, 1000)
M1(1, 1000)
M1(Nothing, "String Parameter 1")
M1("String Parameter 2", "Should not print")
M1(Of Integer?)(Nothing, 4)
M1(Of Integer?)(5, 1000)
M2(1000, 6)
M2(Of Object, Integer?)(7, Nothing)
M2(Of Object, Integer?)(1000, 8)
M2(Of Integer?, Integer?)(9, Nothing)
M2(Of Integer?, Integer?)(1000, 10)
End Sub
End Module
</file>
</compilation>, expectedOutput:=<![CDATA[
0
1
String Parameter 1
String Parameter 2
4
5
6
7
8
9
10
]]>).VerifyIL("Mod1.M1", <![CDATA[
{
// Code size 22 (0x16)
.maxstack 2
IL_0000: ldarg.0
IL_0001: dup
IL_0002: box "T"
IL_0007: brtrue.s IL_000b
IL_0009: pop
IL_000a: ldarg.1
IL_000b: box "T"
IL_0010: call "Sub System.Console.WriteLine(Object)"
IL_0015: ret
}
]]>).VerifyIL("Mod1.M2", <![CDATA[
{
// Code size 33 (0x21)
.maxstack 1
IL_0000: ldarg.1
IL_0001: box "T2"
IL_0006: brtrue.s IL_000b
IL_0008: ldarg.0
IL_0009: br.s IL_0016
IL_000b: ldarg.1
IL_000c: box "T2"
IL_0011: unbox.any "T1"
IL_0016: box "T1"
IL_001b: call "Sub System.Console.WriteLine(Object)"
IL_0020: ret
}
]]>)
End Sub
<Fact>
Public Sub IfOnUnconstrainedTypeParameterWithNothingLHS()
CompileAndVerify(
<compilation>
<file name="a.vb">
Imports System
Friend Module Mod1
Sub M1(Of T)(arg As T)
Console.WriteLine(If(Nothing, arg))
End Sub
Sub Main()
' Note that this behavior is different than C#'s behavior. This is consistent with Roslyn's handling
' of If(Nothing, 1), which will evaluate to 1
M1(1)
Console.WriteLine(If(Nothing, 1))
M1("String Parameter 1")
M1(Of Integer?)(3)
End Sub
End Module
</file>
</compilation>, expectedOutput:=<![CDATA[
1
1
String Parameter 1
3
]]>).VerifyIL("Mod1.M1", <![CDATA[
{
// Code size 12 (0xc)
.maxstack 1
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: box "T"
IL_0006: call "Sub System.Console.WriteLine(Object)"
IL_000b: ret
}
]]>)
End Sub
<Fact>
Public Sub IfOnUnconstrainedTypeParametersOldLanguageVersion()
CreateCompilation(
<compilation>
<file name="a.vb">
Friend Module Mod1
Sub M1(Of T)(arg1 As T, arg2 As T)
System.Console.WriteLine(If(arg1, arg2))
End Sub
End Module
</file>
</compilation>, parseOptions:=TestOptions.Regular15_5).AssertTheseDiagnostics(<![CDATA[
BC36716: Visual Basic 15.5 does not support unconstrained type parameters in binary conditional expressions.
System.Console.WriteLine(If(arg1, arg2))
~~~~~~~~~~~~~~
]]>)
End Sub
End Class
End Namespace
|