' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.PooledObjects 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 System.Collections.Immutable Imports Roslyn.Test.Utilities Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests Public Class CodeGenNullable Inherits BasicTestBase Public Sub LiftedIntrinsicNegationLocal() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As New Integer?(1) Dim y = -x Console.Write("y1={0} ", y) x = Nothing y = -x Console.Write("y2={0} ", y) y = -New Long?() Console.Write("y3={0} ", y) End Sub End Module , expectedOutput:="y1=-1 y2= y3="). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedIntrinsicNegationField() CompileAndVerify( Imports System Module MyClass1 Dim x As New Integer?(1) Sub Main(args As String()) Dim y = -x Console.WriteLine(y) End Sub End Module , expectedOutput:="-1"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedIntrinsicNegationNull() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim y = ---CType(Nothing, Int32?) Console.WriteLine(y.HasValue) End Sub End Module , expectedOutput:="False"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedIntrinsicNegationNotNull() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim y = ---CType(42, Int32?) Console.WriteLine(y.HasValue) End Sub End Module , expectedOutput:="True"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedIsTrueLiteral() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) If Not Not Not (CType(False, Boolean?)) Then Console.Write("hi") End If End Sub End Module , expectedOutput:="hi"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedIsTrueLocal() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x as boolean? = false If Not Not Not x Then Console.Write("hi") End If End Sub End Module , expectedOutput:="hi"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryPlus() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As Integer? = 2 Dim y As Integer? = 4 If x + x = y Then Console.Write("hi") End If End Sub End Module , expectedOutput:="hi"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryPlus1() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As Integer? = 0 Console.WriteLine(x + goo(x)) End Sub Function goo(ByRef v As Integer?) As Integer v = 0 Return 42 End Function End Module , expectedOutput:="42"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryPlusHasValue1() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As Integer? = 2 If x + x = 4 Then Console.Write("hi") End If End Sub End Module , expectedOutput:="hi"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryPlusHasValue2() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As Integer? = 2 If 4 = x + x Then Console.Write("hi") End If End Sub End Module , expectedOutput:="hi"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryBooleanXor() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As Boolean? = True If (x Xor Nothing) Then Else Console.WriteLine("hi") End If End Sub End Module , expectedOutput:="hi"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryBooleanXor1() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As Boolean? = True Dim y As Boolean? = False If (x Xor y) Then Console.WriteLine("hi") End If End Sub End Module , expectedOutput:="hi"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryBooleanOrNothing() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As Boolean? = True If (x or Nothing) Then Console.WriteLine("hi") End If End Sub End Module , expectedOutput:="hi"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryBooleanAndNothing() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As Boolean? = True If (Nothing And x) Then Else Console.WriteLine("hi") End If End Sub End Module , expectedOutput:="hi"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryBooleanAnd() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) If (T() And T()) Then Console.Write("hi") End If End Sub Function T() As Boolean? Return True End Function End Module , expectedOutput:="hi"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryBooleanOr() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As Boolean? = True Dim y As Boolean? = True If (x Or y) Then Console.Write("hi") End If End Sub End Module , expectedOutput:="hi"). VerifyIL("MyClass1.Main", ) End Sub Public Sub BinaryBool() CompileAndVerify( Option Strict On Imports System Module MyClass1 Sub Main(args As String()) Print("== And ==") Print(T() And T()) Print(T() And F()) Print(T() And N()) Print(F() And T()) Print(F() And F()) Print(F() And N()) Print(N() And T()) Print(N() And F()) Print(N() And N()) Print("== Or ==") Print(T() Or T()) Print(T() Or F()) Print(T() Or N()) Print(F() Or T()) Print(F() Or F()) Print(F() Or N()) Print(N() Or T()) Print(N() Or F()) Print(N() Or N()) Print("== AndAlso ==") Print(T() AndAlso T()) Print(T() AndAlso F()) Print(T() AndAlso N()) Print(F() AndAlso T()) Print(F() AndAlso F()) Print(F() AndAlso N()) Print(N() AndAlso T()) Print(N() AndAlso F()) Print(N() AndAlso N()) Print("== OrElse ==") Print(T() OrElse T()) Print(T() OrElse F()) Print(T() OrElse N()) Print(F() OrElse T()) Print(F() OrElse F()) Print(F() OrElse N()) Print(N() OrElse T()) Print(N() OrElse F()) Print(N() OrElse N()) End Sub Private Sub Print(s As String) Console.WriteLine(s) End Sub Private Sub Print(r As Boolean?) Console.Write(": HasValue = ") Console.Write(r.HasValue) Console.Write(": Value =") If r.HasValue Then Console.Write(" ") Console.Write(r) End If Console.WriteLine() End Sub Private Function T() As Boolean? Console.Write("T") Return True End Function Private Function F() As Boolean? Console.Write("F") Return False End Function Private Function N() As Boolean? Console.Write("N") Return Nothing End Function End Module , expectedOutput:= ) End Sub Public Sub BinaryBoolConstLeft() CompileAndVerify( Option Strict On Imports System Module MyClass1 Sub Main(args As String()) Print("== And ==") Print(True And T()) Print(True And F()) Print(True And N()) Print(False And T()) Print(False And F()) Print(False And N()) Print(Nothing And T()) Print(Nothing And F()) Print(Nothing And N()) Print("== Or ==") Print(True Or T()) Print(True Or F()) Print(True Or N()) Print(False Or T()) Print(False Or F()) Print(False Or N()) Print(Nothing Or T()) Print(Nothing Or F()) Print(Nothing Or N()) Print("== AndAlso ==") Print(True AndAlso T()) Print(True AndAlso F()) Print(True AndAlso N()) Print(False AndAlso T()) Print(False AndAlso F()) Print(False AndAlso N()) Print(Nothing AndAlso T()) Print(Nothing AndAlso F()) Print(Nothing AndAlso N()) Print("== OrElse ==") Print(True OrElse T()) Print(True OrElse F()) Print(True OrElse N()) Print(False OrElse T()) Print(False OrElse F()) Print(False OrElse N()) Print(Nothing OrElse T()) Print(Nothing OrElse F()) Print(Nothing OrElse N()) End Sub Private Sub Print(s As String) Console.WriteLine(s) End Sub Private Sub Print(r As Boolean?) Console.Write(": HasValue = ") Console.Write(r.HasValue) Console.Write(": Value =") If r.HasValue Then Console.Write(" ") Console.Write(r) End If Console.WriteLine() End Sub Private Function T() As Boolean? Console.Write("T") Return True End Function Private Function F() As Boolean? Console.Write("F") Return False End Function Private Function N() As Boolean? Console.Write("N") Return Nothing End Function End Module , expectedOutput:= ) End Sub Public Sub BinaryBoolConstRight() CompileAndVerify( Option Strict On Imports System Module MyClass1 Sub Main(args As String()) Print("== And ==") Print(T() And True) Print(T() And False) Print(T() And Nothing) Print(F() And True) Print(F() And False) Print(F() And Nothing) Print(N() And True) Print(N() And False) Print(N() And Nothing) Print("== Or ==") Print(T() Or True) Print(T() Or False) Print(T() Or Nothing) Print(F() Or True) Print(F() Or False) Print(F() Or Nothing) Print(N() Or True) Print(N() Or False) Print(N() Or Nothing) Print("== AndAlso ==") Print(T() AndAlso True) Print(T() AndAlso False) Print(T() AndAlso Nothing) Print(F() AndAlso True) Print(F() AndAlso False) Print(F() AndAlso Nothing) Print(N() AndAlso True) Print(N() AndAlso False) Print(N() AndAlso Nothing) Print("== OrElse ==") Print(T() OrElse True) Print(T() OrElse False) Print(T() OrElse Nothing) Print(F() OrElse True) Print(F() OrElse False) Print(F() OrElse Nothing) Print(N() OrElse True) Print(N() OrElse False) Print(N() OrElse Nothing) End Sub Private Sub Print(s As String) Console.WriteLine(s) End Sub Private Sub Print(r As Boolean?) Console.Write(": HasValue = ") Console.Write(r.HasValue) Console.Write(": Value =") If r.HasValue Then Console.Write(" ") Console.Write(r) End If Console.WriteLine() End Sub Private Function T() As Boolean? Console.Write("T") Return True End Function Private Function F() As Boolean? Console.Write("F") Return False End Function Private Function N() As Boolean? Console.Write("N") Return Nothing End Function End Module , expectedOutput:= ) End Sub Public Sub NewBooleanInLogicalExpression() CompileAndVerify( Imports System Module M Sub Main() Dim bRet As Boolean? bRet = New Boolean?(True) And Nothing Console.WriteLine("Ret1={0}", bRet) Select Case bret Case Nothing Console.WriteLine("Nothing") Case Else Console.Write("Else: ") If (Nothing Or New Boolean?(False)) Is Nothing Then Console.WriteLine("Ret2={0}", New Boolean?(True) OrElse New Boolean?() AndAlso New Boolean?(False)) End If End Select End Sub End Module , expectedOutput:= ).VerifyDiagnostics(Diagnostic(ERRID.WRN_EqualToLiteralNothing, "Nothing")) End Sub Public Sub NothingOrZeroInBinaryExpression() CompileAndVerify( Imports System Enum E Zero One End Enum Module M Friend bN As Boolean? = Nothing Public x As ULong? = 11 Sub Main() Dim nZ As Integer? = 0 Dim r = nZ + 0 - nZ * 0 Console.Write("r1={0}", r) Dim eN As E? = Nothing Dim y As UShort? = Nothing r = eN - bN * nZ + Nothing ^ y Mod x Console.Write(" r2={0}", r) End Sub End Module , expectedOutput:="r1=0 r2=") End Sub Public Sub NullableIs() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As Boolean? = Nothing If (x Is Nothing) Then Console.WriteLine("hi") End If End Sub End Module , expectedOutput:="hi"). VerifyIL("MyClass1.Main", ) End Sub Public Sub NullableIsNot() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) If Nothing IsNot CType(3, Int32?) Then Console.WriteLine("hi") End If End Sub End Module , expectedOutput:="hi"). VerifyIL("MyClass1.Main", ) End Sub Public Sub NullableIsAndIsNot() CompileAndVerify( Imports System Module MyClass1 Sub Main() While New Boolean?(False) Is Nothing OrElse Nothing IsNot New Boolean?(True) If Nothing Is New Ulong?() Then Console.Write("True") Exit While End If End While End Sub End Module , expectedOutput:="True"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedIntrinsicConversion() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As Integer = 123 Dim y As Long? = x Console.WriteLine(y) End Sub End Module , expectedOutput:="123"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedInterfaceConversion() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As IComparable(Of Integer) = 123 Dim y As Integer? = x Console.WriteLine(y) End Sub End Module , expectedOutput:="123"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedReferenceConversionNarrowingFail() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As Short? = 42 Dim z As ValueType = x Try Dim y As UInteger? = z Console.WriteLine(y) Catch ex As InvalidCastException Console.WriteLine("pass") End Try End Sub End Module , expectedOutput:="pass"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedInterfaceConversion1() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) Dim x As Integer? = 123 Dim y As IComparable(Of Integer) = x Console.WriteLine(y) End Sub End Module , expectedOutput:="123"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedInterfaceConversionGeneric() CompileAndVerify( Imports System Module MyClass1 Sub Main(args As String()) goo(42) End Sub Sub goo(Of T As {Structure, IComparable(Of T)})(x As T?) Dim y As IComparable(Of T) = x Console.Write(y.CompareTo(x.Value)) End Sub End Module , expectedOutput:="0"). VerifyIL("MyClass1.goo", ) End Sub Public Sub LiftedInterfaceConversionGeneric1() Dim compilationDef = Imports System Module MyClass1 Sub Main(args As String()) goo(42) End Sub Sub goo(Of T As {Structure, IComparable(Of T)})(x As T?) Dim y As IComparable(Of Integer) = x Console.Write(y.CompareTo(43)) End Sub End Module Dim compilation = CreateCompilationWithMscorlib40AndVBRuntime(compilationDef, TestOptions.ReleaseExe.WithOptionStrict(OptionStrict.Custom)) CompilationUtils.AssertTheseDiagnostics(compilation, BC42016: Implicit conversion from 'T?' to 'IComparable(Of Integer)'. Dim y As IComparable(Of Integer) = x ~ ) CompileAndVerify(compilation, expectedOutput:="-1"). VerifyIL("MyClass1.goo", ) End Sub Public Sub LiftedCompoundOp() CompileAndVerify( imports System Module MyClass1 Sub Main() Dim y As Integer? = 42 y += 1 Console.WriteLine(y) End Sub End Module , expectedOutput:="43"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedCompoundOp1() CompileAndVerify( imports System Module MyClass1 Sub Main() Dim y As Integer? = 42 y += Nothing Console.WriteLine(y.HasValue) End Sub End Module , expectedOutput:="False"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryIf() CompileAndVerify( imports System Module MyClass1 Sub Main() Dim y As Integer? = 123 Console.Write(If(If(New Long?(), New Short?(42)), y)) Console.Write(If(If(New Short?(42), New Long?()), y)) End Sub End Module , expectedOutput:="4242"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryIf1() CompileAndVerify( imports System Module MyClass1 Sub Main() Dim x As Long? = Nothing Dim y As Integer? = 42 Console.WriteLine(If(y, x)) End Sub End Module , expectedOutput:="42"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryIf1a() CompileAndVerify( imports System Module MyClass1 Sub Main() Console.Write(If(y, x)) Console.Write(If(x, y)) End Sub Function x() As Long? Console.Write("x") Return Nothing End Function Function y() As Integer? Console.Write("y") Return 42 End Function End Module , expectedOutput:="y42xy42") End Sub Public Sub LiftedBinaryIf2() CompileAndVerify( imports System Module MyClass1 Sub Main() Dim x As Short? = Nothing Dim y As Ushort? = 42 Console.WriteLine(If(y, x)) End Sub End Module , expectedOutput:="42"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryIf3() CompileAndVerify( Imports System Module MyClass1 Sub Main() Dim x As Short? = Nothing Dim y As Long = 42S Dim z = If(x, y) Console.WriteLine(z) End Sub End Module , expectedOutput:="42"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryIf4() CompileAndVerify( Imports System Module MyClass1 Sub Main() Dim x As Short? = Nothing Dim y As IComparable(Of Short) = 42S Dim z = If(x, y) Console.WriteLine(z) End Sub End Module , expectedOutput:="42"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedBinaryIf5_Nested() Dim source = Dim verifier = CompileAndVerify(source, expectedOutput:="Pass") End Sub Public Sub LiftedBinaryRelationalWithNothingLiteral() Dim source = = Nothing ' = Nothing Console.Write("r1={0} ", r1) Dim r2 As Boolean? = Nothing < x ' = Nothing Console.Write("r2={0} ", r2) r1 = x > y Console.Write("r3={0} ", r1) r2 = y <= x Console.Write("r4={0} ", r2) End Sub End Class ]]> 'emitOptions:=EmitOptions.RefEmitBug, CompileAndVerify(source, expectedOutput:="r1= r2= r3= r4=") End Sub Public Sub LiftedBinaryConcatLikeWithNothingLiteral() Dim source = 'emitOptions:=EmitOptions.RefEmitBug, CompileAndVerify(source, expectedOutput:="r1=127 r2=False") End Sub Public Sub LiftedBinaryDivisionWithNothingLiteral() Dim source = CompileAndVerify(source, expectedOutput:="r1= r2= r3= r4= r5= r6=") End Sub Public Sub LiftedConversionHasValue() CompileAndVerify( Imports System Module MyClass1 Structure S1 Public x As Integer Public Shared Widening Operator CType(ByVal a As S1) As S2 Console.Write("W") Dim result As S2 result.x = a.x + 1 Return result End Operator Sub New(x As Integer) Me.x = x End Sub End Structure Structure S2 Public x As Integer End Structure Sub Main() Dim y As S2 = New S1?(New S1(42)) Console.WriteLine(y.x) End Sub End Module , expectedOutput:="W43"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedConversionHasNoValue() CompileAndVerify( Imports System Module MyClass1 Structure S1 Public x As Integer Public Shared Widening Operator CType(ByVal a As S1) As S2 Console.Write("W") Dim result As S2 result.x = a.x + 1 Return result End Operator Sub New(x As Integer) Me.x = x End Sub End Structure Structure S2 Public x As Integer End Structure Sub Main() Try Dim y As S2 = New S1?() Console.WriteLine(y.x) Catch ex As InvalidOperationException Console.WriteLine("pass") End Try End Sub End Module , expectedOutput:="pass"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedConversion() CompileAndVerify( Imports System Module MyClass1 Structure S1 Public x As Integer Public Shared Widening Operator CType(ByVal a As S1) As S2 Console.Write("W") Dim result As S2 result.x = a.x + 1 Return result End Operator Sub New(x As Integer) Me.x = x End Sub End Structure Structure S2 Public x As Integer End Structure Sub Main() Dim x As S1? = New S1(42) Dim y As S2? = x Console.WriteLine(y.Value.x) End Sub End Module , expectedOutput:="W43"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedConversionDev10() CompileAndVerify( imports System imports Microsoft.VisualBasic Module Module1 Sub Main() Dim av As New S1 Dim c As S1? Dim d As T1? d = c Console.WriteLine("Lifted UD conversion: null check skips conversion call. d.HasValue= {0}" & Environment.NewLine, d.HasValue) 'expect 7 c = 1 Console.WriteLine("widening to nullable UD conversion: c=1; c.value= {0}" & Environment.NewLine, c.Value.i) 'expect 7 c = Nothing Console.WriteLine("widening to nullable UD conversion: c=Nothing; c.HasValue= {0}" & Environment.NewLine, c.HasValue) 'expect 7 av.i = 7 Dim a2 As New S1?(av) Dim b2 As T1 b2 = a2 Console.WriteLine("regular UD conversion+PDconversion: S1?->S1 -->T1, value passed:{0}" & Environment.NewLine, b2.i) 'expect 7 Dim a21 As New S1 a21.i = 8 Dim b21 As T1? b21 = a21 Console.WriteLine("regular UD conversion+PD conversion: S1-->T1->T1?, value passed:{0}" & Environment.NewLine, b21.Value.i) 'expect 8 Dim val As New S1 val.i = 3 c = New S1?(val) d = c Console.WriteLine("lifted UD conversion, value passed:{0}" & Environment.NewLine, d.Value.i) 'expect 3 Dim k As New S2 k.i = 2 Dim c2 As New S2?(k) Dim d2 As T2? d2 = c2 'UD conversion on nullable preferred over lifting Console.WriteLine(" UD nullable conversion, preferred over lifted value passed: {0}" & Environment.NewLine, d2.Value.i) 'expect 2 av.i = 5 Dim a As New S1?(av) 'a.i = 2 Dim b As T1? b = a Console.WriteLine("lifted UD conversion, value passed:{0}" & Environment.NewLine, b.Value.i) 'expect 5 Dim a1 As S1 a1.i = 6 Dim b1 As T1 b1 = a1 Console.WriteLine("regular UD conversion, value passed:{0}" & Environment.NewLine, b1.i) 'expect 6 Dim a3 As S1 a3.i = 8 Dim b3 As T1? b3 = a3 Console.WriteLine("regular UD conversion+PD conversion, value passed:{0}" & Environment.NewLine, b3.Value.i) 'expect 8 Dim atv = New st(Of Integer) atv.i = 9 Dim at As New st(Of Integer)?(atv) Dim bt As Integer? bt = at Console.WriteLine("generic UD, value passed bt.value = :{0}" & Environment.NewLine, bt.Value) 'expect 8 End Sub Structure S1 Dim i As Integer 'Public Shared Widening Operator CType(ByVal a As S1?) As T1? ' Dim t As New T1 ' t.i = a.Value.i ' Return t 'End Operator Public Shared Narrowing Operator CType(ByVal a As S1) As T1 Dim t As New T1 t.i = a.i Console.WriteLine("UD regular conversion S1->T1 (possible by lifting) invoked") Return t End Operator Public Shared Widening Operator CType(ByVal a As Integer) As S1 Dim t As New S1 t.i = a Console.WriteLine("UD regular conversion int->S1 (possible by lifting) invoked") Return t End Operator End Structure Structure T1 Dim i As Integer End Structure Structure S2 Dim i As Integer Public Shared Widening Operator CType(ByVal a As S2?) As T2? Console.WriteLine("UD S2?->T2? conversion on nullable invoked") If a.HasValue Then Dim t As New T2 t.i = a.Value.i Return t Else Return Nothing End If End Operator Public Shared Narrowing Operator CType(ByVal a As S2) As T2 Dim t As New T2 t.i = a.i Console.WriteLine("UD regular conversion S2->T2 (possible by lifting) invoked") Return t End Operator End Structure Structure T2 Dim i As Integer 'Public Shared Narrowing Operator CType(ByVal a As T2) As T2 ' Dim t As New T2 ' t.i = a.i ' Return t 'End Operator End Structure Structure st(Of T As Structure) Dim i As T Public Shared Narrowing Operator CType(ByVal a As st(Of T)) As T Dim t As New T t = a.i Console.WriteLine("UD generic regular conversion st(of T)->T (possible by lifting) invoked") Return t End Operator End Structure End Module , expectedOutput:= S1 (possible by lifting) invoked widening to nullable UD conversion: c=1; c.value= 1 widening to nullable UD conversion: c=Nothing; c.HasValue= False UD regular conversion S1->T1 (possible by lifting) invoked regular UD conversion+PDconversion: S1?->S1 -->T1, value passed:7 UD regular conversion S1->T1 (possible by lifting) invoked regular UD conversion+PD conversion: S1-->T1->T1?, value passed:8 UD regular conversion S1->T1 (possible by lifting) invoked lifted UD conversion, value passed:3 UD S2?->T2? conversion on nullable invoked UD nullable conversion, preferred over lifted value passed: 2 UD regular conversion S1->T1 (possible by lifting) invoked lifted UD conversion, value passed:5 UD regular conversion S1->T1 (possible by lifting) invoked regular UD conversion, value passed:6 UD regular conversion S1->T1 (possible by lifting) invoked regular UD conversion+PD conversion, value passed:8 UD generic regular conversion st(of T)->T (possible by lifting) invoked generic UD, value passed bt.value = :9 ]]>) End Sub Public Sub LiftedWideningAndNarrowingConversions() CompileAndVerify( Imports System Imports System.Collections.Generic Structure S(Of T As Structure) Shared Narrowing Operator CType(x As S(Of T)) As T System.Console.Write("Narrowing ") Return Nothing End Operator Shared Widening Operator CType(x As S(Of T)) As T? System.Console.Write("Widening ") Return Nothing End Operator End Structure Module Program Sub Main() Dim x As S(Of Integer)? = New S(Of Integer)() Dim y As Integer? = 123 Dim ret = If(x, y) Console.Write("Ret={0}", ret) End Sub End Module , expectedOutput:="Widening Ret="). VerifyIL("Program.Main", ) End Sub Public Sub LiftedBinaryUserDefinedMinusDev10() CompileAndVerify( imports System imports Microsoft.VisualBasic Structure S1 Public x As Integer Public Sub New(ByVal x As Integer) Me.x = x End Sub Public Shared Operator -(ByVal x As S1, ByVal y As S1?) As S1 Return New S1(x.x - y.Value.x) End Operator End Structure Module M1 Sub OutputEntry(ByVal expr As String, ByVal value As S1) Console.WriteLine("{0} = {1}", expr, value.x) End Sub Sub Main() Dim a As S1? = Nothing Dim b As S1? = New S1(1) Dim c As New S1(2) Dim tmp As S1 Try tmp = a - c Catch ex As InvalidOperationException Console.WriteLine("a - c threw an InvalidOperationException as expected!") End Try Try tmp = c - a Catch ex As InvalidOperationException Console.WriteLine("c - a threw an InvalidOperationException as expected!") End Try Try tmp = a - b Catch ex As InvalidOperationException Console.WriteLine("a - b threw an InvalidOperationException as expected!") End Try Try tmp = b - a Catch ex As InvalidOperationException Console.WriteLine("a - b threw an InvalidOperationException as expected!") End Try OutputEntry("b - c", b - c) OutputEntry("c - b", c - b) End Sub End Module , expectedOutput:= ) End Sub Public Sub LiftedUnaryUserDefinedMinusDev10() CompileAndVerify( Imports System Imports Microsoft.VisualBasic Structure S1 Dim x As Integer Public Sub New(ByVal x As Integer) Me.x = x End Sub Public Shared Operator -(ByVal x As S1) As S1 Return New S1(-x.x) End Operator End Structure Module M1 Sub Main() Dim arg As S1? = New S1(1) Dim x = -arg Dim y = -New S1? Dim z = -New S1?(New S1(4)) Console.WriteLine("x.Value = {0}", x.Value.x) Console.WriteLine("y.HasValue = {0}", y.HasValue) Console.WriteLine("z.Value = {0}", z.Value.x) End Sub End Module , expectedOutput:= ). VerifyIL("M1.Main", ) End Sub Public Sub LiftedBinaryUserDefinedOneArgNotNullable() CompileAndVerify( Imports System Imports Microsoft.VisualBasic Structure S1 Dim x As Integer Public Sub New(ByVal x As Integer) Me.x = x End Sub Public Shared Operator -(ByVal x As S1, ByVal y As S1) As S1 Return New S1(x.x - y.x) End Operator End Structure Module M1 Sub Main() Dim x As New S1?(New S1(42)) Dim y = x - New S1(2) Console.WriteLine(y.Value.x) End Sub End Module , expectedOutput:="40"). VerifyIL("M1.Main", ) End Sub Public Sub LiftedBinaryUserDefinedReturnsNullable() CompileAndVerify( Imports System Imports Microsoft.VisualBasic Structure S1 Dim x As Integer Public Sub New(ByVal x As Integer) Me.x = x End Sub Public Shared Operator +(ByVal x As S1, ByVal y As S1) As S1? Return New S1(x.x + y.x) End Operator End Structure Module M1 Sub Main() Dim x As New S1?(New S1(42)) Dim y = x + x Console.WriteLine(y.Value.x) End Sub End Module , expectedOutput:="84"). VerifyIL("M1.Main", ) End Sub Public Sub LiftedUserConversionShortToInt() CompileAndVerify( Imports System Module M1 Structure S1 Shared Widening Operator CType(x As Byte) As S1 Return New S1() End Operator End Structure Sub Main() Dim y As S1? = new Long?(42) ' === UDC Console.WriteLine(y.HasValue) End Sub End Module , expectedOutput:="True"). VerifyIL("M1.Main", ) End Sub Public Sub LiftedUserConversionShortToIntA() CompileAndVerify( Imports System Module M1 Structure S1 Shared Widening Operator CType(x As Byte) As S1 Return New S1() End Operator End Structure Sub Main() Dim y As S1? = x ' === UDC Console.WriteLine(y.HasValue) End Sub Function x() As Long? Console.Write("x") Return New Long?(42) End Function End Module , expectedOutput:="xTrue"). VerifyIL("M1.Main", ) End Sub Public Sub LiftedShortCircuitOperations() CompileAndVerify( Imports System Module M Sub Main() Dim bF As Boolean? = False Dim bT As Boolean? = True Dim bN As Boolean? = Nothing If bF OrElse bT AndAlso bN Then Console.Write("True") Else Console.Write("False") End If End Sub End Module , expectedOutput:="False"). VerifyIL("M.Main", ) End Sub Public Sub LogicalOperationsWithNullableEnum() CompileAndVerify( Imports System Enum EnumItems Item1 = 1 Item2 = 2 Item3 = 4 Item4 = 8 End Enum Module M Sub Main() Dim value1a As EnumItems? = 10 Dim value1b As EnumItems = EnumItems.Item3 Console.Write(Not value1a And value1b Or value1a Xor value1b) End Sub End Module , expectedOutput:="10"). VerifyIL("M.Main", ) End Sub Public Sub ArithmeticOperationsWithNullableType() CompileAndVerify( Imports System Friend Module M Public Function goo_exception() As Integer Console.Write("1st Called ") Throw New ArgumentNullException() End Function Public Function goo_eval_check() As Integer? Console.Write("2nd Called ") goo_eval_check = 2 End Function Sub Main() Try Dim r1 = goo_exception() \ goo_eval_check() Catch ex As ArgumentNullException End Try End Sub End Module , expectedOutput:="1st Called"). VerifyIL("M.Main", ) End Sub Public Sub Regress13840() CompileAndVerify( Module Module1 Sub Main() Dim y As MyStruct? = Nothing If (CType(CType(Nothing, MyStruct?), MyStruct?) = y) Then 'expect warning System.Console.WriteLine("Equals") End If End Sub Structure MyStruct Shared Operator =(ByVal left As MyStruct, ByVal right As MyStruct) As Boolean Return True End Operator Shared Operator <>(ByVal left As MyStruct, ByVal right As MyStruct) As Boolean Return False End Operator End Structure End Module , expectedOutput:="") End Sub #Region "Diagnostics" Public Sub BC30424ERR_ConstAsNonConstant_Nullable() Dim source = Structure S : End Structure Enum E : Zero : End Enum Class C Sub M() Const c1 As Boolean? = Nothing Const c2 As ULong? = 12345 Const c3 As E? = E.Zero Dim d = Sub() Const c4 As S? = Nothing End Sub End Sub End Class Dim comp = CreateCompilationWithMscorlib40(source) comp.VerifyDiagnostics(Diagnostic(ERRID.ERR_ConstAsNonConstant, "Boolean?"), Diagnostic(ERRID.ERR_ConstAsNonConstant, "ULong?"), Diagnostic(ERRID.ERR_ConstAsNonConstant, "E?"), Diagnostic(ERRID.ERR_ConstAsNonConstant, "S?")) End Sub Public Sub BC30456ERR_NameNotMember2_Nullable() Dim source = Option Strict Off Option Explicit Off Imports System Structure S Public field As C End Structure Class C Public field As S Shared Widening Operator CType(p As C) As S Console.Write("N") Return p.field End Operator Shared Narrowing Operator CType(p As S) As C Console.Write("W") Return p.field End Operator End Class Module Program Sub Main(args As String()) Dim x As New S() x.field = New C() x.field.field = x Dim y As C = x.field Dim ns As S? = y Console.Write(ns.field.field Is y) ' BC30456 End Sub End Module Dim comp = CreateCompilationWithMscorlib40AndVBRuntime(source) comp.VerifyDiagnostics(Diagnostic(ERRID.ERR_NameNotMember2, "ns.field").WithArguments("field", "S?")) End Sub Public Sub BC42037And42038WRN_EqualToLiteralNothing_Nullable() Dim source = y) Then Console.WriteLine("FAIL") Else Console.WriteLine("PASS") End If End Sub End Class ]]> CompileAndVerify(source, expectedOutput:="PASS").VerifyDiagnostics( Diagnostic(ERRID.WRN_EqualToLiteralNothing, "x = Nothing"), Diagnostic(ERRID.WRN_NotEqualToLiteralNothing, "Nothing <> y") ) End Sub Public Sub DoNotGiveBC32126ERR_AddressOfNullableMethod() Dim source = CompileAndVerify(source).VerifyDiagnostics().VerifyIL("Program.Main", ) End Sub Public Sub BC36629ERR_NullableTypeInferenceNotSupported() Dim source = Imports System Class C Public X? = 10 Public X1? = {10} Public Property Z? = 10 Public Property Z1? = {10} Sub Test() Dim Y? = 10 Dim Y1? = {10} End Sub Sub Test1() ' Option Strict Off, Option Infer Off - Expected No errors ' Option Strict Off, Option Infer On - Expected BC33112: Nullable modifier cannot be used with a variable whose implicit type is 'Object'. ' Option Strict On, Option Infer On - Expected BC33112: Nullable modifier cannot be used with a variable whose implicit type is 'Object'. Static U? = 10 ' Option Strict Off, Option Infer Off - Expected No errors ' Option Strict Off, Option Infer On - Expected BC33112: Nullable modifier cannot be used with a variable whose implicit type is 'Object'. ' Option Strict On, Option Infer On - Expected BC33112: Nullable modifier cannot be used with a variable whose implicit type is 'Object'. Static U1? = {10} Static V?() = Nothing Static V1?(1) = Nothing End Sub Sub Test2() Const U? = 10 Dim x As Object = U End Sub End Class Dim compilation = CreateCompilationWithMscorlib40AndVBRuntime(source, options:=TestOptions.ReleaseDll.WithOptionStrict(OptionStrict.Off).WithOptionInfer(False)) AssertTheseDiagnostics(compilation, BC36629: Nullable type inference is not supported in this context. Public X? = 10 ~~ BC36629: Nullable type inference is not supported in this context. Public X1? = {10} ~~~ BC30205: End of statement expected. Public Property Z? = 10 ~ BC30205: End of statement expected. Public Property Z1? = {10} ~ BC36629: Nullable type inference is not supported in this context. Dim Y? = 10 ~~ BC36629: Nullable type inference is not supported in this context. Dim Y1? = {10} ~~~ BC30672: Explicit initialization is not permitted for arrays declared with explicit bounds. Static V1?(1) = Nothing ~~~~~~ ) compilation = compilation.WithOptions(TestOptions.ReleaseDll.WithOptionStrict(OptionStrict.Off).WithOptionInfer(True)) AssertTheseDiagnostics(compilation, BC36629: Nullable type inference is not supported in this context. Public X? = 10 ~~ BC36629: Nullable type inference is not supported in this context. Public X1? = {10} ~~~ BC30205: End of statement expected. Public Property Z? = 10 ~ BC30205: End of statement expected. Public Property Z1? = {10} ~ BC36628: A nullable type cannot be inferred for variable 'Y1'. Dim Y1? = {10} ~~ BC33112: Nullable modifier cannot be used with a variable whose implicit type is 'Object'. Static U? = 10 ~~ BC33112: Nullable modifier cannot be used with a variable whose implicit type is 'Object'. Static U1? = {10} ~~~ BC33112: Nullable modifier cannot be used with a variable whose implicit type is 'Object'. Static V?() = Nothing ~~~~ BC30672: Explicit initialization is not permitted for arrays declared with explicit bounds. Static V1?(1) = Nothing ~~~~~~ BC33112: Nullable modifier cannot be used with a variable whose implicit type is 'Object'. Static V1?(1) = Nothing ~~~~~~ ) compilation = compilation.WithOptions(TestOptions.ReleaseDll.WithOptionStrict(OptionStrict.On).WithOptionInfer(False)) AssertTheseDiagnostics(compilation, BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Public X? = 10 ~ BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Public X1? = {10} ~~ BC30210: Option Strict On requires all Function, Property, and Operator declarations to have an 'As' clause. Public Property Z? = 10 ~ BC30205: End of statement expected. Public Property Z? = 10 ~ BC30210: Option Strict On requires all Function, Property, and Operator declarations to have an 'As' clause. Public Property Z1? = {10} ~~ BC30205: End of statement expected. Public Property Z1? = {10} ~ BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Dim Y? = 10 ~ BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Dim Y1? = {10} ~~ BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Static U? = 10 ~ BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Static U1? = {10} ~~ BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Static V?() = Nothing ~ BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Static V1?(1) = Nothing ~~ BC30672: Explicit initialization is not permitted for arrays declared with explicit bounds. Static V1?(1) = Nothing ~~~~~~ BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Const U? = 10 ~ ) compilation = compilation.WithOptions(TestOptions.ReleaseDll.WithOptionStrict(OptionStrict.On).WithOptionInfer(True)) AssertTheseDiagnostics(compilation, BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Public X? = 10 ~ BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Public X1? = {10} ~~ BC30210: Option Strict On requires all Function, Property, and Operator declarations to have an 'As' clause. Public Property Z? = 10 ~ BC30205: End of statement expected. Public Property Z? = 10 ~ BC30210: Option Strict On requires all Function, Property, and Operator declarations to have an 'As' clause. Public Property Z1? = {10} ~~ BC30205: End of statement expected. Public Property Z1? = {10} ~ BC36628: A nullable type cannot be inferred for variable 'Y1'. Dim Y1? = {10} ~~ BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Static U? = 10 ~ BC33112: Nullable modifier cannot be used with a variable whose implicit type is 'Object'. Static U? = 10 ~~ BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Static U1? = {10} ~~ BC33112: Nullable modifier cannot be used with a variable whose implicit type is 'Object'. Static U1? = {10} ~~~ BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Static V?() = Nothing ~ BC33112: Nullable modifier cannot be used with a variable whose implicit type is 'Object'. Static V?() = Nothing ~~~~ BC30209: Option Strict On requires all variable declarations to have an 'As' clause. Static V1?(1) = Nothing ~~ BC30672: Explicit initialization is not permitted for arrays declared with explicit bounds. Static V1?(1) = Nothing ~~~~~~ BC33112: Nullable modifier cannot be used with a variable whose implicit type is 'Object'. Static V1?(1) = Nothing ~~~~~~ ) End Sub Public Sub BC36629ERR_NullableTypeInferenceNotSupported_2() Dim source = Imports System Class C Public X%? = 10 Public X1%? = {10} Public Property Z%? = 10 Public Property Z1%? = {10} Sub Test() Dim Y%? = 10 Dim Y1%? = {10} End Sub Sub Test1() Static U%? = 10 Static U1%? = {10} End Sub Sub Test2() Const V%? = 10 Dim x As Object = V End Sub End Class Dim compilation = CreateCompilationWithMscorlib40AndVBRuntime(source, options:=TestOptions.ReleaseDll.WithOptionStrict(OptionStrict.Off).WithOptionInfer(False)) AssertTheseDiagnostics(compilation, BC30311: Value of type 'Integer()' cannot be converted to 'Integer?'. Public X1%? = {10} ~~~~ BC30205: End of statement expected. Public Property Z%? = 10 ~ BC30205: End of statement expected. Public Property Z1%? = {10} ~ BC30311: Value of type 'Integer()' cannot be converted to 'Integer?'. Dim Y1%? = {10} ~~~~ BC30311: Value of type 'Integer()' cannot be converted to 'Integer?'. Static U1%? = {10} ~~~~ BC30424: Constants must be of an intrinsic or enumerated type, not a class, structure, type parameter, or array type. Const V%? = 10 ~~~ ) compilation = compilation.WithOptions(TestOptions.ReleaseDll.WithOptionStrict(OptionStrict.Off).WithOptionInfer(True)) AssertTheseDiagnostics(compilation, BC30311: Value of type 'Integer()' cannot be converted to 'Integer?'. Public X1%? = {10} ~~~~ BC30205: End of statement expected. Public Property Z%? = 10 ~ BC30205: End of statement expected. Public Property Z1%? = {10} ~ BC30311: Value of type 'Integer()' cannot be converted to 'Integer?'. Dim Y1%? = {10} ~~~~ BC30311: Value of type 'Integer()' cannot be converted to 'Integer?'. Static U1%? = {10} ~~~~ BC30424: Constants must be of an intrinsic or enumerated type, not a class, structure, type parameter, or array type. Const V%? = 10 ~~~ ) compilation = compilation.WithOptions(TestOptions.ReleaseDll.WithOptionStrict(OptionStrict.On).WithOptionInfer(False)) AssertTheseDiagnostics(compilation, BC30311: Value of type 'Integer()' cannot be converted to 'Integer?'. Public X1%? = {10} ~~~~ BC30205: End of statement expected. Public Property Z%? = 10 ~ BC30205: End of statement expected. Public Property Z1%? = {10} ~ BC30311: Value of type 'Integer()' cannot be converted to 'Integer?'. Dim Y1%? = {10} ~~~~ BC30311: Value of type 'Integer()' cannot be converted to 'Integer?'. Static U1%? = {10} ~~~~ BC30424: Constants must be of an intrinsic or enumerated type, not a class, structure, type parameter, or array type. Const V%? = 10 ~~~ ) compilation = compilation.WithOptions(TestOptions.ReleaseDll.WithOptionStrict(OptionStrict.On).WithOptionInfer(True)) AssertTheseDiagnostics(compilation, BC30311: Value of type 'Integer()' cannot be converted to 'Integer?'. Public X1%? = {10} ~~~~ BC30205: End of statement expected. Public Property Z%? = 10 ~ BC30205: End of statement expected. Public Property Z1%? = {10} ~ BC30311: Value of type 'Integer()' cannot be converted to 'Integer?'. Dim Y1%? = {10} ~~~~ BC30311: Value of type 'Integer()' cannot be converted to 'Integer?'. Static U1%? = {10} ~~~~ BC30424: Constants must be of an intrinsic or enumerated type, not a class, structure, type parameter, or array type. Const V%? = 10 ~~~ ) End Sub #End Region #Region "For Loop" Public Sub LiftedForTo() CompileAndVerify( Option Strict On Imports System Public Class MyClass1 Public Shared Sub Main() Dim l As UInteger? = 1 For x As UInteger? = 1 To 10 Step l Console.Write(x) If x >= 5 Then x = Nothing End If Next End Sub End Class , expectedOutput:="12345"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedForToDefaultStep() CompileAndVerify( Option Strict On Imports System Public Class MyClass1 Public Shared Sub Main() Dim x As Integer? = 1 For x = 1 To 10 Console.Write(x) If x >= 5 Then x = Nothing End If Next End Sub End Class , expectedOutput:="12345"). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedForToDecimalSideeffectsNullStep() CompileAndVerify( Option Strict On Imports System Public Class MyClass1 Public Shared Sub Main() For x As Decimal? = Init() To Limit() Step [Step]() Console.Write(x) Next End Sub Private Shared Function Init() As Integer Console.WriteLine("init") Return 9 End Function Private Shared Function Limit() As Integer Console.WriteLine("limit") Return 1 End Function Private Shared Function [Step]() As Decimal? Console.WriteLine("step") Return nothing End Function End Class , expectedOutput:=). VerifyIL("MyClass1.Main", ) End Sub Public Sub LiftedForCombinationsOneToThree() CompileAndVerify( Option Strict On Imports System Public Class MyClass1 Public Shared Sub Main() ' Step 1 For x As Integer? = One() To Three() Step One() Console.Write(x) Next Console.WriteLine() For x As Integer? = One() To Null() Step One() Console.Write(x) Next Console.WriteLine() For x As Integer? = Null() To Three() Step One() Console.Write(x) Next Console.WriteLine() ' Step -1 For x As Integer? = One() To Three() Step MOne() Console.Write(x) Next Console.WriteLine() For x As Integer? = One() To Null() Step MOne() Console.Write(x) Next Console.WriteLine() For x As Integer? = Null() To Three() Step MOne() Console.Write(x) Next Console.WriteLine() ' Step Null For x As Integer? = One() To Three() Step Null() Console.Write(x) Next Console.WriteLine() For x As Integer? = One() To Null() Step Null() Console.Write(x) Next Console.WriteLine() For x As Integer? = Null() To Three() Step Null() Console.Write(x) Next Console.WriteLine() End Sub Private Shared Function One() As Integer? Console.Write("one ") Return 1 End Function Private Shared Function MOne() As Integer? Console.Write("-one ") Return -1 End Function Private Shared Function Three() As Integer? Console.Write("three ") Return 3 End Function Private Shared Function Null() As Integer? Console.Write("null ") Return Nothing End Function End Class , expectedOutput:=) End Sub Public Sub LiftedForCombinationsTreeToOne() CompileAndVerify( Option Strict On Imports System Public Class MyClass1 Public Shared Sub Main() ' Step 1 For x As Integer? = Three() To One() Step One() Console.Write(x) Next Console.WriteLine() For x As Integer? = Three() To Null() Step One() Console.Write(x) Next Console.WriteLine() For x As Integer? = Null() To One() Step One() Console.Write(x) Next Console.WriteLine() ' Step -1 For x As Integer? = Three() To One() Step MOne() Console.Write(x) Next Console.WriteLine() For x As Integer? = Three() To Null() Step MOne() Console.Write(x) Next Console.WriteLine() For x As Integer? = Null() To One() Step MOne() Console.Write(x) Next Console.WriteLine() ' Step Null For x As Integer? = Three() To One() Step Null() Console.Write(x) Next Console.WriteLine() For x As Integer? = Three() To Null() Step Null() Console.Write(x) Next Console.WriteLine() For x As Integer? = Null() To One() Step Null() Console.Write(x) Next Console.WriteLine() End Sub Private Shared Function One() As Integer? Console.Write("one ") Return 1 End Function Private Shared Function MOne() As Integer? Console.Write("-one ") Return -1 End Function Private Shared Function Three() As Integer? Console.Write("three ") Return 3 End Function Private Shared Function Null() As Integer? Console.Write("null ") Return Nothing End Function End Class , expectedOutput:=) End Sub Public Sub LiftedStringConversion() CompileAndVerify( Imports System Class MyClass1 Shared Sub Main() Dim x As SByte? = 42 Dim y As String = x x = y Console.Write(x) End Sub End Class , expectedOutput:="42"). VerifyIL("MyClass1.Main", ) End Sub #End Region Public Sub Regress14397() CompileAndVerify( Option Strict Off Imports System Module Module1 Const a As Integer = If(True, 1, 2) Sub Main() Dim s As String Dim inull As Integer? = Nothing s = " :catenation right to integer?(null): " & inull Console.WriteLine(s) s = inull & " :catenation left to integer?(null): " Console.WriteLine(s) s = inull & inull Console.WriteLine(" :catenation Integer?(null) & Integer?(null): " & s) End Sub End Module , expectedOutput:=) End Sub ''' ''' same as Dev11 ''' implicit: int --> int? ''' explicit: int? --> int ''' ''' Public Sub Op_ExplicitImplicitOnNullable() CompileAndVerify( Imports System Module MyClass1 Sub Main() Dim x = (Integer?).op_Implicit(1) x = (Integer?).op_Explicit(2) Dim y = (Nullable(Of Integer)).op_Implicit(1) y = (Nullable(Of Integer)).op_Explicit(2) End Sub End Module ). VerifyIL("MyClass1.Main", ) End Sub Public Sub DecimalConst() CompileAndVerify( Imports System Public Class NullableTest Shared NULL As Decimal? = Nothing Public Shared Sub EqualEqual() Test.Eval(CType(1D, Decimal?) is Nothing, False) Test.Eval(CType(1D, Decimal?) = NULL, False) Test.Eval(CType(0, Decimal?) = NULL, False) End Sub End Class Public Class Test Public Shared Sub Eval(obj1 As Object, obj2 As Object) End Sub End Class ). VerifyIL("NullableTest.EqualEqual", ) End Sub Public Sub LiftedToIntPtrConversion() Dim source = Imports System Module M Sub Main() Console.WriteLine(CType(M(Nothing), IntPtr?)) Console.WriteLine(CType(M(42), IntPtr?)) End Sub Function M(p as Integer?) As Integer? Return p End Function End Module Dim expectedOutput = "" + vbCrLf + "42" CompileAndVerify(source, expectedOutput) End Sub Public Sub SubtractFromZero() CompileAndVerify( Imports System Module Module1 Sub Main() Dim a As Integer? = 1 Dim b As Integer? = 0 - a Console.WriteLine(String.Format("a: {0}, b: {1}", a, b)) Dim a1 As Integer? = 1 Dim b1 As Integer? = a - 0 Console.WriteLine(String.Format("a1: {0}, b1: {1}", a1, b1)) End Sub End Module , expectedOutput:="a: 1, b: -1 a1: 1, b1: 1"). VerifyIL("Module1.Main", ) End Sub Public Sub BooleanExpression_01() CompileAndVerify( Test1") If GetBool3(x) = True AndAlso y.GetBool2() System.Console.WriteLine("In If") End If System.Console.WriteLine("<-Test1") End Sub Public Shared Sub Test2(x as C, y As C) System.Console.WriteLine("->Test2") If x?.GetBool1() = True AndAlso y.GetBool2() System.Console.WriteLine("In If") End If System.Console.WriteLine("<-Test2") End Sub Public Shared Sub Test3(x as C, y As C) System.Console.WriteLine("->Test3") Dim z = GetBool3(x) = True AndAlso y.GetBool2() If z System.Console.WriteLine("In If") End If System.Console.WriteLine("<-Test3") End Sub Public Shared Sub Test4(x as C, y As C) System.Console.WriteLine("->Test4") Dim z = x?.GetBool1() = True AndAlso y.GetBool2() If z System.Console.WriteLine("In If") End If System.Console.WriteLine("<-Test4") End Sub Public Shared Sub Test5(x as C, y As C) System.Console.WriteLine("->Test5") If GetBool3(x) AndAlso y.GetBool2() System.Console.WriteLine("In If") End If System.Console.WriteLine("<-Test5") End Sub Function GetBool1() As Boolean Return True End Function Function GetBool2() As Boolean System.Console.WriteLine("GetBool2") Return True End Function Shared Function GetBool3(x as C) As Boolean? if x Is Nothing Return Nothing End If Return True End Function End Class ]]> , expectedOutput:= Test1 GetBool2 <-Test1 ->Test2 GetBool2 <-Test2 ->Test3 GetBool2 <-Test3 ->Test4 GetBool2 <-Test4 ->Test5 GetBool2 <-Test5 ]]> ) End Sub Public Sub BooleanExpression_02() CompileAndVerify( , expectedOutput:= (((y.GetBool3() == Convert(True)) AndAlso Convert(y.GetBool2())) ?? False) y => (((y.GetBool3() == Convert(True)) OrElse Convert(y.GetBool2())) ?? False) ]]> ) End Sub Public Sub BooleanExpression_03() CompileAndVerify( , expectedOutput:= IIF((((GetBool3() == Convert(True)) AndAlso Convert(GetBool2())) ?? False), True, False) () => IIF((((GetBool3() == Convert(True)) ?? False) OrElse GetBool2()), True, False) () => IIF(((new Nullable`1() AndAlso new Nullable`1()) ?? False), True, False) () => IIF(((new Nullable`1() ?? False) OrElse (new Nullable`1() ?? False)), True, False) () => IIF(((new Nullable`1() AndAlso Convert(GetBool2())) ?? False), True, False) () => IIF(((new Nullable`1() ?? False) OrElse GetBool2()), True, False) () => IIF(((new Nullable`1() AndAlso GetBool3()) ?? False), True, False) () => IIF(((new Nullable`1() ?? False) OrElse (GetBool3() ?? False)), True, False) () => IIF((GetBool2() AndAlso (new Nullable`1() ?? False)), True, False) () => IIF((GetBool2() OrElse (new Nullable`1() ?? False)), True, False) () => IIF(((GetBool3() AndAlso new Nullable`1()) ?? False), True, False) () => IIF(((GetBool3() ?? False) OrElse (new Nullable`1() ?? False)), True, False) () => IIF(((GetBool3() AndAlso GetBool3()) ?? False), True, False) () => IIF(((GetBool3() ?? False) OrElse (GetBool3() ?? False)), True, False) () => IIF((((GetBool3() ?? False) OrElse (GetBool3() ?? False)) OrElse (GetBool3() ?? False)), True, False) () => IIF((((GetBool3() ?? False) OrElse (GetBool3() ?? False)) OrElse (GetBool3() ?? False)), True, False) () => IIF(((GetBool3() ?? False) OrElse ((GetBool3() ?? False) OrElse (GetBool3() ?? False))), True, False) () => IIF((((GetBool3() ?? False) OrElse (GetBool3() ?? False)) OrElse ((GetBool3() ?? False) OrElse (GetBool3() ?? False))), True, False) () => IIF(((((GetBool3() ?? False) OrElse (GetBool3() ?? False)) OrElse (GetBool3() ?? False)) OrElse (GetBool3() ?? False)), True, False) () => IIF((((GetBool3() AndAlso Convert(GetBool2())) AndAlso Convert(GetBool2())) ?? False), True, False) () => IIF((((GetBool3() AndAlso Convert(GetBool2())) AndAlso Convert(GetBool2())) ?? False), True, False) ]]> ) End Sub Public Sub BooleanExpression_04() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_05() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_06() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_07() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_08() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_09() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_10() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_11() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_12() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_13() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_14() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_15() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_16() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_17() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_18() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_19() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_20() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_21() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_22() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_23() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_24() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_25() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_26() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_27() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_28() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_29() Dim verifyer = CompileAndVerify( ) verifyer.VerifyIL("Module1.Test1", ) End Sub Public Sub BooleanExpression_30() Dim source = True", " => False")) Dim d As System.Linq.Expressions.Expression(Of System.Func(Of String)) = Function() If(placeholder, " => True", " => False") Dim s2 = GetResultString(d.Compile()()) Dim s3 = GetResultString(If(placeholder, " => True", " => False")) Verify(d, s1, s2, s3) End Sub Private Function GetResultString(result As String) As String builder.Append(result) Dim s1 = builder.ToString() builder.Clear() Return s1 End Function Private Sub Verify(d As System.Linq.Expressions.Expression(Of System.Func(Of String)), s1 As String, s2 As String, s3 As String) If s1 <> s3 Then System.Console.WriteLine("1 => ") System.Console.WriteLine(d.ToString()) System.Console.WriteLine(s1) System.Console.WriteLine(s3) End If If s2 <> s3 Then System.Console.WriteLine("2 => ") System.Console.WriteLine(d.ToString()) System.Console.WriteLine(s2) System.Console.WriteLine(s3) End If End Sub Function BooleanTrue(i As Integer) As Boolean builder.AppendFormat(" BooleanTrue({0})", i) Return True End Function Function BooleanFalse(i As Integer) As Boolean builder.AppendFormat(" BooleanFalse({0})", i) Return False End Function Function NullableTrue(i As Integer) As Boolean? builder.AppendFormat(" NullableTrue({0})", i) Return True End Function Function NullableFalse(i As Integer) As Boolean? builder.AppendFormat(" NullableFalse({0})", i) Return False End Function Function NullableNull(i As Integer) As Boolean? builder.AppendFormat(" NullableNull({0})", i) Return Nothing End Function End Module ]]> Dim compilation1 = CreateCompilation(source, options:=TestOptions.ReleaseExe) Dim tree1 = compilation1.SyntaxTrees.Single() Dim placeholders = tree1.GetRoot().DescendantNodes().OfType(Of IdentifierNameSyntax)().Where(Function(id) id.Identifier.ValueText = "placeholder").ToArray() Assert.Equal(3, placeholders.Length) Dim nameInInvocation = tree1.GetRoot().DescendantNodes().OfType(Of IdentifierNameSyntax)().Where(Function(id) id.Identifier.ValueText = "Test").Single() Dim invocation = nameInInvocation.Ancestors().OfType(Of ExpressionStatementSyntax)().Single() Dim testMethod = tree1.GetRoot().DescendantNodes().OfType(Of MethodBlockSyntax)().Where(Function(block) block.SubOrFunctionStatement.Identifier.ValueText = "Test").Single() Assert.Equal("Test()", invocation.ToString()) Dim enumerator = BooleanExpression_30_Helpers.BuildConditions(2, 2).GetEnumerator() Const batchSize As Integer = 250 Dim newBlocks = ArrayBuilder(Of MethodBlockSyntax).GetInstance(batchSize) While enumerator.MoveNext newBlocks.Clear() Do Dim replacement = enumerator.Current Dim newBlock = testMethod.ReplaceNodes(placeholders, Function(n1, n2) replacement) newBlock = newBlock.ReplaceToken(newBlock.SubOrFunctionStatement.Identifier, SyntaxFactory.Identifier("Test" + (newBlocks.Count + 1).ToString())) newBlocks.Add(newBlock) Loop While newBlocks.Count < batchSize AndAlso enumerator.MoveNext() Dim newRoot = tree1.GetRoot().ReplaceNode(invocation, Enumerable.Range(1, newBlocks.Count). Select(Function(i) invocation.ReplaceToken(nameInInvocation.Identifier, SyntaxFactory.Identifier("Test" + i.ToString())))) Dim oldBlock = newRoot.DescendantNodes().OfType(Of MethodBlockSyntax)().Where(Function(block) block.SubOrFunctionStatement.Identifier.ValueText = "Test").Single() newRoot = newRoot.ReplaceNode(oldBlock, newBlocks) Dim tree2 = newRoot.SyntaxTree Dim compilation2 = compilation1.ReplaceSyntaxTree(tree1, tree2) CompileAndVerify(compilation2, expectedOutput:="Done") End While newBlocks.Free() End Sub Private Class BooleanExpression_30_Helpers Class TreeNode Public Left As TreeNode Public Right As TreeNode End Class Public Shared Iterator Function BuildConditions(fromOperators As Integer, toOperators As Integer) As IEnumerable(Of ExpressionSyntax) For operatorCount = fromOperators To toOperators For Each shape In Shapes(operatorCount) For Each operators In OperatorSets(operatorCount) For Each operands In OperandSets(operatorCount + 1) Yield BuildCondition(shape, operators, operands) Next Next Next Next End Function Public Shared Function BuildCondition(shape As TreeNode, operators As ImmutableList(Of SyntaxKind), operands As ImmutableList(Of ExpressionSyntax)) As ExpressionSyntax Dim result = BuildConditionWorker(shape, operators, operands) Assert.Empty(operators) Assert.Empty(operands) Return result End Function Private Shared Function BuildConditionWorker(shape As TreeNode, ByRef operators As ImmutableList(Of SyntaxKind), ByRef operands As ImmutableList(Of ExpressionSyntax)) As ExpressionSyntax If shape Is Nothing Then Dim result = operands(0) operands = operands.RemoveAt(0) Return result End If Dim left = BuildConditionWorker(shape.Left, operators, operands) Dim opKind = operators(0) operators = operators.RemoveAt(0) Dim right = BuildConditionWorker(shape.Right, operators, operands) Return SyntaxFactory.BinaryExpression( If(opKind = SyntaxKind.OrElseKeyword, SyntaxKind.OrElseExpression, SyntaxKind.AndAlsoExpression), left, SyntaxFactory.Token(opKind), right) End Function ''' ''' Enumerate all possible shapes of binary trees with given amount of nodes in it. ''' ''' ''' Public Shared Iterator Function Shapes(count As Integer) As IEnumerable(Of TreeNode) Select Case (count) Case 0 Yield Nothing Case 1 Yield New TreeNode() Case Else For i = 0 To count - 1 For Each leftTree In Shapes(count - 1 - i) For Each rightTree In Shapes(i) Yield New TreeNode() With {.Left = leftTree, .Right = rightTree} Next Next Next End Select End Function Shared Iterator Function OperatorSets(count As Integer) As IEnumerable(Of ImmutableList(Of SyntaxKind)) Select Case (count) Case 0 Yield ImmutableList(Of SyntaxKind).Empty Case Else For Each s In OperatorSets(count - 1) Yield s.Add(SyntaxKind.AndAlsoKeyword) Yield s.Add(SyntaxKind.OrElseKeyword) Next End Select End Function Shared Iterator Function OperandSets(count As Integer) As IEnumerable(Of ImmutableList(Of ExpressionSyntax)) Select Case (count) Case 0 Yield ImmutableList(Of ExpressionSyntax).Empty Case Else For Each s In OperandSets(count - 1) ' New Boolean?() Yield s.Add(SyntaxFactory.ObjectCreationExpression(SyntaxFactory.NullableType(SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.BooleanKeyword))))) For Each name In {"BooleanTrue", "BooleanFalse", "NullableTrue", "NullableFalse", "NullableNull"} Yield s.Add(SyntaxFactory.InvocationExpression( SyntaxFactory.IdentifierName(name), SyntaxFactory.ArgumentList( SyntaxFactory.SeparatedList(Of ArgumentSyntax)( New ArgumentSyntax() {SyntaxFactory.SimpleArgument( SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.IntegerLiteralToken(count.ToString(), LiteralBase.Decimal, TypeCharacter.None, CType(count, ULong))))})))) Next Next End Select End Function End Class End Class End Namespace